Extract item equipping functionality from ItemUseSystem

This commit is contained in:
Timothy Warren 2022-01-20 14:04:47 -05:00
parent 6f35a4a933
commit 0f6755b35f
4 changed files with 103 additions and 59 deletions

View File

@ -2,6 +2,7 @@ mod collection_system;
mod drop_system; mod drop_system;
mod identification_system; mod identification_system;
mod remove_system; mod remove_system;
mod use_equip;
mod use_system; mod use_system;
use ::specs::prelude::*; use ::specs::prelude::*;
@ -9,6 +10,7 @@ pub use collection_system::ItemCollectionSystem;
pub use drop_system::ItemDropSystem; pub use drop_system::ItemDropSystem;
pub use identification_system::ItemIdentificationSystem; pub use identification_system::ItemIdentificationSystem;
pub use remove_system::ItemRemoveSystem; pub use remove_system::ItemRemoveSystem;
pub use use_equip::ItemEquipOnUse;
pub use use_system::ItemUseSystem; pub use use_system::ItemUseSystem;
use crate::components::{MagicItem, Name, ObfuscatedName}; use crate::components::{MagicItem, Name, ObfuscatedName};

View File

@ -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");
})
}
}

View File

@ -1,9 +1,9 @@
use ::specs::prelude::*; use ::specs::prelude::*;
use crate::components::{ use crate::components::{
AreaOfEffect, Confusion, Consumable, EquipmentChanged, Equippable, Equipped, HungerClock, AreaOfEffect, Confusion, Consumable, EquipmentChanged, HungerClock, HungerState,
HungerState, IdentifiedItem, InBackpack, InflictsDamage, MagicMapper, Name, Pools, Position, IdentifiedItem, InflictsDamage, MagicMapper, Name, Pools, Position, ProvidesFood,
ProvidesFood, ProvidesHealing, SufferDamage, TownPortal, WantsToUseItem, ProvidesHealing, SufferDamage, TownPortal, WantsToUseItem,
}; };
use crate::game_log::GameLog; use crate::game_log::GameLog;
use crate::particle_system::ParticleBuilder; use crate::particle_system::ParticleBuilder;
@ -27,9 +27,6 @@ impl<'a> System<'a> for ItemUseSystem {
WriteStorage<'a, SufferDamage>, WriteStorage<'a, SufferDamage>,
ReadStorage<'a, AreaOfEffect>, ReadStorage<'a, AreaOfEffect>,
WriteStorage<'a, Confusion>, WriteStorage<'a, Confusion>,
ReadStorage<'a, Equippable>,
WriteStorage<'a, Equipped>,
WriteStorage<'a, InBackpack>,
WriteExpect<'a, ParticleBuilder>, WriteExpect<'a, ParticleBuilder>,
ReadStorage<'a, Position>, ReadStorage<'a, Position>,
ReadStorage<'a, ProvidesFood>, ReadStorage<'a, ProvidesFood>,
@ -57,9 +54,6 @@ impl<'a> System<'a> for ItemUseSystem {
mut suffer_damage, mut suffer_damage,
aoe, aoe,
mut confused, mut confused,
equippable,
mut equipped,
mut backpack,
mut particle_builder, mut particle_builder,
positions, positions,
provides_food, provides_food,
@ -128,53 +122,6 @@ impl<'a> System<'a> for ItemUseSystem {
.expect("Unable to identify item"); .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<Entity> = 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! // If it is edible, eat it!
match provides_food.get(useitem.item) { match provides_food.get(useitem.item) {
None => {} None => {}

View File

@ -7,7 +7,8 @@ use crate::game_log::GameLog;
use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection}; use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection};
use crate::hunger_system::HungerSystem; use crate::hunger_system::HungerSystem;
use crate::inventory_system::{ use crate::inventory_system::{
ItemCollectionSystem, ItemDropSystem, ItemIdentificationSystem, ItemRemoveSystem, ItemUseSystem, ItemCollectionSystem, ItemDropSystem, ItemEquipOnUse, ItemIdentificationSystem,
ItemRemoveSystem, ItemUseSystem,
}; };
use crate::lighting_system::LightingSystem; use crate::lighting_system::LightingSystem;
use crate::map::{self, *}; use crate::map::{self, *};
@ -124,8 +125,11 @@ impl State {
let mut pickup = ItemCollectionSystem {}; let mut pickup = ItemCollectionSystem {};
pickup.run_now(&self.ecs); pickup.run_now(&self.ecs);
let mut items = ItemUseSystem {}; let mut itemequip = ItemEquipOnUse {};
items.run_now(&self.ecs); itemequip.run_now(&self.ecs);
let mut itemuse = ItemUseSystem {};
itemuse.run_now(&self.ecs);
let mut item_id = ItemIdentificationSystem {}; let mut item_id = ItemIdentificationSystem {};
item_id.run_now(&self.ecs); item_id.run_now(&self.ecs);