corridor types, doors, some refactoring
This commit is contained in:
parent
46e0c6ec6b
commit
ab5797078c
19 changed files with 380 additions and 35 deletions
|
|
@ -63,6 +63,14 @@ pub struct Name {
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct BlocksTile {}
|
pub struct BlocksTile {}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct BlocksVisibility {}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct Door {
|
||||||
|
pub open: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
|
||||||
pub enum HungerState {
|
pub enum HungerState {
|
||||||
Satiated,
|
Satiated,
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,6 @@ impl State {
|
||||||
let mut particle_system = particle_system::ParticleSpawnSystem {};
|
let mut particle_system = particle_system::ParticleSpawnSystem {};
|
||||||
|
|
||||||
vis.run_now(&self.ecs);
|
vis.run_now(&self.ecs);
|
||||||
hunger_clock.run_now(&self.ecs);
|
|
||||||
mob.run_now(&self.ecs);
|
mob.run_now(&self.ecs);
|
||||||
mapindex.run_now(&self.ecs);
|
mapindex.run_now(&self.ecs);
|
||||||
trigger_system.run_now(&self.ecs);
|
trigger_system.run_now(&self.ecs);
|
||||||
|
|
@ -142,6 +141,7 @@ impl State {
|
||||||
item_remove_system.run_now(&self.ecs);
|
item_remove_system.run_now(&self.ecs);
|
||||||
melee_system.run_now(&self.ecs);
|
melee_system.run_now(&self.ecs);
|
||||||
damage_system.run_now(&self.ecs);
|
damage_system.run_now(&self.ecs);
|
||||||
|
hunger_clock.run_now(&self.ecs);
|
||||||
particle_system.run_now(&self.ecs);
|
particle_system.run_now(&self.ecs);
|
||||||
|
|
||||||
self.ecs.maintain();
|
self.ecs.maintain();
|
||||||
|
|
@ -515,6 +515,8 @@ fn main() -> rltk::BError {
|
||||||
gs.ecs.register::<Telepath>();
|
gs.ecs.register::<Telepath>();
|
||||||
gs.ecs.register::<Name>();
|
gs.ecs.register::<Name>();
|
||||||
gs.ecs.register::<BlocksTile>();
|
gs.ecs.register::<BlocksTile>();
|
||||||
|
gs.ecs.register::<BlocksVisibility>();
|
||||||
|
gs.ecs.register::<Door>();
|
||||||
gs.ecs.register::<CombatStats>();
|
gs.ecs.register::<CombatStats>();
|
||||||
gs.ecs.register::<Attributes>();
|
gs.ecs.register::<Attributes>();
|
||||||
gs.ecs.register::<HungerClock>();
|
gs.ecs.register::<HungerClock>();
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,14 @@ pub struct Map {
|
||||||
pub visible_tiles: Vec<bool>,
|
pub visible_tiles: Vec<bool>,
|
||||||
pub lit_tiles: Vec<bool>,
|
pub lit_tiles: Vec<bool>,
|
||||||
pub telepath_tiles: Vec<bool>,
|
pub telepath_tiles: Vec<bool>,
|
||||||
|
// Combine these offsets into one Vec<(u8, u8, u8)>
|
||||||
pub red_offset: Vec<u8>,
|
pub red_offset: Vec<u8>,
|
||||||
pub green_offset: Vec<u8>,
|
pub green_offset: Vec<u8>,
|
||||||
pub blue_offset: Vec<u8>,
|
pub blue_offset: Vec<u8>,
|
||||||
pub blocked: Vec<bool>,
|
pub blocked: Vec<bool>,
|
||||||
pub depth: i32,
|
pub depth: i32,
|
||||||
pub bloodstains: HashSet<usize>,
|
pub bloodstains: HashSet<usize>,
|
||||||
|
pub view_blocked: HashSet<usize>,
|
||||||
|
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
|
|
@ -56,6 +58,7 @@ impl Map {
|
||||||
blocked: vec![false; MAPCOUNT],
|
blocked: vec![false; MAPCOUNT],
|
||||||
depth: new_depth,
|
depth: new_depth,
|
||||||
bloodstains: HashSet::new(),
|
bloodstains: HashSet::new(),
|
||||||
|
view_blocked: HashSet::new(),
|
||||||
tile_content: vec![Vec::new(); MAPCOUNT],
|
tile_content: vec![Vec::new(); MAPCOUNT],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -108,7 +111,8 @@ impl Algorithm2D for Map {
|
||||||
|
|
||||||
impl BaseMap for Map {
|
impl BaseMap for Map {
|
||||||
fn is_opaque(&self, idx: usize) -> bool {
|
fn is_opaque(&self, idx: usize) -> bool {
|
||||||
self.tiles[idx as usize] == TileType::Wall
|
let idx_u = idx as usize;
|
||||||
|
return self.tiles[idx_u] == TileType::Wall || self.view_blocked.contains(&idx_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pathing_distance(&self, idx1: usize, idx2: usize) -> f32 {
|
fn get_pathing_distance(&self, idx1: usize, idx2: usize) -> f32 {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{BuilderMap, InitialMapBuilder, Map, Rect, TileType};
|
use super::{BuilderMap, InitialMapBuilder, Rect, TileType};
|
||||||
use rltk::RandomNumberGenerator;
|
use rltk::RandomNumberGenerator;
|
||||||
|
|
||||||
pub struct BspDungeonBuilder {
|
pub struct BspDungeonBuilder {
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,32 @@ pub fn apply_room_to_map(map: &mut Map, room: &Rect) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_horizontal_tunnel(map: &mut Map, x1: i32, x2: i32, y: i32) {
|
pub fn apply_horizontal_tunnel(map: &mut Map, x1: i32, x2: i32, y: i32) -> Vec<usize> {
|
||||||
|
let mut corridor = Vec::new();
|
||||||
for x in min(x1, x2)..=max(x1, x2) {
|
for x in min(x1, x2)..=max(x1, x2) {
|
||||||
let idx = map.xy_idx(x, y);
|
let idx = map.xy_idx(x, y);
|
||||||
if idx > 0 && idx < (map.width as usize) * (map.height as usize) {
|
if idx > 0 && idx < (map.width as usize) * (map.height as usize) {
|
||||||
map.tiles[idx as usize] = TileType::Floor;
|
map.tiles[idx as usize] = TileType::Floor;
|
||||||
|
corridor.push(idx as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_vertical_tunnel(map: &mut Map, y1: i32, y2: i32, x: i32) {
|
pub fn apply_vertical_tunnel(map: &mut Map, y1: i32, y2: i32, x: i32) -> Vec<usize> {
|
||||||
|
let mut corridor = Vec::new();
|
||||||
for y in min(y1, y2)..=max(y1, y2) {
|
for y in min(y1, y2)..=max(y1, y2) {
|
||||||
let idx = map.xy_idx(x, y);
|
let idx = map.xy_idx(x, y);
|
||||||
if idx > 0 && idx < (map.width as usize) * (map.height as usize) {
|
if idx > 0 && idx < (map.width as usize) * (map.height as usize) {
|
||||||
map.tiles[idx as usize] = TileType::Floor;
|
map.tiles[idx as usize] = TileType::Floor;
|
||||||
|
corridor.push(idx as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_corridor(map: &mut Map, x1: i32, y1: i32, x2: i32, y2: i32) {
|
pub fn draw_corridor(map: &mut Map, x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<usize> {
|
||||||
|
let mut corridor = Vec::new();
|
||||||
let mut x = x1;
|
let mut x = x1;
|
||||||
let mut y = y1;
|
let mut y = y1;
|
||||||
|
|
||||||
|
|
@ -44,8 +51,12 @@ pub fn draw_corridor(map: &mut Map, x1: i32, y1: i32, x2: i32, y2: i32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = map.xy_idx(x, y);
|
let idx = map.xy_idx(x, y);
|
||||||
map.tiles[idx] = TileType::Floor;
|
if map.tiles[idx] != TileType::Floor {
|
||||||
|
map.tiles[idx] = TileType::Floor;
|
||||||
|
corridor.push(idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
|
||||||
75
src/map_builders/door_placement.rs
Normal file
75
src/map_builders/door_placement.rs
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
use super::{BuilderMap, MetaMapBuilder, TileType};
|
||||||
|
use rltk::RandomNumberGenerator;
|
||||||
|
|
||||||
|
pub struct DoorPlacement {}
|
||||||
|
|
||||||
|
impl MetaMapBuilder for DoorPlacement {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
self.doors(rng, build_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DoorPlacement {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Box<DoorPlacement> {
|
||||||
|
Box::new(DoorPlacement {})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn doors(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
if let Some(halls_original) = &build_data.corridors {
|
||||||
|
let halls = halls_original.clone(); // Avoids nested borrow
|
||||||
|
for hall in halls.iter() {
|
||||||
|
if hall.len() > 2 {
|
||||||
|
if self.door_possible(build_data, hall[0]) {
|
||||||
|
build_data.spawn_list.push((hall[0], "door".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There are no corridors - scan for possible places
|
||||||
|
let tiles = build_data.map.tiles.clone();
|
||||||
|
for (i, tile) in tiles.iter().enumerate() {
|
||||||
|
if *tile == TileType::Floor && self.door_possible(build_data, i) && rng.roll_dice(1, 3) == 1 {
|
||||||
|
build_data.spawn_list.push((i, "door".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn door_possible(&self, build_data: &mut BuilderMap, idx: usize) -> bool {
|
||||||
|
// Iterate through spawn list. If another entity wants to spawn on this tile, return false
|
||||||
|
for spawn in build_data.spawn_list.iter() {
|
||||||
|
if spawn.0 == idx {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = idx % build_data.map.width as usize;
|
||||||
|
let y = idx / build_data.map.width as usize;
|
||||||
|
|
||||||
|
// Check for east-west door possibility
|
||||||
|
if build_data.map.tiles[idx] == TileType::Floor
|
||||||
|
&& (x > 1 && build_data.map.tiles[idx - 1] == TileType::Floor)
|
||||||
|
&& (x < build_data.map.width as usize - 2 && build_data.map.tiles[idx + 1] == TileType::Floor)
|
||||||
|
&& (y > 1 && build_data.map.tiles[idx - build_data.map.width as usize] == TileType::Wall)
|
||||||
|
&& (y < build_data.map.height as usize - 2
|
||||||
|
&& build_data.map.tiles[idx + build_data.map.width as usize] == TileType::Wall)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for north-south door possibility
|
||||||
|
if build_data.map.tiles[idx] == TileType::Floor
|
||||||
|
&& (x > 1 && build_data.map.tiles[idx - 1] == TileType::Wall)
|
||||||
|
&& (x < build_data.map.width as usize - 2 && build_data.map.tiles[idx + 1] == TileType::Wall)
|
||||||
|
&& (y > 1 && build_data.map.tiles[idx - build_data.map.width as usize] == TileType::Floor)
|
||||||
|
&& (y < build_data.map.height as usize - 2
|
||||||
|
&& build_data.map.tiles[idx + build_data.map.width as usize] == TileType::Floor)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,14 @@ mod room_sorter;
|
||||||
use room_sorter::{RoomSort, RoomSorter};
|
use room_sorter::{RoomSort, RoomSorter};
|
||||||
mod room_draw;
|
mod room_draw;
|
||||||
use room_draw::RoomDrawer;
|
use room_draw::RoomDrawer;
|
||||||
|
mod rooms_corridors_nearest;
|
||||||
|
use rooms_corridors_nearest::NearestCorridors;
|
||||||
|
mod rooms_corridors_bresenham;
|
||||||
|
use rooms_corridors_bresenham::BresenhamCorridors;
|
||||||
|
mod rooms_corridors_spawner;
|
||||||
|
use rooms_corridors_spawner::CorridorSpawner;
|
||||||
|
mod door_placement;
|
||||||
|
use door_placement::DoorPlacement;
|
||||||
|
|
||||||
// Shared data to be passed around build chain
|
// Shared data to be passed around build chain
|
||||||
pub struct BuilderMap {
|
pub struct BuilderMap {
|
||||||
|
|
@ -55,6 +63,7 @@ pub struct BuilderMap {
|
||||||
pub map: Map,
|
pub map: Map,
|
||||||
pub starting_position: Option<Position>,
|
pub starting_position: Option<Position>,
|
||||||
pub rooms: Option<Vec<Rect>>,
|
pub rooms: Option<Vec<Rect>>,
|
||||||
|
pub corridors: Option<Vec<Vec<usize>>>,
|
||||||
pub history: Vec<Map>,
|
pub history: Vec<Map>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,6 +95,7 @@ impl BuilderChain {
|
||||||
map: Map::new(new_depth),
|
map: Map::new(new_depth),
|
||||||
starting_position: None,
|
starting_position: None,
|
||||||
rooms: None,
|
rooms: None,
|
||||||
|
corridors: None,
|
||||||
history: Vec::new(),
|
history: Vec::new(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -182,12 +192,19 @@ fn random_room_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Buil
|
||||||
_ => builder.with(BspCorridors::new()),
|
_ => builder.with(BspCorridors::new()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let corridor_roll = rng.roll_dice(1, 2);
|
let corridor_roll = rng.roll_dice(1, 4);
|
||||||
match corridor_roll {
|
match corridor_roll {
|
||||||
1 => builder.with(DoglegCorridors::new()),
|
1 => builder.with(DoglegCorridors::new()),
|
||||||
|
2 => builder.with(NearestCorridors::new()),
|
||||||
|
3 => builder.with(BresenhamCorridors::new()),
|
||||||
_ => builder.with(BspCorridors::new()),
|
_ => builder.with(BspCorridors::new()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cspawn_roll = rng.roll_dice(1, 2);
|
||||||
|
if cspawn_roll == 1 {
|
||||||
|
builder.with(CorridorSpawner::new());
|
||||||
|
}
|
||||||
|
|
||||||
let modifier_roll = rng.roll_dice(1, 6);
|
let modifier_roll = rng.roll_dice(1, 6);
|
||||||
match modifier_roll {
|
match modifier_roll {
|
||||||
1 => builder.with(RoomExploder::new()),
|
1 => builder.with(RoomExploder::new()),
|
||||||
|
|
@ -255,7 +272,7 @@ fn random_shape_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Bui
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator) -> BuilderChain {
|
pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator) -> BuilderChain {
|
||||||
let mut builder = BuilderChain::new(new_depth);
|
/*let mut builder = BuilderChain::new(new_depth);
|
||||||
let type_roll = rng.roll_dice(1, 2);
|
let type_roll = rng.roll_dice(1, 2);
|
||||||
match type_roll {
|
match type_roll {
|
||||||
1 => random_room_builder(rng, &mut builder),
|
1 => random_room_builder(rng, &mut builder),
|
||||||
|
|
@ -264,13 +281,30 @@ pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator) ->
|
||||||
|
|
||||||
/*if rng.roll_dice(1, 3)==1 {
|
/*if rng.roll_dice(1, 3)==1 {
|
||||||
builder.with(WaveformCollapseBuilder::new());
|
builder.with(WaveformCollapseBuilder::new());
|
||||||
|
|
||||||
|
// Now set the start to a random starting area
|
||||||
|
let (start_x, start_y) = random_start_position(rng);
|
||||||
|
builder.with(AreaStartingPosition::new(start_x, start_y));
|
||||||
|
|
||||||
|
// Setup an exit and spawn mobs
|
||||||
|
builder.with(VoronoiSpawning::new());
|
||||||
|
builder.with(DistantExit::new());
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if rng.roll_dice(1, 20) == 1 {
|
if rng.roll_dice(1, 20) == 1 {
|
||||||
builder.with(PrefabBuilder::sectional(prefab_builder::prefab_sections::UNDERGROUND_FORT));
|
builder.with(PrefabBuilder::sectional(prefab_builder::prefab_sections::UNDERGROUND_FORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.with(DoorPlacement::new());
|
||||||
builder.with(PrefabBuilder::vaults());
|
builder.with(PrefabBuilder::vaults());
|
||||||
|
|
||||||
|
builder*/
|
||||||
|
|
||||||
|
let mut builder = BuilderChain::new(new_depth);
|
||||||
|
builder.start_with(BspInteriorBuilder::new());
|
||||||
|
builder.with(DoorPlacement::new());
|
||||||
|
builder.with(RoomBasedSpawner::new());
|
||||||
|
builder.with(RoomBasedStairs::new());
|
||||||
|
builder.with(RoomBasedStartingPosition::new());
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ impl RoomDrawer {
|
||||||
if let Some(rooms_builder) = &build_data.rooms {
|
if let Some(rooms_builder) = &build_data.rooms {
|
||||||
rooms = rooms_builder.clone();
|
rooms = rooms_builder.clone();
|
||||||
} else {
|
} else {
|
||||||
panic!("Room Drawing require a builder with room structures");
|
panic!("RoomDrawer require a builder with rooms");
|
||||||
}
|
}
|
||||||
|
|
||||||
for room in rooms.iter() {
|
for room in rooms.iter() {
|
||||||
|
|
|
||||||
64
src/map_builders/rooms_corridors_bresenham.rs
Normal file
64
src/map_builders/rooms_corridors_bresenham.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use super::{BuilderMap, MetaMapBuilder, Rect, TileType};
|
||||||
|
use rltk::RandomNumberGenerator;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub struct BresenhamCorridors {}
|
||||||
|
|
||||||
|
impl MetaMapBuilder for BresenhamCorridors {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
self.corridors(rng, build_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BresenhamCorridors {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Box<BresenhamCorridors> {
|
||||||
|
Box::new(BresenhamCorridors {})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn corridors(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
let rooms: Vec<Rect>;
|
||||||
|
if let Some(rooms_builder) = &build_data.rooms {
|
||||||
|
rooms = rooms_builder.clone();
|
||||||
|
} else {
|
||||||
|
panic!("BresenhamCorridors require a builder with room structures");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut connected: HashSet<usize> = HashSet::new();
|
||||||
|
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||||
|
for (i, room) in rooms.iter().enumerate() {
|
||||||
|
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
||||||
|
let room_centre = room.centre();
|
||||||
|
let room_centre_pt = rltk::Point::new(room_centre.0, room_centre.1);
|
||||||
|
for (j, other_room) in rooms.iter().enumerate() {
|
||||||
|
if i != j && !connected.contains(&j) {
|
||||||
|
let other_centre = other_room.centre();
|
||||||
|
let other_centre_pt = rltk::Point::new(other_centre.0, other_centre.1);
|
||||||
|
let distance = rltk::DistanceAlg::Pythagoras.distance2d(room_centre_pt, other_centre_pt);
|
||||||
|
room_distance.push((j, distance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !room_distance.is_empty() {
|
||||||
|
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||||
|
let dest_centre = rooms[room_distance[0].0].centre();
|
||||||
|
let line = rltk::line2d(
|
||||||
|
rltk::LineAlg::Bresenham,
|
||||||
|
room_centre_pt,
|
||||||
|
rltk::Point::new(dest_centre.0, dest_centre.1),
|
||||||
|
);
|
||||||
|
let mut corridor = Vec::new();
|
||||||
|
for cell in line.iter() {
|
||||||
|
let idx = build_data.map.xy_idx(cell.x, cell.y);
|
||||||
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
|
corridor.push(idx);
|
||||||
|
}
|
||||||
|
corridors.push(corridor);
|
||||||
|
connected.insert(i);
|
||||||
|
build_data.take_snapshot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build_data.corridors = Some(corridors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ impl BspCorridors {
|
||||||
panic!("BSP Corridors require a builder with room structures");
|
panic!("BSP Corridors require a builder with room structures");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||||
for i in 0..rooms.len() - 1 {
|
for i in 0..rooms.len() - 1 {
|
||||||
let room = rooms[i];
|
let room = rooms[i];
|
||||||
let next_room = rooms[i + 1];
|
let next_room = rooms[i + 1];
|
||||||
|
|
@ -31,8 +32,10 @@ impl BspCorridors {
|
||||||
let start_y = room.y1 + (rng.roll_dice(1, i32::abs(room.y1 - room.y2)) - 1);
|
let start_y = room.y1 + (rng.roll_dice(1, i32::abs(room.y1 - room.y2)) - 1);
|
||||||
let end_x = next_room.x1 + (rng.roll_dice(1, i32::abs(next_room.x1 - next_room.x2)) - 1);
|
let end_x = next_room.x1 + (rng.roll_dice(1, i32::abs(next_room.x1 - next_room.x2)) - 1);
|
||||||
let end_y = next_room.y1 + (rng.roll_dice(1, i32::abs(next_room.y1 - next_room.y2)) - 1);
|
let end_y = next_room.y1 + (rng.roll_dice(1, i32::abs(next_room.y1 - next_room.y2)) - 1);
|
||||||
draw_corridor(&mut build_data.map, start_x, start_y, end_x, end_y);
|
let corridor = draw_corridor(&mut build_data.map, start_x, start_y, end_x, end_y);
|
||||||
|
corridors.push(corridor);
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
|
build_data.corridors = Some(corridors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,25 @@ impl DoglegCorridors {
|
||||||
panic!("DoglegCorridors require a builder with rooms.");
|
panic!("DoglegCorridors require a builder with rooms.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||||
for (i, room) in rooms.iter().enumerate() {
|
for (i, room) in rooms.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
let (new_x, new_y) = room.centre();
|
let (new_x, new_y) = room.centre();
|
||||||
let (prev_x, prev_y) = rooms[i as usize - 1].centre();
|
let (prev_x, prev_y) = rooms[i as usize - 1].centre();
|
||||||
if rng.range(0, 2) == 1 {
|
if rng.range(0, 2) == 1 {
|
||||||
apply_horizontal_tunnel(&mut build_data.map, prev_x, new_x, prev_y);
|
let mut c1 = apply_horizontal_tunnel(&mut build_data.map, prev_x, new_x, prev_y);
|
||||||
apply_vertical_tunnel(&mut build_data.map, prev_y, new_y, new_x);
|
let mut c2 = apply_vertical_tunnel(&mut build_data.map, prev_y, new_y, new_x);
|
||||||
|
c1.append(&mut c2);
|
||||||
|
corridors.push(c1);
|
||||||
} else {
|
} else {
|
||||||
apply_vertical_tunnel(&mut build_data.map, prev_y, new_y, prev_x);
|
let mut c1 = apply_vertical_tunnel(&mut build_data.map, prev_y, new_y, prev_x);
|
||||||
apply_horizontal_tunnel(&mut build_data.map, prev_x, new_x, new_y);
|
let mut c2 = apply_horizontal_tunnel(&mut build_data.map, prev_x, new_x, new_y);
|
||||||
|
c1.append(&mut c2);
|
||||||
|
corridors.push(c1);
|
||||||
}
|
}
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
build_data.corridors = Some(corridors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
src/map_builders/rooms_corridors_nearest.rs
Normal file
55
src/map_builders/rooms_corridors_nearest.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
use super::{draw_corridor, BuilderMap, MetaMapBuilder, Rect};
|
||||||
|
use rltk::RandomNumberGenerator;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub struct NearestCorridors {}
|
||||||
|
|
||||||
|
impl MetaMapBuilder for NearestCorridors {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
self.corridors(rng, build_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NearestCorridors {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Box<NearestCorridors> {
|
||||||
|
return Box::new(NearestCorridors {});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn corridors(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
let rooms: Vec<Rect>;
|
||||||
|
if let Some(rooms_builder) = &build_data.rooms {
|
||||||
|
rooms = rooms_builder.clone();
|
||||||
|
} else {
|
||||||
|
panic!("NearestCorridors requires a builder with rooms");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut connected: HashSet<usize> = HashSet::new();
|
||||||
|
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||||
|
for (i, room) in rooms.iter().enumerate() {
|
||||||
|
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
||||||
|
let room_centre = room.centre();
|
||||||
|
let room_centre_pt = rltk::Point::new(room_centre.0, room_centre.1);
|
||||||
|
for (j, other_room) in rooms.iter().enumerate() {
|
||||||
|
if i != j && !connected.contains(&j) {
|
||||||
|
let other_centre = other_room.centre();
|
||||||
|
let other_centre_pt = rltk::Point::new(other_centre.0, other_centre.1);
|
||||||
|
let distance = rltk::DistanceAlg::Pythagoras.distance2d(room_centre_pt, other_centre_pt);
|
||||||
|
room_distance.push((j, distance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !room_distance.is_empty() {
|
||||||
|
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||||
|
let dest_centre = rooms[room_distance[0].0].centre();
|
||||||
|
let corridor =
|
||||||
|
draw_corridor(&mut build_data.map, room_centre.0, room_centre.1, dest_centre.0, dest_centre.1);
|
||||||
|
connected.insert(i);
|
||||||
|
build_data.take_snapshot();
|
||||||
|
corridors.push(corridor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build_data.corridors = Some(corridors);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/map_builders/rooms_corridors_spawner.rs
Normal file
28
src/map_builders/rooms_corridors_spawner.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
use super::{spawner, BuilderMap, MetaMapBuilder};
|
||||||
|
use rltk::RandomNumberGenerator;
|
||||||
|
|
||||||
|
pub struct CorridorSpawner {}
|
||||||
|
|
||||||
|
impl MetaMapBuilder for CorridorSpawner {
|
||||||
|
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
self.build(rng, build_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CorridorSpawner {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Box<CorridorSpawner> {
|
||||||
|
return Box::new(CorridorSpawner {});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
if let Some(corridors) = &build_data.corridors {
|
||||||
|
for corridor in corridors.iter() {
|
||||||
|
let depth = build_data.map.depth;
|
||||||
|
spawner::spawn_region(&build_data.map, rng, &corridor, depth, &mut build_data.spawn_list);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("CorridorSpawner only works after corridors have been created");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,6 +59,10 @@ impl ParticleBuilder {
|
||||||
self.request(x, y, rltk::RGB::named(rltk::ORANGE), rltk::RGB::named(rltk::BLACK), rltk::to_cp437('‼'), 200.0);
|
self.request(x, y, rltk::RGB::named(rltk::ORANGE), rltk::RGB::named(rltk::BLACK), rltk::to_cp437('‼'), 200.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trap_triggered(&mut self, x: i32, y: i32) {
|
||||||
|
self.request(x, y, rltk::RGB::named(rltk::RED), rltk::RGB::named(rltk::RED), rltk::to_cp437('‼'), 200.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Makes a particle request in the shape of an 'x'. Sort of.
|
// 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) {
|
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, y, fg, bg, glyph, lifetime * 2.0);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use super::{
|
use super::{
|
||||||
gamelog, CombatStats, EntityMoved, Hidden, HungerClock, HungerState, Item, Map, Monster, Name, Player, Position,
|
gamelog, BlocksTile, BlocksVisibility, CombatStats, Door, EntityMoved, Hidden, HungerClock, HungerState, Item, Map,
|
||||||
RunState, State, Telepath, TileType, Viewshed, WantsToMelee, WantsToPickupItem, MAPHEIGHT, MAPWIDTH,
|
Monster, Name, Player, Position, Renderable, RunState, State, Telepath, TileType, Viewshed, WantsToMelee,
|
||||||
|
WantsToPickupItem, MAPHEIGHT, MAPWIDTH,
|
||||||
};
|
};
|
||||||
use rltk::{Point, RandomNumberGenerator, Rltk, VirtualKeyCode};
|
use rltk::{Point, RandomNumberGenerator, Rltk, VirtualKeyCode};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
@ -17,6 +18,11 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> bool {
|
||||||
|
|
||||||
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 mut doors = ecs.write_storage::<Door>();
|
||||||
|
let mut blocks_visibility = ecs.write_storage::<BlocksVisibility>();
|
||||||
|
let mut blocks_movement = ecs.write_storage::<BlocksTile>();
|
||||||
|
let mut renderables = ecs.write_storage::<Renderable>();
|
||||||
|
let names = ecs.read_storage::<Name>();
|
||||||
|
|
||||||
for (entity, _player, pos, viewshed) in (&entities, &mut players, &mut positions, &mut viewsheds).join() {
|
for (entity, _player, pos, viewshed) in (&entities, &mut players, &mut positions, &mut viewsheds).join() {
|
||||||
if pos.x + delta_x < 1
|
if pos.x + delta_x < 1
|
||||||
|
|
@ -34,14 +40,27 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> bool {
|
||||||
wants_to_melee.insert(entity, WantsToMelee { target: *potential_target }).expect("Add target failed.");
|
wants_to_melee.insert(entity, WantsToMelee { target: *potential_target }).expect("Add target failed.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
let door = doors.get_mut(*potential_target);
|
||||||
|
if let Some(door) = door {
|
||||||
|
if door.open == false {
|
||||||
|
door.open = true;
|
||||||
|
blocks_visibility.remove(*potential_target);
|
||||||
|
blocks_movement.remove(*potential_target);
|
||||||
|
let render_data = renderables.get_mut(*potential_target).unwrap();
|
||||||
|
if let Some(name) = names.get(entity) {
|
||||||
|
gamelog::Logger::new().append("You open the").item_name_n(&name.name).period().log();
|
||||||
|
}
|
||||||
|
render_data.glyph = rltk::to_cp437('▓'); // Nethack open door, maybe just use '/' instead.
|
||||||
|
viewshed.dirty = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if map.blocked[destination_idx] {
|
if map.blocked[destination_idx] {
|
||||||
gamelog::Logger::new().append("You can't move there.").log();
|
gamelog::Logger::new().append("You can't move there.").log();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let names = ecs.read_storage::<Name>();
|
|
||||||
let hidden = ecs.read_storage::<Hidden>();
|
let hidden = ecs.read_storage::<Hidden>();
|
||||||
// Push every entity name in the pile to a vector of strings
|
// Push every entity name in the pile to a vector of strings
|
||||||
let mut item_names: Vec<String> = Vec::new();
|
let mut item_names: Vec<String> = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,14 @@ pub fn save_game(ecs: &mut World) {
|
||||||
AOE,
|
AOE,
|
||||||
Attributes,
|
Attributes,
|
||||||
BlocksTile,
|
BlocksTile,
|
||||||
|
BlocksVisibility,
|
||||||
CombatStats,
|
CombatStats,
|
||||||
Confusion,
|
Confusion,
|
||||||
Consumable,
|
Consumable,
|
||||||
Cursed,
|
Cursed,
|
||||||
DefenceBonus,
|
DefenceBonus,
|
||||||
Destructible,
|
Destructible,
|
||||||
|
Door,
|
||||||
EntityMoved,
|
EntityMoved,
|
||||||
EntryTrigger,
|
EntryTrigger,
|
||||||
Equippable,
|
Equippable,
|
||||||
|
|
@ -143,12 +145,14 @@ pub fn load_game(ecs: &mut World) {
|
||||||
AOE,
|
AOE,
|
||||||
Attributes,
|
Attributes,
|
||||||
BlocksTile,
|
BlocksTile,
|
||||||
|
BlocksVisibility,
|
||||||
CombatStats,
|
CombatStats,
|
||||||
Confusion,
|
Confusion,
|
||||||
Consumable,
|
Consumable,
|
||||||
Cursed,
|
Cursed,
|
||||||
DefenceBonus,
|
DefenceBonus,
|
||||||
Destructible,
|
Destructible,
|
||||||
|
Door,
|
||||||
EntityMoved,
|
EntityMoved,
|
||||||
EntryTrigger,
|
EntryTrigger,
|
||||||
Equippable,
|
Equippable,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use super::{
|
use super::{
|
||||||
random_table::RandomTable, Attribute, Attributes, BlocksTile, CombatStats, Confusion, Consumable, Cursed,
|
random_table::RandomTable, Attribute, Attributes, BlocksTile, BlocksVisibility, CombatStats, Confusion, Consumable,
|
||||||
DefenceBonus, Destructible, EntryTrigger, EquipmentSlot, Equippable, Hidden, HungerClock, HungerState,
|
Cursed, DefenceBonus, Destructible, Door, EntryTrigger, EquipmentSlot, Equippable, Hidden, HungerClock,
|
||||||
InflictsDamage, Item, MagicMapper, Map, MeleePowerBonus, Mind, Monster, Name, Player, Position, ProvidesHealing,
|
HungerState, InflictsDamage, Item, MagicMapper, Map, MeleePowerBonus, Mind, Monster, Name, Player, Position,
|
||||||
ProvidesNutrition, Ranged, Rect, Renderable, SerializeMe, SingleActivation, TileType, Viewshed, Wand, AOE,
|
ProvidesHealing, ProvidesNutrition, Ranged, Rect, Renderable, SerializeMe, SingleActivation, TileType, Viewshed,
|
||||||
MAPWIDTH,
|
Wand, AOE, MAPWIDTH,
|
||||||
};
|
};
|
||||||
use rltk::{console, RandomNumberGenerator, RGB};
|
use rltk::{console, RandomNumberGenerator, RGB};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
@ -113,15 +113,6 @@ pub fn spawn_region(
|
||||||
) {
|
) {
|
||||||
let mut spawn_points: HashMap<usize, String> = HashMap::new();
|
let mut spawn_points: HashMap<usize, String> = HashMap::new();
|
||||||
let mut areas: Vec<usize> = Vec::from(area);
|
let mut areas: Vec<usize> = Vec::from(area);
|
||||||
let category = category_table().roll(rng);
|
|
||||||
let spawn_table;
|
|
||||||
match category.as_ref() {
|
|
||||||
"mob" => spawn_table = mob_table(map_depth),
|
|
||||||
"item" => spawn_table = item_table(map_depth),
|
|
||||||
"food" => spawn_table = food_table(map_depth),
|
|
||||||
"trap" => spawn_table = trap_table(map_depth),
|
|
||||||
_ => spawn_table = debug_table(),
|
|
||||||
}
|
|
||||||
|
|
||||||
let num_spawns = i32::min(areas.len() as i32, rng.roll_dice(1, MAX_ENTITIES + 2) - 2);
|
let num_spawns = i32::min(areas.len() as i32, rng.roll_dice(1, MAX_ENTITIES + 2) - 2);
|
||||||
if num_spawns <= 0 {
|
if num_spawns <= 0 {
|
||||||
|
|
@ -129,6 +120,15 @@ pub fn spawn_region(
|
||||||
}
|
}
|
||||||
|
|
||||||
for _i in 0..num_spawns {
|
for _i in 0..num_spawns {
|
||||||
|
let category = category_table().roll(rng);
|
||||||
|
let spawn_table;
|
||||||
|
match category.as_ref() {
|
||||||
|
"mob" => spawn_table = mob_table(map_depth),
|
||||||
|
"item" => spawn_table = item_table(map_depth),
|
||||||
|
"food" => spawn_table = food_table(map_depth),
|
||||||
|
"trap" => spawn_table = trap_table(map_depth),
|
||||||
|
_ => spawn_table = debug_table(),
|
||||||
|
}
|
||||||
let array_idx = if areas.len() == 1 { 0usize } else { (rng.roll_dice(1, areas.len() as i32) - 1) as usize };
|
let array_idx = if areas.len() == 1 { 0usize } else { (rng.roll_dice(1, areas.len() as i32) - 1) as usize };
|
||||||
let map_idx = areas[array_idx];
|
let map_idx = areas[array_idx];
|
||||||
spawn_points.insert(map_idx, spawn_table.roll(rng));
|
spawn_points.insert(map_idx, spawn_table.roll(rng));
|
||||||
|
|
@ -174,6 +174,8 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
||||||
// Traps
|
// Traps
|
||||||
"bear trap" => bear_trap(ecs, x, y),
|
"bear trap" => bear_trap(ecs, x, y),
|
||||||
"confusion trap" => confusion_trap(ecs, x, y),
|
"confusion trap" => confusion_trap(ecs, x, y),
|
||||||
|
// Other
|
||||||
|
"door" => door(ecs, x, y),
|
||||||
_ => console::log(format!("Tried to spawn nothing ({}). Bugfix needed!", spawn.1)),
|
_ => console::log(format!("Tried to spawn nothing ({}). Bugfix needed!", spawn.1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,6 +230,23 @@ fn trap_table(_map_depth: i32) -> RandomTable {
|
||||||
return RandomTable::new().add("bear trap", 0).add("confusion trap", 1);
|
return RandomTable::new().add("bear trap", 0).add("confusion trap", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn door(ecs: &mut World, x: i32, y: i32) {
|
||||||
|
ecs.create_entity()
|
||||||
|
.with(Position { x, y })
|
||||||
|
.with(Renderable {
|
||||||
|
glyph: rltk::to_cp437('+'),
|
||||||
|
fg: RGB::named(rltk::LIGHTYELLOW),
|
||||||
|
bg: RGB::named(rltk::BLACK),
|
||||||
|
render_order: 2,
|
||||||
|
})
|
||||||
|
.with(Name { name: "door".to_string(), plural: "doors".to_string() })
|
||||||
|
.with(BlocksTile {})
|
||||||
|
.with(BlocksVisibility {})
|
||||||
|
.with(Door { open: false })
|
||||||
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
||||||
ecs.create_entity()
|
ecs.create_entity()
|
||||||
.with(Position { x, y })
|
.with(Position { x, y })
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ impl<'a> System<'a> for TriggerSystem {
|
||||||
let name = names.get(*entity_id);
|
let name = names.get(*entity_id);
|
||||||
hidden.remove(*entity_id);
|
hidden.remove(*entity_id);
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
|
particle_builder.trap_triggered(pos.x, pos.y);
|
||||||
gamelog::Logger::new().item_name(&name.name).append("triggers!").log();
|
gamelog::Logger::new().item_name(&name.name).append("triggers!").log();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{gamelog, Hidden, Map, Name, Player, Position, Telepath, Viewshed};
|
use super::{gamelog, BlocksVisibility, Hidden, Map, Name, Player, Position, Telepath, Viewshed};
|
||||||
use rltk::{FieldOfViewAlg::SymmetricShadowcasting, Point};
|
use rltk::{FieldOfViewAlg::SymmetricShadowcasting, Point};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
|
@ -15,10 +15,18 @@ impl<'a> System<'a> for VisibilitySystem {
|
||||||
ReadStorage<'a, Player>,
|
ReadStorage<'a, Player>,
|
||||||
WriteStorage<'a, Hidden>,
|
WriteStorage<'a, Hidden>,
|
||||||
ReadStorage<'a, Name>,
|
ReadStorage<'a, Name>,
|
||||||
|
ReadStorage<'a, BlocksVisibility>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (mut map, mut rng, entities, mut viewshed, mut telepath, pos, player, mut hidden, names) = data;
|
let (mut map, mut rng, entities, mut viewshed, mut telepath, pos, player, mut hidden, names, blocks_visibility) =
|
||||||
|
data;
|
||||||
|
|
||||||
|
map.view_blocked.clear();
|
||||||
|
for (block_pos, _block) in (&pos, &blocks_visibility).join() {
|
||||||
|
let idx = map.xy_idx(block_pos.x, block_pos.y);
|
||||||
|
map.view_blocked.insert(idx);
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue