use crate::{ gamelog, gui::{ item_colour, obfuscate_name }, Beatitude, EquipmentChanged, Equippable, Equipped, IdentifiedBeatitude, IdentifiedItem, InBackpack, MagicItem, MasterDungeonMap, Name, ObfuscatedName, WantsToUseItem, BUC, }; use specs::prelude::*; use crate::data::messages; use bracket_lib::prelude::*; pub struct ItemEquipSystem {} impl<'a> System<'a> for ItemEquipSystem { #[allow(clippy::type_complexity)] type SystemData = ( ReadExpect<'a, Entity>, Entities<'a>, WriteStorage<'a, WantsToUseItem>, WriteStorage<'a, IdentifiedItem>, ReadStorage<'a, Name>, ReadStorage<'a, Equippable>, WriteStorage<'a, Equipped>, WriteStorage<'a, InBackpack>, WriteStorage<'a, EquipmentChanged>, ReadStorage<'a, MagicItem>, ReadStorage<'a, ObfuscatedName>, ReadStorage<'a, Beatitude>, WriteStorage<'a, IdentifiedBeatitude>, ReadExpect<'a, MasterDungeonMap>, ); #[allow(clippy::cognitive_complexity)] fn run(&mut self, data: Self::SystemData) { let ( player_entity, entities, mut wants_to_use_item, mut identified_items, names, equippable, mut equipped, mut backpack, mut dirty, magic_items, obfuscated_names, beatitudes, mut identified_beatitude, dm, ) = data; let mut remove: Vec = Vec::new(); // For every item with a target, if the item is equippable, find the correct slot. for (target, wants_to_use_item) in (&entities, &wants_to_use_item).join() { if let Some(can_equip) = equippable.get(wants_to_use_item.item) { let target_slot = can_equip.slot; let mut logger = gamelog::Logger::new(); // Remove any items target has in item's slot let mut can_equip = true; 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 { if let Some(beatitude) = beatitudes.get(item_entity) { if beatitude.buc == BUC::Cursed { can_equip = false; logger = logger .append(messages::YOU_REMOVE_ITEM_CURSED) .colour(item_colour(item_entity, &beatitudes)) .append_n( obfuscate_name( item_entity, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None ).0 ) .colour(WHITE) .append("!"); identified_beatitude .insert(item_entity, IdentifiedBeatitude {}) .expect("Unable to push"); } } to_unequip.push(item_entity); } } if !can_equip { logger.log(); continue; } for item in to_unequip.iter() { equipped.remove(*item); backpack .insert(*item, InBackpack { owner: target }) .expect("Unable to insert backpack"); if target == *player_entity { logger = logger .append(messages::YOU_REMOVE_ITEM) .colour(item_colour(*item, &beatitudes)) .append_n( obfuscate_name( *item, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None ).0 ) .colour(WHITE) .period(); } } // Wield the item equipped .insert(wants_to_use_item.item, Equipped { owner: target, slot: target_slot }) .expect("Unable to insert equipped component"); backpack.remove(wants_to_use_item.item); if target == *player_entity { logger = logger .append(messages::YOU_EQUIP_ITEM) .colour(item_colour(wants_to_use_item.item, &beatitudes)) .append_n( obfuscate_name( wants_to_use_item.item, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None ).0 ) .colour(WHITE) .period(); logger.log(); identified_items .insert(target, IdentifiedItem { name: names.get(wants_to_use_item.item).unwrap().name.clone(), }) .expect("Unable to insert IdentifiedItem"); identified_beatitude .insert(wants_to_use_item.item, IdentifiedBeatitude {}) .expect("Unable to push"); } remove.push(target); } } remove.iter().for_each(|e| { dirty.insert(*e, EquipmentChanged {}).expect("Unabble to insert EquipmentChanged"); wants_to_use_item.remove(*e).expect("Unable to remove *e"); }) } }