Add Fireball scroll

This commit is contained in:
Timothy Warren 2021-11-05 13:12:22 -04:00
parent d2ebe5dc1d
commit 36af877217
4 changed files with 83 additions and 18 deletions

View File

@ -128,3 +128,8 @@ pub struct Ranged {
pub struct InflictsDamage {
pub damage: i32,
}
#[derive(Component, Debug)]
pub struct AreaOfEffect {
pub radius: i32,
}

View File

@ -1,6 +1,7 @@
use crate::{
game_log::GameLog, CombatStats, Consumable, InBackpack, InflictsDamage, Map, Name, Position,
ProvidesHealing, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToUseItem,
game_log::GameLog, AreaOfEffect, CombatStats, Consumable, InBackpack, InflictsDamage, Map,
Name, Position, ProvidesHealing, SufferDamage, WantsToDropItem, WantsToPickupItem,
WantsToUseItem,
};
use specs::prelude::*;
@ -60,6 +61,7 @@ impl<'a> System<'a> for ItemUseSystem {
ReadStorage<'a, InflictsDamage>,
WriteStorage<'a, CombatStats>,
WriteStorage<'a, SufferDamage>,
ReadStorage<'a, AreaOfEffect>,
);
fn run(&mut self, data: Self::SystemData) {
@ -75,17 +77,55 @@ impl<'a> System<'a> for ItemUseSystem {
inflict_damage,
mut combat_stats,
mut suffer_damage,
aoe,
) = data;
for (entity, useitem, stats) in (&entities, &wants_use, &mut combat_stats).join() {
for (entity, useitem) in (&entities, &wants_use).join() {
let mut used_item = true;
// Targeting
let mut targets: Vec<Entity> = Vec::new();
match useitem.target {
None => {
targets.push(*player_entity);
}
Some(target) => {
match aoe.get(useitem.item) {
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);
}
}
}
}
}
}
// If the item heals, apply the healing
match healing.get(useitem.item) {
None => {}
Some(healer) => {
used_item = false;
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!(
@ -98,16 +138,16 @@ impl<'a> System<'a> for ItemUseSystem {
used_item = true;
}
}
}
}
// If it inflicts damage, apply it to the target cell
match inflict_damage.get(useitem.item) {
None => {}
Some(damage) => {
let target_point = useitem.target.unwrap();
let idx = map.xy_idx(target_point.x, target_point.y);
used_item = false;
for mob in map.tile_content[idx].iter() {
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();

View File

@ -253,6 +253,7 @@ fn main() -> rltk::BError {
Consumable,
Ranged,
InflictsDamage,
AreaOfEffect,
);
let map = Map::new_map_rooms_and_corridors();

View File

@ -1,6 +1,6 @@
use crate::{
BlocksTile, CombatStats, Consumable, InflictsDamage, Item, Monster, Name, Player, Position,
ProvidesHealing, Ranged, Rect, Renderable, Viewshed, MAP_WIDTH,
AreaOfEffect, BlocksTile, CombatStats, Consumable, InflictsDamage, Item, Monster, Name, Player,
Position, ProvidesHealing, Ranged, Rect, Renderable, Viewshed, MAP_WIDTH,
};
use rltk::{RandomNumberGenerator, RGB};
use specs::prelude::*;
@ -172,11 +172,30 @@ fn random_item(ecs: &mut World, x: i32, y: i32) {
let roll: i32;
{
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
roll = rng.roll_dice(1, 2);
roll = rng.roll_dice(1, 3);
}
match roll {
1 => health_potion(ecs, x, y),
2 => fireball_scroll(ecs, x, y),
_ => magic_missile_scroll(ecs, x, y),
}
}
fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
ecs.create_entity()
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437(')'),
fg: RGB::named(rltk::ORANGE),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Fireball Scroll"))
.with(Item {})
.with(Consumable {})
.with(Ranged { range: 6 })
.with(InflictsDamage { damage: 20 })
.with(AreaOfEffect { radius: 3 })
.build();
}