From 0f6755b35f4f0d04e66ab7fb5d284d353b56c163 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 20 Jan 2022 14:04:47 -0500 Subject: [PATCH] Extract item equipping functionality from ItemUseSystem --- src/inventory_system.rs | 2 + src/inventory_system/use_equip.rs | 91 ++++++++++++++++++++++++++++++ src/inventory_system/use_system.rs | 59 +------------------ src/state.rs | 10 +++- 4 files changed, 103 insertions(+), 59 deletions(-) create mode 100644 src/inventory_system/use_equip.rs diff --git a/src/inventory_system.rs b/src/inventory_system.rs index ce8659c..3e40f43 100644 --- a/src/inventory_system.rs +++ b/src/inventory_system.rs @@ -2,6 +2,7 @@ mod collection_system; mod drop_system; mod identification_system; mod remove_system; +mod use_equip; mod use_system; use ::specs::prelude::*; @@ -9,6 +10,7 @@ pub use collection_system::ItemCollectionSystem; pub use drop_system::ItemDropSystem; pub use identification_system::ItemIdentificationSystem; pub use remove_system::ItemRemoveSystem; +pub use use_equip::ItemEquipOnUse; pub use use_system::ItemUseSystem; use crate::components::{MagicItem, Name, ObfuscatedName}; diff --git a/src/inventory_system/use_equip.rs b/src/inventory_system/use_equip.rs new file mode 100644 index 0000000..a5a10f2 --- /dev/null +++ b/src/inventory_system/use_equip.rs @@ -0,0 +1,91 @@ +use ::specs::prelude::*; + +use crate::components::{EquipmentChanged, Equippable, Equipped, InBackpack, Name, WantsToUseItem}; +use crate::GameLog; + +pub struct ItemEquipOnUse {} + +impl<'a> System<'a> for ItemEquipOnUse { + #[allow(clippy::type_complexity)] + type SystemData = ( + ReadExpect<'a, Entity>, + WriteExpect<'a, GameLog>, + Entities<'a>, + WriteStorage<'a, WantsToUseItem>, + ReadStorage<'a, Name>, + ReadStorage<'a, Equippable>, + WriteStorage<'a, Equipped>, + WriteStorage<'a, InBackpack>, + WriteStorage<'a, EquipmentChanged>, + ); + + fn run(&mut self, data: Self::SystemData) { + let ( + player_entity, + mut gamelog, + entities, + mut wants_use, + names, + equippable, + mut equipped, + mut backpack, + mut dirty, + ) = data; + + let mut remove_use = Vec::new(); + for (target, useitem) in (&entities, &wants_use).join() { + // If it is equippable, then we want to equip it -- + // and un-equip whatever else was in that slot + if let Some(can_equip) = equippable.get(useitem.item) { + let target_slot = can_equip.slot; + + // Remove any items the target has in the item's slot + let mut to_unequip = Vec::new(); + for (item_entity, already_equipped, name) in (&entities, &equipped, &names).join() { + if already_equipped.owner == target && already_equipped.slot == target_slot { + to_unequip.push(item_entity); + if target == *player_entity { + gamelog.append(format!("You un-equip {}.", name.name)); + } + } + } + for item in to_unequip.iter() { + equipped.remove(*item); + backpack + .insert(*item, InBackpack { owner: target }) + .expect("Unable to move equipped item to backpack."); + } + + // Wield the item + equipped + .insert( + useitem.item, + Equipped { + owner: target, + slot: target_slot, + }, + ) + .expect("Unable to equip item"); + backpack.remove(useitem.item); + if target == *player_entity { + gamelog.append(format!( + "You equip {}.", + names.get(useitem.item).unwrap().name + )); + } + + // Done with item + remove_use.push(target); + } + } + + remove_use.iter().for_each(|e| { + dirty + .insert(*e, EquipmentChanged {}) + .expect("Unable to insert EquipmentChanged tag"); + wants_use + .remove(*e) + .expect("Failed to remove WantsToUseItem tag"); + }) + } +} diff --git a/src/inventory_system/use_system.rs b/src/inventory_system/use_system.rs index 1bc0b57..ec56c7f 100644 --- a/src/inventory_system/use_system.rs +++ b/src/inventory_system/use_system.rs @@ -1,9 +1,9 @@ use ::specs::prelude::*; use crate::components::{ - AreaOfEffect, Confusion, Consumable, EquipmentChanged, Equippable, Equipped, HungerClock, - HungerState, IdentifiedItem, InBackpack, InflictsDamage, MagicMapper, Name, Pools, Position, - ProvidesFood, ProvidesHealing, SufferDamage, TownPortal, WantsToUseItem, + AreaOfEffect, Confusion, Consumable, EquipmentChanged, HungerClock, HungerState, + IdentifiedItem, InflictsDamage, MagicMapper, Name, Pools, Position, ProvidesFood, + ProvidesHealing, SufferDamage, TownPortal, WantsToUseItem, }; use crate::game_log::GameLog; use crate::particle_system::ParticleBuilder; @@ -27,9 +27,6 @@ impl<'a> System<'a> for ItemUseSystem { WriteStorage<'a, SufferDamage>, ReadStorage<'a, AreaOfEffect>, WriteStorage<'a, Confusion>, - ReadStorage<'a, Equippable>, - WriteStorage<'a, Equipped>, - WriteStorage<'a, InBackpack>, WriteExpect<'a, ParticleBuilder>, ReadStorage<'a, Position>, ReadStorage<'a, ProvidesFood>, @@ -57,9 +54,6 @@ impl<'a> System<'a> for ItemUseSystem { mut suffer_damage, aoe, mut confused, - equippable, - mut equipped, - mut backpack, mut particle_builder, positions, provides_food, @@ -128,53 +122,6 @@ impl<'a> System<'a> for ItemUseSystem { .expect("Unable to identify item"); } - // If it is equippable, then we want to equip it - and unequip whatever else was in that slot - match equippable.get(useitem.item) { - None => {} - Some(can_equip) => { - let target_slot = can_equip.slot; - let target = targets[0]; - - // Remove any items the target has in the item's slot - let mut to_unequip: Vec = Vec::new(); - for (item_entity, already_equipped, name) in - (&entities, &equipped, &names).join() - { - if already_equipped.owner == target && already_equipped.slot == target_slot - { - to_unequip.push(item_entity); - if target == *player_entity { - gamelog.append(format!("You unequip {}.", name.name)); - } - } - } - for item in to_unequip.iter() { - equipped.remove(*item); - backpack - .insert(*item, InBackpack { owner: target }) - .expect("Unable to put unequipped item back in backpack"); - } - - // Wield the item - equipped - .insert( - useitem.item, - Equipped { - owner: target, - slot: target_slot, - }, - ) - .expect("Failed to equip item"); - backpack.remove(useitem.item); - if target == *player_entity { - gamelog.append(format!( - "You equip {}.", - names.get(useitem.item).unwrap().name - )); - } - } - } - // If it is edible, eat it! match provides_food.get(useitem.item) { None => {} diff --git a/src/state.rs b/src/state.rs index 0cc62d1..ef6d31d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,7 +7,8 @@ use crate::game_log::GameLog; use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection}; use crate::hunger_system::HungerSystem; use crate::inventory_system::{ - ItemCollectionSystem, ItemDropSystem, ItemIdentificationSystem, ItemRemoveSystem, ItemUseSystem, + ItemCollectionSystem, ItemDropSystem, ItemEquipOnUse, ItemIdentificationSystem, + ItemRemoveSystem, ItemUseSystem, }; use crate::lighting_system::LightingSystem; use crate::map::{self, *}; @@ -124,8 +125,11 @@ impl State { let mut pickup = ItemCollectionSystem {}; pickup.run_now(&self.ecs); - let mut items = ItemUseSystem {}; - items.run_now(&self.ecs); + let mut itemequip = ItemEquipOnUse {}; + itemequip.run_now(&self.ecs); + + let mut itemuse = ItemUseSystem {}; + itemuse.run_now(&self.ecs); let mut item_id = ItemIdentificationSystem {}; item_id.run_now(&self.ecs);