Add traps
This commit is contained in:
parent
835a416013
commit
7c67291031
@ -217,3 +217,14 @@ pub struct ProvidesFood {}
|
|||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct MagicMapper {}
|
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 {}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct SingleActivation {}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::components::{CombatStats, Player, SufferDamage};
|
use crate::components::{CombatStats, Player, SufferDamage};
|
||||||
|
45
src/gui.rs
45
src/gui.rs
@ -1,15 +1,15 @@
|
|||||||
use rltk::{Point, VirtualKeyCode};
|
|
||||||
use rltk::RGB;
|
|
||||||
use rltk::Rltk;
|
use rltk::Rltk;
|
||||||
|
use rltk::RGB;
|
||||||
|
use rltk::{Point, VirtualKeyCode};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{CombatStats, InBackpack, RunState, State, Viewshed};
|
|
||||||
use crate::{Equipped, Map};
|
|
||||||
use crate::{HungerClock, HungerState, Name};
|
|
||||||
use crate::gamelog::GameLog;
|
use crate::gamelog::GameLog;
|
||||||
|
use crate::rex_assets::RexAssets;
|
||||||
use crate::Player;
|
use crate::Player;
|
||||||
use crate::Position;
|
use crate::Position;
|
||||||
use crate::rex_assets::RexAssets;
|
use crate::{CombatStats, Hidden, InBackpack, RunState, State, Viewshed};
|
||||||
|
use crate::{Equipped, Map};
|
||||||
|
use crate::{HungerClock, HungerState, Name};
|
||||||
|
|
||||||
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
ctx.draw_box(
|
ctx.draw_box(
|
||||||
@ -100,6 +100,7 @@ fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
|||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let names = ecs.read_storage::<Name>();
|
let names = ecs.read_storage::<Name>();
|
||||||
let positions = ecs.read_storage::<Position>();
|
let positions = ecs.read_storage::<Position>();
|
||||||
|
let hidden = ecs.read_storage::<Hidden>();
|
||||||
|
|
||||||
let mouse_pos = ctx.mouse_pos();
|
let mouse_pos = ctx.mouse_pos();
|
||||||
if mouse_pos.0 >= map.width || mouse_pos.1 >= map.height {
|
if mouse_pos.0 >= map.width || mouse_pos.1 >= map.height {
|
||||||
@ -107,7 +108,7 @@ fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut tooltip: Vec<String> = Vec::new();
|
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);
|
let idx = map.xy_idx(position.x, position.y);
|
||||||
if position.x == mouse_pos.0 && position.y == mouse_pos.1 && map.visible_tiles[idx] {
|
if position.x == mouse_pos.0 && position.y == mouse_pos.1 && map.visible_tiles[idx] {
|
||||||
tooltip.push(name.name.to_string());
|
tooltip.push(name.name.to_string());
|
||||||
@ -446,10 +447,32 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||||||
let assets = gs.ecs.fetch::<RexAssets>();
|
let assets = gs.ecs.fetch::<RexAssets>();
|
||||||
ctx.render_xp_sprite(&assets.menu, 0, 0);
|
ctx.render_xp_sprite(&assets.menu, 0, 0);
|
||||||
|
|
||||||
ctx.draw_box_double(24, 18, 31, 10, RGB::named(rltk::WHEAT), RGB::named(rltk::BLACK));
|
ctx.draw_box_double(
|
||||||
ctx.print_color_centered(20, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Rust Roguelike Tutorial");
|
24,
|
||||||
ctx.print_color_centered(21, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "by Herbert Wolverson");
|
18,
|
||||||
ctx.print_color_centered(22, RGB::named(rltk::GRAY), RGB::named(rltk::BLACK), "Use Up/Down Arrows and Enter");
|
31,
|
||||||
|
10,
|
||||||
|
RGB::named(rltk::WHEAT),
|
||||||
|
RGB::named(rltk::BLACK),
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
20,
|
||||||
|
RGB::named(rltk::YELLOW),
|
||||||
|
RGB::named(rltk::BLACK),
|
||||||
|
"Rust Roguelike Tutorial",
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
21,
|
||||||
|
RGB::named(rltk::CYAN),
|
||||||
|
RGB::named(rltk::BLACK),
|
||||||
|
"by Herbert Wolverson",
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
22,
|
||||||
|
RGB::named(rltk::GRAY),
|
||||||
|
RGB::named(rltk::BLACK),
|
||||||
|
"Use Up/Down Arrows and Enter",
|
||||||
|
);
|
||||||
|
|
||||||
let mut y = 24;
|
let mut y = 24;
|
||||||
if let RunState::MainMenu {
|
if let RunState::MainMenu {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
use crate::{GameLog, Heals, HungerClock, HungerState, RunState, SufferDamage};
|
use crate::{GameLog, Heals, HungerClock, HungerState, RunState, SufferDamage};
|
||||||
|
|
||||||
pub struct HungerSystem {}
|
pub struct HungerSystem {}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{AreaOfEffect, CombatStats, Confusion, Consumable, Equippable, Equipped, HungerClock, HungerState, InBackpack, InflictsDamage, MagicMapper, Map, Name, Position, ProvidesFood, ProvidesHealing, Ranged, RunState, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem};
|
|
||||||
use crate::gamelog::GameLog;
|
use crate::gamelog::GameLog;
|
||||||
use crate::particle_system::ParticleBuilder;
|
use crate::particle_system::ParticleBuilder;
|
||||||
|
use crate::{
|
||||||
|
AreaOfEffect, CombatStats, Confusion, Consumable, Equippable, Equipped, HungerClock,
|
||||||
|
HungerState, InBackpack, InflictsDamage, MagicMapper, Map, Name, Position, ProvidesFood,
|
||||||
|
ProvidesHealing, Ranged, RunState, SufferDamage, WantsToDropItem, WantsToPickupItem,
|
||||||
|
WantsToRemoveItem, WantsToUseItem,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct ItemCollectionSystem {}
|
pub struct ItemCollectionSystem {}
|
||||||
|
|
||||||
@ -71,7 +76,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
ReadStorage<'a, ProvidesFood>,
|
ReadStorage<'a, ProvidesFood>,
|
||||||
WriteStorage<'a, HungerClock>,
|
WriteStorage<'a, HungerClock>,
|
||||||
ReadStorage<'a, MagicMapper>,
|
ReadStorage<'a, MagicMapper>,
|
||||||
WriteExpect<'a, RunState>
|
WriteExpect<'a, RunState>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
@ -98,7 +103,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
provides_food,
|
provides_food,
|
||||||
mut hunger_clocks,
|
mut hunger_clocks,
|
||||||
magic_mapper,
|
magic_mapper,
|
||||||
mut run_state
|
mut run_state,
|
||||||
) = data;
|
) = data;
|
||||||
|
|
||||||
for (entity, use_item) in (&entities, &wants_use).join() {
|
for (entity, use_item) in (&entities, &wants_use).join() {
|
||||||
@ -144,8 +149,10 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
|
|
||||||
if let Some(_mapper) = magic_mapper.get(use_item.item) {
|
if let Some(_mapper) = magic_mapper.get(use_item.item) {
|
||||||
used_item = true;
|
used_item = true;
|
||||||
game_log.entries.push("The map is revealed to you!".to_string());
|
game_log
|
||||||
*run_state = RunState::MagicMapReveal {row: 0};
|
.entries
|
||||||
|
.push("The map is revealed to you!".to_string());
|
||||||
|
*run_state = RunState::MagicMapReveal { row: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_item_edible) = provides_food.get(use_item.item) {
|
if let Some(_item_edible) = provides_food.get(use_item.item) {
|
||||||
|
36
src/main.rs
36
src/main.rs
@ -20,6 +20,7 @@ use crate::inventory_system::{
|
|||||||
ItemCollectionSystem, ItemDropSystem, ItemRemoveSystem, ItemUseSystem,
|
ItemCollectionSystem, ItemDropSystem, ItemRemoveSystem, ItemUseSystem,
|
||||||
};
|
};
|
||||||
use crate::particle_system::ParticleSpawnSystem;
|
use crate::particle_system::ParticleSpawnSystem;
|
||||||
|
use crate::trigger_system::TriggerSystem;
|
||||||
|
|
||||||
mod components;
|
mod components;
|
||||||
mod damage_system;
|
mod damage_system;
|
||||||
@ -36,10 +37,11 @@ mod particle_system;
|
|||||||
mod player;
|
mod player;
|
||||||
mod random_table;
|
mod random_table;
|
||||||
mod rect;
|
mod rect;
|
||||||
|
mod rex_assets;
|
||||||
mod save_load_system;
|
mod save_load_system;
|
||||||
mod spawner;
|
mod spawner;
|
||||||
mod visibility_system;
|
mod visibility_system;
|
||||||
mod rex_assets;
|
mod trigger_system;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum RunState {
|
pub enum RunState {
|
||||||
@ -60,7 +62,9 @@ pub enum RunState {
|
|||||||
NextLevel,
|
NextLevel,
|
||||||
ShowRemoveItem,
|
ShowRemoveItem,
|
||||||
GameOver,
|
GameOver,
|
||||||
MagicMapReveal { row: i32 },
|
MagicMapReveal {
|
||||||
|
row: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
@ -210,6 +214,9 @@ impl State {
|
|||||||
let mut mob = MonsterAI {};
|
let mut mob = MonsterAI {};
|
||||||
mob.run_now(&self.ecs);
|
mob.run_now(&self.ecs);
|
||||||
|
|
||||||
|
let mut trigger = TriggerSystem {};
|
||||||
|
trigger.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut map_index = MapIndexingSystem {};
|
let mut map_index = MapIndexingSystem {};
|
||||||
map_index.run_now(&self.ecs);
|
map_index.run_now(&self.ecs);
|
||||||
|
|
||||||
@ -262,11 +269,14 @@ impl GameState for State {
|
|||||||
|
|
||||||
let positions = self.ecs.read_storage::<Position>();
|
let positions = self.ecs.read_storage::<Position>();
|
||||||
let renderables = self.ecs.read_storage::<Renderable>();
|
let renderables = self.ecs.read_storage::<Renderable>();
|
||||||
|
let hidden = self.ecs.read_storage::<Hidden>();
|
||||||
let map = self.ecs.fetch::<Map>();
|
let map = self.ecs.fetch::<Map>();
|
||||||
|
|
||||||
let mut data = (&positions, &renderables).join().collect::<Vec<_>>();
|
let mut data = (&positions, &renderables, !&hidden)
|
||||||
|
.join()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
|
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);
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
if map.visible_tiles[idx] {
|
if map.visible_tiles[idx] {
|
||||||
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
|
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
|
||||||
@ -287,8 +297,12 @@ impl GameState for State {
|
|||||||
self.run_systems();
|
self.run_systems();
|
||||||
new_run_state = RunState::MonsterTurn;
|
new_run_state = RunState::MonsterTurn;
|
||||||
match *self.ecs.fetch::<RunState>() {
|
match *self.ecs.fetch::<RunState>() {
|
||||||
RunState::MagicMapReveal { .. } => { new_run_state = RunState::MagicMapReveal { row: 0 } }
|
RunState::MagicMapReveal { .. } => {
|
||||||
_ => { new_run_state = RunState::MonsterTurn; }
|
new_run_state = RunState::MagicMapReveal { row: 0 }
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
new_run_state = RunState::MonsterTurn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::MonsterTurn => {
|
RunState::MonsterTurn => {
|
||||||
@ -422,9 +436,7 @@ impl GameState for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::MagicMapReveal {
|
RunState::MagicMapReveal { row } => {
|
||||||
row
|
|
||||||
} => {
|
|
||||||
let mut map = self.ecs.fetch_mut::<Map>();
|
let mut map = self.ecs.fetch_mut::<Map>();
|
||||||
for x in 0..MAP_WIDTH {
|
for x in 0..MAP_WIDTH {
|
||||||
let idx = map.xy_idx(x as i32, row);
|
let idx = map.xy_idx(x as i32, row);
|
||||||
@ -433,7 +445,7 @@ impl GameState for State {
|
|||||||
if row as usize == MAP_HEIGHT - 1 {
|
if row as usize == MAP_HEIGHT - 1 {
|
||||||
new_run_state = RunState::MonsterTurn;
|
new_run_state = RunState::MonsterTurn;
|
||||||
} else {
|
} else {
|
||||||
new_run_state = RunState::MagicMapReveal {row: row + 1}
|
new_run_state = RunState::MagicMapReveal { row: row + 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,6 +505,10 @@ fn main() -> rltk::BError {
|
|||||||
gs.ecs.register::<Heals>();
|
gs.ecs.register::<Heals>();
|
||||||
gs.ecs.register::<ProvidesFood>();
|
gs.ecs.register::<ProvidesFood>();
|
||||||
gs.ecs.register::<MagicMapper>();
|
gs.ecs.register::<MagicMapper>();
|
||||||
|
gs.ecs.register::<Hidden>();
|
||||||
|
gs.ecs.register::<EntryTrigger>();
|
||||||
|
gs.ecs.register::<EntityMoved>();
|
||||||
|
gs.ecs.register::<SingleActivation>();
|
||||||
|
|
||||||
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::particle_system::ParticleBuilder;
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::{Monster, Position, Viewshed, WantsToMelee},
|
components::{Monster, Position, Viewshed, WantsToMelee},
|
||||||
map::Map,
|
map::Map,
|
||||||
Confusion, RunState,
|
Confusion, EntityMoved, RunState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct MonsterAI {}
|
pub struct MonsterAI {}
|
||||||
@ -24,6 +24,7 @@ impl<'a> System<'a> for MonsterAI {
|
|||||||
WriteStorage<'a, WantsToMelee>,
|
WriteStorage<'a, WantsToMelee>,
|
||||||
WriteStorage<'a, Confusion>,
|
WriteStorage<'a, Confusion>,
|
||||||
WriteExpect<'a, ParticleBuilder>,
|
WriteExpect<'a, ParticleBuilder>,
|
||||||
|
WriteStorage<'a, EntityMoved>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
@ -39,6 +40,7 @@ impl<'a> System<'a> for MonsterAI {
|
|||||||
mut wants_to_melee,
|
mut wants_to_melee,
|
||||||
mut confused,
|
mut confused,
|
||||||
mut particle_builder,
|
mut particle_builder,
|
||||||
|
mut entity_moved,
|
||||||
) = data;
|
) = data;
|
||||||
|
|
||||||
if *runstate != RunState::MonsterTurn {
|
if *runstate != RunState::MonsterTurn {
|
||||||
@ -96,6 +98,10 @@ impl<'a> System<'a> for MonsterAI {
|
|||||||
idx = map.xy_idx(pos.x, pos.y);
|
idx = map.xy_idx(pos.x, pos.y);
|
||||||
map.blocked[idx] = true;
|
map.blocked[idx] = true;
|
||||||
viewshed.dirty = true;
|
viewshed.dirty = true;
|
||||||
|
|
||||||
|
entity_moved
|
||||||
|
.insert(entity, EntityMoved {})
|
||||||
|
.expect("Unable to insert entity moved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@ use crate::gamelog::GameLog;
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::{CombatStats, Player, Position, Viewshed, WantsToMelee},
|
components::{CombatStats, Player, Position, Viewshed, WantsToMelee},
|
||||||
map::Map,
|
map::Map,
|
||||||
HungerClock, HungerState, Item, Monster, RunState, State, TileType, WantsToPickupItem,
|
EntityMoved, HungerClock, HungerState, Item, Monster, RunState, State, TileType,
|
||||||
|
WantsToPickupItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
||||||
@ -19,6 +20,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
|||||||
let entities = ecs.entities();
|
let entities = ecs.entities();
|
||||||
let mut wants_to_melee = ecs.write_storage::<WantsToMelee>();
|
let mut wants_to_melee = ecs.write_storage::<WantsToMelee>();
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
|
let mut entity_moved = ecs.write_storage::<EntityMoved>();
|
||||||
|
|
||||||
for (entity, _player, pos, viewshed) in
|
for (entity, _player, pos, viewshed) in
|
||||||
(&entities, &mut players, &mut positions, &mut viewsheds).join()
|
(&entities, &mut players, &mut positions, &mut viewsheds).join()
|
||||||
@ -54,6 +56,10 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
|||||||
let mut ppos = ecs.write_resource::<Point>();
|
let mut ppos = ecs.write_resource::<Point>();
|
||||||
ppos.x = pos.x;
|
ppos.x = pos.x;
|
||||||
ppos.y = pos.y;
|
ppos.y = pos.y;
|
||||||
|
|
||||||
|
entity_moved
|
||||||
|
.insert(entity, EntityMoved {})
|
||||||
|
.expect("Unable to insert marker");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ impl RexAssets {
|
|||||||
rltk::link_resource!(SMALL_DUNGEON, "../resources/SmallDungeon_80x50.xp");
|
rltk::link_resource!(SMALL_DUNGEON, "../resources/SmallDungeon_80x50.xp");
|
||||||
|
|
||||||
RexAssets {
|
RexAssets {
|
||||||
menu: XpFile::from_resource("../resources/SmallDungeon_80x50.xp").unwrap()
|
menu: XpFile::from_resource("../resources/SmallDungeon_80x50.xp").unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,11 @@ pub fn save_game(ecs: &mut World) {
|
|||||||
HungerClock,
|
HungerClock,
|
||||||
Heals,
|
Heals,
|
||||||
ProvidesFood,
|
ProvidesFood,
|
||||||
MagicMapper
|
MagicMapper,
|
||||||
|
Hidden,
|
||||||
|
EntryTrigger,
|
||||||
|
EntityMoved,
|
||||||
|
SingleActivation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +169,11 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
HungerClock,
|
HungerClock,
|
||||||
Heals,
|
Heals,
|
||||||
ProvidesFood,
|
ProvidesFood,
|
||||||
MagicMapper
|
MagicMapper,
|
||||||
|
Hidden,
|
||||||
|
EntryTrigger,
|
||||||
|
EntityMoved,
|
||||||
|
SingleActivation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use rltk::{FontCharType, RandomNumberGenerator, RGB};
|
|||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||||
|
|
||||||
use crate::{AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, DefenseBonus, EquipmentSlot, Equippable, HungerClock, HungerState, InflictsDamage, Item, MagicMapper, MAP_WIDTH, MAX_MONSTER, MeleePowerBonus, Monster, Name, Player, Position, ProvidesFood, ProvidesHealing, Ranged, Renderable, SerializeMe, Viewshed};
|
use crate::{AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, DefenseBonus, EntryTrigger, EquipmentSlot, Equippable, Hidden, HungerClock, HungerState, InflictsDamage, Item, MagicMapper, MAP_WIDTH, MAX_MONSTER, MeleePowerBonus, Monster, Name, Player, Position, ProvidesFood, ProvidesHealing, Ranged, Renderable, SerializeMe, SingleActivation, Viewshed};
|
||||||
use crate::random_table::RandomTable;
|
use crate::random_table::RandomTable;
|
||||||
use crate::rect::Rect;
|
use crate::rect::Rect;
|
||||||
|
|
||||||
@ -127,6 +127,7 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) {
|
|||||||
"Sabatons" => sabatons(ecs, x, y),
|
"Sabatons" => sabatons(ecs, x, y),
|
||||||
"Rations" => rations(ecs, x, y),
|
"Rations" => rations(ecs, x, y),
|
||||||
"Magic Mapping Scroll" => magic_mapper_scroll(ecs, x, y),
|
"Magic Mapping Scroll" => magic_mapper_scroll(ecs, x, y),
|
||||||
|
"Bear Trap" => bear_trap(ecs, x, y),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,6 +231,7 @@ pub fn room_table(map_depth: i32) -> RandomTable {
|
|||||||
.add("Sabatons", map_depth - 4)
|
.add("Sabatons", map_depth - 4)
|
||||||
.add("Rations", 10)
|
.add("Rations", 10)
|
||||||
.add("Magic Mapping Scroll", 2)
|
.add("Magic Mapping Scroll", 2)
|
||||||
|
.add("Bear Trap", 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dagger(ecs: &mut World, x: i32, y: i32) {
|
fn dagger(ecs: &mut World, x: i32, y: i32) {
|
||||||
@ -438,4 +440,24 @@ fn magic_mapper_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(MagicMapper {})
|
.with(MagicMapper {})
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bear_trap(ecs: &mut World, x: i32, y: i32) {
|
||||||
|
ecs.create_entity()
|
||||||
|
.with(Position { x, y })
|
||||||
|
.with(Renderable {
|
||||||
|
glyph: rltk::to_cp437('^'),
|
||||||
|
render_order: 2,
|
||||||
|
fg: RGB::named(rltk::RED),
|
||||||
|
bg: RGB::named(rltk::BLACK),
|
||||||
|
})
|
||||||
|
.with(Name {
|
||||||
|
name: "Bear Trap".to_string(),
|
||||||
|
})
|
||||||
|
.with(Hidden {})
|
||||||
|
.with(EntryTrigger {})
|
||||||
|
.with(InflictsDamage { damage: 6 })
|
||||||
|
.with(SingleActivation {})
|
||||||
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
62
src/trigger_system.rs
Normal file
62
src/trigger_system.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
use crate::{EntityMoved, EntryTrigger, GameLog, Hidden, InflictsDamage, Map, Name, Position, SingleActivation, SufferDamage};
|
||||||
|
use crate::particle_system::ParticleBuilder;
|
||||||
|
|
||||||
|
pub struct TriggerSystem {}
|
||||||
|
|
||||||
|
impl<'a> System<'a> for TriggerSystem {
|
||||||
|
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>,
|
||||||
|
WriteStorage<'a, SingleActivation>
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
|
let (map, mut entity_moved, position, entry_trigger, mut hidden, names, entities, mut game_log, inflicts_damage, mut particle_builder, mut inflict_damage, mut single_activation) = data;
|
||||||
|
|
||||||
|
let mut remove_entities: Vec<Entity> = Vec::new();
|
||||||
|
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() {
|
||||||
|
if *entity_id == entity {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_trigger) = entry_trigger.get(*entity_id) {
|
||||||
|
if let Some(name) = names.get(*entity_id) {
|
||||||
|
game_log.entries.push(format!("{} triggers", name.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
hidden.remove(*entity_id);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_sa) = single_activation.get(*entity_id) {
|
||||||
|
remove_entities.push(*entity_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for trap in remove_entities.iter() {
|
||||||
|
entities.delete(*trap).expect("Could not delete trap");
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_moved.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,7 @@
|
|||||||
use rltk::{field_of_view, Point};
|
use rltk::{field_of_view, Point, RandomNumberGenerator};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{components::{Player, Position, Viewshed}, GameLog, Hidden, map::Map, Name};
|
||||||
components::{Player, Position, Viewshed},
|
|
||||||
map::Map,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct VisibilitySystem {}
|
pub struct VisibilitySystem {}
|
||||||
|
|
||||||
@ -15,10 +12,14 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||||||
WriteStorage<'a, Viewshed>,
|
WriteStorage<'a, Viewshed>,
|
||||||
WriteStorage<'a, Position>,
|
WriteStorage<'a, Position>,
|
||||||
ReadStorage<'a, Player>,
|
ReadStorage<'a, Player>,
|
||||||
|
WriteStorage<'a, Hidden>,
|
||||||
|
WriteExpect<'a, RandomNumberGenerator>,
|
||||||
|
ReadStorage<'a, Name>,
|
||||||
|
WriteExpect<'a, GameLog>
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (mut map, entities, mut viewshed, pos, player) = data;
|
let (mut map, entities, mut viewshed, pos, player, mut hidden, mut rng, names, mut game_log) = data;
|
||||||
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
|
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
|
||||||
if !viewshed.dirty {
|
if !viewshed.dirty {
|
||||||
continue;
|
continue;
|
||||||
@ -39,6 +40,17 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||||||
let idx = map.xy_idx(vis.x, vis.y);
|
let idx = map.xy_idx(vis.x, vis.y);
|
||||||
map.revealed_tiles[idx] = true;
|
map.revealed_tiles[idx] = true;
|
||||||
map.visible_tiles[idx] = true;
|
map.visible_tiles[idx] = true;
|
||||||
|
|
||||||
|
for e in map.tile_content[idx].iter() {
|
||||||
|
if let Some(_maybe_hidden) = hidden.get(*e) {
|
||||||
|
if rng.roll_dice(1, 24) == 1 {
|
||||||
|
if let Some(name) = names.get(*e) {
|
||||||
|
game_log.entries.push(format!("You spotted a {}.", &name.name));
|
||||||
|
}
|
||||||
|
hidden.remove(*e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user