healing potions

This commit is contained in:
Tyrel Souza 2021-08-31 15:14:42 -04:00
parent aee89fade7
commit c17b62985b
7 changed files with 161 additions and 11 deletions

View File

@ -69,3 +69,19 @@ impl FieldOfView {
} }
} }
} }
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ProvidesHealing {
pub amount: i32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ProvidesDungeonMap;
#[derive(Clone, PartialEq)]
pub struct Carried(pub Entity);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ActivateItem {
pub used_by: Entity,
pub item: Entity,
}

View File

@ -44,7 +44,7 @@ impl State {
map_builder map_builder
.monster_spawns .monster_spawns
.iter() .iter()
.for_each(|pos| spawn_monster(&mut ecs, &mut rng, *pos)); .for_each(|pos| spawn_entity(&mut ecs, &mut rng, *pos));
resources.insert(map_builder.map); resources.insert(map_builder.map);
resources.insert(Camera::new(map_builder.player_start)); resources.insert(Camera::new(map_builder.player_start));
@ -95,7 +95,7 @@ impl State {
map_builder map_builder
.monster_spawns .monster_spawns
.iter() .iter()
.for_each(|pos| spawn_monster(&mut self.ecs, &mut rng, *pos)); .for_each(|pos| spawn_entity(&mut self.ecs, &mut rng, *pos));
self.resources.insert(map_builder.map); self.resources.insert(map_builder.map);
self.resources.insert(Camera::new(map_builder.player_start)); self.resources.insert(Camera::new(map_builder.player_start));
self.resources.insert(TurnState::AwaitingInput); self.resources.insert(TurnState::AwaitingInput);

View File

@ -58,3 +58,36 @@ pub fn spawn_amulet_of_yala(ecs: &mut World, pos: Point) {
Name("Amulet of Yala".to_string()), Name("Amulet of Yala".to_string()),
)); ));
} }
pub fn spawn_healing_potion(ecs: &mut World, pos: Point) {
ecs.push((
Item,
pos,
Render {
color: ColorPair::new(WHITE, BLACK),
glyph: to_cp437('!'),
},
Name("Healing Potion".to_string()),
ProvidesHealing { amount: 6 },
));
}
pub fn spawn_magic_mapper(ecs: &mut World, pos: Point) {
ecs.push((
Item,
pos,
Render {
color: ColorPair::new(WHITE, BLACK),
glyph: to_cp437('{'),
},
Name("Magic Map".to_string()),
ProvidesDungeonMap {},
));
}
pub fn spawn_entity(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Point) {
let roll = rng.roll_dice(1, 6);
match roll {
1 => spawn_healing_potion(ecs, pos),
2 => spawn_magic_mapper(ecs, pos),
_ => spawn_monster(ecs, rng, pos),
}
}

View File

@ -3,6 +3,9 @@ use crate::prelude::*;
#[system] #[system]
#[read_component(Health)] #[read_component(Health)]
#[read_component(Player)] #[read_component(Player)]
#[read_component(Item)]
#[read_component(Carried)]
#[read_component(Name)]
pub fn hud(ecs: &SubWorld) { pub fn hud(ecs: &SubWorld) {
let mut health_query = <&Health>::query().filter(component::<Player>()); let mut health_query = <&Health>::query().filter(component::<Player>());
let player_health = health_query.iter(ecs).nth(0).unwrap(); let player_health = health_query.iter(ecs).nth(0).unwrap();
@ -22,5 +25,27 @@ pub fn hud(ecs: &SubWorld) {
format!(" Health: {}/{} ", player_health.current, player_health.max,), format!(" Health: {}/{} ", player_health.current, player_health.max,),
ColorPair::new(WHITE, RED), ColorPair::new(WHITE, RED),
); );
let player = <(Entity, &Player)>::query()
.iter(ecs)
.find_map(|(entity, _player)| Some(*entity))
.unwrap();
let mut item_query = <(&Item, &Name, &Carried)>::query();
let mut y = 3;
item_query
.iter(ecs)
.filter(|(_, _, carried)| carried.0 == player)
.for_each(|(_, name, _)| {
draw_batch.print(Point::new(3, y), format!("{} : {}", y - 2, &name.0));
y += 1;
});
if y > 3 {
draw_batch.print_color(
Point::new(3, 2),
"Items Carried",
ColorPair::new(YELLOW, BLACK),
);
}
draw_batch.submit(10000).expect("Batch Error"); draw_batch.submit(10000).expect("Batch Error");
} }

View File

