inventory_system.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. use specs::prelude::*;
  2. use crate::{Consumable, ProvidesHealing, InflictsDamage};
  3. use super::{WantsToPickupItem, Name, InBackpack,
  4. Position, GameLog, WantsToUseItem,
  5. CombatStats, Item, WantsToDropItem,
  6. Map, SufferDamage, AreaOfEffect};
  7. pub struct ItemCollectionSystem {}
  8. impl<'a> System<'a> for ItemCollectionSystem {
  9. #[allow(clippy::type_complexity)]
  10. type SystemData = ( ReadExpect<'a, Entity>,
  11. WriteExpect<'a, GameLog>,
  12. WriteStorage<'a, WantsToPickupItem>,
  13. WriteStorage<'a, Position>,
  14. ReadStorage<'a, Name>,
  15. WriteStorage<'a, InBackpack>
  16. );
  17. fn run(&mut self, data : Self::SystemData) {
  18. let (player_entity, mut gamelog, mut wants_pickup, mut positions, names, mut backpack) = data;
  19. for pickup in wants_pickup.join() {
  20. positions.remove(pickup.item);
  21. backpack.insert(pickup.item, InBackpack{ owner: pickup.collected_by }).expect("Unable to insert backpack entry");
  22. if pickup.collected_by == *player_entity {
  23. gamelog.entries.push(format!("You pick up the {}.", names.get(pickup.item).unwrap().name));
  24. }
  25. }
  26. wants_pickup.clear();
  27. }
  28. }
  29. pub struct ItemUseSystem {}
  30. impl<'a> System<'a> for ItemUseSystem {
  31. #[allow(clippy::type_complexity)]
  32. type SystemData = ( ReadExpect<'a, Entity>,
  33. WriteExpect<'a, GameLog>,
  34. ReadExpect<'a, Map>,
  35. Entities<'a>,
  36. WriteStorage<'a, WantsToUseItem>,
  37. ReadStorage<'a, Name>,
  38. ReadStorage<'a, ProvidesHealing>,
  39. WriteStorage<'a, CombatStats>,
  40. ReadStorage<'a, Consumable>,
  41. ReadStorage<'a, Item>,
  42. ReadStorage<'a, InflictsDamage>,
  43. WriteStorage<'a, SufferDamage>,
  44. ReadStorage<'a, AreaOfEffect>,
  45. );
  46. fn run(&mut self, data : Self::SystemData) {
  47. let (player_entity,
  48. mut gamelog,
  49. map,
  50. entities,
  51. mut wants_use,
  52. names,
  53. healing,
  54. mut combat_stats,
  55. consumables,
  56. _item,
  57. inflict_damage,
  58. mut suffer_damage,
  59. aoe) = data;
  60. for (entity, useitem) in (&entities, &wants_use).join() {
  61. // Targeting
  62. let mut targets : Vec<Entity> = Vec::new();
  63. match useitem.target {
  64. None => { targets.push( *player_entity ); }
  65. Some(target) => {
  66. let area_effect = aoe.get(useitem.item);
  67. match area_effect {
  68. None => {
  69. // Single target in tile
  70. let idx = map.xy_idx(target.x, target.y);
  71. for mob in map.tile_content[idx].iter() {
  72. targets.push(*mob);
  73. }
  74. }
  75. Some(area_effect) => {
  76. // AoE
  77. let mut blast_tiles = rltk::field_of_view(target, area_effect.radius, &*map);
  78. blast_tiles.retain(|p| p.x > 0 && p.x < map.width-1 && p.y > 0 && p.y < map.height-1 );
  79. for tile_idx in blast_tiles.iter() {
  80. let idx = map.xy_idx(tile_idx.x, tile_idx.y);
  81. for mob in map.tile_content[idx].iter() {
  82. targets.push(*mob);
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }
  89. // If it inflicts damage, apply it to the target cell
  90. let item_damages = inflict_damage.get(useitem.item);
  91. match item_damages {
  92. None => {}
  93. Some(damage) => {
  94. for mob in targets.iter() {
  95. SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage);
  96. if entity == *player_entity {
  97. let mob_name = names.get(*mob).unwrap();
  98. let item_name = names.get(useitem.item).unwrap();
  99. gamelog.entries.push(format!("You use {} on {}, inflicting {} damage.", item_name.name, mob_name.name, damage.damage));
  100. }
  101. }
  102. }
  103. }
  104. // If it heals, apply the healing
  105. let item_heals = healing.get(useitem.item);
  106. match item_heals {
  107. None => {}
  108. Some(healer) => {
  109. for target in targets.iter() {
  110. let stats = combat_stats.get_mut(*target);
  111. if let Some(stats) = stats {
  112. stats.hp = i32::min(stats.max_hp, stats.hp + healer.heal_amount);
  113. if entity == *player_entity {
  114. gamelog.entries.push(format!("You use the {}, healing {} hp.", names.get(useitem.item).unwrap().name, healer.heal_amount));
  115. }
  116. }
  117. }
  118. }
  119. }
  120. let consumable = consumables.get(useitem.item);
  121. match consumable {
  122. None => {}
  123. Some(_) => {
  124. entities.delete(useitem.item).expect("Delete failed");
  125. }
  126. }
  127. }
  128. wants_use.clear();
  129. }
  130. }
  131. pub struct ItemDropSystem {}
  132. impl<'a> System<'a> for ItemDropSystem {
  133. #[allow(clippy::type_complexity)]
  134. type SystemData = ( ReadExpect<'a, Entity>,
  135. WriteExpect<'a, GameLog>,
  136. Entities<'a>,
  137. WriteStorage<'a, WantsToDropItem>,
  138. ReadStorage<'a, Name>,
  139. WriteStorage<'a, Position>,
  140. WriteStorage<'a, InBackpack>
  141. );
  142. fn run(&mut self, data : Self::SystemData) {
  143. let (player_entity, mut gamelog, entities, mut wants_drop, names, mut positions, mut backpack) = data;
  144. for (entity, to_drop) in (&entities, &wants_drop).join() {
  145. let mut dropper_pos : Position = Position{x:0, y:0};
  146. {
  147. let dropped_pos = positions.get(entity).unwrap();
  148. dropper_pos.x = dropped_pos.x;
  149. dropper_pos.y = dropped_pos.y;
  150. }
  151. positions.insert(to_drop.item, Position{ x : dropper_pos.x, y : dropper_pos.y }).expect("Unable to insert position");
  152. backpack.remove(to_drop.item);
  153. if entity == *player_entity {
  154. gamelog.entries.push(format!("You drop the {}.", names.get(to_drop.item).unwrap().name));
  155. }
  156. }
  157. wants_drop.clear();
  158. }
  159. }