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 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};

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 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<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!
match provides_food.get(useitem.item) {
None => {}

View File

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