From 9173dca03f87624ca83e06b1fe37ec5df3a80e8a Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 9 May 2021 16:18:36 -0500 Subject: [PATCH 01/11] Added equip slots for other weapons. --- common/src/combat.rs | 8 +- common/src/comp/inventory/loadout.rs | 6 +- common/src/comp/inventory/loadout_builder.rs | 72 ++++++++++-------- common/src/comp/inventory/mod.rs | 7 +- common/src/comp/inventory/slot.rs | 12 ++- common/src/lib.rs | 1 + common/src/states/utils.rs | 74 ++++++++++++++----- common/src/states/wielding.rs | 9 ++- common/systems/src/character_behavior.rs | 16 +++- server/src/character_creator.rs | 2 +- server/src/events/interaction.rs | 8 +- server/src/migrations/V37__equip_slots.sql | 8 ++ server/src/sys/agent.rs | 2 +- .../src/audio/sfx/event_mapper/combat/mod.rs | 2 +- voxygen/src/hud/bag.rs | 8 +- voxygen/src/hud/hotbar.rs | 21 +++--- voxygen/src/hud/skillbar.rs | 22 +++--- voxygen/src/hud/slots.rs | 20 ++--- voxygen/src/menu/char_selection/ui/mod.rs | 4 +- voxygen/src/scene/figure/cache.rs | 4 +- voxygen/src/scene/figure/mod.rs | 4 +- voxygen/src/scene/simple.rs | 4 +- voxygen/src/session/mod.rs | 2 +- 23 files changed, 197 insertions(+), 119 deletions(-) create mode 100644 server/src/migrations/V37__equip_slots.sql diff --git a/common/src/combat.rs b/common/src/combat.rs index d57e219e96..4755f3d170 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -805,8 +805,8 @@ fn equipped_item_and_tool(inv: &Inventory, slot: EquipSlot) -> Option<(&Item, &T #[cfg(not(target_arch = "wasm32"))] pub fn get_weapons(inv: &Inventory) -> (Option, Option) { ( - equipped_item_and_tool(inv, EquipSlot::Mainhand).map(|(_, tool)| tool.kind), - equipped_item_and_tool(inv, EquipSlot::Offhand).map(|(_, tool)| tool.kind), + equipped_item_and_tool(inv, EquipSlot::ActiveMainhand).map(|(_, tool)| tool.kind), + equipped_item_and_tool(inv, EquipSlot::ActiveOffhand).map(|(_, tool)| tool.kind), ) } @@ -845,14 +845,14 @@ fn weapon_skills(inventory: &Inventory, skill_set: &SkillSet) -> f32 { fn get_weapon_rating(inventory: &Inventory, msm: &MaterialStatManifest) -> f32 { let mainhand_rating = - if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::Mainhand) { + if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::ActiveMainhand) { weapon_rating(item, msm) } else { 0.0 }; let offhand_rating = - if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::Offhand) { + if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::ActiveOffhand) { weapon_rating(item, msm) } else { 0.0 diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index e095e401e2..c4b6566900 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -75,8 +75,10 @@ impl Loadout { (EquipSlot::Armor(ArmorSlot::Bag2), "bag2".to_string()), (EquipSlot::Armor(ArmorSlot::Bag3), "bag3".to_string()), (EquipSlot::Armor(ArmorSlot::Bag4), "bag4".to_string()), - (EquipSlot::Mainhand, "active_item".to_string()), - (EquipSlot::Offhand, "second_item".to_string()), + (EquipSlot::ActiveMainhand, "active_mainhand".to_string()), + (EquipSlot::ActiveOffhand, "active_offhand".to_string()), + (EquipSlot::InactiveMainhand, "inactive_mainhand".to_string()), + (EquipSlot::InactiveOffhand, "inactive_offhand".to_string()), ] .into_iter() .map(|(equip_slot, persistence_key)| LoadoutSlot::new(equip_slot, persistence_key)) diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index be0c2728c7..030851e417 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -30,7 +30,7 @@ use tracing::warn; /// // Build a loadout with character starter defaults and a specific sword with default sword abilities /// let loadout = LoadoutBuilder::new() /// .defaults() -/// .active_item(Some(Item::new_from_asset_expect("common.items.weapons.sword.steel-8"))) +/// .active_mainhand(Some(Item::new_from_asset_expect("common.items.weapons.sword.steel-8"))) /// .build(); /// ``` #[derive(Clone)] @@ -376,7 +376,7 @@ impl LoadoutBuilder { match config { Adlet => match active_tool_kind { Some(ToolKind::Bow) => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.adlet.head.adlet_bow", ))) @@ -397,7 +397,7 @@ impl LoadoutBuilder { ))) .build(), Some(ToolKind::Spear) | Some(ToolKind::Staff) => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.adlet.head.adlet_spear", ))) @@ -417,11 +417,11 @@ impl LoadoutBuilder { "common.items.npc_armor.biped_small.adlet.tail.adlet", ))) .build(), - _ => LoadoutBuilder::new().active_item(active_item).build(), + _ => LoadoutBuilder::new().active_mainhand(active_item).build(), }, Gnarling => match active_tool_kind { Some(ToolKind::Bow) => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.gnarling.head.gnarling", ))) @@ -442,7 +442,7 @@ impl LoadoutBuilder { ))) .build(), Some(ToolKind::Staff) => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.gnarling.head.gnarling", ))) @@ -463,7 +463,7 @@ impl LoadoutBuilder { ))) .build(), Some(ToolKind::Spear) => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.gnarling.head.gnarling", ))) @@ -480,10 +480,10 @@ impl LoadoutBuilder { "common.items.npc_armor.biped_small.gnarling.pants.gnarling", ))) .build(), - _ => LoadoutBuilder::new().active_item(active_item).build(), + _ => LoadoutBuilder::new().active_mainhand(active_item).build(), }, Sahagin => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.sahagin.head.sahagin", ))) @@ -504,7 +504,7 @@ impl LoadoutBuilder { ))) .build(), Haniwa => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.haniwa.head.haniwa", ))) @@ -522,7 +522,7 @@ impl LoadoutBuilder { ))) .build(), Myrmidon => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.myrmidon.head.myrmidon", ))) @@ -543,7 +543,7 @@ impl LoadoutBuilder { ))) .build(), Husk => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .head(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_small.husk.head.husk", ))) @@ -561,7 +561,7 @@ impl LoadoutBuilder { ))) .build(), Guard => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.leather_plate.shoulder", ))) @@ -703,7 +703,7 @@ impl LoadoutBuilder { } } LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.twigsflowers.shoulder", ))) @@ -742,7 +742,7 @@ impl LoadoutBuilder { .build() }, Outcast => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.cloth_purple.shoulder", ))) @@ -767,7 +767,7 @@ impl LoadoutBuilder { }) .build(), Highwayman => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.swift.shoulder", ))) @@ -795,7 +795,7 @@ impl LoadoutBuilder { ))) .build(), Bandit => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.assassin.shoulder", ))) @@ -823,7 +823,7 @@ impl LoadoutBuilder { ))) .build(), CultistNovice => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.steel.shoulder", ))) @@ -854,7 +854,7 @@ impl LoadoutBuilder { ))) .build(), CultistAcolyte => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.cultist.shoulder", ))) @@ -885,7 +885,7 @@ impl LoadoutBuilder { ))) .build(), Warlord => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.warlord.shoulder", ))) @@ -916,7 +916,7 @@ impl LoadoutBuilder { ))) .build(), Warlock => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .shoulder(Some(Item::new_from_asset_expect( "common.items.armor.warlock.shoulder", ))) @@ -947,7 +947,7 @@ impl LoadoutBuilder { ))) .build(), Villager => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .chest(Some(Item::new_from_asset_expect( match rand::thread_rng().gen_range(0..10) { 0 => "common.items.armor.misc.chest.worker_green_0", @@ -981,36 +981,46 @@ impl LoadoutBuilder { match body { Body::BipedLarge(b) => match b.species { biped_large::Species::Mindflayer => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .chest(Some(Item::new_from_asset_expect( "common.items.npc_armor.biped_large.mindflayer", ))) .build(), - _ => LoadoutBuilder::new().active_item(active_item).build(), + _ => LoadoutBuilder::new().active_mainhand(active_item).build(), }, Body::Golem(g) => match g.species { golem::Species::ClayGolem => LoadoutBuilder::new() - .active_item(active_item) + .active_mainhand(active_item) .chest(Some(Item::new_from_asset_expect( "common.items.npc_armor.golem.claygolem", ))) .build(), - _ => LoadoutBuilder::new().active_item(active_item).build(), + _ => LoadoutBuilder::new().active_mainhand(active_item).build(), }, - _ => LoadoutBuilder::new().active_item(active_item).build(), + _ => LoadoutBuilder::new().active_mainhand(active_item).build(), } }; Self(loadout) } - pub fn active_item(mut self, item: Option) -> Self { - self.0.swap(EquipSlot::Mainhand, item); + pub fn active_mainhand(mut self, item: Option) -> Self { + self.0.swap(EquipSlot::ActiveMainhand, item); self } - pub fn second_item(mut self, item: Option) -> Self { - self.0.swap(EquipSlot::Offhand, item); + pub fn active_offhand(mut self, item: Option) -> Self { + self.0.swap(EquipSlot::ActiveOffhand, item); + self + } + + pub fn inactive_mainhand(mut self, item: Option) -> Self { + self.0.swap(EquipSlot::InactiveMainhand, item); + self + } + + pub fn inactive_offhand(mut self, item: Option) -> Self { + self.0.swap(EquipSlot::InactiveOffhand, item); self } diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 8b9108e016..3fd8caa2ed 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -553,10 +553,11 @@ impl Inventory { self.get(inv_slot) .and_then(|item| self.loadout.get_slot_to_equip_into(item.kind())) .map(|equip_slot| { - // Special case when equipping into main hand - swap with offhand first - if equip_slot == EquipSlot::Mainhand { + // Special case when equipping into active main hand - swap with active offhand + // first + if equip_slot == EquipSlot::ActiveMainhand { self.loadout - .swap_slots(EquipSlot::Mainhand, EquipSlot::Offhand); + .swap_slots(EquipSlot::ActiveMainhand, EquipSlot::InactiveMainhand); } self.swap_inventory_loadout(inv_slot, equip_slot) diff --git a/common/src/comp/inventory/slot.rs b/common/src/comp/inventory/slot.rs index 4a5ad3b97a..ec3319514a 100644 --- a/common/src/comp/inventory/slot.rs +++ b/common/src/comp/inventory/slot.rs @@ -81,8 +81,10 @@ impl From for SlotId { #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)] pub enum EquipSlot { Armor(ArmorSlot), - Mainhand, - Offhand, + ActiveMainhand, + ActiveOffhand, + InactiveMainhand, + InactiveOffhand, Lantern, Glider, } @@ -120,8 +122,10 @@ impl EquipSlot { pub fn can_hold(self, item_kind: &item::ItemKind) -> bool { match (self, item_kind) { (Self::Armor(slot), ItemKind::Armor(armor::Armor { kind, .. })) => slot.can_hold(kind), - (Self::Mainhand, ItemKind::Tool(_)) => true, - (Self::Offhand, ItemKind::Tool(_)) => true, + (Self::ActiveMainhand, ItemKind::Tool(_)) => true, + (Self::ActiveOffhand, ItemKind::Tool(_)) => true, + (Self::InactiveMainhand, ItemKind::Tool(_)) => true, + (Self::InactiveOffhand, ItemKind::Tool(_)) => true, (Self::Lantern, ItemKind::Lantern(_)) => true, (Self::Glider, ItemKind::Glider(_)) => true, _ => false, diff --git a/common/src/lib.rs b/common/src/lib.rs index b561bf0720..132fee892a 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -14,6 +14,7 @@ option_expect_none, option_unwrap_none, option_zip, + or_patterns, trait_alias, type_alias_impl_trait )] diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 1547bc9838..880fc594e1 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -440,14 +440,34 @@ pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) { /// If a tool is equipped, goes into Equipping state, otherwise goes to Idle pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) { - if let Some((item, ItemKind::Tool(tool))) = data - .inventory - .equipped(EquipSlot::Mainhand) - .map(|i| (i, i.kind())) - { + // Closure to get equip time provided an equip slot if a tool is equipped in + // equip slot + let equip_time = |equip_slot| { + data.inventory + .equipped(equip_slot) + .and_then(|item| match item.kind() { + ItemKind::Tool(tool) => Some((item, tool)), + _ => None, + }) + .map(|(item, tool)| tool.equip_time(data.msm, item.components())) + }; + + // Calcualtes time required to equip weapons, if weapon in mainhand and offhand, + // uses maximum duration + let mainhand_equip_time = equip_time(EquipSlot::ActiveMainhand); + let offhand_equip_time = equip_time(EquipSlot::ActiveOffhand); + let equip_time = match (mainhand_equip_time, offhand_equip_time) { + (Some(a), Some(b)) => Some(a.max(b)), + (Some(a), None) | (None, Some(a)) => Some(a), + (None, None) => None, + }; + + // Moves entity into equipping state if there is some equip time, else moves + // intantly into wield + if let Some(equip_time) = equip_time { update.character = CharacterState::Equipping(equipping::Data { static_data: equipping::StaticData { - buildup_duration: tool.equip_time(data.msm, item.components()), + buildup_duration: equip_time, }, timer: Duration::default(), }); @@ -504,7 +524,15 @@ pub fn handle_climb(data: &JoinData, update: &mut StateUpdate) -> bool { /// Checks that player can Swap Weapons and updates `Loadout` if so pub fn attempt_swap_equipped_weapons(data: &JoinData, update: &mut StateUpdate) { - if data.inventory.equipped(EquipSlot::Offhand).is_some() { + if data + .inventory + .equipped(EquipSlot::InactiveMainhand) + .is_some() + || data + .inventory + .equipped(EquipSlot::InactiveOffhand) + .is_some() + { update.swap_equipped_weapons = true; } } @@ -556,14 +584,14 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) { let no_main_hand = hands.0.is_none(); // skill_index used to select ability for the AbilityKey::Skill2 input let (equip_slot, skill_index) = if no_main_hand { - (Some(EquipSlot::Offhand), 1) + (Some(EquipSlot::ActiveOffhand), 1) } else if always_main_hand { - (Some(EquipSlot::Mainhand), 0) + (Some(EquipSlot::ActiveMainhand), 0) } else { match hands { - (Some(Hands::Two), _) => (Some(EquipSlot::Mainhand), 1), - (_, Some(Hands::One)) => (Some(EquipSlot::Offhand), 0), - (Some(Hands::One), _) => (Some(EquipSlot::Mainhand), 1), + (Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1), + (_, Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0), + (Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1), (_, _) => (None, 0), } }; @@ -596,7 +624,11 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) { { update.character = CharacterState::from(( &ability, - AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input), + AbilityInfo::from_input( + data, + matches!(equip_slot, EquipSlot::ActiveOffhand), + input, + ), )); } } @@ -640,7 +672,8 @@ pub fn handle_block_input(data: &JoinData, update: &mut StateUpdate) { |equip_slot| matches!(unwrap_tool_data(data, equip_slot), Some(tool) if tool.can_block()); let hands = get_hands(data); if input_is_pressed(data, InputKind::Block) - && (can_block(EquipSlot::Mainhand) || (hands.0.is_none() && can_block(EquipSlot::Offhand))) + && (can_block(EquipSlot::ActiveMainhand) + || (hands.0.is_none() && can_block(EquipSlot::ActiveOffhand))) { let ability = CharacterAbility::default_block(); if ability.requirements_paid(data, update) { @@ -696,15 +729,18 @@ pub fn get_hands(data: &JoinData) -> (Option, Option) { None } }; - (hand(EquipSlot::Mainhand), hand(EquipSlot::Offhand)) + ( + hand(EquipSlot::ActiveMainhand), + hand(EquipSlot::ActiveOffhand), + ) } pub fn get_crit_data(data: &JoinData, ai: AbilityInfo) -> (f32, f32) { const DEFAULT_CRIT_DATA: (f32, f32) = (0.5, 1.3); use HandInfo::*; let slot = match ai.hand { - Some(TwoHanded) | Some(MainHand) => EquipSlot::Mainhand, - Some(OffHand) => EquipSlot::Offhand, + Some(TwoHanded) | Some(MainHand) => EquipSlot::ActiveMainhand, + Some(OffHand) => EquipSlot::ActiveOffhand, None => return DEFAULT_CRIT_DATA, }; if let Some(item) = data.inventory.equipped(slot) { @@ -792,9 +828,9 @@ pub struct AbilityInfo { impl AbilityInfo { pub fn from_input(data: &JoinData, from_offhand: bool, input: InputKind) -> Self { let tool_data = if from_offhand { - unwrap_tool_data(data, EquipSlot::Offhand) + unwrap_tool_data(data, EquipSlot::ActiveOffhand) } else { - unwrap_tool_data(data, EquipSlot::Mainhand) + unwrap_tool_data(data, EquipSlot::ActiveMainhand) }; let (tool, hand) = ( tool_data.map(|t| t.kind), diff --git a/common/src/states/wielding.rs b/common/src/states/wielding.rs index 4798b44834..48673483bd 100644 --- a/common/src/states/wielding.rs +++ b/common/src/states/wielding.rs @@ -60,9 +60,12 @@ impl CharacterBehavior for Data { fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { let mut update = StateUpdate::from(data); match inv_action { - InventoryAction::Drop(EquipSlot::Mainhand) - | InventoryAction::Swap(EquipSlot::Mainhand, _) - | InventoryAction::Swap(_, Slot::Equip(EquipSlot::Mainhand)) => { + InventoryAction::Drop(EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand) + | InventoryAction::Swap(EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand, _) + | InventoryAction::Swap( + _, + Slot::Equip(EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand), + ) => { update.character = CharacterState::Idle; }, _ => (), diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index a97350888b..7b9b4cb62d 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -51,12 +51,22 @@ fn incorporate_update(join: &mut JoinStruct, mut state_update: StateUpdate) { assert!( inventory .swap( - Slot::Equip(EquipSlot::Mainhand), - Slot::Equip(EquipSlot::Offhand), + Slot::Equip(EquipSlot::ActiveMainhand), + Slot::Equip(EquipSlot::InactiveMainhand), ) .first() .is_none(), - "Swapping main and offhand never results in leftover items", + "Swapping active and inactive mainhand never results in leftover items", + ); + assert!( + inventory + .swap( + Slot::Equip(EquipSlot::ActiveOffhand), + Slot::Equip(EquipSlot::InactiveOffhand), + ) + .first() + .is_none(), + "Swapping active and inactive offhand never results in leftover items", ); } } diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index 39df6e851c..fd9b896b7e 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -38,7 +38,7 @@ pub fn create_character( let loadout = LoadoutBuilder::new() .defaults() - .active_item(Some(Item::new_from_asset_expect(&tool_id))) + .active_mainhand(Some(Item::new_from_asset_expect(&tool_id))) .build(); let mut inventory = Inventory::new_with_loadout(loadout); diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index d671b1e341..e8c4a5e0e9 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -254,15 +254,15 @@ pub fn handle_possess(server: &mut Server, possessor_uid: Uid, possesse_uid: Uid assert!( inventory .swap( - Slot::Equip(EquipSlot::Mainhand), - Slot::Equip(EquipSlot::Offhand), + Slot::Equip(EquipSlot::ActiveMainhand), + Slot::Equip(EquipSlot::InactiveMainhand), ) .first() .is_none(), - "Swapping main and offhand never results in leftover items", + "Swapping active and inactive mainhands never results in leftover items", ); - inventory.replace_loadout_item(EquipSlot::Mainhand, Some(debug_item)); + inventory.replace_loadout_item(EquipSlot::ActiveMainhand, Some(debug_item)); } // Remove will of the entity diff --git a/server/src/migrations/V37__equip_slots.sql b/server/src/migrations/V37__equip_slots.sql new file mode 100644 index 0000000000..b9c3c0fc6a --- /dev/null +++ b/server/src/migrations/V37__equip_slots.sql @@ -0,0 +1,8 @@ +-- Sets active_item to active_mainhand and second_item to inactive_mainhand. +-- +-- second_item becomes inactive_mainhand because active_offhand is enforced to be 1h +-- and second_item was not necessarily guaranteed to be 1h. +UPDATE item +SET position = 'active_mainhand' WHERE position = 'active_item'; +UPDATE item +SET position = 'inactive_mainhand' WHERE position = 'second_item'; \ No newline at end of file diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 5182caee2d..7f7f987356 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1568,7 +1568,7 @@ impl<'a> AgentData<'a> { let tactic = self .inventory - .equipped(EquipSlot::Mainhand) + .equipped(EquipSlot::ActiveMainhand) .as_ref() .map(|item| { if let Some(ability_spec) = item.ability_spec() { diff --git a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs b/voxygen/src/audio/sfx/event_mapper/combat/mod.rs index c63f378b1d..58ec98bf46 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/mod.rs @@ -145,7 +145,7 @@ impl CombatEventMapper { previous_state: &PreviousEntityState, inventory: &Inventory, ) -> SfxEvent { - if let Some(item) = inventory.equipped(EquipSlot::Mainhand) { + if let Some(item) = inventory.equipped(EquipSlot::ActiveMainhand) { if let ItemKind::Tool(data) = item.kind() { if character_state.is_attack() { return SfxEvent::Attack( diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index c9baa92f9b..0673f3132d 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -1154,11 +1154,11 @@ impl<'a> Widget for Bag<'a> { } // Mainhand/Left-Slot let mainhand_item = inventory - .equipped(EquipSlot::Mainhand) + .equipped(EquipSlot::ActiveMainhand) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::Mainhand, [85.0; 2]) + .fabricate(EquipSlot::ActiveMainhand, [85.0; 2]) .bottom_right_with_margins_on(state.ids.back_slot, -95.0, 0.0) .with_icon(self.imgs.mainhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN)) .filled_slot(filled_slot); @@ -1177,10 +1177,10 @@ impl<'a> Widget for Bag<'a> { } // Offhand/Right-Slot let offhand_item = inventory - .equipped(EquipSlot::Offhand) + .equipped(EquipSlot::ActiveOffhand) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::Offhand, [85.0; 2]) + .fabricate(EquipSlot::ActiveOffhand, [85.0; 2]) .bottom_left_with_margins_on(state.ids.feet_slot, -95.0, 0.0) .with_icon(self.imgs.offhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN)) .filled_slot(filled_slot); diff --git a/voxygen/src/hud/hotbar.rs b/voxygen/src/hud/hotbar.rs index 56107833de..7bfe10b8d4 100644 --- a/voxygen/src/hud/hotbar.rs +++ b/voxygen/src/hud/hotbar.rs @@ -88,9 +88,12 @@ impl State { _ => None, }; - let equip_slot = match (hands(EquipSlot::Mainhand), hands(EquipSlot::Offhand)) { - (Some(_), _) => Some(EquipSlot::Mainhand), - (_, Some(_)) => Some(EquipSlot::Offhand), + let equip_slot = match ( + hands(EquipSlot::ActiveMainhand), + hands(EquipSlot::ActiveOffhand), + ) { + (Some(_), _) => Some(EquipSlot::ActiveMainhand), + (_, Some(_)) => Some(EquipSlot::ActiveOffhand), _ => None, }; @@ -140,14 +143,14 @@ impl State { _ => None, }; - let active_tool_hands = hands(EquipSlot::Mainhand); - let second_tool_hands = hands(EquipSlot::Offhand); + let active_tool_hands = hands(EquipSlot::ActiveMainhand); + let second_tool_hands = hands(EquipSlot::ActiveOffhand); let (equip_slot, skill_index) = match (active_tool_hands, second_tool_hands) { - (Some(Hands::Two), _) => (Some(EquipSlot::Mainhand), 1), - (Some(_), Some(Hands::One)) => (Some(EquipSlot::Offhand), 0), - (Some(Hands::One), _) => (Some(EquipSlot::Mainhand), 1), - (None, Some(_)) => (Some(EquipSlot::Offhand), 1), + (Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1), + (Some(_), Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0), + (Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1), + (None, Some(_)) => (Some(EquipSlot::ActiveOffhand), 1), (_, _) => (None, 0), }; diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index a458a8aef8..f48eb11aa9 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -536,7 +536,7 @@ impl<'a> Widget for Skillbar<'a> { .map(|item| (item.name(), item.description())), hotbar::SlotContents::Ability3 => content_source .1 - .equipped(EquipSlot::Mainhand) + .equipped(EquipSlot::ActiveMainhand) .map(|i| i.kind()) .and_then(|kind| match kind { ItemKind::Tool(Tool { kind, .. }) => ability_description(kind), @@ -552,14 +552,14 @@ impl<'a> Widget for Skillbar<'a> { _ => None, }; - let active_tool_hands = hands(EquipSlot::Mainhand); - let second_tool_hands = hands(EquipSlot::Offhand); + let active_tool_hands = hands(EquipSlot::ActiveMainhand); + let second_tool_hands = hands(EquipSlot::ActiveOffhand); let equip_slot = match (active_tool_hands, second_tool_hands) { - (Some(Hands::Two), _) => Some(EquipSlot::Mainhand), - (Some(_), Some(Hands::One)) => Some(EquipSlot::Offhand), - (Some(Hands::One), _) => Some(EquipSlot::Mainhand), - (None, Some(_)) => Some(EquipSlot::Offhand), + (Some(Hands::Two), _) => Some(EquipSlot::ActiveMainhand), + (Some(_), Some(Hands::One)) => Some(EquipSlot::ActiveOffhand), + (Some(Hands::One), _) => Some(EquipSlot::ActiveMainhand), + (None, Some(_)) => Some(EquipSlot::ActiveOffhand), (_, _) => None, }; @@ -657,8 +657,8 @@ impl<'a> Widget for Skillbar<'a> { .right_from(state.ids.slot5, slot_offset) .set(state.ids.m1_slot_bg, ui); - let active_tool = get_item_and_tool(self.inventory, EquipSlot::Mainhand); - let second_tool = get_item_and_tool(self.inventory, EquipSlot::Offhand); + let active_tool = get_item_and_tool(self.inventory, EquipSlot::ActiveMainhand); + let second_tool = get_item_and_tool(self.inventory, EquipSlot::ActiveOffhand); let tool = match ( active_tool.map(|(_, x)| x.hands), @@ -700,8 +700,8 @@ impl<'a> Widget for Skillbar<'a> { } } - let active_tool = get_item_and_tool(self.inventory, EquipSlot::Mainhand); - let second_tool = get_item_and_tool(self.inventory, EquipSlot::Offhand); + let active_tool = get_item_and_tool(self.inventory, EquipSlot::ActiveMainhand); + let second_tool = get_item_and_tool(self.inventory, EquipSlot::ActiveOffhand); let tool = match ( active_tool.map(|(_, x)| x.hands), diff --git a/voxygen/src/hud/slots.rs b/voxygen/src/hud/slots.rs index d5b587f5ec..d77bebb153 100644 --- a/voxygen/src/hud/slots.rs +++ b/voxygen/src/hud/slots.rs @@ -143,12 +143,12 @@ impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { _ => None, }; - let active_tool_hands = hands(EquipSlot::Mainhand); - let second_tool_hands = hands(EquipSlot::Offhand); + let active_tool_hands = hands(EquipSlot::ActiveMainhand); + let second_tool_hands = hands(EquipSlot::ActiveOffhand); let equip_slot = match (active_tool_hands, second_tool_hands) { - (Some(_), _) => Some(EquipSlot::Mainhand), - (None, Some(_)) => Some(EquipSlot::Offhand), + (Some(_), _) => Some(EquipSlot::ActiveMainhand), + (None, Some(_)) => Some(EquipSlot::ActiveOffhand), (_, _) => None, }; @@ -189,14 +189,14 @@ impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { _ => None, }; - let active_tool_hands = hands(EquipSlot::Mainhand); - let second_tool_hands = hands(EquipSlot::Offhand); + let active_tool_hands = hands(EquipSlot::ActiveMainhand); + let second_tool_hands = hands(EquipSlot::ActiveOffhand); let (equip_slot, skill_index) = match (active_tool_hands, second_tool_hands) { - (Some(Hands::Two), _) => (Some(EquipSlot::Mainhand), 1), - (Some(_), Some(Hands::One)) => (Some(EquipSlot::Offhand), 0), - (Some(Hands::One), _) => (Some(EquipSlot::Mainhand), 1), - (None, Some(_)) => (Some(EquipSlot::Offhand), 1), + (Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1), + (Some(_), Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0), + (Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1), + (None, Some(_)) => (Some(EquipSlot::ActiveOffhand), 1), (_, _) => (None, 0), }; diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index df028ea997..502320c95d 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -182,7 +182,7 @@ impl Mode { let loadout = LoadoutBuilder::new() .defaults() - .active_item(Some(Item::new_from_asset_expect(tool))) + .active_mainhand(Some(Item::new_from_asset_expect(tool))) .build(); let inventory = Box::new(Inventory::new_with_loadout(loadout)); @@ -1328,7 +1328,7 @@ impl Controls { { *tool = value; inventory.replace_loadout_item( - EquipSlot::Mainhand, + EquipSlot::ActiveMainhand, Some(Item::new_from_asset_expect(*tool)), ); } diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 8ac24de101..c148d5a9dd 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -221,10 +221,10 @@ impl CharacterCacheKey { }; Some(CharacterToolKey { active: inventory - .equipped(EquipSlot::Mainhand) + .equipped(EquipSlot::ActiveMainhand) .map(tool_key_from_item), second: inventory - .equipped(EquipSlot::Offhand) + .equipped(EquipSlot::ActiveOffhand) .map(tool_key_from_item), }) } else { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index be968bb815..b4b16a1778 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -740,9 +740,9 @@ impl FigureMgr { }; let (active_tool_kind, active_tool_hand, active_tool_spec) = - tool_info(EquipSlot::Mainhand); + tool_info(EquipSlot::ActiveMainhand); let (second_tool_kind, second_tool_hand, second_tool_spec) = - tool_info(EquipSlot::Offhand); + tool_info(EquipSlot::ActiveOffhand); let hands = (active_tool_hand, second_tool_hand); diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 4901a5972c..2b0b0135a9 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -307,7 +307,7 @@ impl Scene { .clean(&mut self.col_lights, scene_data.tick); let active_item_kind = inventory - .and_then(|inv| inv.equipped(EquipSlot::Mainhand)) + .and_then(|inv| inv.equipped(EquipSlot::ActiveMainhand)) .map(|i| i.kind()); let (active_tool_kind, active_tool_hand) = @@ -318,7 +318,7 @@ impl Scene { }; let second_item_kind = inventory - .and_then(|inv| inv.equipped(EquipSlot::Offhand)) + .and_then(|inv| inv.equipped(EquipSlot::ActiveOffhand)) .map(|i| i.kind()); let (second_tool_kind, second_tool_hand) = diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index bbc2a76e05..647308dcf2 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -329,7 +329,7 @@ impl PlayState for SessionState { .borrow() .inventories() .get(player_entity) - .and_then(|inv| inv.equipped(EquipSlot::Mainhand)) + .and_then(|inv| inv.equipped(EquipSlot::ActiveMainhand)) .and_then(|item| item.tool()) .map_or(false, |tool| tool.kind == ToolKind::Pick) && self.client.borrow().is_wielding() == Some(true); From 6b153bcf472ae25d085cb10e380b1ccd2fb575c4 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 11 May 2021 21:10:41 -0500 Subject: [PATCH 02/11] Enforced certain invariants in how an item was equipped into the loadout: - a 2h weapon can only be equipped in a mainhand slot if the offhand slot is empty - a 1h weapon can only be equipped in an offhand slot if the mainhand slot has a 1h weapon - 2h weapons can never be equipped in an offhand slot Fixed some tests --- common/src/comp/inventory/loadout.rs | 66 +++++++++++++++++-- common/src/comp/inventory/mod.rs | 8 +-- common/src/comp/inventory/test.rs | 18 +++-- .../audio/sfx/event_mapper/combat/tests.rs | 10 +-- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index c4b6566900..5116648b14 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -1,6 +1,6 @@ use crate::comp::{ inventory::{ - item::ItemKind, + item::{tool, ItemKind}, slot::{ArmorSlot, EquipSlot}, InvSlot, }, @@ -173,10 +173,10 @@ impl Loadout { // Check if items can go in the other slots if item_a .as_ref() - .map_or(true, |i| equip_slot_b.can_hold(&i.kind())) + .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) && item_b .as_ref() - .map_or(true, |i| equip_slot_a.can_hold(&i.kind())) + .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) { // Swap self.swap(equip_slot_b, item_a).unwrap_none(); @@ -197,7 +197,7 @@ impl Loadout { let mut suitable_slots = self .slots .iter() - .filter(|s| s.equip_slot.can_hold(item_kind)); + .filter(|s| self.slot_can_hold(s.equip_slot, item_kind)); let first = suitable_slots.next(); @@ -217,7 +217,7 @@ impl Loadout { ) -> impl Iterator { self.slots .iter() - .filter(move |s| s.equip_slot.can_hold(&item_kind)) + .filter(move |s| self.slot_can_hold(s.equip_slot, &item_kind)) .filter_map(|s| s.slot.as_ref()) } @@ -296,21 +296,73 @@ impl Loadout { /// If no slot is available the item is returned. #[must_use = "Returned item will be lost if not used"] pub(super) fn try_equip(&mut self, item: Item) -> Result<(), Item> { - if let Some(loadout_slot) = self + /* if let Some(loadout_slot) = self .slots .iter_mut() - .find(|s| s.slot.is_none() && s.equip_slot.can_hold(item.kind())) + .find(|s| s.slot.is_none() && self.slot_can_hold(s.equip_slot, item.kind())) { loadout_slot.slot = Some(item); Ok(()) } else { Err(item) + } */ + // TODO: Get XVar to see if there better way to handle mutability issues + let loadout_slot = self + .slots + .iter() + .find(|s| s.slot.is_none() && self.slot_can_hold(s.equip_slot, item.kind())) + .map(|s| s.equip_slot); + if let Some(slot) = self + .slots + .iter_mut() + .find(|s| Some(s.equip_slot) == loadout_slot) + { + slot.slot = Some(item); + Ok(()) + } else { + Err(item) } } pub(super) fn items(&self) -> impl Iterator { self.slots.iter().filter_map(|x| x.slot.as_ref()) } + + /// Checks that a slot can hold a given item + pub(super) fn slot_can_hold(&self, equip_slot: EquipSlot, item_kind: &ItemKind) -> bool { + // Checks if item can be equipped in a mainhand slot + let mainhand_check = |offhand_slot| { + // Allows item to be equipped if itemkind is a tool and... + matches!(item_kind, ItemKind::Tool(mainhand) if { + if let Some(ItemKind::Tool(offhand)) = self.equipped(offhand_slot).map(|i| i.kind()) { + // if offhand is 1 handed, only if mainhand is also 1 handed + matches!(offhand.hands, tool::Hands::One) && matches!(mainhand.hands, tool::Hands::One) + } else { + // else there is no tool equipped in offhand, so only if slot can normally hold this item + equip_slot.can_hold(item_kind) + } + }) + }; + + // Checks if item can be equipped in an offhand slot + let offhand_check = |mainhand_slot| { + // Allows item to be equipped if itemkind is a tool and... + matches!(item_kind, ItemKind::Tool(offhand) if { + // if offhand weapon is 1 handed... + matches!(offhand.hands, tool::Hands::One) + // and if mainhand has a 1 handed weapon... + && matches!(self.equipped(mainhand_slot).map(|i| i.kind()), Some(ItemKind::Tool(mainhand)) if matches!(mainhand.hands, tool::Hands::One)) + }) + }; + + match equip_slot { + EquipSlot::ActiveMainhand => mainhand_check(EquipSlot::ActiveOffhand), + EquipSlot::ActiveOffhand => offhand_check(EquipSlot::ActiveMainhand), + EquipSlot::InactiveMainhand => mainhand_check(EquipSlot::InactiveOffhand), + EquipSlot::InactiveOffhand => offhand_check(EquipSlot::InactiveMainhand), + _ => equip_slot.can_hold(item_kind), + } + } } #[cfg(test)] diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 3fd8caa2ed..5bc40e586b 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -744,12 +744,12 @@ impl Inventory { /// account whether there will be free space in the inventory for the /// loadout item once any slots that were provided by it have been /// removed. + #[allow(clippy::blocks_in_if_conditions)] pub fn can_swap(&self, inv_slot_id: InvSlotId, equip_slot: EquipSlot) -> bool { // Check if loadout slot can hold item - if !self - .get(inv_slot_id) - .map_or(true, |item| equip_slot.can_hold(&item.kind())) - { + if !self.get(inv_slot_id).map_or(true, |item| { + self.loadout.slot_can_hold(equip_slot, &item.kind()) + }) { trace!("can_swap = false, equip slot can't hold item"); return false; } diff --git a/common/src/comp/inventory/test.rs b/common/src/comp/inventory/test.rs index 5b6ec62919..fae0a8174c 100644 --- a/common/src/comp/inventory/test.rs +++ b/common/src/comp/inventory/test.rs @@ -231,23 +231,29 @@ fn unequip_items_both_hands() { let sword = Item::new_from_asset_expect("common.items.weapons.sword.steel-8"); - inv.replace_loadout_item(EquipSlot::Mainhand, Some(sword.duplicate(ability_map, msm))); - inv.replace_loadout_item(EquipSlot::Offhand, Some(sword.duplicate(ability_map, msm))); + inv.replace_loadout_item( + EquipSlot::ActiveMainhand, + Some(sword.duplicate(ability_map, msm)), + ); + inv.replace_loadout_item( + EquipSlot::InactiveMainhand, + Some(sword.duplicate(ability_map, msm)), + ); // Fill all inventory slots except one fill_inv_slots(&mut inv, 17); - let result = inv.unequip(EquipSlot::Mainhand); + let result = inv.unequip(EquipSlot::ActiveMainhand); // We have space in the inventory, so this should have unequipped - assert_eq!(None, inv.equipped(EquipSlot::Mainhand)); + assert_eq!(None, inv.equipped(EquipSlot::ActiveMainhand)); assert_eq!(18, inv.populated_slots()); assert_eq!(true, result.is_ok()); - let result = inv.unequip(EquipSlot::Offhand).unwrap_err(); + let result = inv.unequip(EquipSlot::InactiveMainhand).unwrap_err(); assert_eq!(SlotError::InventoryFull, result); // There is no more space in the inventory, so this should still be equipped - assert_eq!(&sword, inv.equipped(EquipSlot::Offhand).unwrap()); + assert_eq!(&sword, inv.equipped(EquipSlot::InactiveMainhand).unwrap()); // Verify inventory assert_eq!(inv.slots[17], Some(sword)); diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs index 19856b36ab..bf50ae96f6 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs @@ -13,7 +13,7 @@ use std::time::{Duration, Instant}; #[test] fn maps_wield_while_equipping() { let loadout = LoadoutBuilder::new() - .active_item(Some(Item::new_from_asset_expect( + .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) .build(); @@ -40,7 +40,7 @@ fn maps_wield_while_equipping() { #[test] fn maps_unwield() { let loadout = LoadoutBuilder::new() - .active_item(Some(Item::new_from_asset_expect( + .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.bow.starter", ))) .build(); @@ -62,7 +62,7 @@ fn maps_unwield() { #[test] fn maps_basic_melee() { let loadout = LoadoutBuilder::new() - .active_item(Some(Item::new_from_asset_expect( + .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) .build(); @@ -104,7 +104,7 @@ fn maps_basic_melee() { #[test] fn matches_ability_stage() { let loadout = LoadoutBuilder::new() - .active_item(Some(Item::new_from_asset_expect( + .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.sword.starter", ))) .build(); @@ -163,7 +163,7 @@ fn matches_ability_stage() { #[test] fn ignores_different_ability_stage() { let loadout = LoadoutBuilder::new() - .active_item(Some(Item::new_from_asset_expect( + .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) .build(); From 23cc3d671b2a9fe3ac0d885f52fd326488fb9110 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 15 May 2021 14:01:37 -0500 Subject: [PATCH 03/11] Now allows weapons to be swapped between the mainhand and offhand slot. (Probably hacky?) --- common/src/comp/inventory/loadout.rs | 88 +++++++++++++++++++++++----- common/src/comp/inventory/slot.rs | 6 +- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index 5116648b14..7b4ba29ffb 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -167,24 +167,84 @@ impl Loadout { return; } + enum MainhandHand { + MainhandA, + MainhandB, + } + + let hands_swapping = match (equip_slot_a, equip_slot_b) { + (EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand) => Some(MainhandHand::MainhandA), + (EquipSlot::ActiveOffhand, EquipSlot::ActiveMainhand) => Some(MainhandHand::MainhandB), + (EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand) => { + Some(MainhandHand::MainhandA) + }, + (EquipSlot::InactiveOffhand, EquipSlot::InactiveMainhand) => { + Some(MainhandHand::MainhandB) + }, + _ => None, + }; + let item_a = self.swap(equip_slot_a, None); let item_b = self.swap(equip_slot_b, None); - // Check if items can go in the other slots - if item_a - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) - && item_b - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) - { - // Swap - self.swap(equip_slot_b, item_a).unwrap_none(); - self.swap(equip_slot_a, item_b).unwrap_none(); + if let Some(hands_swapping) = hands_swapping { + match hands_swapping { + MainhandHand::MainhandA => { + if item_b + .as_ref() + .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) + && item_a + .as_ref() + .map_or(true, |i| equip_slot_b.can_hold(&i.kind())) + { + // Checks that item b (from offhand) can go into equip slot a (mainhand + // slot) and that item a (from mainhand) is a valid item to insert into + // equip slot b (offhand slot) Swap + self.swap(equip_slot_a, item_b).unwrap_none(); + self.swap(equip_slot_b, item_a).unwrap_none(); + } else { + // Otherwise put the items back + self.swap(equip_slot_a, item_a).unwrap_none(); + self.swap(equip_slot_b, item_b).unwrap_none(); + } + }, + MainhandHand::MainhandB => { + if item_a + .as_ref() + .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) + && item_b + .as_ref() + .map_or(true, |i| equip_slot_b.can_hold(&i.kind())) + { + // Checks that item a (from offhand) can go into equip slot b (mainhand + // slot) and that item b (from mainhand) is a valid item to insert into + // equip slot a (offhand slot) Swap + self.swap(equip_slot_b, item_a).unwrap_none(); + self.swap(equip_slot_a, item_b).unwrap_none(); + } else { + // Otherwise put the items back + self.swap(equip_slot_a, item_a).unwrap_none(); + self.swap(equip_slot_b, item_b).unwrap_none(); + } + }, + } } else { - // Otherwise put the items back - self.swap(equip_slot_a, item_a).unwrap_none(); - self.swap(equip_slot_b, item_b).unwrap_none(); + // Check if items can go in the other slots + if item_a + .as_ref() + .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) + && item_b + .as_ref() + .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) + { + // Swap + self.swap(equip_slot_b, item_a).unwrap_none(); + self.swap(equip_slot_a, item_b).unwrap_none(); + } else { + // Otherwise put the items back + self.swap(equip_slot_a, item_a).unwrap_none(); + self.swap(equip_slot_b, item_b).unwrap_none(); + } } } diff --git a/common/src/comp/inventory/slot.rs b/common/src/comp/inventory/slot.rs index ec3319514a..48f2789264 100644 --- a/common/src/comp/inventory/slot.rs +++ b/common/src/comp/inventory/slot.rs @@ -3,7 +3,7 @@ use std::{cmp::Ordering, convert::TryFrom}; use crate::comp::{ inventory::{ - item::{armor, armor::ArmorKind, ItemKind}, + item::{armor, armor::ArmorKind, tool, ItemKind}, loadout::LoadoutSlotId, }, item, @@ -123,9 +123,9 @@ impl EquipSlot { match (self, item_kind) { (Self::Armor(slot), ItemKind::Armor(armor::Armor { kind, .. })) => slot.can_hold(kind), (Self::ActiveMainhand, ItemKind::Tool(_)) => true, - (Self::ActiveOffhand, ItemKind::Tool(_)) => true, + (Self::ActiveOffhand, ItemKind::Tool(tool)) => matches!(tool.hands, tool::Hands::One), (Self::InactiveMainhand, ItemKind::Tool(_)) => true, - (Self::InactiveOffhand, ItemKind::Tool(_)) => true, + (Self::InactiveOffhand, ItemKind::Tool(tool)) => matches!(tool.hands, tool::Hands::One), (Self::Lantern, ItemKind::Lantern(_)) => true, (Self::Glider, ItemKind::Glider(_)) => true, _ => false, From 19926a2322c43578e74ac22d43d003471d50e8b8 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 15 May 2021 14:20:15 -0500 Subject: [PATCH 04/11] Swapping weapon sets is now functional. (Though very hacky?) --- common/src/comp/inventory/loadout.rs | 30 ++++++++++++++++++++++ common/src/comp/inventory/mod.rs | 2 ++ common/systems/src/character_behavior.rs | 32 +++--------------------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index 7b4ba29ffb..0d02b9c8d6 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -423,6 +423,36 @@ impl Loadout { _ => equip_slot.can_hold(item_kind), } } + + pub(super) fn swap_equipped_weapons(&mut self) { + // Checks if a given slot can hold an item right now, defaults to true if + // nothing is equipped in slot + let valid_slot = |equip_slot| { + self.equipped(equip_slot) + .map_or(true, |i| self.slot_can_hold(equip_slot, i.kind())) + }; + + if valid_slot(EquipSlot::ActiveMainhand) + && valid_slot(EquipSlot::ActiveOffhand) + && valid_slot(EquipSlot::InactiveMainhand) + && valid_slot(EquipSlot::InactiveOffhand) + { + // Get weapons from each slot + let active_mainhand = self.swap(EquipSlot::ActiveMainhand, None); + let active_offhand = self.swap(EquipSlot::ActiveOffhand, None); + let inactive_mainhand = self.swap(EquipSlot::InactiveMainhand, None); + let inactive_offhand = self.swap(EquipSlot::InactiveOffhand, None); + // Equip weapons into new slots + self.swap(EquipSlot::ActiveMainhand, inactive_mainhand) + .unwrap_none(); + self.swap(EquipSlot::ActiveOffhand, inactive_offhand) + .unwrap_none(); + self.swap(EquipSlot::InactiveMainhand, active_mainhand) + .unwrap_none(); + self.swap(EquipSlot::InactiveOffhand, active_offhand) + .unwrap_none(); + } + } } #[cfg(test)] diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 5bc40e586b..08440a2a43 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -778,6 +778,8 @@ impl Inventory { pub fn equipped_items_of_kind(&self, item_kind: ItemKind) -> impl Iterator { self.loadout.equipped_items_of_kind(item_kind) } + + pub fn swap_equipped_weapons(&mut self) { self.loadout.swap_equipped_weapons() } } impl Component for Inventory { diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 7b9b4cb62d..20590f825f 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -5,14 +5,9 @@ use specs::{ use common::{ comp::{ - self, - inventory::{ - item::MaterialStatManifest, - slot::{EquipSlot, Slot}, - }, - Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health, Inventory, Mass, - Melee, Mounting, Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, - Vel, + self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, Controller, + Density, Energy, Health, Inventory, Mass, Melee, Mounting, Ori, PhysicsState, Poise, + PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, outcome::Outcome, @@ -48,26 +43,7 @@ fn incorporate_update(join: &mut JoinStruct, mut state_update: StateUpdate) { if state_update.swap_equipped_weapons { let mut inventory = join.inventory.get_mut_unchecked(); let inventory = &mut *inventory; - assert!( - inventory - .swap( - Slot::Equip(EquipSlot::ActiveMainhand), - Slot::Equip(EquipSlot::InactiveMainhand), - ) - .first() - .is_none(), - "Swapping active and inactive mainhand never results in leftover items", - ); - assert!( - inventory - .swap( - Slot::Equip(EquipSlot::ActiveOffhand), - Slot::Equip(EquipSlot::InactiveOffhand), - ) - .first() - .is_none(), - "Swapping active and inactive offhand never results in leftover items", - ); + inventory.swap_equipped_weapons(); } } From 5cc6168553988bbb8d06584d4ea26656a1bfc390 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 15 May 2021 14:53:03 -0500 Subject: [PATCH 05/11] Unequipping a mainhand weapon now moves offhand weapon into mainhand. --- common/src/comp/inventory/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 08440a2a43..bf285a2433 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -731,6 +731,31 @@ impl Inventory { }) .unwrap_or_default(); + // If 2 1h weapons are equipped, and mainhand weapon removed, move offhand into mainhand + match equip_slot { + EquipSlot::ActiveMainhand => { + if self.loadout.equipped(EquipSlot::ActiveMainhand).is_none() + && self.loadout.equipped(EquipSlot::ActiveOffhand).is_some() + { + let offhand = self.loadout.swap(EquipSlot::ActiveOffhand, None); + self.loadout + .swap(EquipSlot::ActiveMainhand, offhand) + .unwrap_none(); + } + }, + EquipSlot::InactiveMainhand => { + if self.loadout.equipped(EquipSlot::InactiveMainhand).is_none() + && self.loadout.equipped(EquipSlot::InactiveOffhand).is_some() + { + let offhand = self.loadout.swap(EquipSlot::InactiveOffhand, None); + self.loadout + .swap(EquipSlot::InactiveMainhand, offhand) + .unwrap_none(); + } + }, + _ => {}, + } + // Attempt to put any items unloaded from the unequipped item into empty // inventory slots and return any that don't fit to the caller where they // will be dropped on the ground From ad0c247838e31405fe719b5430d88dcc09777c2a Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 15 May 2021 15:15:52 -0500 Subject: [PATCH 06/11] Removed special case for equipping a weapon that is no longer needed. --- common/src/comp/inventory/mod.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index bf285a2433..ad8c887f10 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -552,16 +552,7 @@ impl Inventory { pub fn equip(&mut self, inv_slot: InvSlotId) -> Vec { self.get(inv_slot) .and_then(|item| self.loadout.get_slot_to_equip_into(item.kind())) - .map(|equip_slot| { - // Special case when equipping into active main hand - swap with active offhand - // first - if equip_slot == EquipSlot::ActiveMainhand { - self.loadout - .swap_slots(EquipSlot::ActiveMainhand, EquipSlot::InactiveMainhand); - } - - self.swap_inventory_loadout(inv_slot, equip_slot) - }) + .map(|equip_slot| self.swap_inventory_loadout(inv_slot, equip_slot)) .unwrap_or_else(Vec::new) } @@ -731,7 +722,8 @@ impl Inventory { }) .unwrap_or_default(); - // If 2 1h weapons are equipped, and mainhand weapon removed, move offhand into mainhand + // If 2 1h weapons are equipped, and mainhand weapon removed, move offhand into + // mainhand match equip_slot { EquipSlot::ActiveMainhand => { if self.loadout.equipped(EquipSlot::ActiveMainhand).is_none() From a4384b81c7c0064ee897cdf07120eb9fa56a3910 Mon Sep 17 00:00:00 2001 From: hqurve Date: Sun, 16 May 2021 20:43:19 -0400 Subject: [PATCH 07/11] Add offhand weapons to bag ui --- assets/voxygen/i18n/en/hud/bag.ron | 2 + voxygen/src/hud/bag.rs | 81 ++++++++++++++++++++++++++---- voxygen/src/hud/img_ids.rs | 3 ++ voxygen/src/hud/mod.rs | 4 ++ voxygen/src/session/mod.rs | 3 ++ 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/assets/voxygen/i18n/en/hud/bag.ron b/assets/voxygen/i18n/en/hud/bag.ron index e10c54ddcd..67a37986d2 100644 --- a/assets/voxygen/i18n/en/hud/bag.ron +++ b/assets/voxygen/i18n/en/hud/bag.ron @@ -24,6 +24,8 @@ "hud.bag.feet": "Feet", "hud.bag.mainhand": "Mainhand", "hud.bag.offhand": "Offhand", + "hud.bag.inactive_mainhand": "Inactive Mainhand", + "hud.bag.inactive_offhand": "Inactive Offhand", "hud.bag.bag": "Bag", "hud.bag.health": "Health", "hud.bag.stamina": "Stamina", diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 0673f3132d..e6f69b6b00 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -448,8 +448,11 @@ widget_ids! { back_slot, tabard_slot, glider_slot, - mainhand_slot, - offhand_slot, + active_mainhand_slot, + active_offhand_slot, + inactive_mainhand_slot, + inactive_offhand_slot, + swap_equipped_weapons_btn, bag1_slot, bag2_slot, bag3_slot, @@ -543,6 +546,7 @@ pub enum Event { BagExpand, Close, SortInventory, + SwapEquippedWeapons, } impl<'a> Widget for Bag<'a> { @@ -690,7 +694,7 @@ impl<'a> Widget for Bag<'a> { if inventory.slots().count() > 45 || self.show.bag_inv { let expand_btn_top = if self.show.bag_inv { 53.0 } else { 460.0 }; if expand_btn - .top_left_with_margins_on(state.bg_ids.bg_frame, expand_btn_top, 211.5) + .top_right_with_margins_on(state.bg_ids.bg_frame, expand_btn_top, 30.0) .with_tooltip(self.tooltip_manager, &txt, "", &bag_tooltip, TEXT_COLOR) .set(state.ids.bag_expand_btn, ui) .was_clicked() @@ -1152,7 +1156,7 @@ impl<'a> Widget for Bag<'a> { ) .set(state.ids.tabard_slot, ui) } - // Mainhand/Left-Slot + // Active Mainhand/Left-Slot let mainhand_item = inventory .equipped(EquipSlot::ActiveMainhand) .map(|item| item.to_owned()); @@ -1164,7 +1168,7 @@ impl<'a> Widget for Bag<'a> { .filled_slot(filled_slot); if let Some(item) = mainhand_item { slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) - .set(state.ids.mainhand_slot, ui) + .set(state.ids.active_mainhand_slot, ui) } else { slot.with_tooltip( self.tooltip_manager, @@ -1173,9 +1177,10 @@ impl<'a> Widget for Bag<'a> { &tooltip, color::WHITE, ) - .set(state.ids.mainhand_slot, ui) + .set(state.ids.active_mainhand_slot, ui) } - // Offhand/Right-Slot + + // Active Offhand/Right-Slot let offhand_item = inventory .equipped(EquipSlot::ActiveOffhand) .map(|item| item.to_owned()); @@ -1186,7 +1191,7 @@ impl<'a> Widget for Bag<'a> { .filled_slot(filled_slot); if let Some(item) = offhand_item { slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) - .set(state.ids.offhand_slot, ui) + .set(state.ids.active_offhand_slot, ui) } else { slot.with_tooltip( self.tooltip_manager, @@ -1195,7 +1200,65 @@ impl<'a> Widget for Bag<'a> { &tooltip, color::WHITE, ) - .set(state.ids.offhand_slot, ui) + .set(state.ids.active_offhand_slot, ui) + } + // Inactive Mainhand/Left-Slot + let mainhand_item = inventory + .equipped(EquipSlot::InactiveMainhand) + .map(|item| item.to_owned()); + + let slot = slot_maker + .fabricate(EquipSlot::InactiveMainhand, [38.0; 2]) + .bottom_right_with_margins_on(state.ids.active_mainhand_slot, 2.0, -44.0) + .with_icon(self.imgs.mainhand_bg, Vec2::new(33.5, 33.5), Some(UI_MAIN)) + .filled_slot(filled_slot); + if let Some(item) = mainhand_item { + slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) + .set(state.ids.inactive_mainhand_slot, ui) + } else { + slot.with_tooltip( + self.tooltip_manager, + i18n.get("hud.bag.inactive_mainhand"), + "", + &tooltip, + color::WHITE, + ) + .set(state.ids.inactive_mainhand_slot, ui) + } + + // Inctive Offhand/Right-Slot + let offhand_item = inventory + .equipped(EquipSlot::InactiveOffhand) + .map(|item| item.to_owned()); + let slot = slot_maker + .fabricate(EquipSlot::InactiveOffhand, [38.0; 2]) + .bottom_left_with_margins_on(state.ids.active_offhand_slot, 2.0, -44.0) + .with_icon(self.imgs.offhand_bg, Vec2::new(33.5, 33.5), Some(UI_MAIN)) + .filled_slot(filled_slot); + if let Some(item) = offhand_item { + slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) + .set(state.ids.inactive_offhand_slot, ui) + } else { + slot.with_tooltip( + self.tooltip_manager, + i18n.get("hud.bag.inactive_offhand"), + "", + &tooltip, + color::WHITE, + ) + .set(state.ids.inactive_offhand_slot, ui) + } + + if Button::image(self.imgs.swap_equipped_weapons_btn) + .hover_image(self.imgs.swap_equipped_weapons_btn_hover) + .press_image(self.imgs.swap_equipped_weapons_btn_press) + .w_h(12.0, 30.0) + .down_from(state.ids.legs_slot, 19.5) + .align_middle_x_of(state.ids.legs_slot) + .set(state.ids.swap_equipped_weapons_btn, ui) + .was_clicked() + { + event = Some(Event::SwapEquippedWeapons); } } diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index ae25ebf567..641679a555 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -421,6 +421,9 @@ image_ids! { inv_sort_btn: "voxygen.element.ui.bag.buttons.inv_sort", inv_sort_btn_hover: "voxygen.element.ui.bag.buttons.inv_sort_hover", inv_sort_btn_press: "voxygen.element.ui.bag.buttons.inv_sort_press", + swap_equipped_weapons_btn: "voxygen.element.ui.generic.buttons.button", + swap_equipped_weapons_btn_hover: "voxygen.element.ui.generic.buttons.button_hover", + swap_equipped_weapons_btn_press: "voxygen.element.ui.generic.buttons.button_press", coin_ico: "voxygen.element.items.coin", cheese_ico: "voxygen.element.items.item_cheese", inv_bg_armor: "voxygen.element.ui.bag.inv_bg_0", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index de3a920bc7..293ee3907c 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -373,6 +373,7 @@ pub enum Event { slot: comp::slot::Slot, bypass_dialog: bool, }, + SwapEquippedWeapons, SwapSlots { slot_a: comp::slot::Slot, slot_b: comp::slot::Slot, @@ -2479,6 +2480,9 @@ impl Hud { }; }, Some(bag::Event::SortInventory) => self.events.push(Event::SortInventory), + Some(bag::Event::SwapEquippedWeapons) => { + self.events.push(Event::SwapEquippedWeapons) + }, None => {}, } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 647308dcf2..5a7b3ab069 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1034,6 +1034,9 @@ impl PlayState for SessionState { self.client.borrow_mut().use_slot(slot); } }, + HudEvent::SwapEquippedWeapons => { + self.client.borrow_mut().swap_loadout(); + }, HudEvent::SwapSlots { slot_a, slot_b, From fcf4ab76190453c71d81e75b6f071e5363df9a6b Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Sun, 16 May 2021 19:38:29 +0100 Subject: [PATCH 08/11] main/offhand weapon swap check refactor --- common/src/comp/inventory/loadout.rs | 159 ++++++++------------------- common/src/comp/inventory/mod.rs | 2 +- voxygen/src/hud/bag.rs | 8 +- 3 files changed, 53 insertions(+), 116 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index 0d02b9c8d6..b0ebde4170 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -1,6 +1,6 @@ use crate::comp::{ inventory::{ - item::{tool, ItemKind}, + item::{Hands, ItemKind, Tool}, slot::{ArmorSlot, EquipSlot}, InvSlot, }, @@ -167,84 +167,18 @@ impl Loadout { return; } - enum MainhandHand { - MainhandA, - MainhandB, - } - - let hands_swapping = match (equip_slot_a, equip_slot_b) { - (EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand) => Some(MainhandHand::MainhandA), - (EquipSlot::ActiveOffhand, EquipSlot::ActiveMainhand) => Some(MainhandHand::MainhandB), - (EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand) => { - Some(MainhandHand::MainhandA) - }, - (EquipSlot::InactiveOffhand, EquipSlot::InactiveMainhand) => { - Some(MainhandHand::MainhandB) - }, - _ => None, - }; - let item_a = self.swap(equip_slot_a, None); - let item_b = self.swap(equip_slot_b, None); + let item_b = self.swap(equip_slot_b, item_a); + assert_eq!(self.swap(equip_slot_a, item_b), None); - if let Some(hands_swapping) = hands_swapping { - match hands_swapping { - MainhandHand::MainhandA => { - if item_b - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) - && item_a - .as_ref() - .map_or(true, |i| equip_slot_b.can_hold(&i.kind())) - { - // Checks that item b (from offhand) can go into equip slot a (mainhand - // slot) and that item a (from mainhand) is a valid item to insert into - // equip slot b (offhand slot) Swap - self.swap(equip_slot_a, item_b).unwrap_none(); - self.swap(equip_slot_b, item_a).unwrap_none(); - } else { - // Otherwise put the items back - self.swap(equip_slot_a, item_a).unwrap_none(); - self.swap(equip_slot_b, item_b).unwrap_none(); - } - }, - MainhandHand::MainhandB => { - if item_a - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) - && item_b - .as_ref() - .map_or(true, |i| equip_slot_b.can_hold(&i.kind())) - { - // Checks that item a (from offhand) can go into equip slot b (mainhand - // slot) and that item b (from mainhand) is a valid item to insert into - // equip slot a (offhand slot) Swap - self.swap(equip_slot_b, item_a).unwrap_none(); - self.swap(equip_slot_a, item_b).unwrap_none(); - } else { - // Otherwise put the items back - self.swap(equip_slot_a, item_a).unwrap_none(); - self.swap(equip_slot_b, item_b).unwrap_none(); - } - }, - } - } else { - // Check if items can go in the other slots - if item_a - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_b, &i.kind())) - && item_b - .as_ref() - .map_or(true, |i| self.slot_can_hold(equip_slot_a, &i.kind())) - { - // Swap - self.swap(equip_slot_b, item_a).unwrap_none(); - self.swap(equip_slot_a, item_b).unwrap_none(); - } else { - // Otherwise put the items back - self.swap(equip_slot_a, item_a).unwrap_none(); - self.swap(equip_slot_b, item_b).unwrap_none(); - } + // Check if items are valid in their new positions + if !self.slot_can_hold(equip_slot_a, self.equipped(equip_slot_b).map(|x| x.kind())) + || !self.slot_can_hold(equip_slot_b, self.equipped(equip_slot_a).map(|x| x.kind())) + { + // If not, revert the swap + let item_a = self.swap(equip_slot_a, None); + let item_b = self.swap(equip_slot_b, item_a); + assert_eq!(self.swap(equip_slot_a, item_b), None); } } @@ -257,7 +191,7 @@ impl Loadout { let mut suitable_slots = self .slots .iter() - .filter(|s| self.slot_can_hold(s.equip_slot, item_kind)); + .filter(|s| self.slot_can_hold(s.equip_slot, Some(item_kind))); let first = suitable_slots.next(); @@ -277,7 +211,7 @@ impl Loadout { ) -> impl Iterator { self.slots .iter() - .filter(move |s| self.slot_can_hold(s.equip_slot, &item_kind)) + .filter(move |s| self.slot_can_hold(s.equip_slot, Some(&item_kind))) .filter_map(|s| s.slot.as_ref()) } @@ -370,7 +304,7 @@ impl Loadout { let loadout_slot = self .slots .iter() - .find(|s| s.slot.is_none() && self.slot_can_hold(s.equip_slot, item.kind())) + .find(|s| s.slot.is_none() && self.slot_can_hold(s.equip_slot, Some(item.kind()))) .map(|s| s.equip_slot); if let Some(slot) = self .slots @@ -389,39 +323,42 @@ impl Loadout { } /// Checks that a slot can hold a given item - pub(super) fn slot_can_hold(&self, equip_slot: EquipSlot, item_kind: &ItemKind) -> bool { - // Checks if item can be equipped in a mainhand slot - let mainhand_check = |offhand_slot| { - // Allows item to be equipped if itemkind is a tool and... - matches!(item_kind, ItemKind::Tool(mainhand) if { - if let Some(ItemKind::Tool(offhand)) = self.equipped(offhand_slot).map(|i| i.kind()) { - // if offhand is 1 handed, only if mainhand is also 1 handed - matches!(offhand.hands, tool::Hands::One) && matches!(mainhand.hands, tool::Hands::One) - } else { - // else there is no tool equipped in offhand, so only if slot can normally hold this item - equip_slot.can_hold(item_kind) - } - }) + pub(super) fn slot_can_hold( + &self, + equip_slot: EquipSlot, + item_kind: Option<&ItemKind>, + ) -> bool { + let weapon_compare_slots = match equip_slot { + EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand => { + Some((EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand)) + }, + EquipSlot::InactiveMainhand | EquipSlot::InactiveOffhand => { + Some((EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand)) + }, + _ => None, }; - // Checks if item can be equipped in an offhand slot - let offhand_check = |mainhand_slot| { - // Allows item to be equipped if itemkind is a tool and... - matches!(item_kind, ItemKind::Tool(offhand) if { - // if offhand weapon is 1 handed... - matches!(offhand.hands, tool::Hands::One) - // and if mainhand has a 1 handed weapon... - && matches!(self.equipped(mainhand_slot).map(|i| i.kind()), Some(ItemKind::Tool(mainhand)) if matches!(mainhand.hands, tool::Hands::One)) - }) - }; - - match equip_slot { - EquipSlot::ActiveMainhand => mainhand_check(EquipSlot::ActiveOffhand), - EquipSlot::ActiveOffhand => offhand_check(EquipSlot::ActiveMainhand), - EquipSlot::InactiveMainhand => mainhand_check(EquipSlot::InactiveOffhand), - EquipSlot::InactiveOffhand => offhand_check(EquipSlot::InactiveMainhand), - _ => equip_slot.can_hold(item_kind), + // Disallow equipping incompatible weapon pairs (i.e a two-handed weapon and a + // one-handed weapon) + if let Some(weapon_compare_slots) = weapon_compare_slots { + if !Loadout::is_valid_weapon_pair( + self.equipped(weapon_compare_slots.0).map(|x| &x.kind), + self.equipped(weapon_compare_slots.1).map(|x| &x.kind), + ) { + return false; + } } + + item_kind.map_or(true, |item_kind| equip_slot.can_hold(item_kind)) + } + + #[rustfmt::skip] + fn is_valid_weapon_pair(main_hand: Option<&ItemKind>, off_hand: Option<&ItemKind>) -> bool { + matches!((main_hand, off_hand), + (Some(ItemKind::Tool(Tool { hands: Hands::One, .. })), None) | + (Some(ItemKind::Tool(Tool { hands: Hands::Two, .. })), None) | + (Some(ItemKind::Tool(Tool { hands: Hands::One, .. })), Some(ItemKind::Tool(Tool { hands: Hands::One, .. }))) | + (None, None)) } pub(super) fn swap_equipped_weapons(&mut self) { @@ -429,7 +366,7 @@ impl Loadout { // nothing is equipped in slot let valid_slot = |equip_slot| { self.equipped(equip_slot) - .map_or(true, |i| self.slot_can_hold(equip_slot, i.kind())) + .map_or(true, |i| self.slot_can_hold(equip_slot, Some(i.kind()))) }; if valid_slot(EquipSlot::ActiveMainhand) diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index ad8c887f10..0fed36145a 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -765,7 +765,7 @@ impl Inventory { pub fn can_swap(&self, inv_slot_id: InvSlotId, equip_slot: EquipSlot) -> bool { // Check if loadout slot can hold item if !self.get(inv_slot_id).map_or(true, |item| { - self.loadout.slot_can_hold(equip_slot, &item.kind()) + self.loadout.slot_can_hold(equip_slot, Some(&item.kind())) }) { trace!("can_swap = false, equip slot can't hold item"); return false; diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index e6f69b6b00..844797a42a 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -1004,10 +1004,10 @@ impl<'a> Widget for Bag<'a> { } // Ring let ring1_item = inventory - .equipped(EquipSlot::Armor(ArmorSlot::Ring1)) + .equipped(EquipSlot::InactiveOffhand) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::Armor(ArmorSlot::Ring1), [45.0; 2]) + .fabricate(EquipSlot::InactiveOffhand, [45.0; 2]) .bottom_left_with_margins_on(state.ids.hands_slot, -55.0, 0.0) .with_icon(self.imgs.ring_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN)) .filled_slot(filled_slot); @@ -1026,10 +1026,10 @@ impl<'a> Widget for Bag<'a> { } // Ring 2 let ring2_item = inventory - .equipped(EquipSlot::Armor(ArmorSlot::Ring2)) + .equipped(EquipSlot::InactiveMainhand) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::Armor(ArmorSlot::Ring2), [45.0; 2]) + .fabricate(EquipSlot::InactiveMainhand, [45.0; 2]) .bottom_right_with_margins_on(state.ids.shoulders_slot, -55.0, 0.0) .with_icon(self.imgs.ring_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN)) .filled_slot(filled_slot); From 93b5e674f65e3bb8852f5cd9b56451c5394484ca Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 16 May 2021 21:35:17 -0500 Subject: [PATCH 09/11] Fixed comments and some functionality. --- common/src/comp/inventory/loadout.rs | 85 +++++++++++++++++++--------- common/src/comp/inventory/mod.rs | 22 ++++--- common/src/states/utils.rs | 2 +- voxygen/src/hud/bag.rs | 8 +-- 4 files changed, 77 insertions(+), 40 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index b0ebde4170..b519959588 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -260,7 +260,7 @@ impl Loadout { pub(super) fn inv_slots_mut(&mut self) -> impl Iterator { self.slots.iter_mut() .filter_map(|x| x.slot.as_mut().map(|item| item.slots_mut())) // Discard loadout items that have no slots of their own - .flat_map(|loadout_slots| loadout_slots.iter_mut()) //Collapse iter of Vec to iter of InvSlot + .flat_map(|loadout_slots| loadout_slots.iter_mut()) //Collapse iter of Vec to iter of InvSlot } /// Gets the range of loadout-provided inventory slot indexes that are @@ -328,26 +328,47 @@ impl Loadout { equip_slot: EquipSlot, item_kind: Option<&ItemKind>, ) -> bool { - let weapon_compare_slots = match equip_slot { - EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand => { - Some((EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand)) - }, - EquipSlot::InactiveMainhand | EquipSlot::InactiveOffhand => { - Some((EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand)) - }, - _ => None, - }; + // let weapon_compare_slots = match equip_slot { + // EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand => { + // Some((EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand)) + // }, + // EquipSlot::InactiveMainhand | EquipSlot::InactiveOffhand => { + // Some((EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand)) + // }, + // _ => None, + // }; + if !(match equip_slot { + EquipSlot::ActiveMainhand => Loadout::is_valid_weapon_pair( + item_kind, + self.equipped(EquipSlot::ActiveOffhand).map(|x| &x.kind), + ), + EquipSlot::ActiveOffhand => Loadout::is_valid_weapon_pair( + self.equipped(EquipSlot::ActiveMainhand).map(|x| &x.kind), + item_kind, + ), + EquipSlot::InactiveMainhand => Loadout::is_valid_weapon_pair( + item_kind, + self.equipped(EquipSlot::InactiveOffhand).map(|x| &x.kind), + ), + EquipSlot::InactiveOffhand => Loadout::is_valid_weapon_pair( + self.equipped(EquipSlot::InactiveMainhand).map(|x| &x.kind), + item_kind, + ), + _ => true, + }) { + return false; + } // Disallow equipping incompatible weapon pairs (i.e a two-handed weapon and a // one-handed weapon) - if let Some(weapon_compare_slots) = weapon_compare_slots { - if !Loadout::is_valid_weapon_pair( - self.equipped(weapon_compare_slots.0).map(|x| &x.kind), - self.equipped(weapon_compare_slots.1).map(|x| &x.kind), - ) { - return false; - } - } + // if let Some(weapon_compare_slots) = weapon_compare_slots { + // if !Loadout::is_valid_weapon_pair( + // self.equipped(weapon_compare_slots.0).map(|x| &x.kind), + // self.equipped(weapon_compare_slots.1).map(|x| &x.kind), + // ) { + // return false; + // } + // } item_kind.map_or(true, |item_kind| equip_slot.can_hold(item_kind)) } @@ -369,6 +390,10 @@ impl Loadout { .map_or(true, |i| self.slot_can_hold(equip_slot, Some(i.kind()))) }; + // If every weapon is currently in a valid slot, after this change they will + // still be in a valid slot. This is because active mainhand and + // inactive mainhand, and active offhand and inactive offhand have the same + // requirements on what can be equipped. if valid_slot(EquipSlot::ActiveMainhand) && valid_slot(EquipSlot::ActiveOffhand) && valid_slot(EquipSlot::InactiveMainhand) @@ -380,14 +405,22 @@ impl Loadout { let inactive_mainhand = self.swap(EquipSlot::InactiveMainhand, None); let inactive_offhand = self.swap(EquipSlot::InactiveOffhand, None); // Equip weapons into new slots - self.swap(EquipSlot::ActiveMainhand, inactive_mainhand) - .unwrap_none(); - self.swap(EquipSlot::ActiveOffhand, inactive_offhand) - .unwrap_none(); - self.swap(EquipSlot::InactiveMainhand, active_mainhand) - .unwrap_none(); - self.swap(EquipSlot::InactiveOffhand, active_offhand) - .unwrap_none(); + assert!( + self.swap(EquipSlot::ActiveMainhand, inactive_mainhand) + .is_none() + ); + assert!( + self.swap(EquipSlot::ActiveOffhand, inactive_offhand) + .is_none() + ); + assert!( + self.swap(EquipSlot::InactiveMainhand, active_mainhand) + .is_none() + ); + assert!( + self.swap(EquipSlot::InactiveOffhand, active_offhand) + .is_none() + ); } } } diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 0fed36145a..ff0bfb11f4 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -577,7 +577,7 @@ impl Inventory { + i32::try_from(slots_from_inv).expect("Inventory item with more than i32::MAX slots") - i32::try_from(self.populated_slots()) .expect("Inventory item with more than i32::MAX used slots") - + inv_slot_for_equipped // If there is no item already in the equip slot we gain 1 slot + + inv_slot_for_equipped // If there is no item already in the equip slot we gain 1 slot } /// Handles picking up an item, unloading any items inside the item being @@ -640,7 +640,7 @@ impl Inventory { .expect("Equipped item with more than i32::MAX slots") - i32::try_from(self.populated_slots()) .expect("Inventory item with more than i32::MAX used slots") - - inv_slot_for_unequipped // If there is an item being unequipped we lose 1 slot + - inv_slot_for_unequipped // If there is an item being unequipped we lose 1 slot } /// Swaps items from two slots, regardless of if either is inventory or @@ -684,7 +684,7 @@ impl Inventory { - i32::try_from(self.populated_slots()) .expect("inventory with more than i32::MAX used slots") - inv_slot_for_equipped // +1 inventory slot required if an item was unequipped - + inv_slot_for_inv_item // -1 inventory slot required if an item was equipped + + inv_slot_for_inv_item // -1 inventory slot required if an item was equipped } /// Swap item in an inventory slot with one in a loadout slot. @@ -730,9 +730,11 @@ impl Inventory { && self.loadout.equipped(EquipSlot::ActiveOffhand).is_some() { let offhand = self.loadout.swap(EquipSlot::ActiveOffhand, None); - self.loadout - .swap(EquipSlot::ActiveMainhand, offhand) - .unwrap_none(); + assert!( + self.loadout + .swap(EquipSlot::ActiveMainhand, offhand) + .is_none() + ); } }, EquipSlot::InactiveMainhand => { @@ -740,9 +742,11 @@ impl Inventory { && self.loadout.equipped(EquipSlot::InactiveOffhand).is_some() { let offhand = self.loadout.swap(EquipSlot::InactiveOffhand, None); - self.loadout - .swap(EquipSlot::InactiveMainhand, offhand) - .unwrap_none(); + assert!( + self.loadout + .swap(EquipSlot::InactiveMainhand, offhand) + .is_none() + ); } }, _ => {}, diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 880fc594e1..c7eff5efe7 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -452,7 +452,7 @@ pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) { .map(|(item, tool)| tool.equip_time(data.msm, item.components())) }; - // Calcualtes time required to equip weapons, if weapon in mainhand and offhand, + // Calculates time required to equip weapons, if weapon in mainhand and offhand, // uses maximum duration let mainhand_equip_time = equip_time(EquipSlot::ActiveMainhand); let offhand_equip_time = equip_time(EquipSlot::ActiveOffhand); diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 844797a42a..e6f69b6b00 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -1004,10 +1004,10 @@ impl<'a> Widget for Bag<'a> { } // Ring let ring1_item = inventory - .equipped(EquipSlot::InactiveOffhand) + .equipped(EquipSlot::Armor(ArmorSlot::Ring1)) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::InactiveOffhand, [45.0; 2]) + .fabricate(EquipSlot::Armor(ArmorSlot::Ring1), [45.0; 2]) .bottom_left_with_margins_on(state.ids.hands_slot, -55.0, 0.0) .with_icon(self.imgs.ring_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN)) .filled_slot(filled_slot); @@ -1026,10 +1026,10 @@ impl<'a> Widget for Bag<'a> { } // Ring 2 let ring2_item = inventory - .equipped(EquipSlot::InactiveMainhand) + .equipped(EquipSlot::Armor(ArmorSlot::Ring2)) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::InactiveMainhand, [45.0; 2]) + .fabricate(EquipSlot::Armor(ArmorSlot::Ring2), [45.0; 2]) .bottom_right_with_margins_on(state.ids.shoulders_slot, -55.0, 0.0) .with_icon(self.imgs.ring_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN)) .filled_slot(filled_slot); From 6974ab919968b0f6b1494ca57345abd1e2b62941 Mon Sep 17 00:00:00 2001 From: hqurve Date: Mon, 17 May 2021 15:35:27 -0400 Subject: [PATCH 10/11] Added swap_equipped_weapons icon and resized inactive weapons --- .../ui/bag/buttons/swap_equipped_weapons.png | 3 ++ .../buttons/swap_equipped_weapons_hover.png | 3 ++ .../buttons/swap_equipped_weapons_press.png | 3 ++ assets/voxygen/i18n/en/hud/bag.ron | 2 + voxygen/src/hud/bag.rs | 44 ++++++++++++++----- voxygen/src/hud/img_ids.rs | 6 +-- voxygen/src/hud/mod.rs | 1 + 7 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons.png create mode 100644 assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_hover.png create mode 100644 assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_press.png diff --git a/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons.png b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons.png new file mode 100644 index 0000000000..8c718d8b72 --- /dev/null +++ b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75e7cf295ea4ba4f8b80fab7498fb7106c142c1b100af284ee14f7e126df5a86 +size 856 diff --git a/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_hover.png b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_hover.png new file mode 100644 index 0000000000..974d1382f5 --- /dev/null +++ b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_hover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9fc5bd3785f311e832ebb744751fd477ccbbc8df8cc7679a9e31e6e9ee775e3f +size 877 diff --git a/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_press.png b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_press.png new file mode 100644 index 0000000000..186e315bae --- /dev/null +++ b/assets/voxygen/element/ui/bag/buttons/swap_equipped_weapons_press.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94548ae5b84e4a9e9d0b25ad1f558f08787c3d93d40790af0c51f37d6bfc6ffa +size 877 diff --git a/assets/voxygen/i18n/en/hud/bag.ron b/assets/voxygen/i18n/en/hud/bag.ron index 67a37986d2..b8a0271369 100644 --- a/assets/voxygen/i18n/en/hud/bag.ron +++ b/assets/voxygen/i18n/en/hud/bag.ron @@ -26,6 +26,8 @@ "hud.bag.offhand": "Offhand", "hud.bag.inactive_mainhand": "Inactive Mainhand", "hud.bag.inactive_offhand": "Inactive Offhand", + "hud.bag.swap_equipped_weapons_title": "Swap equipped weapons", + "hud.bag.swap_equipped_weapons_desc": "Press {key}", "hud.bag.bag": "Bag", "hud.bag.health": "Health", "hud.bag.stamina": "Stamina", diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index e6f69b6b00..7a1027da61 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -13,6 +13,8 @@ use crate::{ ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager, Tooltipable, }, + window::GameInput, + GlobalState, }; use client::Client; use common::{ @@ -466,6 +468,7 @@ widget_ids! { #[derive(WidgetCommon)] pub struct Bag<'a> { client: &'a Client, + global_state: &'a GlobalState, imgs: &'a Imgs, item_imgs: &'a ItemImgs, fonts: &'a Fonts, @@ -490,6 +493,7 @@ impl<'a> Bag<'a> { #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 pub fn new( client: &'a Client, + global_state: &'a GlobalState, imgs: &'a Imgs, item_imgs: &'a ItemImgs, fonts: &'a Fonts, @@ -509,6 +513,7 @@ impl<'a> Bag<'a> { ) -> Self { Self { client, + global_state, imgs, item_imgs, fonts, @@ -571,6 +576,7 @@ impl<'a> Widget for Bag<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; let i18n = &self.localized_strings; + let key_layout = &self.global_state.window.key_layout; let mut event = None; let bag_tooltip = Tooltip::new({ @@ -694,7 +700,7 @@ impl<'a> Widget for Bag<'a> { if inventory.slots().count() > 45 || self.show.bag_inv { let expand_btn_top = if self.show.bag_inv { 53.0 } else { 460.0 }; if expand_btn - .top_right_with_margins_on(state.bg_ids.bg_frame, expand_btn_top, 30.0) + .top_right_with_margins_on(state.bg_ids.bg_frame, expand_btn_top, 37.0) .with_tooltip(self.tooltip_manager, &txt, "", &bag_tooltip, TEXT_COLOR) .set(state.ids.bag_expand_btn, ui) .was_clicked() @@ -1208,9 +1214,9 @@ impl<'a> Widget for Bag<'a> { .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::InactiveMainhand, [38.0; 2]) - .bottom_right_with_margins_on(state.ids.active_mainhand_slot, 2.0, -44.0) - .with_icon(self.imgs.mainhand_bg, Vec2::new(33.5, 33.5), Some(UI_MAIN)) + .fabricate(EquipSlot::InactiveMainhand, [40.0; 2]) + .bottom_right_with_margins_on(state.ids.active_mainhand_slot, 3.0, -47.0) + .with_icon(self.imgs.mainhand_bg, Vec2::new(35.0, 35.0), Some(UI_MAIN)) .filled_slot(filled_slot); if let Some(item) = mainhand_item { slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) @@ -1231,9 +1237,9 @@ impl<'a> Widget for Bag<'a> { .equipped(EquipSlot::InactiveOffhand) .map(|item| item.to_owned()); let slot = slot_maker - .fabricate(EquipSlot::InactiveOffhand, [38.0; 2]) - .bottom_left_with_margins_on(state.ids.active_offhand_slot, 2.0, -44.0) - .with_icon(self.imgs.offhand_bg, Vec2::new(33.5, 33.5), Some(UI_MAIN)) + .fabricate(EquipSlot::InactiveOffhand, [40.0; 2]) + .bottom_left_with_margins_on(state.ids.active_offhand_slot, 3.0, -47.0) + .with_icon(self.imgs.offhand_bg, Vec2::new(35.0, 35.0), Some(UI_MAIN)) .filled_slot(filled_slot); if let Some(item) = offhand_item { slot.with_item_tooltip(self.item_tooltip_manager, &item, &None, &item_tooltip) @@ -1252,9 +1258,27 @@ impl<'a> Widget for Bag<'a> { if Button::image(self.imgs.swap_equipped_weapons_btn) .hover_image(self.imgs.swap_equipped_weapons_btn_hover) .press_image(self.imgs.swap_equipped_weapons_btn_press) - .w_h(12.0, 30.0) - .down_from(state.ids.legs_slot, 19.5) - .align_middle_x_of(state.ids.legs_slot) + .w_h(32.0, 40.0) + .bottom_left_with_margins_on(state.bg_ids.bg_frame, 0.0, 23.3) + .align_middle_y_of(state.ids.active_mainhand_slot) + .with_tooltip( + self.tooltip_manager, + i18n.get("hud.bag.swap_equipped_weapons_title"), + if let Some(key) = self + .global_state + .settings + .controls + .get_binding(GameInput::SwapLoadout) + { + i18n.get("hud.bag.swap_equipped_weapons_desc") + .replace("{key}", key.display_string(key_layout).as_str()) + } else { + "".to_string() + } + .as_str(), + &tooltip, + color::WHITE, + ) .set(state.ids.swap_equipped_weapons_btn, ui) .was_clicked() { diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 641679a555..712754a2b3 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -421,9 +421,9 @@ image_ids! { inv_sort_btn: "voxygen.element.ui.bag.buttons.inv_sort", inv_sort_btn_hover: "voxygen.element.ui.bag.buttons.inv_sort_hover", inv_sort_btn_press: "voxygen.element.ui.bag.buttons.inv_sort_press", - swap_equipped_weapons_btn: "voxygen.element.ui.generic.buttons.button", - swap_equipped_weapons_btn_hover: "voxygen.element.ui.generic.buttons.button_hover", - swap_equipped_weapons_btn_press: "voxygen.element.ui.generic.buttons.button_press", + swap_equipped_weapons_btn: "voxygen.element.ui.bag.buttons.swap_equipped_weapons", + swap_equipped_weapons_btn_hover: "voxygen.element.ui.bag.buttons.swap_equipped_weapons_hover", + swap_equipped_weapons_btn_press: "voxygen.element.ui.bag.buttons.swap_equipped_weapons_press", coin_ico: "voxygen.element.items.coin", cheese_ico: "voxygen.element.items.item_cheese", inv_bg_armor: "voxygen.element.ui.bag.inv_bg_0", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 293ee3907c..3bc56d24ee 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -2449,6 +2449,7 @@ impl Hud { ) { match Bag::new( client, + global_state, &self.imgs, &self.item_imgs, &self.fonts, From 3a004d9d4c92dcaf2d0dfef15d8e68f606fedcac Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 17 May 2021 16:48:56 -0500 Subject: [PATCH 11/11] Removed commented code --- common/src/comp/inventory/loadout.rs | 33 ++-------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index b519959588..fbcc81d0c6 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -290,17 +290,6 @@ impl Loadout { /// If no slot is available the item is returned. #[must_use = "Returned item will be lost if not used"] pub(super) fn try_equip(&mut self, item: Item) -> Result<(), Item> { - /* if let Some(loadout_slot) = self - .slots - .iter_mut() - .find(|s| s.slot.is_none() && self.slot_can_hold(s.equip_slot, item.kind())) - { - loadout_slot.slot = Some(item); - Ok(()) - } else { - Err(item) - } */ - // TODO: Get XVar to see if there better way to handle mutability issues let loadout_slot = self .slots .iter() @@ -328,15 +317,8 @@ impl Loadout { equip_slot: EquipSlot, item_kind: Option<&ItemKind>, ) -> bool { - // let weapon_compare_slots = match equip_slot { - // EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand => { - // Some((EquipSlot::ActiveMainhand, EquipSlot::ActiveOffhand)) - // }, - // EquipSlot::InactiveMainhand | EquipSlot::InactiveOffhand => { - // Some((EquipSlot::InactiveMainhand, EquipSlot::InactiveOffhand)) - // }, - // _ => None, - // }; + // Disallow equipping incompatible weapon pairs (i.e a two-handed weapon and a + // one-handed weapon) if !(match equip_slot { EquipSlot::ActiveMainhand => Loadout::is_valid_weapon_pair( item_kind, @@ -359,17 +341,6 @@ impl Loadout { return false; } - // Disallow equipping incompatible weapon pairs (i.e a two-handed weapon and a - // one-handed weapon) - // if let Some(weapon_compare_slots) = weapon_compare_slots { - // if !Loadout::is_valid_weapon_pair( - // self.equipped(weapon_compare_slots.0).map(|x| &x.kind), - // self.equipped(weapon_compare_slots.1).map(|x| &x.kind), - // ) { - // return false; - // } - // } - item_kind.map_or(true, |item_kind| equip_slot.can_hold(item_kind)) }