diff --git a/src/components.rs b/src/components.rs index dc14ee4..84afd8a 100644 --- a/src/components.rs +++ b/src/components.rs @@ -165,3 +165,13 @@ pub struct Equipped { pub owner: Entity, pub slot: EquipmentSlot, } + +#[derive(Component, ConvertSaveload, Clone)] +pub struct MeleePowerBonus { + pub power: i32, +} + +#[derive(Component, ConvertSaveload, Clone)] +pub struct DefenseBonus { + pub defense: i32, +} diff --git a/src/main.rs b/src/main.rs index 4b10a4a..ff48ea6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -402,6 +402,9 @@ fn main() -> rltk::BError { SimpleMarker, SerializationHelper, Equippable, + Equipped, + MeleePowerBonus, + DefenseBonus, ); gs.ecs.insert(SimpleMarkerAllocator::::new()); diff --git a/src/melee_combat_system.rs b/src/melee_combat_system.rs index 68ad684..7114085 100644 --- a/src/melee_combat_system.rs +++ b/src/melee_combat_system.rs @@ -1,4 +1,7 @@ -use crate::{game_log::GameLog, CombatStats, Name, SufferDamage, WantsToMelee}; +use crate::components::{ + CombatStats, DefenseBonus, Equipped, MeleePowerBonus, Name, SufferDamage, WantsToMelee, +}; +use crate::game_log::GameLog; use specs::prelude::*; pub struct MeleeCombatSystem {} @@ -11,19 +14,54 @@ impl<'a> System<'a> for MeleeCombatSystem { ReadStorage<'a, Name>, ReadStorage<'a, CombatStats>, WriteStorage<'a, SufferDamage>, + ReadStorage<'a, MeleePowerBonus>, + ReadStorage<'a, DefenseBonus>, + ReadStorage<'a, Equipped>, ); fn run(&mut self, data: Self::SystemData) { - let (entities, mut log, mut wants_melee, names, combat_stats, mut inflict_damage) = data; + let ( + entities, + mut log, + mut wants_melee, + names, + combat_stats, + mut inflict_damage, + melee_power_bonuses, + defense_bonuses, + equipped, + ) = data; - for (_entity, wants_melee, name, stats) in + for (entity, wants_melee, name, stats) in (&entities, &wants_melee, &names, &combat_stats).join() { if stats.hp > 0 { + let mut offensive_bonus = 0; + for (_item_entity, power_bonus, equipped_by) in + (&entities, &melee_power_bonuses, &equipped).join() + { + if equipped_by.owner == entity { + offensive_bonus += power_bonus.power; + } + } + let target_stats = combat_stats.get(wants_melee.target).unwrap(); if target_stats.hp > 0 { let target_name = names.get(wants_melee.target).unwrap(); - let damage = i32::max(0, stats.power - target_stats.defense); + + let mut defensive_bonus = 0; + for (_item_entity, defense_bonus, equipped_by) in + (&entities, &defense_bonuses, &equipped).join() + { + if equipped_by.owner == wants_melee.target { + defensive_bonus += defense_bonus.defense; + } + } + + let damage = i32::max( + 0, + (stats.power + offensive_bonus) - (target_stats.defense + defensive_bonus), + ); if damage == 0 { log.entries.push(format!( diff --git a/src/spawner.rs b/src/spawner.rs index 7eab31c..62d71f9 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -1,7 +1,7 @@ use crate::components::{ - AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, EquipmentSlot, Equippable, - InflictsDamage, Item, Monster, Name, Player, Position, ProvidesHealing, Ranged, Renderable, - SerializeMe, Viewshed, + AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, DefenseBonus, EquipmentSlot, + Equippable, InflictsDamage, Item, MeleePowerBonus, Monster, Name, Player, Position, + ProvidesHealing, Ranged, Renderable, SerializeMe, Viewshed, }; use crate::{random_table::RandomTable, Rect, MAP_WIDTH}; use rltk::{RandomNumberGenerator, RGB}; @@ -214,6 +214,7 @@ fn dagger(ecs: &mut World, x: i32, y: i32) { .with(Equippable { slot: EquipmentSlot::Melee, }) + .with(MeleePowerBonus { power: 2 }) .marked::>() .build(); } @@ -232,6 +233,7 @@ fn shield(ecs: &mut World, x: i32, y: i32) { .with(Equippable { slot: EquipmentSlot::Shield, }) + .with(DefenseBonus { defense: 1 }) .marked::>() .build(); }