Added ranged items and spawn menu
This commit is contained in:
parent
e1459cc27b
commit
70c46ab9d2
@ -42,6 +42,8 @@ pub enum RunState {
|
||||
MonsterTurn,
|
||||
ShowInventory,
|
||||
ShowDropItem,
|
||||
ShowSpawnMenu,
|
||||
ShowTargeting { range : i32, item : Entity},
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
@ -100,6 +102,7 @@ pub struct WantsToPickupItem {
|
||||
#[derive(Component, Debug)]
|
||||
pub struct WantsToUseItem {
|
||||
pub item: Entity,
|
||||
pub target: Option<rltk::Point>
|
||||
}
|
||||
#[derive(Component, Debug, Clone)]
|
||||
pub struct WantsToDropItem {
|
||||
@ -108,3 +111,23 @@ pub struct WantsToDropItem {
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Consumable {}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Ranged {
|
||||
pub range : i32
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct InflictsDamage {
|
||||
pub damage : i32
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct AreaOfEffect {
|
||||
pub radius : i32
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Confusion {
|
||||
pub turns : i32
|
||||
}
|
||||
93
src/gui.rs
93
src/gui.rs
@ -1,8 +1,7 @@
|
||||
use rltk::{RGB, Rltk, Point, VirtualKeyCode};
|
||||
use specs::prelude::*;
|
||||
use crate::{InBackpack, player};
|
||||
|
||||
use super::{CombatStats, Player, GameLog, Map, Name, Position, State};
|
||||
use super::{CombatStats, Player, GameLog, Map, Name, Position, State, InBackpack, Viewshed, spawner};
|
||||
|
||||
fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
||||
let map = ecs.fetch::<Map>();
|
||||
@ -131,6 +130,54 @@ pub fn show_inventory(gs : &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Opti
|
||||
|
||||
}
|
||||
|
||||
pub fn spawn_item(gs: &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
||||
let mut item_names : Vec<String> = Vec::new();
|
||||
item_names.push("Health Potion".to_string());
|
||||
item_names.push("Magic Missle Scroll".to_string());
|
||||
item_names.push("Fireball Scroll".to_string());
|
||||
item_names.push("Confusion Scroll".to_string());
|
||||
|
||||
|
||||
let count = item_names.len();
|
||||
let mut y : i32 = (25 - (count / 2)) as i32;
|
||||
ctx.draw_box(15, y - 2 , 31, (count + 3) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
||||
ctx.print_color(18, y - 2, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Spawn which item?");
|
||||
ctx.print_color(18, y + count as i32 + 1, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Escape to cancel");
|
||||
|
||||
let mut spawnable : Vec<String> = Vec::new();
|
||||
let mut j = 0;
|
||||
for item in item_names.iter() {
|
||||
ctx.set(17, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), rltk::to_cp437('('));
|
||||
ctx.set(18, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + j as rltk::FontCharType);
|
||||
ctx.set(19, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), rltk::to_cp437(')'));
|
||||
|
||||
ctx.print(21, y, &item.to_string());
|
||||
spawnable.push(item.to_string());
|
||||
y+=1;
|
||||
j+=1;
|
||||
}
|
||||
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => {
|
||||
match (key) {
|
||||
VirtualKeyCode::Escape => { (ItemMenuResult::Cancel, None)},
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
let mouse_pos = ctx.mouse_pos();
|
||||
match selection {
|
||||
0 => {spawner::health_potion(&mut gs.ecs, mouse_pos.0, mouse_pos.1)},
|
||||
1 => {spawner::magic_missile_scroll(&mut gs.ecs, mouse_pos.0, mouse_pos.1)},
|
||||
2 => {spawner::fireball_scroll(&mut gs.ecs, mouse_pos.0, mouse_pos.1)},
|
||||
_ => {spawner::confusion_scroll(&mut gs.ecs, mouse_pos.0, mouse_pos.1)},
|
||||
}
|
||||
(ItemMenuResult::Cancel, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_item_menu(gs: &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
||||
let player_entity = gs.ecs.fetch::<Entity>();
|
||||
let names = gs.ecs.read_storage::<Name>();
|
||||
@ -175,3 +222,45 @@ pub fn drop_item_menu(gs: &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Optio
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn ranged_target(gs: &mut State, ctx : &mut Rltk, range: 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 target cells
|
||||
let mut available_cells = Vec::new();
|
||||
let visible = viewsheds.get(*player_entity);
|
||||
if let Some(visible) = visible {
|
||||
// We have a viewshed component
|
||||
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 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 {
|
||||
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)
|
||||
}
|
||||
@ -1,8 +1,10 @@
|
||||
use specs::prelude::*;
|
||||
|
||||
use crate::player;
|
||||
|
||||
use super::{
|
||||
gamelog::GameLog, CombatStats, Consumable, InBackpack, Name, Position, ProvidesHealing,
|
||||
WantsToDropItem, WantsToPickupItem, WantsToUseItem,
|
||||
WantsToDropItem, WantsToPickupItem, WantsToUseItem, InflictsDamage, Map, SufferDamage, AreaOfEffect, Confusion
|
||||
};
|
||||
|
||||
pub struct ItemCollectionSystem {}
|
||||
@ -51,37 +53,128 @@ 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>,
|
||||
ReadStorage<'a, InflictsDamage>,
|
||||
WriteStorage<'a, SufferDamage>,
|
||||
ReadStorage<'a, AreaOfEffect>,
|
||||
WriteStorage<'a, Confusion>
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
player_entity,
|
||||
mut gamelog,
|
||||
map,
|
||||
entities,
|
||||
mut wants_use,
|
||||
names,
|
||||
consumables,
|
||||
healing,
|
||||
mut combat_stats,
|
||||
inflict_damage,
|
||||
mut suffer_damage,
|
||||
aoe,
|
||||
mut confused,
|
||||
) = data;
|
||||
|
||||
for (entity, useitem) in (&entities, &wants_use).join() {
|
||||
for (entity, useitem,) in (&entities, &wants_use).join() {
|
||||
let mut used_item = true;
|
||||
|
||||
|
||||
|
||||
let mut targets : Vec<Entity> = Vec::new();
|
||||
match useitem.target {
|
||||
None => {targets.push( *player_entity )}
|
||||
Some(target) => {
|
||||
let area_effect = aoe.get(useitem.item);
|
||||
match area_effect {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut add_confusion = Vec::new();
|
||||
{
|
||||
let causes_confusion = confused.get(useitem.item);
|
||||
match causes_confusion {
|
||||
None => {}
|
||||
Some(confusion) => {
|
||||
used_item = false;
|
||||
for mob in targets.iter() {
|
||||
add_confusion.push((*mob, confusion.turns));
|
||||
if entity == *player_entity {
|
||||
let mob_name = names.get(*mob).unwrap();
|
||||
let item_name = names.get(useitem.item).unwrap();
|
||||
gamelog.entries.push(format!("You use {} on {}, confusing them", item_name.name, mob_name.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for mob in add_confusion.iter() {
|
||||
confused.insert(mob.0, Confusion{ turns: mob.1 }).expect("Unable to insert status");
|
||||
}
|
||||
|
||||
let item_heals = healing.get(useitem.item);
|
||||
match item_heals {
|
||||
None => {}
|
||||
Some(healer) => {
|
||||
let stats = combat_stats.get_mut(*player_entity);
|
||||
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!("You use the {}, healing {} hp.", names.get(useitem.item).unwrap().name, healer.heal_amount));
|
||||
}
|
||||
}
|
||||
}
|
||||
let consumable = consumables.get(useitem.item);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let item_damages = inflict_damage.get(useitem.item);
|
||||
match item_damages {
|
||||
None => {}
|
||||
Some(damage) => {
|
||||
used_item = false;
|
||||
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();
|
||||
let item_name = names.get(useitem.item).unwrap();
|
||||
gamelog.entries.push(format!("You use {} on {}, inflicting {} hp.", item_name.name, mob_name.name, damage.damage));
|
||||
}
|
||||
used_item = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let consumable = consumables.get(useitem.item);
|
||||
match consumable {
|
||||
None => {}
|
||||
Some(_) => {
|
||||
|
||||
47
src/main.rs
47
src/main.rs
@ -60,8 +60,8 @@ impl State {
|
||||
pickup.run_now(&self.ecs);
|
||||
let mut drop_items = ItemDropSystem {};
|
||||
drop_items.run_now(&self.ecs);
|
||||
let mut potions = ItemUseSystem {};
|
||||
potions.run_now(&self.ecs);
|
||||
let mut item_use = ItemUseSystem {};
|
||||
item_use.run_now(&self.ecs);
|
||||
self.ecs.maintain();
|
||||
}
|
||||
}
|
||||
@ -127,17 +127,25 @@ impl GameState for State {
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
let mut intent = self.ecs.write_storage::<WantsToDrinkPotion>();
|
||||
let is_ranged = self.ecs.read_storage::<Ranged>();
|
||||
let is_item_ranged = is_ranged.get(item_entity);
|
||||
if let Some(is_item_ranged) = is_item_ranged {
|
||||
newrunstate = RunState::ShowTargeting { range: is_item_ranged.range, item: item_entity };
|
||||
} else {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent
|
||||
.insert(
|
||||
*self.ecs.fetch::<Entity>(),
|
||||
WantsToDrinkPotion {
|
||||
potion: item_entity,
|
||||
WantsToUseItem {
|
||||
item: item_entity,
|
||||
target: None,
|
||||
},
|
||||
)
|
||||
.expect("Failed to insert intent");
|
||||
newrunstate = RunState::PlayerTurn;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowDropItem => {
|
||||
@ -176,6 +184,28 @@ impl GameState for State {
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowTargeting { range, item } => {
|
||||
let result = gui::ranged_target(self, ctx, range);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => newrunstate = 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");
|
||||
newrunstate = RunState::PlayerTurn;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
RunState::ShowSpawnMenu => {
|
||||
let result = gui::spawn_item(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {newrunstate = RunState::AwaitingInput;}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -209,7 +239,12 @@ fn main() -> rltk::BError {
|
||||
gs.ecs.register::<InBackpack>();
|
||||
gs.ecs.register::<WantsToPickupItem>();
|
||||
gs.ecs.register::<WantsToDropItem>();
|
||||
gs.ecs.register::<WantsToDrinkPotion>();
|
||||
gs.ecs.register::<WantsToUseItem>();
|
||||
gs.ecs.register::<Consumable>();
|
||||
gs.ecs.register::<Ranged>();
|
||||
gs.ecs.register::<InflictsDamage>();
|
||||
gs.ecs.register::<AreaOfEffect>();
|
||||
gs.ecs.register::<Confusion>();
|
||||
|
||||
let map = Map::new_map_rooms_and_corridors();
|
||||
let (player_x, player_y) = map.rooms[0].center();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::{Map, Monster, Position, Viewshed, WantsToMelee, RunState};
|
||||
use super::{Map, Monster, Position, Viewshed, WantsToMelee, RunState, Confusion};
|
||||
use rltk::{Point};
|
||||
use specs::prelude::*;
|
||||
|
||||
@ -16,15 +16,28 @@ impl<'a> System<'a> for MonsterAI {
|
||||
ReadStorage<'a, Monster>,
|
||||
WriteStorage<'a, Position>,
|
||||
WriteStorage<'a, WantsToMelee>,
|
||||
WriteStorage<'a, Confusion>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (mut map, player_pos, player_entity, runstate, entities, mut viewshed, monster, mut position, mut wants_to_melee) = data;
|
||||
let (mut map, player_pos, player_entity, runstate, entities, mut viewshed, monster, mut position, mut wants_to_melee, mut confused) = data;
|
||||
|
||||
if *runstate != RunState::MonsterTurn { return; }
|
||||
|
||||
for (entity, mut viewshed, _monster, mut pos) in (&entities, &mut viewshed, &monster, &mut position).join()
|
||||
{
|
||||
let mut can_act = true;
|
||||
|
||||
let is_confused = confused.get_mut(entity);
|
||||
if let Some(i_am_confused) = is_confused {
|
||||
i_am_confused.turns -= 1;
|
||||
if i_am_confused.turns < 1 {
|
||||
confused.remove(entity);
|
||||
}
|
||||
can_act = false;
|
||||
}
|
||||
|
||||
if can_act {
|
||||
if viewshed.visible_tiles.contains(&*player_pos) {
|
||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(Point::new(pos.x, pos.y), *player_pos);
|
||||
if distance < 1.5 {
|
||||
@ -50,5 +63,8 @@ impl<'a> System<'a> for MonsterAI {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats, WantsToMelee, Item, GameLog, WantsToPickupItem};
|
||||
use crate::spawn_item;
|
||||
|
||||
use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats, WantsToMelee, Item, GameLog, WantsToPickupItem, spawner};
|
||||
use rltk::{Point, Rltk, VirtualKeyCode};
|
||||
use specs::prelude::*;
|
||||
use std::cmp::{max, min};
|
||||
@ -80,13 +82,19 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
||||
try_move_player(0, 1, &mut gs.ecs)
|
||||
}
|
||||
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::Y => {try_move_player(1, -1, &mut gs.ecs)}
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::U => {try_move_player(-1, -1, &mut gs.ecs)}
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::U => {try_move_player(1, -1, &mut gs.ecs)}
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => {try_move_player(-1, -1, &mut gs.ecs)}
|
||||
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => {try_move_player(1, 1, &mut gs.ecs)}
|
||||
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => {try_move_player(-1, 1, &mut gs.ecs)}
|
||||
VirtualKeyCode::G => get_item(&mut gs.ecs),
|
||||
VirtualKeyCode::I => return RunState::ShowInventory,
|
||||
VirtualKeyCode::D => return RunState::ShowDropItem,
|
||||
VirtualKeyCode::Minus => {return RunState::ShowSpawnMenu}
|
||||
VirtualKeyCode::NumpadAdd => {
|
||||
let mouse_pos = ctx.mouse_pos();
|
||||
spawner::health_potion(&mut gs.ecs, mouse_pos.0, mouse_pos.1);
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
_ => return RunState::AwaitingInput,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use crate::MAPWIDTH;
|
||||
use crate::AreaOfEffect;
|
||||
|
||||
use super::{
|
||||
BlocksTile, CombatStats, Item, Monster, Name, Player, Position, ProvidesHealing, Rect,
|
||||
Renderable, Viewshed,
|
||||
Renderable, Viewshed, InflictsDamage, MAPWIDTH, Ranged, Consumable, Confusion
|
||||
};
|
||||
use rltk::{RandomNumberGenerator, RGB};
|
||||
use specs::prelude::*;
|
||||
@ -53,6 +53,20 @@ pub fn random_monster(ecs: &mut World, x: i32, y: i32) {
|
||||
}
|
||||
}
|
||||
|
||||
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, 4);
|
||||
}
|
||||
match roll {
|
||||
1 => { health_potion(ecs, x, y) }
|
||||
2 => { fireball_scroll(ecs, x, y) }
|
||||
3 => { confusion_scroll(ecs, x, y)}
|
||||
_ => { magic_missile_scroll(ecs, x, y) }
|
||||
}
|
||||
}
|
||||
|
||||
fn orc(ecs: &mut World, x: i32, y: i32) {
|
||||
monster(ecs, x, y, rltk::to_cp437('o'), "Orc");
|
||||
}
|
||||
@ -133,11 +147,11 @@ pub fn spawn_room(ecs: &mut World, room: &Rect) {
|
||||
for idx in item_spawn_points.iter() {
|
||||
let x = *idx % MAPWIDTH;
|
||||
let y = *idx / MAPWIDTH;
|
||||
health_potion(ecs, x as i32, y as i32);
|
||||
random_item(ecs, x as i32, y as i32);
|
||||
}
|
||||
}
|
||||
|
||||
fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
||||
pub fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
||||
ecs.create_entity()
|
||||
.with(Position { x, y })
|
||||
.with(Renderable {
|
||||
@ -150,6 +164,59 @@ fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
||||
name: "Health Potion".to_string(),
|
||||
})
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(ProvidesHealing { heal_amount: 8 })
|
||||
.build();
|
||||
}
|
||||
|
||||
pub 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::CYAN),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 2
|
||||
})
|
||||
.with(Name{ name: "Magic Missile Scroll".to_string() })
|
||||
.with(Item{})
|
||||
.with(Consumable{})
|
||||
.with(Ranged{ range: 6 })
|
||||
.with(InflictsDamage{ damage: 8 })
|
||||
.build();
|
||||
}
|
||||
|
||||
pub 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: "Fireball Scroll".to_string() })
|
||||
.with(Item {})
|
||||
.with(Consumable {})
|
||||
.with(Ranged { range: 6 })
|
||||
.with(InflictsDamage{ damage: 20 })
|
||||
.with(AreaOfEffect { radius: 3 })
|
||||
.build();
|
||||
}
|
||||
|
||||
pub fn confusion_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::PINK),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 2
|
||||
})
|
||||
.with(Name{ name: "Confusion Scroll".to_string() })
|
||||
.with(Item{})
|
||||
.with(Consumable{})
|
||||
.with(Ranged{ range: 6 })
|
||||
.with(Confusion{ turns: 4})
|
||||
.build();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user