1 use specs::prelude::*;
2 use super::{CombatStats, WantsToMelee, Name,
3 SufferDamage, GameLog, MeleePowerBonus,
4 DefenseBonus, Equipped, particle_system::ParticleBuilder,
5 Position};
6
7 pub struct MeleeCombatSystem {}
8
9 impl<'a> System<'a> for MeleeCombatSystem {
10 type SystemData = ( Entities<'a>,
11 WriteExpect<'a, GameLog>,
12 WriteStorage<'a, WantsToMelee>,
13 ReadStorage<'a, Name>,
14 ReadStorage<'a, CombatStats>,
15 WriteStorage<'a, SufferDamage>,
16 ReadStorage<'a, MeleePowerBonus>,
17 ReadStorage<'a, DefenseBonus>,
18 ReadStorage<'a, Equipped>,
19 WriteExpect<'a, ParticleBuilder>,
20 ReadStorage<'a, Position>
21 );
22
23 fn run(&mut self, data : Self::SystemData) {
24 let (entities,
25 mut log,
26 mut wants_melee,
27 names,
28 combat_stats,
29 mut inflict_damage,
30 melee_power_bonuses,
31 defense_bonuses,
32 equipped,
33 mut particle_builder,
34 positions) = data;
35
36 for (entity, wants_melee, name, stats) in (&entities, &wants_melee, &names, &combat_stats).join() {
37 if stats.hp > 0 {
38 let mut offensive_bonus = 0;
39 for (_item_entity, power_bonus, equipped_by) in (&entities, &melee_power_bonuses, &equipped).join() {
40 if equipped_by.owner == entity {
41 offensive_bonus += power_bonus.power;
42 }
43 }
44
45 let target_stats = combat_stats.get(wants_melee.target).unwrap();
46 if target_stats.hp > 0 {
47 let target_name = names.get(wants_melee.target).unwrap();
48
49 let mut defensive_bonus = 0;
50 for (_item_entity, defense_bonus, equipped_by) in (&entities, &defense_bonuses, &equipped).join() {
51 if equipped_by.owner == wants_melee.target {
52 defensive_bonus += defense_bonus.defense;
53 }
54 }
55
56 let pos = positions.get(wants_melee.target);
57 if let Some(pos) = pos {
58 particle_builder.request(pos.x, pos.y, rltk::RGB::named(rltk::ORANGE), rltk::RGB::named(rltk::BLACK), rltk::to_cp437('‼'), 200.0);
59 }
60 let damage = i32::max(0, (stats.power + offensive_bonus) - (target_stats.defense + defensive_bonus));
61
62 if damage == 0 {
63 log.entries.push(format!("{} is unable to hurt {}", &name.name, &target_name.name));
64 } else {
65 log.entries.push(format!("{} hits {}, for {} damage.", &name.name, &target_name.name, damage));
66 SufferDamage::new_damage(&mut inflict_damage, wants_melee.target, damage);
67 }
68 }
69 }
70 }
71
72 wants_melee.clear();
73 }
74 }