123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- use specs::prelude::*;
- use crate::{Consumable, ProvidesHealing, InflictsDamage};
- use super::{WantsToPickupItem, Name, InBackpack,
- Position, GameLog, WantsToUseItem,
- CombatStats, Item, WantsToDropItem,
- Map, SufferDamage, AreaOfEffect,
- Equippable,Equipped,WantsToRemoveItem};
- pub struct ItemCollectionSystem {}
- impl<'a> System<'a> for ItemCollectionSystem {
- #[allow(clippy::type_complexity)]
- type SystemData = ( ReadExpect<'a, Entity>,
- WriteExpect<'a, GameLog>,
- WriteStorage<'a, WantsToPickupItem>,
- WriteStorage<'a, Position>,
- ReadStorage<'a, Name>,
- WriteStorage<'a, InBackpack>
- );
- fn run(&mut self, data : Self::SystemData) {
- let (player_entity, mut gamelog, mut wants_pickup, mut positions, names, mut backpack) = data;
- for pickup in wants_pickup.join() {
- positions.remove(pickup.item);
- backpack.insert(pickup.item, InBackpack{ owner: pickup.collected_by }).expect("Unable to insert backpack entry");
- if pickup.collected_by == *player_entity {
- gamelog.entries.push(format!("You pick up the {}.", names.get(pickup.item).unwrap().name));
- }
- }
- wants_pickup.clear();
- }
- }
- pub struct ItemRemoveSystem {}
- impl<'a> System<'a> for ItemRemoveSystem {
- #[allow(clippy::type_complexity)]
- type SystemData = (
- Entities<'a>,
- WriteStorage<'a, WantsToRemoveItem>,
- WriteStorage<'a, Equipped>,
- WriteStorage<'a, InBackpack>
- );
- fn run(&mut self, data : Self::SystemData) {
- let (entities, mut wants_remove, mut equipped, mut backpack) = data;
- for (entity, to_remove) in (&entities, &wants_remove).join() {
- equipped.remove(to_remove.item);
- backpack.insert(to_remove.item, InBackpack{ owner: entity }).expect("Unable to insert backpack");
- }
- wants_remove.clear();
- }
- }
- pub struct ItemUseSystem {}
- impl<'a> System<'a> for ItemUseSystem {
- #[allow(clippy::type_complexity)]
- type SystemData = ( ReadExpect<'a, Entity>,
- WriteExpect<'a, GameLog>,
- ReadExpect<'a, Map>,
- Entities<'a>,
- WriteStorage<'a, WantsToUseItem>,
- ReadStorage<'a, Name>,
- ReadStorage<'a, ProvidesHealing>,
- WriteStorage<'a, CombatStats>,
- ReadStorage<'a, Consumable>,
- ReadStorage<'a, Item>,
- ReadStorage<'a, InflictsDamage>,
- WriteStorage<'a, SufferDamage>,
- ReadStorage<'a, AreaOfEffect>,
- ReadStorage<'a, Equippable>,
- WriteStorage<'a, Equipped>,
- WriteStorage<'a, InBackpack>
- );
- fn run(&mut self, data : Self::SystemData) {
- let (player_entity,
- mut gamelog,
- map,
- entities,
- mut wants_use,
- names,
- healing,
- mut combat_stats,
- consumables,
- _item,
- inflict_damage,
- mut suffer_damage,
- aoe,
- equippable,
- mut equipped,
- mut backpack) = data;
- for (entity, useitem) in (&entities, &wants_use).join() {
- // Targeting
- let mut targets : Vec<Entity> = Vec::new();
- match useitem.target {
- None => { targets.push( *player_entity ); }
- Some(target) => {
- let area_effect = aoe.get(useitem.item);
- match area_effect {
- None => {
- // Single target in tile
- let idx = map.xy_idx(target.x, target.y);
- for mob in map.tile_content[idx].iter() {
- targets.push(*mob);
- }
- }
- Some(area_effect) => {
- // AoE
- let mut blast_tiles = rltk::field_of_view(target, area_effect.radius, &*map);
- blast_tiles.retain(|p| p.x > 0 && p.x < map.width-1 && p.y > 0 && p.y < map.height-1 );
- for tile_idx in blast_tiles.iter() {
- let idx = map.xy_idx(tile_idx.x, tile_idx.y);
- for mob in map.tile_content[idx].iter() {
- targets.push(*mob);
- }
- }
- }
- }
- }
- }
-
- let item_equippable = equippable.get(useitem.item);
- match item_equippable {
- 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.entries.push(format!("You unequip {}.", name.name));
- }
- }
- }
- for item in to_unequip.iter() {
- equipped.remove(*item);
- backpack.insert(*item, InBackpack{ owner: target }).expect("Unable to insert backpack entry");
- }
- // Wield the item
- equipped.insert(useitem.item, Equipped{ owner: target, slot: target_slot }).expect("Unable to insert equipped component");
- backpack.remove(useitem.item);
- if target == *player_entity {
- gamelog.entries.push(format!("You equip {}.", names.get(useitem.item).unwrap().name));
- }
- }
- }
- // If it inflicts damage, apply it to the target cell
- let item_damages = inflict_damage.get(useitem.item);
- match item_damages {
- None => {}
- Some(damage) => {
- for mob in targets.iter() {
- SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage);
- if entity == *player_entity {
- let mob_name = names.get(*mob).unwrap();
- let item_name = names.get(useitem.item).unwrap();
- gamelog.entries.push(format!("You use {} on {}, inflicting {} damage.", item_name.name, mob_name.name, damage.damage));
- }
- }
- }
- }
-
- // If it heals, apply the healing
- let item_heals = healing.get(useitem.item);
- match item_heals {
- None => {}
- Some(healer) => {
- for target in targets.iter() {
- let stats = combat_stats.get_mut(*target);
- if let Some(stats) = stats {
- stats.hp = i32::min(stats.max_hp, stats.hp + healer.heal_amount);
- if entity == *player_entity {
- gamelog.entries.push(format!("You use the {}, healing {} hp.", names.get(useitem.item).unwrap().name, healer.heal_amount));
- }
- }
- }
- }
- }
-
- let consumable = consumables.get(useitem.item);
- match consumable {
- None => {}
- Some(_) => {
- entities.delete(useitem.item).expect("Delete failed");
- }
- }
- }
- wants_use.clear();
- }
- }
- pub struct ItemDropSystem {}
- impl<'a> System<'a> for ItemDropSystem {
- #[allow(clippy::type_complexity)]
- type SystemData = ( ReadExpect<'a, Entity>,
- WriteExpect<'a, GameLog>,
- Entities<'a>,
- WriteStorage<'a, WantsToDropItem>,
- ReadStorage<'a, Name>,
- WriteStorage<'a, Position>,
- WriteStorage<'a, InBackpack>
- );
- fn run(&mut self, data : Self::SystemData) {
- let (player_entity, mut gamelog, entities, mut wants_drop, names, mut positions, mut backpack) = data;
- for (entity, to_drop) in (&entities, &wants_drop).join() {
- let mut dropper_pos : Position = Position{x:0, y:0};
- {
- let dropped_pos = positions.get(entity).unwrap();
- dropper_pos.x = dropped_pos.x;
- dropper_pos.y = dropped_pos.y;
- }
- positions.insert(to_drop.item, Position{ x : dropper_pos.x, y : dropper_pos.y }).expect("Unable to insert position");
- backpack.remove(to_drop.item);
- if entity == *player_entity {
- gamelog.entries.push(format!("You drop the {}.", names.get(to_drop.item).unwrap().name));
- }
- }
- wants_drop.clear();
- }
- }
|