@ -10,6 +10,7 @@ mod movement;
mod player_input; mod player_input;
mod random_move; mod random_move;
mod tooltips; mod tooltips;
mod use_items;
pub fn build_input_scheduler() -> Schedule { pub fn build_input_scheduler() -> Schedule {
Schedule::builder() Schedule::builder()
@ -24,6 +25,7 @@ pub fn build_input_scheduler() -> Schedule {
} }
pub fn build_player_scheduler() -> Schedule { pub fn build_player_scheduler() -> Schedule {
Schedule::builder() Schedule::builder()
.add_system(use_items::use_items_system())
.add_system(combat::combat_system()) .add_system(combat::combat_system())
.flush() .flush()
.add_system(movement::movement_system()) .add_system(movement::movement_system())
@ -43,6 +45,7 @@ pub fn build_monster_scheduler() -> Schedule {
.flush() .flush()
.add_system(fov::fov_system()) .add_system(fov::fov_system())
.flush() .flush()
.add_system(use_items::use_items_system())
.add_system(combat::combat_system()) .add_system(combat::combat_system())
.flush() .flush()
.add_system(movement::movement_system()) .add_system(movement::movement_system())

View File

@ -5,6 +5,8 @@ use crate::prelude::*;
#[read_component(Player)] #[read_component(Player)]
#[read_component(Enemy)] #[read_component(Enemy)]
#[write_component(Health)] #[write_component(Health)]
#[read_component(Item)]
#[read_component(Carried)]
pub fn player_input( pub fn player_input(
ecs: &mut SubWorld, ecs: &mut SubWorld,
commands: &mut CommandBuffer, commands: &mut CommandBuffer,
@ -18,6 +20,30 @@ pub fn player_input(
VirtualKeyCode::Right => Point::new(1, 0), VirtualKeyCode::Right => Point::new(1, 0),
VirtualKeyCode::Up => Point::new(0, -1), VirtualKeyCode::Up => Point::new(0, -1),
VirtualKeyCode::Down => Point::new(0, 1), VirtualKeyCode::Down => Point::new(0, 1),
VirtualKeyCode::G => {
let (player, player_pos) = players
.iter(ecs)
.find_map(|(entity, pos)| Some((*entity, *pos)))
.unwrap();
let mut items = <(Entity, &Item, &Point)>::query();
items
.iter(ecs)
.filter(|(_entity, _item, &item_pos)| item_pos == player_pos)
.for_each(|(entity, _item, _item_pos)| {
commands.remove_component::<Point>(*entity);
commands.add_component(*entity, Carried(player));
});
Point::new(0, 0)
}
VirtualKeyCode::Key1 => use_item(0, ecs, commands),
VirtualKeyCode::Key2 => use_item(1, ecs, commands),
VirtualKeyCode::Key3 => use_item(2, ecs, commands),
VirtualKeyCode::Key4 => use_item(3, ecs, commands),
VirtualKeyCode::Key5 => use_item(4, ecs, commands),
VirtualKeyCode::Key6 => use_item(5, ecs, commands),
VirtualKeyCode::Key7 => use_item(6, ecs, commands),
VirtualKeyCode::Key8 => use_item(7, ecs, commands),
VirtualKeyCode::Key9 => use_item(8, ecs, commands),
_ => Point::new(0, 0), _ => Point::new(0, 0),
}; };
let (player_entity, destination) = players let (player_entity, destination) = players
@ -57,15 +83,30 @@ pub fn player_input(
} }
} }
if !did_something {
if let Ok(mut health) = ecs
.entry_mut(player_entity)
.unwrap()
.get_component_mut::<Health>()
{
health.current = i32::min(health.max, health.current + 1);
}
}
*turn_state = TurnState::PlayerTurn; *turn_state = TurnState::PlayerTurn;
} }
} }
fn use_item(n: usize, ecs: &mut SubWorld, commands: &mut CommandBuffer) -> Point {
let player_entity = <(Entity, &Point)>::query()
.iter(ecs)
.find_map(|(entity, _player)| Some(*entity))
.unwrap();
let item_entity = <(Entity, &Item, &Carried)>::query()
.iter(ecs)
.filter(|(_, _, carried)| carried.0 == player_entity)
.enumerate()
.filter(|(item_count, (_, _, _))| *item_count == n)
.find_map(|(_, (item_entity, _, _))| Some(*item_entity));
if let Some(item_entity) = item_entity {
commands.push((
(),
ActivateItem {
used_by: player_entity,
item: item_entity,
},
));
}
Point::zero()
}

32
src/systems/use_items.rs Normal file
View File

@ -0,0 +1,32 @@
use crate::prelude::*;
#[system]
#[read_component(ActivateItem)]
#[read_component(ProvidesHealing)]
#[write_component(Health)]
#[read_component(ProvidesDungeonMap)]
pub fn use_items(ecs: &mut SubWorld, commands: &mut CommandBuffer, #[resource] map: &mut Map) {
let mut healing_to_apply = Vec::<(Entity, i32)>::new();
<(Entity, &ActivateItem)>::query()
.iter(ecs)
.for_each(|(entity, activate)| {
let item = ecs.entry_ref(activate.item);
if let Ok(item) = item {
if let Ok(healing) = item.get_component::<ProvidesHealing>() {
healing_to_apply.push((activate.used_by, healing.amount));
}
if let Ok(_mapper) = item.get_component::<ProvidesDungeonMap>() {
map.revealed_tiles.iter_mut().for_each(|t| *t = true);
}
}
commands.remove(activate.item);
commands.remove(*entity);
});
for heal in healing_to_apply.iter() {
if let Ok(mut target) = ecs.entry_mut(heal.0) {
if let Ok(health) = target.get_component_mut::<Health>() {
health.current = i32::min(health.max, health.current + heal.1);
}
}
}
}