Add a basic hidden trap mechanism
This commit is contained in:
parent
32874bf9f5
commit
804904dd4b
@ -199,6 +199,15 @@ pub struct ProvidesFood {}
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct MagicMapper {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Hidden {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct EntryTrigger {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct EntityMoved {}
|
||||
|
||||
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
|
||||
// Entity.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::components::{
|
||||
CombatStats, HungerClock, HungerState, InBackpack, Name, Player, Position, Viewshed,
|
||||
};
|
||||
use crate::{game_log::GameLog, rex_assets::RexAssets, Equipped, Map, RunState, State};
|
||||
use crate::{game_log::GameLog, rex_assets::RexAssets, Equipped, Hidden, Map, RunState, State};
|
||||
use rltk::{Point, Rltk, VirtualKeyCode, RGB};
|
||||
use specs::prelude::*;
|
||||
|
||||
@ -98,6 +98,7 @@ fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
||||
let map = ecs.fetch::<Map>();
|
||||
let names = ecs.read_storage::<Name>();
|
||||
let positions = ecs.read_storage::<Position>();
|
||||
let hidden = ecs.read_storage::<Hidden>();
|
||||
|
||||
let mouse_pos = ctx.mouse_pos();
|
||||
if mouse_pos.0 >= map.width || mouse_pos.1 >= map.height {
|
||||
@ -105,7 +106,7 @@ fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
||||
}
|
||||
let mut tooltip: Vec<String> = Vec::new();
|
||||
|
||||
for (name, position) in (&names, &positions).join() {
|
||||
for (name, position, _hidden) in (&names, &positions, !&hidden).join() {
|
||||
let idx = map.xy_idx(position.x, position.y);
|
||||
if position.x == mouse_pos.0 && position.y == mouse_pos.1 && map.visible_tiles[idx] {
|
||||
tooltip.push(name.name.to_string());
|
||||
|
13
src/main.rs
13
src/main.rs
@ -19,6 +19,7 @@ mod rect;
|
||||
mod rex_assets;
|
||||
pub mod saveload_system;
|
||||
mod spawner;
|
||||
mod trigger_system;
|
||||
mod visibility_system;
|
||||
|
||||
use crate::inventory_system::ItemRemoveSystem;
|
||||
@ -85,6 +86,9 @@ impl State {
|
||||
let mut mob = MonsterAI {};
|
||||
mob.run_now(&self.ecs);
|
||||
|
||||
let mut triggers = trigger_system::TriggerSystem {};
|
||||
triggers.run_now(&self.ecs);
|
||||
|
||||
let mut mapindex = MapIndexingSystem {};
|
||||
mapindex.run_now(&self.ecs);
|
||||
|
||||
@ -129,17 +133,19 @@ impl GameState for State {
|
||||
|
||||
match newrunstate {
|
||||
RunState::MainMenu { .. } => {}
|
||||
RunState::GameOver { .. } => {}
|
||||
_ => {
|
||||
// Draw the UI
|
||||
draw_map(&self.ecs, ctx);
|
||||
{
|
||||
let positions = self.ecs.read_storage::<Position>();
|
||||
let renderables = self.ecs.read_storage::<Renderable>();
|
||||
let hidden = self.ecs.read_storage::<Hidden>();
|
||||
let map = self.ecs.fetch::<Map>();
|
||||
|
||||
let mut data: Vec<_> = (&positions, &renderables).join().collect();
|
||||
let mut data: Vec<_> = (&positions, &renderables, !&hidden).join().collect();
|
||||
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
|
||||
for (pos, render) in data.iter() {
|
||||
for (pos, render, _hidden) in data.iter() {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
|
||||
if map.visible_tiles[idx] {
|
||||
@ -511,6 +517,9 @@ fn main() -> rltk::BError {
|
||||
HungerClock,
|
||||
ProvidesFood,
|
||||
MagicMapper,
|
||||
Hidden,
|
||||
EntryTrigger,
|
||||
EntityMoved,
|
||||
);
|
||||
|
||||
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::components::{Confusion, Monster, Position, Viewshed, WantsToMelee};
|
||||
use crate::{particle_system::ParticleBuilder, Map, RunState};
|
||||
use crate::{particle_system::ParticleBuilder, EntityMoved, Map, RunState};
|
||||
use rltk::{Point, RGB};
|
||||
use specs::prelude::*;
|
||||
|
||||
@ -19,6 +19,7 @@ impl<'a> System<'a> for MonsterAI {
|
||||
WriteStorage<'a, WantsToMelee>,
|
||||
WriteStorage<'a, Confusion>,
|
||||
WriteExpect<'a, ParticleBuilder>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
@ -34,6 +35,7 @@ impl<'a> System<'a> for MonsterAI {
|
||||
mut wants_to_melee,
|
||||
mut confused,
|
||||
mut particle_builder,
|
||||
mut entity_moved,
|
||||
) = data;
|
||||
|
||||
if *runstate != RunState::MonsterTurn {
|
||||
@ -91,6 +93,10 @@ impl<'a> System<'a> for MonsterAI {
|
||||
pos.x = path.steps[1] as i32 % map.width;
|
||||
pos.y = path.steps[1] as i32 / map.width;
|
||||
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to add EntityMoved flag to monster");
|
||||
|
||||
idx = map.xy_idx(pos.x, pos.y);
|
||||
map.blocked[idx] = true;
|
||||
viewshed.dirty = true;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::components::{
|
||||
CombatStats, HungerClock, HungerState, Item, Monster, Player, Position, Viewshed, WantsToMelee,
|
||||
WantsToPickupItem,
|
||||
CombatStats, EntityMoved, HungerClock, HungerState, Item, Monster, Player, Position, Viewshed,
|
||||
WantsToMelee, WantsToPickupItem,
|
||||
};
|
||||
use crate::{game_log::GameLog, Map, RunState, State, TileType};
|
||||
use rltk::{Point, Rltk, VirtualKeyCode};
|
||||
@ -15,6 +15,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
||||
let combat_stats = ecs.read_storage::<CombatStats>();
|
||||
let map = ecs.fetch::<Map>();
|
||||
let mut wants_to_melee = ecs.write_storage::<WantsToMelee>();
|
||||
let mut entity_moved = ecs.write_storage::<EntityMoved>();
|
||||
|
||||
for (entity, _player, pos, viewshed) in
|
||||
(&entities, &players, &mut positions, &mut viewsheds).join()
|
||||
@ -45,6 +46,9 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
||||
if !map.blocked[destination_idx] {
|
||||
pos.x = min(79, max(0, pos.x + delta_x));
|
||||
pos.y = min(49, max(0, pos.y + delta_y));
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Failed to add EntityMoved flag to player");
|
||||
|
||||
viewshed.dirty = true;
|
||||
let mut ppos = ecs.write_resource::<Point>();
|
||||
|
@ -79,6 +79,9 @@ pub fn save_game(ecs: &mut World) {
|
||||
HungerClock,
|
||||
ProvidesFood,
|
||||
MagicMapper,
|
||||
Hidden,
|
||||
EntryTrigger,
|
||||
EntityMoved,
|
||||
);
|
||||
}
|
||||
|
||||
@ -164,6 +167,9 @@ pub fn load_game(ecs: &mut World) {
|
||||
HungerClock,
|
||||
ProvidesFood,
|
||||
MagicMapper,
|
||||
Hidden,
|
||||
EntryTrigger,
|
||||
EntityMoved,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ fn room_table(map_depth: i32) -> RandomTable {
|
||||
.add("Tower Shield", map_depth - 1)
|
||||
.add("Rations", 10)
|
||||
.add("Magic Mapping Scroll", 2)
|
||||
.add("Bear Trap", 2)
|
||||
}
|
||||
|
||||
/// fills a room with stuff!
|
||||
@ -101,6 +102,7 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) {
|
||||
"Tower Shield" => tower_shield(ecs, x, y),
|
||||
"Rations" => rations(ecs, x, y),
|
||||
"Magic Mapping Scroll" => magic_mapping_scroll(ecs, x, y),
|
||||
"Bear Trap" => bear_trap(ecs, x, y),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -318,3 +320,20 @@ fn magic_mapping_scroll(ecs: &mut World, x: i32, y: i32) {
|
||||
.marked::<SimpleMarker<SerializeMe>>()
|
||||
.build();
|
||||
}
|
||||
|
||||
fn bear_trap(ecs: &mut World, x: i32, y: i32) {
|
||||
ecs.create_entity()
|
||||
.with(Position { x, y })
|
||||
.with(Renderable {
|
||||
glyph: rltk::to_cp437('^'),
|
||||
fg: RGB::named(rltk::RED),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 2,
|
||||
})
|
||||
.with(Name::from("Bear Trap"))
|
||||
.with(Hidden {})
|
||||
.with(EntryTrigger {})
|
||||
.with(InflictsDamage { damage: 6 })
|
||||
.marked::<SimpleMarker<SerializeMe>>()
|
||||
.build();
|
||||
}
|
||||
|
84
src/trigger_system.rs
Normal file
84
src/trigger_system.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use crate::components::{
|
||||
EntityMoved, EntryTrigger, Hidden, InflictsDamage, Name, Position, SufferDamage,
|
||||
};
|
||||
use crate::{game_log::GameLog, particle_system::ParticleBuilder, Map};
|
||||
use specs::prelude::*;
|
||||
|
||||
pub struct TriggerSystem {}
|
||||
|
||||
impl<'a> System<'a> for TriggerSystem {
|
||||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
ReadExpect<'a, Map>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
ReadStorage<'a, Position>,
|
||||
ReadStorage<'a, EntryTrigger>,
|
||||
WriteStorage<'a, Hidden>,
|
||||
ReadStorage<'a, Name>,
|
||||
Entities<'a>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
ReadStorage<'a, InflictsDamage>,
|
||||
WriteExpect<'a, ParticleBuilder>,
|
||||
WriteStorage<'a, SufferDamage>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
map,
|
||||
mut entity_moved,
|
||||
position,
|
||||
entry_trigger,
|
||||
mut hidden,
|
||||
names,
|
||||
entities,
|
||||
mut log,
|
||||
inflicts_damage,
|
||||
mut particle_builder,
|
||||
mut inflict_damage,
|
||||
) = data;
|
||||
|
||||
// Iterate the entities that moved and their final position
|
||||
for (entity, mut _entity_moved, pos) in (&entities, &mut entity_moved, &position).join() {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
|
||||
for entity_id in map.tile_content[idx].iter() {
|
||||
// Do not bother to check yourself for being a trap!
|
||||
if entity != *entity_id {
|
||||
match entry_trigger.get(*entity_id) {
|
||||
None => {}
|
||||
Some(_trigger) => {
|
||||
// We triggered it
|
||||
if let Some(name) = names.get(*entity_id) {
|
||||
log.append(format!("{} triggers!", &name.name));
|
||||
}
|
||||
|
||||
// The trap is no longer hidden
|
||||
hidden.remove(*entity_id);
|
||||
|
||||
// If the trap is damage inflicting, do it
|
||||
if let Some(damage) = inflicts_damage.get(*entity_id) {
|
||||
particle_builder.request(
|
||||
pos.x,
|
||||
pos.y,
|
||||
rltk::RGB::named(rltk::ORANGE),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('‼'),
|
||||
200.0,
|
||||
);
|
||||
|
||||
SufferDamage::new_damage(
|
||||
&mut inflict_damage,
|
||||
entity,
|
||||
damage.damage,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all entity movement markers
|
||||
entity_moved.clear();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user