magic missile, fireball scrolls
This commit is contained in:
parent
2266998e80
commit
06c3d40c65
7 changed files with 315 additions and 50 deletions
|
|
@ -71,7 +71,22 @@ pub struct Item {}
|
|||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct ProvidesHealing {
|
||||
pub heal_amount: i32,
|
||||
pub amount: i32,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct InflictsDamage {
|
||||
pub amount: i32,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Ranged {
|
||||
pub range: i32,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct AOE {
|
||||
pub radius: i32,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Clone)]
|
||||
|
|
@ -93,6 +108,7 @@ pub struct WantsToDropItem {
|
|||
#[derive(Component, Debug)]
|
||||
pub struct WantsToUseItem {
|
||||
pub item: Entity,
|
||||
pub target: Option<rltk::Point>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::{gamelog::GameLog, CombatStats, Entities, Map, Name, Player, Position, SufferDamage};
|
||||
use super::{gamelog::GameLog, CombatStats, Entities, Item, Map, Name, Player, Position, SufferDamage};
|
||||
use specs::prelude::*;
|
||||
|
||||
pub struct DamageSystem {}
|
||||
|
|
@ -35,6 +35,7 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
let combat_stats = ecs.read_storage::<CombatStats>();
|
||||
let players = ecs.read_storage::<Player>();
|
||||
let names = ecs.read_storage::<Name>();
|
||||
let items = ecs.read_storage::<Item>();
|
||||
let entities = ecs.entities();
|
||||
let mut log = ecs.write_resource::<GameLog>();
|
||||
for (entity, stats) in (&entities, &combat_stats).join() {
|
||||
|
|
@ -44,7 +45,12 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
None => {
|
||||
let victim_name = names.get(entity);
|
||||
if let Some(victim_name) = victim_name {
|
||||
log.entries.push(format!("{} died!", &victim_name.name));
|
||||
let item = items.get(entity);
|
||||
if let Some(_item) = item {
|
||||
log.entries.push(format!("{} was destroyed!", &victim_name.name));
|
||||
} else {
|
||||
log.entries.push(format!("{} died!", &victim_name.name));
|
||||
}
|
||||
}
|
||||
dead.push(entity)
|
||||
}
|
||||
|
|
|
|||
56
src/gui.rs
56
src/gui.rs
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
gamelog::GameLog, rex_assets::RexAssets, CombatStats, InBackpack, Map, Name, Player, Point, Position, RunState,
|
||||
State,
|
||||
State, Viewshed,
|
||||
};
|
||||
use rltk::{Rltk, VirtualKeyCode, RGB};
|
||||
use specs::prelude::*;
|
||||
|
|
@ -205,6 +205,60 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ranged_target(gs: &mut State, ctx: &mut Rltk, range: i32, aoe: i32) -> (ItemMenuResult, Option<Point>) {
|
||||
let player_entity = gs.ecs.fetch::<Entity>();
|
||||
let player_pos = gs.ecs.fetch::<Point>();
|
||||
let viewsheds = gs.ecs.read_storage::<Viewshed>();
|
||||
|
||||
ctx.print_color(5, 0, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "select target");
|
||||
|
||||
// Highlight available cells
|
||||
let mut available_cells = Vec::new();
|
||||
let visible = viewsheds.get(*player_entity);
|
||||
if let Some(visible) = visible {
|
||||
// We have a viewshed
|
||||
for idx in visible.visible_tiles.iter() {
|
||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
||||
if distance <= range as f32 {
|
||||
ctx.set_bg(idx.x, idx.y, RGB::named(rltk::BLUE));
|
||||
available_cells.push(idx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return (ItemMenuResult::Cancel, None);
|
||||
}
|
||||
|
||||
// Draw mouse cursor
|
||||
let mouse_pos = ctx.mouse_pos();
|
||||
let map = gs.ecs.fetch::<Map>();
|
||||
let mut valid_target = false;
|
||||
for idx in available_cells.iter() {
|
||||
if idx.x == mouse_pos.0 && idx.y == mouse_pos.1 {
|
||||
valid_target = true;
|
||||
}
|
||||
}
|
||||
if valid_target {
|
||||
if aoe > 0 {
|
||||
let mut blast_tiles = rltk::field_of_view(Point::new(mouse_pos.0, mouse_pos.1), aoe, &*map);
|
||||
blast_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
||||
for tile in blast_tiles.iter() {
|
||||
ctx.set_bg(tile.x, tile.y, RGB::named(rltk::DARKCYAN));
|
||||
}
|
||||
}
|
||||
ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::CYAN));
|
||||
if ctx.left_click {
|
||||
return (ItemMenuResult::Selected, Some(Point::new(mouse_pos.0, mouse_pos.1)));
|
||||
}
|
||||
} else {
|
||||
ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::RED));
|
||||
if ctx.left_click {
|
||||
return (ItemMenuResult::Cancel, None);
|
||||
}
|
||||
}
|
||||
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum MainMenuSelection {
|
||||
NewGame,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
gamelog::GameLog, CombatStats, Consumable, InBackpack, Name, ParticleBuilder, Position, ProvidesHealing,
|
||||
WantsToDropItem, WantsToPickupItem, WantsToUseItem, DEFAULT_PARTICLE_LIFETIME,
|
||||
gamelog::GameLog, CombatStats, Consumable, InBackpack, InflictsDamage, Map, Name, ParticleBuilder, Position,
|
||||
ProvidesHealing, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -39,65 +39,156 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
type SystemData = (
|
||||
ReadExpect<'a, Entity>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
ReadExpect<'a, Map>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, WantsToUseItem>,
|
||||
ReadStorage<'a, Name>,
|
||||
ReadStorage<'a, Consumable>,
|
||||
ReadStorage<'a, ProvidesHealing>,
|
||||
WriteStorage<'a, CombatStats>,
|
||||
WriteStorage<'a, SufferDamage>,
|
||||
WriteExpect<'a, ParticleBuilder>,
|
||||
ReadStorage<'a, Position>,
|
||||
ReadStorage<'a, InflictsDamage>,
|
||||
ReadStorage<'a, AOE>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
player_entity,
|
||||
mut gamelog,
|
||||
map,
|
||||
entities,
|
||||
mut wants_use,
|
||||
mut wants_to_use,
|
||||
names,
|
||||
consumables,
|
||||
healing,
|
||||
provides_healing,
|
||||
mut combat_stats,
|
||||
mut suffer_damage,
|
||||
mut particle_builder,
|
||||
positions,
|
||||
inflicts_damage,
|
||||
aoe,
|
||||
) = data;
|
||||
|
||||
for (entity, use_item, stats) in (&entities, &wants_use, &mut combat_stats).join() {
|
||||
let item_heals = healing.get(use_item.item);
|
||||
match item_heals {
|
||||
None => {}
|
||||
Some(healer) => {
|
||||
stats.hp = i32::min(stats.max_hp, stats.hp + healer.heal_amount);
|
||||
let pos = positions.get(entity);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.request(
|
||||
pos.x,
|
||||
pos.y,
|
||||
rltk::RGB::named(rltk::GREEN),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('♥'),
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
);
|
||||
}
|
||||
if entity == *player_entity {
|
||||
gamelog.entries.push(format!(
|
||||
"You quaff the {}, and heal {} hp.",
|
||||
names.get(use_item.item).unwrap().name,
|
||||
healer.heal_amount
|
||||
));
|
||||
}
|
||||
let consumable = consumables.get(use_item.item);
|
||||
match consumable {
|
||||
None => {}
|
||||
Some(_) => {
|
||||
entities.delete(use_item.item).expect("Delete failed");
|
||||
for (entity, wants_to_use) in (&entities, &wants_to_use).join() {
|
||||
let mut used_item = true;
|
||||
let mut aoe_item = false;
|
||||
let item_being_used = names.get(wants_to_use.item).unwrap();
|
||||
|
||||
// TARGETING
|
||||
let mut targets: Vec<Entity> = Vec::new();
|
||||
match wants_to_use.target {
|
||||
None => {
|
||||
targets.push(*player_entity);
|
||||
}
|
||||
Some(target) => {
|
||||
let area_effect = aoe.get(wants_to_use.item);
|
||||
match area_effect {
|
||||
None => {
|
||||
// Single target in a 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
|
||||
aoe_item = true;
|
||||
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);
|
||||
}
|
||||
particle_builder.request(
|
||||
tile_idx.x,
|
||||
tile_idx.y,
|
||||
rltk::RGB::named(rltk::ORANGE),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('░'),
|
||||
200.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HEALING ITEM
|
||||
let item_heals = provides_healing.get(wants_to_use.item);
|
||||
match item_heals {
|
||||
None => {}
|
||||
Some(heal) => {
|
||||
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 + heal.amount);
|
||||
if entity == *player_entity {
|
||||
gamelog.entries.push(format!(
|
||||
"You quaff the {}, and heal {} hp.",
|
||||
item_being_used.name, heal.amount
|
||||
));
|
||||
}
|
||||
let pos = positions.get(entity);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.request(
|
||||
pos.x,
|
||||
pos.y,
|
||||
rltk::RGB::named(rltk::GREEN),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('♥'),
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DAMAGING ITEM
|
||||
let item_damages = inflicts_damage.get(wants_to_use.item);
|
||||
match item_damages {
|
||||
None => {}
|
||||
Some(damage) => {
|
||||
let target_point = wants_to_use.target.unwrap();
|
||||
gamelog.entries.push(format!("You use the {}!", item_being_used.name));
|
||||
if !aoe_item {
|
||||
particle_builder.request_star(
|
||||
target_point.x,
|
||||
target_point.y,
|
||||
rltk::RGB::named(rltk::CYAN),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('*'),
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
);
|
||||
}
|
||||
for mob in targets.iter() {
|
||||
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.amount);
|
||||
if entity == *player_entity {
|
||||
let mob_name = names.get(*mob).unwrap();
|
||||
gamelog.entries.push(format!(
|
||||
"{} takes {} damage from the {}!",
|
||||
mob_name.name, damage.amount, item_being_used.name
|
||||
));
|
||||
}
|
||||
|
||||
used_item = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if used_item {
|
||||
let consumable = consumables.get(wants_to_use.item);
|
||||
match consumable {
|
||||
None => {}
|
||||
Some(_) => {
|
||||
entities.delete(wants_to_use.item).expect("Delete failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wants_use.clear();
|
||||
wants_to_use.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
49
src/main.rs
49
src/main.rs
|
|
@ -42,6 +42,7 @@ pub enum RunState {
|
|||
MonsterTurn,
|
||||
ShowInventory,
|
||||
ShowDropItem,
|
||||
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
||||
MainMenu { menu_selection: gui::MainMenuSelection },
|
||||
}
|
||||
|
||||
|
|
@ -139,11 +140,28 @@ impl GameState for State {
|
|||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent
|
||||
.insert(*self.ecs.fetch::<Entity>(), WantsToUseItem { item: item_entity })
|
||||
.expect("Unable to insert intent.");
|
||||
new_runstate = RunState::PlayerTurn;
|
||||
let is_ranged = self.ecs.read_storage::<Ranged>();
|
||||
let ranged_item = is_ranged.get(item_entity);
|
||||
if let Some(ranged_item) = ranged_item {
|
||||
let is_aoe = self.ecs.read_storage::<AOE>();
|
||||
let aoe_item = is_aoe.get(item_entity);
|
||||
if let Some(aoe_item) = aoe_item {
|
||||
new_runstate = RunState::ShowTargeting {
|
||||
range: ranged_item.range,
|
||||
item: item_entity,
|
||||
aoe: aoe_item.radius,
|
||||
}
|
||||
} else {
|
||||
new_runstate =
|
||||
RunState::ShowTargeting { range: ranged_item.range, item: item_entity, aoe: 0 }
|
||||
}
|
||||
} else {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent
|
||||
.insert(*self.ecs.fetch::<Entity>(), WantsToUseItem { item: item_entity, target: None })
|
||||
.expect("Unable to insert intent.");
|
||||
new_runstate = RunState::PlayerTurn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,6 +180,20 @@ impl GameState for State {
|
|||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowTargeting { range, item, aoe } => {
|
||||
let result = gui::ranged_target(self, ctx, range, aoe);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent
|
||||
.insert(*self.ecs.fetch::<Entity>(), WantsToUseItem { item, target: result.1 })
|
||||
.expect("Unable to insert intent.");
|
||||
new_runstate = RunState::PlayerTurn;
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::MainMenu { .. } => {
|
||||
let result = gui::main_menu(self, ctx);
|
||||
match result {
|
||||
|
|
@ -225,6 +257,9 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.register::<SufferDamage>();
|
||||
gs.ecs.register::<Item>();
|
||||
gs.ecs.register::<ProvidesHealing>();
|
||||
gs.ecs.register::<InflictsDamage>();
|
||||
gs.ecs.register::<Ranged>();
|
||||
gs.ecs.register::<AOE>();
|
||||
gs.ecs.register::<InBackpack>();
|
||||
gs.ecs.register::<WantsToPickupItem>();
|
||||
gs.ecs.register::<WantsToDropItem>();
|
||||
|
|
@ -245,7 +280,9 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.insert(map);
|
||||
gs.ecs.insert(Point::new(player_x, player_y));
|
||||
gs.ecs.insert(player_entity);
|
||||
gs.ecs.insert(gamelog::GameLog { entries: vec!["Here's your welcome message.".to_string()] });
|
||||
gs.ecs.insert(gamelog::GameLog {
|
||||
entries: vec!["<pretend i wrote a paragraph explaining why you're here>".to_string()],
|
||||
});
|
||||
gs.ecs.insert(RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame });
|
||||
gs.ecs.insert(particle_system::ParticleBuilder::new());
|
||||
gs.ecs.insert(rex_assets::RexAssets::new());
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ use specs::prelude::*;
|
|||
|
||||
pub const DEFAULT_PARTICLE_LIFETIME: f32 = 150.0;
|
||||
|
||||
/// Runs each tick, deleting particles who are past their expiry.
|
||||
// Should make an addition to this to also spawn delayed particles,
|
||||
// running through a list and removing the frame_time_ms from the
|
||||
// delay. When delay is <= 0, make a particle_builder.request for
|
||||
// the particle.
|
||||
pub fn cull_dead_particles(ecs: &mut World, ctx: &Rltk) {
|
||||
let mut dead_particles: Vec<Entity> = Vec::new();
|
||||
{
|
||||
|
|
@ -41,9 +46,28 @@ impl ParticleBuilder {
|
|||
ParticleBuilder { requests: Vec::new() }
|
||||
}
|
||||
|
||||
/// Makes a single particle request.
|
||||
pub fn request(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32) {
|
||||
self.requests.push(ParticleRequest { x, y, fg, bg, glyph, lifetime });
|
||||
}
|
||||
|
||||
// Makes a particle request in the shape of an 'x'. Sort of.
|
||||
pub fn request_star(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32) {
|
||||
self.request(x, y, fg, bg, glyph, lifetime * 2.0);
|
||||
self.request(x + 1, y + 1, fg, bg, rltk::to_cp437('/'), lifetime);
|
||||
self.request(x + 1, y - 1, fg, bg, rltk::to_cp437('\\'), lifetime);
|
||||
self.request(x - 1, y + 1, fg, bg, rltk::to_cp437('\\'), lifetime);
|
||||
self.request(x - 1, y - 1, fg, bg, rltk::to_cp437('/'), lifetime);
|
||||
}
|
||||
|
||||
/// Makes a particle request in the shape of a +.
|
||||
pub fn request_plus(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32) {
|
||||
self.request(x, y, fg, bg, glyph, lifetime * 2.0);
|
||||
self.request(x + 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
|
||||
self.request(x - 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
|
||||
self.request(x, y + 1, fg, bg, rltk::to_cp437('│'), lifetime);
|
||||
self.request(x, y - 1, fg, bg, rltk::to_cp437('│'), lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParticleSpawnSystem {}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
BlocksTile, CombatStats, Consumable, Item, Monster, Name, Player, Position, ProvidesHealing, Rect, Renderable,
|
||||
Viewshed, MAPWIDTH,
|
||||
BlocksTile, CombatStats, Consumable, InflictsDamage, Item, Monster, Name, Player, Position, ProvidesHealing,
|
||||
Ranged, Rect, Renderable, Viewshed, AOE, MAPWIDTH,
|
||||
};
|
||||
use rltk::{RandomNumberGenerator, RGB};
|
||||
use specs::prelude::*;
|
||||
|
|
@ -45,12 +45,14 @@ pub fn random_item(ecs: &mut World, x: i32, y: i32) {
|
|||
match roll {
|
||||
1 => health_potion(ecs, x, y),
|
||||
2 => poison_potion(ecs, x, y),
|
||||
3 => magic_missile_scroll(ecs, x, y),
|
||||
4 => fireball_scroll(ecs, x, y),
|
||||
_ => weak_health_potion(ecs, x, y),
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_MONSTERS: i32 = 4;
|
||||
const MAX_ITEMS: i32 = 2;
|
||||
const MAX_ITEMS: i32 = 6;
|
||||
|
||||
fn monster<S: ToString>(ecs: &mut World, x: i32, y: i32, glyph: rltk::FontCharType, name: S) {
|
||||
ecs.create_entity()
|
||||
|
|
@ -138,7 +140,7 @@ fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
|||
.with(Name { name: "potion of health".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(ProvidesHealing { heal_amount: 12 })
|
||||
.with(ProvidesHealing { amount: 12 })
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +156,7 @@ fn weak_health_potion(ecs: &mut World, x: i32, y: i32) {
|
|||
.with(Name { name: "potion of lesser health".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(ProvidesHealing { heal_amount: 6 })
|
||||
.with(ProvidesHealing { amount: 6 })
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
@ -170,6 +172,41 @@ fn poison_potion(ecs: &mut World, x: i32, y: i32) {
|
|||
.with(Name { name: "potion of ... health?".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(ProvidesHealing { heal_amount: -12 })
|
||||
.with(ProvidesHealing { amount: -12 })
|
||||
.build();
|
||||
}
|
||||
|
||||
fn magic_missile_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::BLUE),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 2,
|
||||
})
|
||||
.with(Name { name: "scroll of magic missile".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(Ranged { range: 12 })
|
||||
.with(InflictsDamage { amount: 10 })
|
||||
.build();
|
||||
}
|
||||
|
||||
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 { name: "scroll of fireball".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(Ranged { range: 10 })
|
||||
.with(InflictsDamage { amount: 20 })
|
||||
.with(AOE { radius: 3 })
|
||||
.build();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue