made the switch to using bracket-lib directly, instead of rltk wrapper
this should solve the build issues; it makes using the non-crashing github build a lot easier, because it lets the explicit rltk dependency be removed.
This commit is contained in:
parent
455b8f2d80
commit
85efe13dc5
93 changed files with 1528 additions and 770 deletions
|
|
@ -6,7 +6,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rltk = { version = "^0.8.7", features = ["serde"] }
|
|
||||||
bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git", rev = "851f6f08675444fb6fa088b9e67bee9fd75554c6", features = ["serde"] }
|
bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git", rev = "851f6f08675444fb6fa088b9e67bee9fd75554c6", features = ["serde"] }
|
||||||
regex = "1.3.6"
|
regex = "1.3.6"
|
||||||
specs = { version = "0.16.1", features = ["serde"] }
|
specs = { version = "0.16.1", features = ["serde"] }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use criterion::{ black_box, criterion_group, criterion_main, Criterion };
|
use criterion::{ black_box, criterion_group, criterion_main, Criterion };
|
||||||
use rltk::RGB;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
/// Benchmarks methods from rltk used to desaturate non-visible tiles.
|
/// Benchmarks methods from rltk used to desaturate non-visible tiles.
|
||||||
// Greyscale is significantly faster, but generally looks worse - the
|
// Greyscale is significantly faster, but generally looks worse - the
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToApproach };
|
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToApproach };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct ApproachAI {}
|
pub struct ApproachAI {}
|
||||||
|
|
@ -39,7 +39,9 @@ impl<'a> System<'a> for ApproachAI {
|
||||||
&turns,
|
&turns,
|
||||||
).join() {
|
).join() {
|
||||||
turn_done.push(entity);
|
turn_done.push(entity);
|
||||||
let target_idxs = if let Some(paths) = get_adjacent_unblocked(&map, approach.idx as usize) {
|
let target_idxs = if
|
||||||
|
let Some(paths) = get_adjacent_unblocked(&map, approach.idx as usize)
|
||||||
|
{
|
||||||
paths
|
paths
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -47,9 +49,12 @@ impl<'a> System<'a> for ApproachAI {
|
||||||
let mut path: Option<NavigationPath> = None;
|
let mut path: Option<NavigationPath> = None;
|
||||||
let idx = map.xy_idx(pos.x, pos.y);
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
for tar_idx in target_idxs {
|
for tar_idx in target_idxs {
|
||||||
let potential_path = rltk::a_star_search(idx, tar_idx, &mut *map);
|
let potential_path = a_star_search(idx, tar_idx, &mut *map);
|
||||||
if potential_path.success && potential_path.steps.len() > 1 {
|
if potential_path.success && potential_path.steps.len() > 1 {
|
||||||
if path.is_none() || potential_path.steps.len() < path.as_ref().unwrap().steps.len() {
|
if
|
||||||
|
path.is_none() ||
|
||||||
|
potential_path.steps.len() < path.as_ref().unwrap().steps.len()
|
||||||
|
{
|
||||||
path = Some(potential_path);
|
path = Some(potential_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{ Chasing, EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed };
|
use crate::{ Chasing, EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use super::approach_ai_system::get_adjacent_unblocked;
|
use super::approach_ai_system::get_adjacent_unblocked;
|
||||||
|
|
@ -26,8 +26,16 @@ impl<'a> System<'a> for ChaseAI {
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (mut turns, mut chasing, mut positions, mut map, mut viewsheds, mut telepaths, mut entity_moved, entities) =
|
let (
|
||||||
data;
|
mut turns,
|
||||||
|
mut chasing,
|
||||||
|
mut positions,
|
||||||
|
mut map,
|
||||||
|
mut viewsheds,
|
||||||
|
mut telepaths,
|
||||||
|
mut entity_moved,
|
||||||
|
entities,
|
||||||
|
) = data;
|
||||||
let mut targets: HashMap<Entity, (i32, i32)> = HashMap::new();
|
let mut targets: HashMap<Entity, (i32, i32)> = HashMap::new();
|
||||||
let mut end_chase: Vec<Entity> = Vec::new();
|
let mut end_chase: Vec<Entity> = Vec::new();
|
||||||
// For every chasing entity with a turn, look for a valid target position,
|
// For every chasing entity with a turn, look for a valid target position,
|
||||||
|
|
@ -67,9 +75,12 @@ impl<'a> System<'a> for ChaseAI {
|
||||||
let mut path: Option<NavigationPath> = None;
|
let mut path: Option<NavigationPath> = None;
|
||||||
let idx = map.xy_idx(pos.x, pos.y);
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
for tar_idx in target_idxs {
|
for tar_idx in target_idxs {
|
||||||
let potential_path = rltk::a_star_search(idx, tar_idx, &mut *map);
|
let potential_path = a_star_search(idx, tar_idx, &mut *map);
|
||||||
if potential_path.success && potential_path.steps.len() > 1 {
|
if potential_path.success && potential_path.steps.len() > 1 {
|
||||||
if path.is_none() || potential_path.steps.len() < path.as_ref().unwrap().steps.len() {
|
if
|
||||||
|
path.is_none() ||
|
||||||
|
potential_path.steps.len() < path.as_ref().unwrap().steps.len()
|
||||||
|
{
|
||||||
path = Some(potential_path);
|
path = Some(potential_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
use crate::{ tile_walkable, EntityMoved, Map, MoveMode, Movement, Position, TakingTurn, Telepath, Viewshed };
|
use crate::{
|
||||||
|
tile_walkable,
|
||||||
|
EntityMoved,
|
||||||
|
Map,
|
||||||
|
MoveMode,
|
||||||
|
Movement,
|
||||||
|
Position,
|
||||||
|
TakingTurn,
|
||||||
|
Telepath,
|
||||||
|
Viewshed,
|
||||||
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
// Rolling a 1d8+x to decide where to move, where x are the number
|
// Rolling a 1d8+x to decide where to move, where x are the number
|
||||||
// of dice rolls in which they will remian stationary. i.e. If this
|
// of dice rolls in which they will remian stationary. i.e. If this
|
||||||
|
|
@ -16,7 +27,7 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
WriteStorage<'a, Viewshed>,
|
WriteStorage<'a, Viewshed>,
|
||||||
WriteStorage<'a, Telepath>,
|
WriteStorage<'a, Telepath>,
|
||||||
WriteStorage<'a, EntityMoved>,
|
WriteStorage<'a, EntityMoved>,
|
||||||
WriteExpect<'a, rltk::RandomNumberGenerator>,
|
WriteExpect<'a, RandomNumberGenerator>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -85,7 +96,9 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
let idx = map.xy_idx(pos.x, pos.y);
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
pos.x = x;
|
pos.x = x;
|
||||||
pos.y = y;
|
pos.y = y;
|
||||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
entity_moved
|
||||||
|
.insert(entity, EntityMoved {})
|
||||||
|
.expect("Unable to insert EntityMoved");
|
||||||
crate::spatial::move_entity(entity, idx, dest_idx);
|
crate::spatial::move_entity(entity, idx, dest_idx);
|
||||||
viewshed.dirty = true;
|
viewshed.dirty = true;
|
||||||
if let Some(is_telepath) = telepaths.get_mut(entity) {
|
if let Some(is_telepath) = telepaths.get_mut(entity) {
|
||||||
|
|
@ -102,7 +115,9 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
if !crate::spatial::is_blocked(path[1] as usize) {
|
if !crate::spatial::is_blocked(path[1] as usize) {
|
||||||
pos.x = (path[1] as i32) % map.width;
|
pos.x = (path[1] as i32) % map.width;
|
||||||
pos.y = (path[1] as i32) / map.width;
|
pos.y = (path[1] as i32) / map.width;
|
||||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
entity_moved
|
||||||
|
.insert(entity, EntityMoved {})
|
||||||
|
.expect("Unable to insert EntityMoved");
|
||||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||||
crate::spatial::move_entity(entity, idx, new_idx);
|
crate::spatial::move_entity(entity, idx, new_idx);
|
||||||
viewshed.dirty = true;
|
viewshed.dirty = true;
|
||||||
|
|
@ -112,7 +127,7 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
path.remove(0);
|
path.remove(0);
|
||||||
} else {
|
} else {
|
||||||
// If the path is blocked, recalculate a new path to the same waypoint.
|
// If the path is blocked, recalculate a new path to the same waypoint.
|
||||||
let path = rltk::a_star_search(
|
let path = a_star_search(
|
||||||
map.xy_idx(pos.x, pos.y) as i32,
|
map.xy_idx(pos.x, pos.y) as i32,
|
||||||
map.xy_idx(
|
map.xy_idx(
|
||||||
(path[path.len() - 1] as i32) % map.width,
|
(path[path.len() - 1] as i32) % map.width,
|
||||||
|
|
@ -121,7 +136,9 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
&mut *map
|
&mut *map
|
||||||
);
|
);
|
||||||
if path.success && path.steps.len() > 1 {
|
if path.success && path.steps.len() > 1 {
|
||||||
move_mode.mode = Movement::RandomWaypoint { path: Some(path.steps) };
|
move_mode.mode = Movement::RandomWaypoint {
|
||||||
|
path: Some(path.steps),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -132,7 +149,7 @@ impl<'a> System<'a> for DefaultAI {
|
||||||
let target_y = rng.roll_dice(1, map.height - 2);
|
let target_y = rng.roll_dice(1, map.height - 2);
|
||||||
let idx = map.xy_idx(target_x, target_y);
|
let idx = map.xy_idx(target_x, target_y);
|
||||||
if tile_walkable(map.tiles[idx]) {
|
if tile_walkable(map.tiles[idx]) {
|
||||||
let path = rltk::a_star_search(
|
let path = a_star_search(
|
||||||
map.xy_idx(pos.x, pos.y) as i32,
|
map.xy_idx(pos.x, pos.y) as i32,
|
||||||
map.xy_idx(target_x, target_y) as i32,
|
map.xy_idx(target_x, target_y) as i32,
|
||||||
&mut *map
|
&mut *map
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
TakingTurn,
|
TakingTurn,
|
||||||
Confusion,
|
Confusion,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
|
@ -126,7 +126,7 @@ impl<'a> System<'a> for EnergySystem {
|
||||||
if entity == *player {
|
if entity == *player {
|
||||||
*runstate = RunState::AwaitingInput;
|
*runstate = RunState::AwaitingInput;
|
||||||
} else {
|
} else {
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance = DistanceAlg::Pythagoras.distance2d(
|
||||||
*player_pos,
|
*player_pos,
|
||||||
Point::new(pos.x, pos.y)
|
Point::new(pos.x, pos.y)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToFlee };
|
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToFlee };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct FleeAI {}
|
pub struct FleeAI {}
|
||||||
|
|
@ -39,7 +39,13 @@ impl<'a> System<'a> for FleeAI {
|
||||||
turn_done.push(entity);
|
turn_done.push(entity);
|
||||||
let my_idx = map.xy_idx(pos.x, pos.y);
|
let my_idx = map.xy_idx(pos.x, pos.y);
|
||||||
map.populate_blocked();
|
map.populate_blocked();
|
||||||
let flee_map = DijkstraMap::new(map.width as usize, map.height as usize, &fleeing.indices, &*map, 100.0);
|
let flee_map = DijkstraMap::new(
|
||||||
|
map.width as usize,
|
||||||
|
map.height as usize,
|
||||||
|
&fleeing.indices,
|
||||||
|
&*map,
|
||||||
|
100.0
|
||||||
|
);
|
||||||
let flee_target = DijkstraMap::find_highest_exit(&flee_map, my_idx, &*map);
|
let flee_target = DijkstraMap::find_highest_exit(&flee_map, my_idx, &*map);
|
||||||
if let Some(flee_target) = flee_target {
|
if let Some(flee_target) = flee_target {
|
||||||
if !crate::spatial::is_blocked(flee_target as usize) {
|
if !crate::spatial::is_blocked(flee_target as usize) {
|
||||||
|
|
@ -50,7 +56,9 @@ impl<'a> System<'a> for FleeAI {
|
||||||
}
|
}
|
||||||
pos.x = (flee_target as i32) % map.width;
|
pos.x = (flee_target as i32) % map.width;
|
||||||
pos.y = (flee_target as i32) / map.width;
|
pos.y = (flee_target as i32) / map.width;
|
||||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
entity_moved
|
||||||
|
.insert(entity, EntityMoved {})
|
||||||
|
.expect("Unable to insert EntityMoved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{ gamelog, gui::renderable_colour, Name, Quips, Renderable, TakingTurn, Viewshed };
|
use crate::{ gamelog, gui::renderable_colour, Name, Quips, Renderable, TakingTurn, Viewshed };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct QuipSystem {}
|
pub struct QuipSystem {}
|
||||||
|
|
@ -19,8 +19,18 @@ impl<'a> System<'a> for QuipSystem {
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (entities, mut quips, names, renderables, turns, player_pos, viewsheds, mut rng) = data;
|
let (entities, mut quips, names, renderables, turns, player_pos, viewsheds, mut rng) = data;
|
||||||
for (entity, quip, name, viewshed, _turn) in (&entities, &mut quips, &names, &viewsheds, &turns).join() {
|
for (entity, quip, name, viewshed, _turn) in (
|
||||||
if !quip.available.is_empty() && viewshed.visible_tiles.contains(&player_pos) && rng.roll_dice(1, 6) == 1 {
|
&entities,
|
||||||
|
&mut quips,
|
||||||
|
&names,
|
||||||
|
&viewsheds,
|
||||||
|
&turns,
|
||||||
|
).join() {
|
||||||
|
if
|
||||||
|
!quip.available.is_empty() &&
|
||||||
|
viewshed.visible_tiles.contains(&player_pos) &&
|
||||||
|
rng.roll_dice(1, 6) == 1
|
||||||
|
{
|
||||||
let quip_index = if quip.available.len() == 1 {
|
let quip_index = if quip.available.len() == 1 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
Item,
|
Item,
|
||||||
Prop,
|
Prop,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
WantsToApproach,
|
WantsToApproach,
|
||||||
WantsToFlee,
|
WantsToFlee,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
|
@ -81,10 +81,16 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
}
|
}
|
||||||
reactions.sort_by(|(a, _, _), (b, _, _)| {
|
reactions.sort_by(|(a, _, _), (b, _, _)| {
|
||||||
let (a_x, a_y) = (a % (map.width as usize), a / (map.width as usize));
|
let (a_x, a_y) = (a % (map.width as usize), a / (map.width as usize));
|
||||||
let dist_a = DistanceAlg::PythagorasSquared.distance2d(Point::new(a_x, a_y), Point::new(pos.x, pos.y));
|
let dist_a = DistanceAlg::PythagorasSquared.distance2d(
|
||||||
|
Point::new(a_x, a_y),
|
||||||
|
Point::new(pos.x, pos.y)
|
||||||
|
);
|
||||||
let dist_a_estimate = dist_a as i32;
|
let dist_a_estimate = dist_a as i32;
|
||||||
let (b_x, b_y) = (b % (map.width as usize), b / (map.width as usize));
|
let (b_x, b_y) = (b % (map.width as usize), b / (map.width as usize));
|
||||||
let dist_b = DistanceAlg::PythagorasSquared.distance2d(Point::new(b_x, b_y), Point::new(pos.x, pos.y));
|
let dist_b = DistanceAlg::PythagorasSquared.distance2d(
|
||||||
|
Point::new(b_x, b_y),
|
||||||
|
Point::new(pos.x, pos.y)
|
||||||
|
);
|
||||||
let dist_b_estimate = dist_b as i32;
|
let dist_b_estimate = dist_b as i32;
|
||||||
return dist_b_estimate.cmp(&dist_a_estimate);
|
return dist_b_estimate.cmp(&dist_a_estimate);
|
||||||
});
|
});
|
||||||
|
|
@ -96,7 +102,9 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
wants_to_approach
|
wants_to_approach
|
||||||
.insert(entity, WantsToApproach { idx: reaction.0 as i32 })
|
.insert(entity, WantsToApproach { idx: reaction.0 as i32 })
|
||||||
.expect("Error inserting WantsToApproach");
|
.expect("Error inserting WantsToApproach");
|
||||||
chasing.insert(entity, Chasing { target: reaction.2 }).expect("Unable to insert Chasing");
|
chasing
|
||||||
|
.insert(entity, Chasing { target: reaction.2 })
|
||||||
|
.expect("Unable to insert Chasing");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +116,9 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !flee.is_empty() {
|
if !flee.is_empty() {
|
||||||
wants_to_flee.insert(entity, WantsToFlee { indices: flee }).expect("Unable to insert");
|
wants_to_flee
|
||||||
|
.insert(entity, WantsToFlee { indices: flee })
|
||||||
|
.expect("Unable to insert");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ Hidden, Map, Mind, Position, Prop, Renderable };
|
use super::{ Hidden, Map, Mind, Position, Prop, Renderable };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
const SHOW_BOUNDARIES: bool = false;
|
const SHOW_BOUNDARIES: bool = false;
|
||||||
|
|
||||||
pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32, i32, i32) {
|
pub fn get_screen_bounds(ecs: &World, _ctx: &mut BTerm) -> (i32, i32, i32, i32, i32, i32) {
|
||||||
let player_pos = ecs.fetch::<Point>();
|
let player_pos = ecs.fetch::<Point>();
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let (x_chars, y_chars, mut x_offset, mut y_offset) = (69, 41, 1, 10);
|
let (x_chars, y_chars, mut x_offset, mut y_offset) = (69, 41, 1, 10);
|
||||||
|
|
@ -31,7 +31,7 @@ pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32, i
|
||||||
(min_x, max_x, min_y, max_y, x_offset, y_offset)
|
(min_x, max_x, min_y, max_y, x_offset, y_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let (min_x, max_x, min_y, max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx);
|
let (min_x, max_x, min_y, max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx);
|
||||||
|
|
||||||
|
|
@ -52,7 +52,13 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
|
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
|
||||||
}
|
}
|
||||||
} else if SHOW_BOUNDARIES {
|
} else if SHOW_BOUNDARIES {
|
||||||
ctx.set(x + x_offset, y + y_offset, RGB::named(DARKSLATEGRAY), RGB::named(BLACK), rltk::to_cp437('#'));
|
ctx.set(
|
||||||
|
x + x_offset,
|
||||||
|
y + y_offset,
|
||||||
|
RGB::named(DARKSLATEGRAY),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
to_cp437('#')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
x += 1;
|
x += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -112,14 +118,20 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if draw {
|
if draw {
|
||||||
ctx.set(entity_offset_x + x_offset, entity_offset_y + y_offset, fg, bg, render.glyph);
|
ctx.set(
|
||||||
|
entity_offset_x + x_offset,
|
||||||
|
entity_offset_y + y_offset,
|
||||||
|
fg,
|
||||||
|
bg,
|
||||||
|
render.glyph
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
|
pub fn render_debug_map(map: &Map, ctx: &mut BTerm) {
|
||||||
let player_pos = Point::new(map.width / 2, map.height / 2);
|
let player_pos = Point::new(map.width / 2, map.height / 2);
|
||||||
let (x_chars, y_chars) = ctx.get_char_size();
|
let (x_chars, y_chars) = ctx.get_char_size();
|
||||||
|
|
||||||
|
|
@ -141,11 +153,16 @@ pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
|
||||||
if tx >= 0 && tx < map_width && ty >= 0 && ty < map_height {
|
if tx >= 0 && tx < map_width && ty >= 0 && ty < map_height {
|
||||||
let idx = map.xy_idx(tx, ty);
|
let idx = map.xy_idx(tx, ty);
|
||||||
if map.revealed_tiles[idx] {
|
if map.revealed_tiles[idx] {
|
||||||
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None, None);
|
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(
|
||||||
|
idx,
|
||||||
|
&*map,
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
);
|
||||||
ctx.set(x, y, fg, bg, glyph);
|
ctx.set(x, y, fg, bg, glyph);
|
||||||
}
|
}
|
||||||
} else if SHOW_BOUNDARIES {
|
} else if SHOW_BOUNDARIES {
|
||||||
ctx.set(x, y, RGB::named(rltk::GRAY), RGB::named(rltk::BLACK), rltk::to_cp437('·'));
|
ctx.set(x, y, RGB::named(GRAY), RGB::named(BLACK), to_cp437('·'));
|
||||||
}
|
}
|
||||||
x += 1;
|
x += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::gui::Ancestry;
|
use crate::gui::Ancestry;
|
||||||
use crate::gui::Class;
|
use crate::gui::Class;
|
||||||
use rltk::RGB;
|
use bracket_lib::prelude::*;
|
||||||
use serde::{ Deserialize, Serialize };
|
use serde::{ Deserialize, Serialize };
|
||||||
use specs::error::NoError;
|
use specs::error::NoError;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
@ -40,7 +40,7 @@ pub struct OtherLevelPosition {
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component, ConvertSaveload, Clone)]
|
||||||
pub struct Renderable {
|
pub struct Renderable {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: FontCharType,
|
||||||
pub fg: RGB,
|
pub fg: RGB,
|
||||||
pub bg: RGB,
|
pub bg: RGB,
|
||||||
pub render_order: i32,
|
pub render_order: i32,
|
||||||
|
|
@ -104,14 +104,14 @@ pub struct Mind {}
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component, ConvertSaveload, Clone)]
|
||||||
pub struct Viewshed {
|
pub struct Viewshed {
|
||||||
pub visible_tiles: Vec<rltk::Point>,
|
pub visible_tiles: Vec<Point>,
|
||||||
pub range: i32,
|
pub range: i32,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component, ConvertSaveload, Clone)]
|
||||||
pub struct Telepath {
|
pub struct Telepath {
|
||||||
pub telepath_tiles: Vec<rltk::Point>,
|
pub telepath_tiles: Vec<Point>,
|
||||||
pub range: i32,
|
pub range: i32,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -417,7 +417,7 @@ pub struct WantsToRemoveItem {
|
||||||
#[derive(Component, Debug, ConvertSaveload)]
|
#[derive(Component, Debug, ConvertSaveload)]
|
||||||
pub struct WantsToUseItem {
|
pub struct WantsToUseItem {
|
||||||
pub item: Entity,
|
pub item: Entity,
|
||||||
pub target: Option<rltk::Point>,
|
pub target: Option<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
|
@ -446,8 +446,8 @@ pub struct Charges {
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
pub struct SpawnParticleLine {
|
pub struct SpawnParticleLine {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: FontCharType,
|
||||||
pub tail_glyph: rltk::FontCharType,
|
pub tail_glyph: FontCharType,
|
||||||
pub colour: RGB,
|
pub colour: RGB,
|
||||||
pub lifetime_ms: f32,
|
pub lifetime_ms: f32,
|
||||||
pub trail_colour: RGB,
|
pub trail_colour: RGB,
|
||||||
|
|
@ -456,16 +456,16 @@ pub struct SpawnParticleLine {
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
pub struct SpawnParticleSimple {
|
pub struct SpawnParticleSimple {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: FontCharType,
|
||||||
pub colour: RGB,
|
pub colour: RGB,
|
||||||
pub lifetime_ms: f32,
|
pub lifetime_ms: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
pub struct SpawnParticleBurst {
|
pub struct SpawnParticleBurst {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: FontCharType,
|
||||||
pub head_glyph: rltk::FontCharType,
|
pub head_glyph: FontCharType,
|
||||||
pub tail_glyph: rltk::FontCharType,
|
pub tail_glyph: FontCharType,
|
||||||
pub colour: RGB,
|
pub colour: RGB,
|
||||||
pub lerp: RGB,
|
pub lerp: RGB,
|
||||||
pub lifetime_ms: f32,
|
pub lifetime_ms: f32,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use serde::{ Serialize, Deserialize };
|
use serde::{ Serialize, Deserialize };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use super::{
|
||||||
Renderable,
|
Renderable,
|
||||||
RunState,
|
RunState,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::events;
|
use crate::data::events;
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ pub fn delete_the_dead(ecs: &mut World) {
|
||||||
.append("The")
|
.append("The")
|
||||||
.colour(renderable_colour(&renderables, entity))
|
.colour(renderable_colour(&renderables, entity))
|
||||||
.append(&victim_name.name)
|
.append(&victim_name.name)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.append("is destroyed!")
|
.append("is destroyed!")
|
||||||
.log();
|
.log();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -49,7 +49,7 @@ pub fn delete_the_dead(ecs: &mut World) {
|
||||||
.append("The")
|
.append("The")
|
||||||
.colour(renderable_colour(&renderables, entity))
|
.colour(renderable_colour(&renderables, entity))
|
||||||
.append(&victim_name.name)
|
.append(&victim_name.name)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.append("dies!")
|
.append("dies!")
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +86,10 @@ pub fn delete_the_dead(ecs: &mut World) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_dead_entity_items(ecs: &mut World, dead: &Vec<Entity>) -> (Vec<Entity>, Vec<(String, Position)>) {
|
fn handle_dead_entity_items(
|
||||||
|
ecs: &mut World,
|
||||||
|
dead: &Vec<Entity>
|
||||||
|
) -> (Vec<Entity>, Vec<(String, Position)>) {
|
||||||
let mut to_drop: Vec<(Entity, Position)> = Vec::new();
|
let mut to_drop: Vec<(Entity, Position)> = Vec::new();
|
||||||
let mut to_spawn: Vec<(String, Position)> = Vec::new();
|
let mut to_spawn: Vec<(String, Position)> = Vec::new();
|
||||||
let entities = ecs.entities();
|
let entities = ecs.entities();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::names::*;
|
use super::names::*;
|
||||||
use super::visuals::*;
|
use super::visuals::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub const ID_OVERMAP: i32 = 1;
|
pub const ID_OVERMAP: i32 = 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
// POST-PROCESSING
|
// POST-PROCESSING
|
||||||
pub const WITH_DARKEN_BY_DISTANCE: bool = true; // If further away tiles should get darkened, instead of a harsh transition to non-visible.
|
pub const WITH_DARKEN_BY_DISTANCE: bool = true; // If further away tiles should get darkened, instead of a harsh transition to non-visible.
|
||||||
|
|
||||||
|
|
@ -15,8 +17,8 @@ pub const SHORT_PARTICLE_LIFETIME: f32 = 100.0; // in ms
|
||||||
pub const DEFAULT_PARTICLE_LIFETIME: f32 = 200.0;
|
pub const DEFAULT_PARTICLE_LIFETIME: f32 = 200.0;
|
||||||
pub const LONG_PARTICLE_LIFETIME: f32 = 300.0;
|
pub const LONG_PARTICLE_LIFETIME: f32 = 300.0;
|
||||||
|
|
||||||
pub const TARGETING_CURSOR_COL: (u8, u8, u8) = rltk::GOLDENROD;
|
pub const TARGETING_CURSOR_COL: (u8, u8, u8) = GOLDENROD;
|
||||||
pub const TARGETING_LINE_COL: (u8, u8, u8) = rltk::LIGHTGOLDENROD;
|
pub const TARGETING_LINE_COL: (u8, u8, u8) = LIGHTGOLDENROD;
|
||||||
pub const TARGETING_AOE_COL: (u8, u8, u8) = (20, 20, 20);
|
pub const TARGETING_AOE_COL: (u8, u8, u8) = (20, 20, 20);
|
||||||
pub const TARGETING_VALID_COL: (u8, u8, u8) = (10, 10, 10);
|
pub const TARGETING_VALID_COL: (u8, u8, u8) = (10, 10, 10);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME };
|
||||||
use crate::data::messages::LEVELUP_PLAYER;
|
use crate::data::messages::LEVELUP_PLAYER;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
use crate::data::messages::*;
|
use crate::data::messages::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::BUC;
|
use super::BUC;
|
||||||
use crate::spatial;
|
use crate::spatial;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{ add_effect, targeting, EffectSpawner, EffectType, Targets };
|
use super::{ add_effect, targeting, EffectSpawner, EffectType, Targets };
|
||||||
use crate::{ Map, ParticleBuilder, SpawnParticleBurst, SpawnParticleLine, SpawnParticleSimple };
|
use crate::{ Map, ParticleBuilder, SpawnParticleBurst, SpawnParticleLine, SpawnParticleSimple };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub fn particle_to_tile(ecs: &mut World, target: i32, effect: &EffectSpawner) {
|
pub fn particle_to_tile(ecs: &mut World, target: i32, effect: &EffectSpawner) {
|
||||||
|
|
@ -8,9 +8,24 @@ pub fn particle_to_tile(ecs: &mut World, target: i32, effect: &EffectSpawner) {
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let mut particle_builder = ecs.fetch_mut::<ParticleBuilder>();
|
let mut particle_builder = ecs.fetch_mut::<ParticleBuilder>();
|
||||||
if delay <= 0.0 {
|
if delay <= 0.0 {
|
||||||
particle_builder.request(target % map.width, target / map.width, fg, bg, glyph, lifespan);
|
particle_builder.request(
|
||||||
|
target % map.width,
|
||||||
|
target / map.width,
|
||||||
|
fg,
|
||||||
|
bg,
|
||||||
|
glyph,
|
||||||
|
lifespan
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
particle_builder.delay(target % map.width, target / map.width, fg, bg, glyph, lifespan, delay);
|
particle_builder.delay(
|
||||||
|
target % map.width,
|
||||||
|
target / map.width,
|
||||||
|
fg,
|
||||||
|
bg,
|
||||||
|
glyph,
|
||||||
|
lifespan,
|
||||||
|
delay
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,9 +128,14 @@ pub fn handle_line_particles(ecs: &World, entity: Entity, target: &Targets) {
|
||||||
if let Some(part) = ecs.read_storage::<SpawnParticleLine>().get(entity) {
|
if let Some(part) = ecs.read_storage::<SpawnParticleLine>().get(entity) {
|
||||||
if let Some(start_pos) = targeting::find_item_position(ecs, entity) {
|
if let Some(start_pos) = targeting::find_item_position(ecs, entity) {
|
||||||
match target {
|
match target {
|
||||||
Targets::Tile { target } => spawn_line_particles(ecs, start_pos, *target as i32, part),
|
Targets::Tile { target } =>
|
||||||
|
spawn_line_particles(ecs, start_pos, *target as i32, part),
|
||||||
Targets::TileList { targets } => {
|
Targets::TileList { targets } => {
|
||||||
targets.iter().for_each(|target| spawn_line_particles(ecs, start_pos, *target as i32, part))
|
targets
|
||||||
|
.iter()
|
||||||
|
.for_each(|target|
|
||||||
|
spawn_line_particles(ecs, start_pos, *target as i32, part)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Targets::Entity { target } => {
|
Targets::Entity { target } => {
|
||||||
if let Some(end_pos) = targeting::entity_position(ecs, *target) {
|
if let Some(end_pos) = targeting::entity_position(ecs, *target) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{ Equipped, InBackpack, Map, Position };
|
use crate::{ Equipped, InBackpack, Map, Position };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub fn entity_position(ecs: &World, target: Entity) -> Option<usize> {
|
pub fn entity_position(ecs: &World, target: Entity) -> Option<usize> {
|
||||||
|
|
@ -10,8 +10,8 @@ pub fn entity_position(ecs: &World, target: Entity) -> Option<usize> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aoe_tiles(map: &Map, target: rltk::Point, radius: i32) -> Vec<usize> {
|
pub fn aoe_tiles(map: &Map, target: Point, radius: i32) -> Vec<usize> {
|
||||||
let mut blast_tiles = rltk::field_of_view(target, radius, &*map);
|
let mut blast_tiles = field_of_view(target, radius, &*map);
|
||||||
blast_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
blast_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for t in blast_tiles.iter() {
|
for t in blast_tiles.iter() {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ use crate::{
|
||||||
Viewshed,
|
Viewshed,
|
||||||
};
|
};
|
||||||
use crate::data::messages::*;
|
use crate::data::messages::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
pub fn item_trigger(source: Option<Entity>, item: Entity, target: &Targets, ecs: &mut World) {
|
pub fn item_trigger(source: Option<Entity>, item: Entity, target: &Targets, ecs: &mut World) {
|
||||||
// Check if the item has charges, etc.
|
// Check if the item has charges, etc.
|
||||||
|
|
@ -47,8 +47,10 @@ pub fn item_trigger(source: Option<Entity>, item: Entity, target: &Targets, ecs:
|
||||||
gamelog::Logger::new().append(NOCHARGES_DIDNOTHING).log();
|
gamelog::Logger::new().append(NOCHARGES_DIDNOTHING).log();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gamelog::Logger::new().colour(rltk::YELLOW).append(NOCHARGES_WREST);
|
gamelog::Logger::new().colour(YELLOW).append(NOCHARGES_WREST);
|
||||||
ecs.write_storage::<Consumable>().insert(item, Consumable {}).expect("Could not insert consumable");
|
ecs.write_storage::<Consumable>()
|
||||||
|
.insert(item, Consumable {})
|
||||||
|
.expect("Could not insert consumable");
|
||||||
}
|
}
|
||||||
has_charges.uses -= 1;
|
has_charges.uses -= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +85,12 @@ struct EventInfo {
|
||||||
// It does almost no sanity-checking to make sure the logs only appear if the effect is taking
|
// It does almost no sanity-checking to make sure the logs only appear if the effect is taking
|
||||||
// place on the player -- once monsters can use an item, their item usage will make logs for
|
// place on the player -- once monsters can use an item, their item usage will make logs for
|
||||||
// the player saying they were the one who used the item. This will need refactoring then.
|
// the player saying they were the one who used the item. This will need refactoring then.
|
||||||
fn event_trigger(source: Option<Entity>, entity: Entity, target: &Targets, ecs: &mut World) -> bool {
|
fn event_trigger(
|
||||||
|
source: Option<Entity>,
|
||||||
|
entity: Entity,
|
||||||
|
target: &Targets,
|
||||||
|
ecs: &mut World
|
||||||
|
) -> bool {
|
||||||
let buc = if let Some(beatitude) = ecs.read_storage::<Beatitude>().get(entity) {
|
let buc = if let Some(beatitude) = ecs.read_storage::<Beatitude>().get(entity) {
|
||||||
beatitude.buc.clone()
|
beatitude.buc.clone()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -147,7 +154,11 @@ fn handle_restore_nutrition(
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_magic_mapper(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_magic_mapper(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if ecs.read_storage::<MagicMapper>().get(event.entity).is_some() {
|
if ecs.read_storage::<MagicMapper>().get(event.entity).is_some() {
|
||||||
let mut runstate = ecs.fetch_mut::<RunState>();
|
let mut runstate = ecs.fetch_mut::<RunState>();
|
||||||
let cursed = if event.buc == BUC::Cursed { true } else { false };
|
let cursed = if event.buc == BUC::Cursed { true } else { false };
|
||||||
|
|
@ -159,9 +170,17 @@ fn handle_magic_mapper(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_grant_spell(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_grant_spell(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(granted_spell) = ecs.read_storage::<GrantsSpell>().get(event.entity) {
|
if let Some(granted_spell) = ecs.read_storage::<GrantsSpell>().get(event.entity) {
|
||||||
if let Some(known_spells) = ecs.write_storage::<KnownSpells>().get_mut(event.source.unwrap()) {
|
if
|
||||||
|
let Some(known_spells) = ecs
|
||||||
|
.write_storage::<KnownSpells>()
|
||||||
|
.get_mut(event.source.unwrap())
|
||||||
|
{
|
||||||
// TODO: Check if the player knows *this* spell, and add it if not.
|
// TODO: Check if the player knows *this* spell, and add it if not.
|
||||||
} else {
|
} else {
|
||||||
// TODO: Grant the KnownSpells component, and then add the spell.
|
// TODO: Grant the KnownSpells component, and then add the spell.
|
||||||
|
|
@ -170,7 +189,11 @@ fn handle_grant_spell(ecs: &mut World, event: &mut EventInfo, mut logger: gamelo
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_healing(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(healing_item) = ecs.read_storage::<ProvidesHealing>().get(event.entity) {
|
if let Some(healing_item) = ecs.read_storage::<ProvidesHealing>().get(event.entity) {
|
||||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let buc_mod = match event.buc {
|
let buc_mod = match event.buc {
|
||||||
|
|
@ -178,14 +201,19 @@ fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::L
|
||||||
BUC::Cursed => -1,
|
BUC::Cursed => -1,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
let roll = rng.roll_dice(healing_item.n_dice + buc_mod, healing_item.sides) + healing_item.modifier;
|
let roll =
|
||||||
|
rng.roll_dice(healing_item.n_dice + buc_mod, healing_item.sides) +
|
||||||
|
healing_item.modifier;
|
||||||
add_effect(
|
add_effect(
|
||||||
event.source,
|
event.source,
|
||||||
EffectType::Healing { amount: roll, increment_max: get_noncursed(&event.buc) },
|
EffectType::Healing { amount: roll, increment_max: get_noncursed(&event.buc) },
|
||||||
event.target.clone()
|
event.target.clone()
|
||||||
);
|
);
|
||||||
for target in get_entity_targets(&event.target) {
|
for target in get_entity_targets(&event.target) {
|
||||||
if ecs.read_storage::<Prop>().get(target).is_some() || ecs.read_storage::<Item>().get(target).is_some() {
|
if
|
||||||
|
ecs.read_storage::<Prop>().get(target).is_some() ||
|
||||||
|
ecs.read_storage::<Item>().get(target).is_some()
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let renderables = ecs.read_storage::<Renderable>();
|
let renderables = ecs.read_storage::<Renderable>();
|
||||||
|
|
@ -211,7 +239,11 @@ fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::L
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_damage(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_damage(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(damage_item) = ecs.read_storage::<InflictsDamage>().get(event.entity) {
|
if let Some(damage_item) = ecs.read_storage::<InflictsDamage>().get(event.entity) {
|
||||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let roll = rng.roll_dice(damage_item.n_dice, damage_item.sides) + damage_item.modifier;
|
let roll = rng.roll_dice(damage_item.n_dice, damage_item.sides) + damage_item.modifier;
|
||||||
|
|
@ -232,7 +264,9 @@ fn handle_damage(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Lo
|
||||||
.colour(WHITE)
|
.colour(WHITE)
|
||||||
.append(DAMAGE_PLAYER_HIT);
|
.append(DAMAGE_PLAYER_HIT);
|
||||||
event.log = true;
|
event.log = true;
|
||||||
} else if player_viewshed.visible_tiles.contains(&Point::new(target_pos.x, target_pos.y)) {
|
} else if
|
||||||
|
player_viewshed.visible_tiles.contains(&Point::new(target_pos.x, target_pos.y))
|
||||||
|
{
|
||||||
if ecs.read_storage::<Item>().get(target).is_some() {
|
if ecs.read_storage::<Item>().get(target).is_some() {
|
||||||
if ecs.read_storage::<Destructible>().get(target).is_some() {
|
if ecs.read_storage::<Destructible>().get(target).is_some() {
|
||||||
logger = logger
|
logger = logger
|
||||||
|
|
@ -259,9 +293,17 @@ fn handle_damage(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Lo
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
fn handle_confusion(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_confusion(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(confusion) = ecs.read_storage::<Confusion>().get(event.entity) {
|
if let Some(confusion) = ecs.read_storage::<Confusion>().get(event.entity) {
|
||||||
add_effect(event.source, EffectType::Confusion { turns: confusion.turns }, event.target.clone());
|
add_effect(
|
||||||
|
event.source,
|
||||||
|
EffectType::Confusion { turns: confusion.turns },
|
||||||
|
event.target.clone()
|
||||||
|
);
|
||||||
return (logger, true);
|
return (logger, true);
|
||||||
}
|
}
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
|
|
@ -272,7 +314,11 @@ fn select_single(ecs: &World, runstate: RunState) {
|
||||||
*new_runstate = runstate;
|
*new_runstate = runstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_identify(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(_i) = ecs.read_storage::<ProvidesIdentify>().get(event.entity) {
|
if let Some(_i) = ecs.read_storage::<ProvidesIdentify>().get(event.entity) {
|
||||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let mut dm = ecs.fetch_mut::<MasterDungeonMap>();
|
let mut dm = ecs.fetch_mut::<MasterDungeonMap>();
|
||||||
|
|
@ -303,7 +349,10 @@ fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::
|
||||||
.get(event.source.unwrap())
|
.get(event.source.unwrap())
|
||||||
.map(|b| b.known)
|
.map(|b| b.known)
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
return in_this_backpack && (has_obfuscated_name || !already_identified || !known_beatitude);
|
return (
|
||||||
|
in_this_backpack &&
|
||||||
|
(has_obfuscated_name || !already_identified || !known_beatitude)
|
||||||
|
);
|
||||||
}) {
|
}) {
|
||||||
to_identify.push((e, name.name.clone()));
|
to_identify.push((e, name.name.clone()));
|
||||||
}
|
}
|
||||||
|
|
@ -313,14 +362,20 @@ fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::
|
||||||
beatitude.known = true;
|
beatitude.known = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger = logger.append(IDENTIFY_ALL).buc(event.buc.clone(), None, Some(IDENTIFY_ALL_BLESSED));
|
logger = logger
|
||||||
|
.append(IDENTIFY_ALL)
|
||||||
|
.buc(event.buc.clone(), None, Some(IDENTIFY_ALL_BLESSED));
|
||||||
event.log = true;
|
event.log = true;
|
||||||
return (logger, true);
|
return (logger, true);
|
||||||
}
|
}
|
||||||
return (logger, false);
|
return (logger, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
fn handle_remove_curse(
|
||||||
|
ecs: &mut World,
|
||||||
|
event: &mut EventInfo,
|
||||||
|
mut logger: gamelog::Logger
|
||||||
|
) -> (gamelog::Logger, bool) {
|
||||||
if let Some(_r) = ecs.read_storage::<ProvidesRemoveCurse>().get(event.entity) {
|
if let Some(_r) = ecs.read_storage::<ProvidesRemoveCurse>().get(event.entity) {
|
||||||
let mut to_decurse: Vec<Entity> = Vec::new();
|
let mut to_decurse: Vec<Entity> = Vec::new();
|
||||||
match event.buc {
|
match event.buc {
|
||||||
|
|
@ -338,7 +393,9 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
||||||
&ecs.read_storage::<Beatitude>(),
|
&ecs.read_storage::<Beatitude>(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter(|(_e, _i, bp, b)| bp.owner == event.source.unwrap() && b.buc == BUC::Cursed) {
|
.filter(
|
||||||
|
|(_e, _i, bp, b)| bp.owner == event.source.unwrap() && b.buc == BUC::Cursed
|
||||||
|
) {
|
||||||
to_decurse.push(entity);
|
to_decurse.push(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +424,9 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
||||||
}
|
}
|
||||||
let mut beatitudes = ecs.write_storage::<Beatitude>();
|
let mut beatitudes = ecs.write_storage::<Beatitude>();
|
||||||
for e in to_decurse {
|
for e in to_decurse {
|
||||||
beatitudes.insert(e, Beatitude { buc: BUC::Uncursed, known: true }).expect("Unable to insert beatitude");
|
beatitudes
|
||||||
|
.insert(e, Beatitude { buc: BUC::Uncursed, known: true })
|
||||||
|
.expect("Unable to insert beatitude");
|
||||||
}
|
}
|
||||||
logger = logger.append(REMOVECURSE).buc(event.buc.clone(), None, Some(REMOVECURSE_BLESSED));
|
logger = logger.append(REMOVECURSE).buc(event.buc.clone(), None, Some(REMOVECURSE_BLESSED));
|
||||||
event.log = true;
|
event.log = true;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{ append_entry, LogFragment };
|
use super::{ append_entry, LogFragment };
|
||||||
use crate::BUC;
|
use crate::BUC;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct Logger {
|
pub struct Logger {
|
||||||
current_colour: RGB,
|
current_colour: RGB,
|
||||||
|
|
@ -10,7 +10,7 @@ pub struct Logger {
|
||||||
impl Logger {
|
impl Logger {
|
||||||
/// Creates a blank builder for making message log entries.
|
/// Creates a blank builder for making message log entries.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Logger { current_colour: RGB::named(rltk::WHITE), fragments: Vec::new() }
|
Logger { current_colour: RGB::named(WHITE), fragments: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the colour of the current message logger.
|
/// Sets the colour of the current message logger.
|
||||||
|
|
@ -42,11 +42,23 @@ impl Logger {
|
||||||
|
|
||||||
pub fn buc<T: ToString>(mut self, buc: BUC, cursed: Option<T>, blessed: Option<T>) -> Self {
|
pub fn buc<T: ToString>(mut self, buc: BUC, cursed: Option<T>, blessed: Option<T>) -> Self {
|
||||||
if buc == BUC::Cursed && cursed.is_some() {
|
if buc == BUC::Cursed && cursed.is_some() {
|
||||||
self.fragments.push(LogFragment { colour: RGB::named(SALMON), text: cursed.unwrap().to_string() });
|
self.fragments.push(LogFragment {
|
||||||
self.fragments.push(LogFragment { colour: self.current_colour, text: ". ".to_string() });
|
colour: RGB::named(SALMON),
|
||||||
|
text: cursed.unwrap().to_string(),
|
||||||
|
});
|
||||||
|
self.fragments.push(LogFragment {
|
||||||
|
colour: self.current_colour,
|
||||||
|
text: ". ".to_string(),
|
||||||
|
});
|
||||||
} else if buc == BUC::Blessed && blessed.is_some() {
|
} else if buc == BUC::Blessed && blessed.is_some() {
|
||||||
self.fragments.push(LogFragment { colour: RGB::named(CYAN), text: blessed.unwrap().to_string() });
|
self.fragments.push(LogFragment {
|
||||||
self.fragments.push(LogFragment { colour: self.current_colour, text: ". ".to_string() });
|
colour: RGB::named(CYAN),
|
||||||
|
text: blessed.unwrap().to_string(),
|
||||||
|
});
|
||||||
|
self.fragments.push(LogFragment {
|
||||||
|
colour: self.current_colour,
|
||||||
|
text: ". ".to_string(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ events, LogFragment, Logger };
|
use super::{ events, LogFragment, Logger };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
@ -19,7 +19,13 @@ pub fn clear_log() {
|
||||||
LOG.lock().unwrap().clear();
|
LOG.lock().unwrap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_log(console: &mut Box<dyn Console>, pos: Point, _descending: bool, len: usize, maximum_len: i32) {
|
pub fn print_log(
|
||||||
|
console: &mut Box<dyn Console>,
|
||||||
|
pos: Point,
|
||||||
|
_descending: bool,
|
||||||
|
len: usize,
|
||||||
|
maximum_len: i32
|
||||||
|
) {
|
||||||
let mut y = pos.y;
|
let mut y = pos.y;
|
||||||
let mut x = pos.x;
|
let mut x = pos.x;
|
||||||
// Reverse the log, take the number we want to show, and iterate through them
|
// Reverse the log, take the number we want to show, and iterate through them
|
||||||
|
|
@ -61,7 +67,13 @@ pub fn print_log(console: &mut Box<dyn Console>, pos: Point, _descending: bool,
|
||||||
}
|
}
|
||||||
// Stay within bounds
|
// Stay within bounds
|
||||||
if y > pos.y - (len as i32) {
|
if y > pos.y - (len as i32) {
|
||||||
console.print_color(x, y, frag.colour.into(), RGB::named(rltk::BLACK).into(), part);
|
console.print_color(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
frag.colour.into(),
|
||||||
|
RGB::named(BLACK).into(),
|
||||||
|
part
|
||||||
|
);
|
||||||
}
|
}
|
||||||
x += part.len() as i32;
|
x += part.len() as i32;
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +92,7 @@ pub fn setup_log() {
|
||||||
|
|
||||||
Logger::new()
|
Logger::new()
|
||||||
.append("Welcome!")
|
.append("Welcome!")
|
||||||
.colour(rltk::CYAN)
|
.colour(CYAN)
|
||||||
.append_n("Press [?] at any time to view controls")
|
.append_n("Press [?] at any time to view controls")
|
||||||
.period()
|
.period()
|
||||||
.log();
|
.log();
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ mod events;
|
||||||
pub use events::*;
|
pub use events::*;
|
||||||
|
|
||||||
use serde::{ Deserialize, Serialize };
|
use serde::{ Deserialize, Serialize };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct LogFragment {
|
pub struct LogFragment {
|
||||||
pub colour: RGB,
|
pub colour: RGB,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use super::{ Skill, Skills };
|
||||||
use crate::gui::{ Ancestry, Class };
|
use crate::gui::{ Ancestry, Class };
|
||||||
use crate::data::entity;
|
use crate::data::entity;
|
||||||
use crate::data::char_create::*;
|
use crate::data::char_create::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
/// Returns the attribute bonus for a given attribute score, where every 2 points above
|
/// Returns the attribute bonus for a given attribute score, where every 2 points above
|
||||||
|
|
@ -12,13 +12,13 @@ pub fn attr_bonus(value: i32) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of HP gained per level for a given constitution score.
|
/// Returns the number of HP gained per level for a given constitution score.
|
||||||
pub fn hp_per_level(rng: &mut rltk::RandomNumberGenerator, constitution: i32) -> i32 {
|
pub fn hp_per_level(rng: &mut RandomNumberGenerator, constitution: i32) -> i32 {
|
||||||
return max(rng.roll_dice(1, entity::STANDARD_HIT_DIE) + attr_bonus(constitution), 1);
|
return max(rng.roll_dice(1, entity::STANDARD_HIT_DIE) + attr_bonus(constitution), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// Returns a total HP roll for a player, based on a given constitution score and level.
|
/// Returns a total HP roll for a player, based on a given constitution score and level.
|
||||||
pub fn player_hp_at_level(rng: &mut rltk::RandomNumberGenerator, constitution: i32, level: i32) -> i32 {
|
pub fn player_hp_at_level(rng: &mut RandomNumberGenerator, constitution: i32, level: i32) -> i32 {
|
||||||
let mut total = entity::STANDARD_HIT_DIE + attr_bonus(constitution);
|
let mut total = entity::STANDARD_HIT_DIE + attr_bonus(constitution);
|
||||||
for _i in 0..level {
|
for _i in 0..level {
|
||||||
total += hp_per_level(rng, constitution);
|
total += hp_per_level(rng, constitution);
|
||||||
|
|
@ -27,7 +27,7 @@ pub fn player_hp_at_level(rng: &mut rltk::RandomNumberGenerator, constitution: i
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a total HP roll for an NPC, based on a given constitution score and level.
|
/// Returns a total HP roll for an NPC, based on a given constitution score and level.
|
||||||
pub fn npc_hp_at_level(rng: &mut rltk::RandomNumberGenerator, constitution: i32, level: i32) -> i32 {
|
pub fn npc_hp_at_level(rng: &mut RandomNumberGenerator, constitution: i32, level: i32) -> i32 {
|
||||||
if level == 0 {
|
if level == 0 {
|
||||||
return rng.roll_dice(1, entity::STANDARD_HIT_DIE_0);
|
return rng.roll_dice(1, entity::STANDARD_HIT_DIE_0);
|
||||||
}
|
}
|
||||||
|
|
@ -39,12 +39,12 @@ pub fn npc_hp_at_level(rng: &mut rltk::RandomNumberGenerator, constitution: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of mana gained per level for a given intelligence score.
|
/// Returns the number of mana gained per level for a given intelligence score.
|
||||||
pub fn mana_per_level(rng: &mut rltk::RandomNumberGenerator, intelligence: i32) -> i32 {
|
pub fn mana_per_level(rng: &mut RandomNumberGenerator, intelligence: i32) -> i32 {
|
||||||
return max(rng.roll_dice(1, entity::STANDARD_MANA_DIE) + attr_bonus(intelligence), 1);
|
return max(rng.roll_dice(1, entity::STANDARD_MANA_DIE) + attr_bonus(intelligence), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of mana gained per level for a given intelligence score.
|
/// Returns the number of mana gained per level for a given intelligence score.
|
||||||
pub fn mana_at_level(rng: &mut rltk::RandomNumberGenerator, intelligence: i32, level: i32) -> i32 {
|
pub fn mana_at_level(rng: &mut RandomNumberGenerator, intelligence: i32, level: i32) -> i32 {
|
||||||
let mut total = entity::MINIMUM_MANA;
|
let mut total = entity::MINIMUM_MANA;
|
||||||
for _i in 0..level {
|
for _i in 0..level {
|
||||||
total += mana_per_level(rng, intelligence);
|
total += mana_per_level(rng, intelligence);
|
||||||
|
|
@ -63,7 +63,7 @@ pub fn skill_bonus(skill: Skill, skills: &Skills) -> i32 {
|
||||||
|
|
||||||
/// Roll 4d6 and drop the lowest, for rolling d20-style stats
|
/// Roll 4d6 and drop the lowest, for rolling d20-style stats
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn roll_4d6(rng: &mut rltk::RandomNumberGenerator) -> i32 {
|
pub fn roll_4d6(rng: &mut RandomNumberGenerator) -> i32 {
|
||||||
let mut rolls: Vec<i32> = Vec::new();
|
let mut rolls: Vec<i32> = Vec::new();
|
||||||
for _i in 0..4 {
|
for _i in 0..4 {
|
||||||
rolls.push(rng.roll_dice(1, 6));
|
rolls.push(rng.roll_dice(1, 6));
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ use crate::{
|
||||||
Telepath,
|
Telepath,
|
||||||
BUC,
|
BUC,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use serde::{ Deserialize, Serialize };
|
use serde::{ Deserialize, Serialize };
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -111,14 +111,14 @@ pub enum CharCreateResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the player character creation screen.
|
/// Handles the player character creation screen.
|
||||||
pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
pub fn character_creation(gs: &mut State, ctx: &mut BTerm) -> CharCreateResult {
|
||||||
let runstate = gs.ecs.fetch::<RunState>();
|
let runstate = gs.ecs.fetch::<RunState>();
|
||||||
|
|
||||||
let mut x = 2;
|
let mut x = 2;
|
||||||
let mut y = 11;
|
let mut y = 11;
|
||||||
let column_width = 20;
|
let column_width = 20;
|
||||||
|
|
||||||
ctx.print_color(x, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), CHAR_CREATE_HEADER);
|
ctx.print_color(x, y, RGB::named(WHITE), RGB::named(BLACK), CHAR_CREATE_HEADER);
|
||||||
y += 2;
|
y += 2;
|
||||||
|
|
||||||
if let RunState::CharacterCreation { ancestry, class } = *runstate {
|
if let RunState::CharacterCreation { ancestry, class } = *runstate {
|
||||||
|
|
@ -269,9 +269,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
|
||||||
Ancestry::Dwarf => {
|
Ancestry::Dwarf => {
|
||||||
renderables
|
renderables
|
||||||
.insert(*player, Renderable {
|
.insert(*player, Renderable {
|
||||||
glyph: rltk::to_cp437(DWARF_GLYPH),
|
glyph: to_cp437(DWARF_GLYPH),
|
||||||
fg: RGB::named(DWARF_COLOUR),
|
fg: RGB::named(DWARF_COLOUR),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(BLACK),
|
||||||
render_order: 0,
|
render_order: 0,
|
||||||
})
|
})
|
||||||
.expect("Unable to insert renderable component");
|
.expect("Unable to insert renderable component");
|
||||||
|
|
@ -280,9 +280,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
|
||||||
Ancestry::Elf => {
|
Ancestry::Elf => {
|
||||||
renderables
|
renderables
|
||||||
.insert(*player, Renderable {
|
.insert(*player, Renderable {
|
||||||
glyph: rltk::to_cp437(ELF_GLYPH),
|
glyph: to_cp437(ELF_GLYPH),
|
||||||
fg: RGB::named(ELF_COLOUR),
|
fg: RGB::named(ELF_COLOUR),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(BLACK),
|
||||||
render_order: 0,
|
render_order: 0,
|
||||||
})
|
})
|
||||||
.expect("Unable to insert renderable component");
|
.expect("Unable to insert renderable component");
|
||||||
|
|
@ -305,9 +305,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
|
||||||
Ancestry::Catfolk => {
|
Ancestry::Catfolk => {
|
||||||
renderables
|
renderables
|
||||||
.insert(*player, Renderable {
|
.insert(*player, Renderable {
|
||||||
glyph: rltk::to_cp437(CATFOLK_GLYPH),
|
glyph: to_cp437(CATFOLK_GLYPH),
|
||||||
fg: RGB::named(CATFOLK_COLOUR),
|
fg: RGB::named(CATFOLK_COLOUR),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(BLACK),
|
||||||
render_order: 0,
|
render_order: 0,
|
||||||
})
|
})
|
||||||
.expect("Unable to insert renderable component");
|
.expect("Unable to insert renderable component");
|
||||||
|
|
@ -451,11 +451,11 @@ fn pick_random_table_item(
|
||||||
rng: &mut RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
push_to: &mut Vec<String>,
|
push_to: &mut Vec<String>,
|
||||||
table: &'static str,
|
table: &'static str,
|
||||||
dice: &'static str,
|
dice_str: &'static str,
|
||||||
difficulty: Option<i32>
|
difficulty: Option<i32>
|
||||||
) {
|
) {
|
||||||
let (n, d, m) = raws::parse_dice_string(dice);
|
let dice = parse_dice_string(dice_str).expect("Error parsing dice");
|
||||||
for _i in 0..rng.roll_dice(n, d) + m {
|
for _i in 0..rng.roll_dice(dice.n_dice, dice.die_type) + dice.bonus {
|
||||||
push_to.push(raws::table_by_name(&raws::RAWS.lock().unwrap(), table, difficulty).roll(rng));
|
push_to.push(raws::table_by_name(&raws::RAWS.lock().unwrap(), table, difficulty).roll(rng));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::State;
|
use super::State;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum CheatMenuResult {
|
pub enum CheatMenuResult {
|
||||||
|
|
@ -12,13 +12,13 @@ pub enum CheatMenuResult {
|
||||||
GodMode,
|
GodMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_cheat_menu(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
pub fn show_cheat_menu(_gs: &mut State, ctx: &mut BTerm) -> CheatMenuResult {
|
||||||
let (x_offset, y_offset) = (1, 10);
|
let (x_offset, y_offset) = (1, 10);
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::RED),
|
RGB::named(RED),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"DEBUG MENU! [aA-zZ][Esc.]"
|
"DEBUG MENU! [aA-zZ][Esc.]"
|
||||||
);
|
);
|
||||||
let x = 1 + x_offset;
|
let x = 1 + x_offset;
|
||||||
|
|
@ -26,26 +26,26 @@ pub fn show_cheat_menu(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
||||||
let count = 5;
|
let count = 5;
|
||||||
let width = 19;
|
let width = 19;
|
||||||
|
|
||||||
ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(rltk::RED), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(RED), RGB::named(BLACK));
|
||||||
y += 1;
|
y += 1;
|
||||||
// Asc
|
// Asc
|
||||||
ctx.set(x_offset + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), rltk::to_cp437('a'));
|
ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('a'));
|
||||||
ctx.print(x_offset + 4, y, "ASCEND A FLOOR");
|
ctx.print(x_offset + 4, y, "ASCEND A FLOOR");
|
||||||
y += 1;
|
y += 1;
|
||||||
// Desc
|
// Desc
|
||||||
ctx.set(x_offset + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), rltk::to_cp437('d'));
|
ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('d'));
|
||||||
ctx.print(x_offset + 4, y, "DESCEND A FLOOR");
|
ctx.print(x_offset + 4, y, "DESCEND A FLOOR");
|
||||||
y += 1;
|
y += 1;
|
||||||
// Heal
|
// Heal
|
||||||
ctx.set(x_offset + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), rltk::to_cp437('h'));
|
ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('h'));
|
||||||
ctx.print(x_offset + 4, y, "HEAL TO FULL");
|
ctx.print(x_offset + 4, y, "HEAL TO FULL");
|
||||||
y += 1;
|
y += 1;
|
||||||
// Reveal map
|
// Reveal map
|
||||||
ctx.set(x_offset + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), rltk::to_cp437('m'));
|
ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('m'));
|
||||||
ctx.print(x_offset + 4, y, "MAGIC MAP REVEAL");
|
ctx.print(x_offset + 4, y, "MAGIC MAP REVEAL");
|
||||||
y += 1;
|
y += 1;
|
||||||
// Godmode
|
// Godmode
|
||||||
ctx.set(x_offset + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), rltk::to_cp437('g'));
|
ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('g'));
|
||||||
ctx.print(x_offset + 4, y, "GOD MODE");
|
ctx.print(x_offset + 4, y, "GOD MODE");
|
||||||
// Match keys
|
// Match keys
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ State, RunState, tooltip::draw_tooltips, camera::get_screen_bounds };
|
use super::{ State, RunState, tooltip::draw_tooltips, camera::get_screen_bounds };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum FarlookResult {
|
pub enum FarlookResult {
|
||||||
|
|
@ -10,7 +10,7 @@ pub enum FarlookResult {
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_farlook(gs: &mut State, ctx: &mut Rltk) -> FarlookResult {
|
pub fn show_farlook(gs: &mut State, ctx: &mut BTerm) -> FarlookResult {
|
||||||
let runstate = gs.ecs.fetch::<RunState>();
|
let runstate = gs.ecs.fetch::<RunState>();
|
||||||
let (_min_x, _max_x, _min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs, ctx);
|
let (_min_x, _max_x, _min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs, ctx);
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub fn show_farlook(gs: &mut State, ctx: &mut Rltk) -> FarlookResult {
|
||||||
let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32));
|
let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32));
|
||||||
let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32));
|
let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32));
|
||||||
|
|
||||||
ctx.set(x, y, RGB::named(WHITE), RGB::named(BLACK), rltk::to_cp437('X'));
|
ctx.set(x, y, RGB::named(WHITE), RGB::named(BLACK), to_cp437('X'));
|
||||||
draw_tooltips(&gs.ecs, ctx, Some((x, y)));
|
draw_tooltips(&gs.ecs, ctx, Some((x, y)));
|
||||||
|
|
||||||
return match ctx.key {
|
return match ctx.key {
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ use crate::{
|
||||||
Renderable,
|
Renderable,
|
||||||
states::state::*,
|
states::state::*,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// Handles the Identify menu.
|
/// Handles the Identify menu.
|
||||||
pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
|
||||||
let player_entity = gs.ecs.fetch::<Entity>();
|
let player_entity = gs.ecs.fetch::<Entity>();
|
||||||
let equipped = gs.ecs.read_storage::<Equipped>();
|
let equipped = gs.ecs.read_storage::<Equipped>();
|
||||||
let backpack = gs.ecs.read_storage::<InBackpack>();
|
let backpack = gs.ecs.read_storage::<InBackpack>();
|
||||||
|
|
@ -58,7 +58,8 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
||||||
}
|
}
|
||||||
// If not obfuscated, or already identified, return false.
|
// If not obfuscated, or already identified, return false.
|
||||||
if
|
if
|
||||||
(!obfuscated.get(*item_entity).is_some() || dm.identified_items.contains(&n.name)) &&
|
(!obfuscated.get(*item_entity).is_some() ||
|
||||||
|
dm.identified_items.contains(&n.name)) &&
|
||||||
beatitudes
|
beatitudes
|
||||||
.get(*item_entity)
|
.get(*item_entity)
|
||||||
.map(|beatitude| beatitude.known)
|
.map(|beatitude| beatitude.known)
|
||||||
|
|
@ -93,7 +94,9 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
||||||
let mut player_inventory: super::PlayerInventory = BTreeMap::new();
|
let mut player_inventory: super::PlayerInventory = BTreeMap::new();
|
||||||
for (entity, _i, renderable, name) in build_identify_iterator() {
|
for (entity, _i, renderable, name) in build_identify_iterator() {
|
||||||
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
|
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
|
||||||
let beatitude_status = if let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity) {
|
let beatitude_status = if
|
||||||
|
let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity)
|
||||||
|
{
|
||||||
match beatitude.buc {
|
match beatitude.buc {
|
||||||
BUC::Blessed => 1,
|
BUC::Blessed => 1,
|
||||||
BUC::Uncursed => 2,
|
BUC::Uncursed => 2,
|
||||||
|
|
@ -125,8 +128,8 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"Identify which item? [aA-zZ][Esc.]"
|
"Identify which item? [aA-zZ][Esc.]"
|
||||||
);
|
);
|
||||||
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
|
|
@ -138,7 +141,7 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||||
_ => {
|
_ => {
|
||||||
let selection = rltk::letter_to_option(key);
|
let selection = letter_to_option(key);
|
||||||
if selection > -1 && selection < (count as i32) {
|
if selection > -1 && selection < (count as i32) {
|
||||||
let item = player_inventory
|
let item = player_inventory
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub fn letter_to_option(key: VirtualKeyCode, shift: bool) -> i32 {
|
pub fn letter_to_option(key: VirtualKeyCode, shift: bool) -> i32 {
|
||||||
if shift {
|
if shift {
|
||||||
|
|
|
||||||
476
src/gui/mod.rs
476
src/gui/mod.rs
|
|
@ -35,8 +35,13 @@ use super::{
|
||||||
data::ids::get_local_col,
|
data::ids::get_local_col,
|
||||||
};
|
};
|
||||||
use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH;
|
use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH;
|
||||||
use crate::data::visuals::{ TARGETING_LINE_COL, TARGETING_CURSOR_COL, TARGETING_AOE_COL, TARGETING_VALID_COL };
|
use crate::data::visuals::{
|
||||||
use rltk::prelude::*;
|
TARGETING_LINE_COL,
|
||||||
|
TARGETING_CURSOR_COL,
|
||||||
|
TARGETING_AOE_COL,
|
||||||
|
TARGETING_VALID_COL,
|
||||||
|
};
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
mod character_creation;
|
mod character_creation;
|
||||||
|
|
@ -55,9 +60,9 @@ pub use farlook::*;
|
||||||
|
|
||||||
/// Gives a popup box with a message and a title, and waits for a keypress.
|
/// Gives a popup box with a message and a title, and waits for a keypress.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
|
pub fn yes_no(ctx: &mut BTerm, question: String) -> Option<bool> {
|
||||||
ctx.print_color_centered(15, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), question);
|
ctx.print_color_centered(15, RGB::named(YELLOW), RGB::named(BLACK), question);
|
||||||
ctx.print_color_centered(17, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "(y)es or (n)o");
|
ctx.print_color_centered(17, RGB::named(CYAN), RGB::named(BLACK), "(y)es or (n)o");
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
None => None,
|
None => None,
|
||||||
Some(key) =>
|
Some(key) =>
|
||||||
|
|
@ -70,7 +75,7 @@ pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_lerping_bar(
|
pub fn draw_lerping_bar(
|
||||||
ctx: &mut Rltk,
|
ctx: &mut BTerm,
|
||||||
sx: i32,
|
sx: i32,
|
||||||
sy: i32,
|
sy: i32,
|
||||||
width: i32,
|
width: i32,
|
||||||
|
|
@ -82,12 +87,12 @@ pub fn draw_lerping_bar(
|
||||||
let percent = (n as f32) / (max as f32);
|
let percent = (n as f32) / (max as f32);
|
||||||
let fill_width = (percent * (width as f32)) as i32;
|
let fill_width = (percent * (width as f32)) as i32;
|
||||||
let bg = empty_colour.lerp(full_colour, percent);
|
let bg = empty_colour.lerp(full_colour, percent);
|
||||||
let fg = RGB::named(rltk::BLACK);
|
let fg = RGB::named(BLACK);
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
if x <= fill_width {
|
if x <= fill_width {
|
||||||
ctx.print_color(sx + x, sy, fg, bg, " ");
|
ctx.print_color(sx + x, sy, fg, bg, " ");
|
||||||
} else {
|
} else {
|
||||||
ctx.print_color(sx + x, sy, RGB::named(rltk::BLACK), RGB::named(rltk::BLACK), " ");
|
ctx.print_color(sx + x, sy, RGB::named(BLACK), RGB::named(BLACK), " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.print(sx - 1, sy, "[");
|
ctx.print(sx - 1, sy, "[");
|
||||||
|
|
@ -96,7 +101,7 @@ pub fn draw_lerping_bar(
|
||||||
ctx.print(sx + width, sy, "]");
|
ctx.print(sx + width, sy, "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
pub fn draw_ui(ecs: &World, ctx: &mut BTerm) {
|
||||||
// Render stats
|
// Render stats
|
||||||
let pools = ecs.read_storage::<Pools>();
|
let pools = ecs.read_storage::<Pools>();
|
||||||
let attributes = ecs.read_storage::<Attributes>();
|
let attributes = ecs.read_storage::<Attributes>();
|
||||||
|
|
@ -104,7 +109,13 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
let hunger = ecs.read_storage::<HungerClock>();
|
let hunger = ecs.read_storage::<HungerClock>();
|
||||||
let burden = ecs.read_storage::<Burden>();
|
let burden = ecs.read_storage::<Burden>();
|
||||||
let skills = ecs.read_storage::<Skills>();
|
let skills = ecs.read_storage::<Skills>();
|
||||||
for (_player, stats, attributes, hunger, skills) in (&players, &pools, &attributes, &hunger, &skills).join() {
|
for (_player, stats, attributes, hunger, skills) in (
|
||||||
|
&players,
|
||||||
|
&pools,
|
||||||
|
&attributes,
|
||||||
|
&hunger,
|
||||||
|
&skills,
|
||||||
|
).join() {
|
||||||
// Draw hp/mana bars
|
// Draw hp/mana bars
|
||||||
draw_lerping_bar(
|
draw_lerping_bar(
|
||||||
ctx,
|
ctx,
|
||||||
|
|
@ -123,8 +134,8 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
22,
|
22,
|
||||||
stats.mana.current,
|
stats.mana.current,
|
||||||
stats.mana.max,
|
stats.mana.max,
|
||||||
RGB::named(rltk::BLUE),
|
RGB::named(BLUE),
|
||||||
RGB::named(rltk::BLACK)
|
RGB::named(BLACK)
|
||||||
);
|
);
|
||||||
// Draw AC
|
// Draw AC
|
||||||
let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*skills);
|
let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*skills);
|
||||||
|
|
@ -137,70 +148,131 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
armour_ac_bonus += ac.amount;
|
armour_ac_bonus += ac.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let armour_class = stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus;
|
let armour_class =
|
||||||
ctx.print_color(26, 53, RGB::named(rltk::PINK), RGB::named(rltk::BLACK), "AC");
|
stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus;
|
||||||
ctx.print_color(28, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), armour_class);
|
ctx.print_color(26, 53, RGB::named(PINK), RGB::named(BLACK), "AC");
|
||||||
|
ctx.print_color(28, 53, RGB::named(WHITE), RGB::named(BLACK), armour_class);
|
||||||
// Draw level
|
// Draw level
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
26,
|
26,
|
||||||
54,
|
54,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!("XP{}/{}", stats.level, stats.xp)
|
format!("XP{}/{}", stats.level, stats.xp)
|
||||||
);
|
);
|
||||||
// Draw attributes
|
// Draw attributes
|
||||||
let x = 38;
|
let x = 38;
|
||||||
ctx.print_color(x, 53, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "STR");
|
ctx.print_color(x, 53, RGB::named(RED), RGB::named(BLACK), "STR");
|
||||||
ctx.print_color(x + 3, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.strength.base);
|
ctx.print_color(x + 3, 53, RGB::named(WHITE), RGB::named(BLACK), attributes.strength.base);
|
||||||
ctx.print_color(x + 7, 53, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "DEX");
|
ctx.print_color(x + 7, 53, RGB::named(GREEN), RGB::named(BLACK), "DEX");
|
||||||
ctx.print_color(x + 10, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.dexterity.base);
|
ctx.print_color(
|
||||||
ctx.print_color(x + 14, 53, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "CON");
|
x + 10,
|
||||||
ctx.print_color(x + 17, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.constitution.base);
|
53,
|
||||||
ctx.print_color(x, 54, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "INT");
|
RGB::named(WHITE),
|
||||||
ctx.print_color(x + 3, 54, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.intelligence.base);
|
RGB::named(BLACK),
|
||||||
ctx.print_color(x + 7, 54, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "WIS");
|
attributes.dexterity.base
|
||||||
ctx.print_color(x + 10, 54, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.wisdom.base);
|
);
|
||||||
ctx.print_color(x + 14, 54, RGB::named(rltk::PURPLE), RGB::named(rltk::BLACK), "CHA");
|
ctx.print_color(x + 14, 53, RGB::named(ORANGE), RGB::named(BLACK), "CON");
|
||||||
ctx.print_color(x + 17, 54, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.charisma.base);
|
ctx.print_color(
|
||||||
|
x + 17,
|
||||||
|
53,
|
||||||
|
RGB::named(WHITE),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
attributes.constitution.base
|
||||||
|
);
|
||||||
|
ctx.print_color(x, 54, RGB::named(CYAN), RGB::named(BLACK), "INT");
|
||||||
|
ctx.print_color(
|
||||||
|
x + 3,
|
||||||
|
54,
|
||||||
|
RGB::named(WHITE),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
attributes.intelligence.base
|
||||||
|
);
|
||||||
|
ctx.print_color(x + 7, 54, RGB::named(YELLOW), RGB::named(BLACK), "WIS");
|
||||||
|
ctx.print_color(x + 10, 54, RGB::named(WHITE), RGB::named(BLACK), attributes.wisdom.base);
|
||||||
|
ctx.print_color(x + 14, 54, RGB::named(PURPLE), RGB::named(BLACK), "CHA");
|
||||||
|
ctx.print_color(x + 17, 54, RGB::named(WHITE), RGB::named(BLACK), attributes.charisma.base);
|
||||||
// Draw hunger
|
// Draw hunger
|
||||||
match hunger.state {
|
match hunger.state {
|
||||||
HungerState::Satiated => {
|
HungerState::Satiated => {
|
||||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Satiated");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
53,
|
||||||
|
get_hunger_colour(hunger.state),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Satiated"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
HungerState::Normal => {}
|
HungerState::Normal => {}
|
||||||
HungerState::Hungry => {
|
HungerState::Hungry => {
|
||||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Hungry");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
53,
|
||||||
|
get_hunger_colour(hunger.state),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Hungry"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
HungerState::Weak => {
|
HungerState::Weak => {
|
||||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Weak");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
53,
|
||||||
|
get_hunger_colour(hunger.state),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Weak"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
HungerState::Fainting => {
|
HungerState::Fainting => {
|
||||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Fainting");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
53,
|
||||||
|
get_hunger_colour(hunger.state),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Fainting"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
HungerState::Starving => {
|
HungerState::Starving => {
|
||||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Starving");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
53,
|
||||||
|
get_hunger_colour(hunger.state),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Starving"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Burden
|
// Burden
|
||||||
if let Some(burden) = burden.get(*player_entity) {
|
if let Some(burden) = burden.get(*player_entity) {
|
||||||
match burden.level {
|
match burden.level {
|
||||||
crate::BurdenLevel::Burdened => {
|
crate::BurdenLevel::Burdened => {
|
||||||
ctx.print_color_right(70, 50, RGB::named(rltk::BROWN1), RGB::named(rltk::BLACK), "Burdened");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
50,
|
||||||
|
RGB::named(BROWN1),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Burdened"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
crate::BurdenLevel::Strained => {
|
crate::BurdenLevel::Strained => {
|
||||||
ctx.print_color_right(70, 50, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "Strained");
|
ctx.print_color_right(
|
||||||
|
70,
|
||||||
|
50,
|
||||||
|
RGB::named(ORANGE),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"Strained"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
crate::BurdenLevel::Overloaded => {
|
crate::BurdenLevel::Overloaded => {
|
||||||
ctx.print_color_right(70, 50, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "Overloaded");
|
ctx.print_color_right(70, 50, RGB::named(RED), RGB::named(BLACK), "Overloaded");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stats.god {
|
if stats.god {
|
||||||
ctx.print_color(20, 20, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "--- GODMODE: ON ---");
|
ctx.print_color(20, 20, RGB::named(YELLOW), RGB::named(BLACK), "--- GODMODE: ON ---");
|
||||||
}
|
}
|
||||||
// Draw equipment
|
// Draw equipment
|
||||||
let renderables = ecs.read_storage::<Renderable>();
|
let renderables = ecs.read_storage::<Renderable>();
|
||||||
let mut equipment: Vec<(String, RGB, RGB, rltk::FontCharType)> = Vec::new();
|
let mut equipment: Vec<(String, RGB, RGB, FontCharType)> = Vec::new();
|
||||||
let entities = ecs.entities();
|
let entities = ecs.entities();
|
||||||
for (entity, _equipped, renderable) in (&entities, &equipped, &renderables)
|
for (entity, _equipped, renderable) in (&entities, &equipped, &renderables)
|
||||||
.join()
|
.join()
|
||||||
|
|
@ -214,30 +286,37 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
}
|
}
|
||||||
let mut y = 1;
|
let mut y = 1;
|
||||||
if !equipment.is_empty() {
|
if !equipment.is_empty() {
|
||||||
ctx.print_color(72, y, RGB::named(rltk::BLACK), RGB::named(rltk::WHITE), "Equipment");
|
ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Equipment");
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
for item in equipment {
|
for item in equipment {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.set(72, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
ctx.set(72, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType));
|
||||||
j += 1;
|
j += 1;
|
||||||
ctx.set(74, y, item.2, RGB::named(rltk::BLACK), item.3);
|
ctx.set(74, y, item.2, RGB::named(BLACK), item.3);
|
||||||
ctx.print_color(76, y, item.1, RGB::named(rltk::BLACK), &item.0);
|
ctx.print_color(76, y, item.1, RGB::named(BLACK), &item.0);
|
||||||
ctx.print_color(76 + &item.0.len() + 1, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "(worn)");
|
ctx.print_color(
|
||||||
|
76 + &item.0.len() + 1,
|
||||||
|
y,
|
||||||
|
RGB::named(WHITE),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
"(worn)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
y += 2;
|
y += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw consumables
|
// Draw consumables
|
||||||
ctx.print_color(72, y, RGB::named(rltk::BLACK), RGB::named(rltk::WHITE), "Backpack");
|
ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Backpack");
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
81,
|
81,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
&format!(
|
&format!(
|
||||||
"[{:.1}/{} lbs]",
|
"[{:.1}/{} lbs]",
|
||||||
stats.weight,
|
stats.weight,
|
||||||
(attributes.strength.base + attributes.strength.modifiers) * CARRY_CAPACITY_PER_STRENGTH
|
(attributes.strength.base + attributes.strength.modifiers) *
|
||||||
|
CARRY_CAPACITY_PER_STRENGTH
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
|
|
@ -252,7 +331,13 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
y += 1;
|
y += 1;
|
||||||
let mut index = 1;
|
let mut index = 1;
|
||||||
for spell in known_spells.list.iter() {
|
for spell in known_spells.list.iter() {
|
||||||
ctx.print_color(72, y, RGB::named(YELLOW), RGB::named(BLACK), &format!("{}", index));
|
ctx.print_color(
|
||||||
|
72,
|
||||||
|
y,
|
||||||
|
RGB::named(YELLOW),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
&format!("{}", index)
|
||||||
|
);
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
74,
|
74,
|
||||||
y,
|
y,
|
||||||
|
|
@ -296,7 +381,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
let (render_fg, glyph) = if let Some(renderable) = renderables.get(entity) {
|
let (render_fg, glyph) = if let Some(renderable) = renderables.get(entity) {
|
||||||
(renderable.fg, renderable.glyph)
|
(renderable.fg, renderable.glyph)
|
||||||
} else {
|
} else {
|
||||||
(RGB::named(rltk::WHITE), rltk::to_cp437('-'))
|
(RGB::named(WHITE), to_cp437('-'))
|
||||||
};
|
};
|
||||||
seen_entities.push((
|
seen_entities.push((
|
||||||
obfuscate_name_ecs(ecs, entity).0,
|
obfuscate_name_ecs(ecs, entity).0,
|
||||||
|
|
@ -311,38 +396,54 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
|
|
||||||
if !seen_entities.is_empty() {
|
if !seen_entities.is_empty() {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.print_color(72, y, RGB::named(rltk::BLACK), RGB::named(rltk::WHITE), "In View");
|
ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "In View");
|
||||||
for entity in seen_entities {
|
for entity in seen_entities {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.set(72, y, entity.2, RGB::named(rltk::BLACK), entity.3);
|
ctx.set(72, y, entity.2, RGB::named(BLACK), entity.3);
|
||||||
ctx.print_color(74, y, entity.1, RGB::named(rltk::BLACK), entity.0);
|
ctx.print_color(74, y, entity.1, RGB::named(BLACK), entity.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the message log at [1, 7], ascending, with 7 lines and a max width of 68.
|
// Render the message log at [1, 7], ascending, with 7 lines and a max width of 68.
|
||||||
gamelog::print_log(&mut rltk::BACKEND_INTERNAL.lock().consoles[0].console, Point::new(1, 7), false, 7, 68);
|
gamelog::print_log(
|
||||||
|
&mut BACKEND_INTERNAL.lock().consoles[0].console,
|
||||||
|
Point::new(1, 7),
|
||||||
|
false,
|
||||||
|
7,
|
||||||
|
68
|
||||||
|
);
|
||||||
|
|
||||||
// Render id
|
// Render id
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let id = if map.depth > 0 { format!("{}{}", map.short_name, map.depth) } else { format!("{}", map.short_name) };
|
let id = if map.depth > 0 {
|
||||||
ctx.print_color_right(70, 54, get_local_col(map.id), RGB::named(rltk::BLACK), &id);
|
format!("{}{}", map.short_name, map.depth)
|
||||||
|
} else {
|
||||||
|
format!("{}", map.short_name)
|
||||||
|
};
|
||||||
|
ctx.print_color_right(70, 54, get_local_col(map.id), RGB::named(BLACK), &id);
|
||||||
|
|
||||||
// Render turn
|
// Render turn
|
||||||
let turns = crate::gamelog::get_event_count(EVENT::COUNT_TURN);
|
let turns = crate::gamelog::get_event_count(EVENT::COUNT_TURN);
|
||||||
ctx.print_color_right(69 - id.len(), 54, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), &format!("T{}", turns));
|
ctx.print_color_right(
|
||||||
|
69 - id.len(),
|
||||||
|
54,
|
||||||
|
RGB::named(YELLOW),
|
||||||
|
RGB::named(BLACK),
|
||||||
|
&format!("T{}", turns)
|
||||||
|
);
|
||||||
|
|
||||||
// Boxes and tooltips last, so they draw over everything else.
|
// Boxes and tooltips last, so they draw over everything else.
|
||||||
ctx.draw_hollow_box(0, 0, 70, 8, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); // Log box
|
ctx.draw_hollow_box(0, 0, 70, 8, RGB::named(WHITE), RGB::named(BLACK)); // Log box
|
||||||
ctx.draw_hollow_box(0, 9, 70, 42, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); // Camera box
|
ctx.draw_hollow_box(0, 9, 70, 42, RGB::named(WHITE), RGB::named(BLACK)); // Camera box
|
||||||
ctx.draw_hollow_box(0, 52, 70, 3, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); // Stats box
|
ctx.draw_hollow_box(0, 52, 70, 3, RGB::named(WHITE), RGB::named(BLACK)); // Stats box
|
||||||
ctx.draw_hollow_box(71, 0, 33, 55, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); // Side box
|
ctx.draw_hollow_box(71, 0, 33, 55, RGB::named(WHITE), RGB::named(BLACK)); // Side box
|
||||||
tooltip::draw_tooltips(ecs, ctx, None);
|
tooltip::draw_tooltips(ecs, ctx, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_input_direction(
|
pub fn get_input_direction(
|
||||||
ecs: &mut World,
|
ecs: &mut World,
|
||||||
ctx: &mut Rltk,
|
ctx: &mut BTerm,
|
||||||
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState
|
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState
|
||||||
) -> RunState {
|
) -> RunState {
|
||||||
let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs, ctx);
|
let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs, ctx);
|
||||||
|
|
@ -350,8 +451,8 @@ pub fn get_input_direction(
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"In what direction? [0-9]/[YUHJKLBN]"
|
"In what direction? [0-9]/[YUHJKLBN]"
|
||||||
);
|
);
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
|
|
@ -403,7 +504,12 @@ pub enum ItemMenuResult {
|
||||||
Selected,
|
Selected,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_options(inventory: &PlayerInventory, mut x: i32, mut y: i32, ctx: &mut Rltk) -> (i32, i32) {
|
pub fn print_options(
|
||||||
|
inventory: &PlayerInventory,
|
||||||
|
mut x: i32,
|
||||||
|
mut y: i32,
|
||||||
|
ctx: &mut BTerm
|
||||||
|
) -> (i32, i32) {
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
let initial_x: i32 = x;
|
let initial_x: i32 = x;
|
||||||
let mut width: i32 = -1;
|
let mut width: i32 = -1;
|
||||||
|
|
@ -411,44 +517,46 @@ pub fn print_options(inventory: &PlayerInventory, mut x: i32, mut y: i32, ctx: &
|
||||||
x = initial_x;
|
x = initial_x;
|
||||||
// Print the character required to access this item. i.e. (a)
|
// Print the character required to access this item. i.e. (a)
|
||||||
if j < 26 {
|
if j < 26 {
|
||||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
ctx.set(x, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType));
|
||||||
} else {
|
} else {
|
||||||
// If we somehow have more than 26, start using capitals
|
// If we somehow have more than 26, start using capitals
|
||||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 65 - 26 + (j as rltk::FontCharType));
|
ctx.set(x, y, RGB::named(YELLOW), RGB::named(BLACK), 65 - 26 + (j as FontCharType));
|
||||||
}
|
}
|
||||||
|
|
||||||
x += 2;
|
x += 2;
|
||||||
let fg = RGB::from_u8(item.renderables.0, item.renderables.1, item.renderables.2);
|
let fg = RGB::from_u8(item.renderables.0, item.renderables.1, item.renderables.2);
|
||||||
ctx.set(x, y, fg, RGB::named(rltk::BLACK), item.glyph);
|
ctx.set(x, y, fg, RGB::named(BLACK), item.glyph);
|
||||||
x += 2;
|
x += 2;
|
||||||
|
|
||||||
let fg = RGB::from_u8(item.rgb.0, item.rgb.1, item.rgb.2);
|
let fg = RGB::from_u8(item.rgb.0, item.rgb.1, item.rgb.2);
|
||||||
if item_count > &1 {
|
if item_count > &1 {
|
||||||
// If more than one, print the number and pluralise
|
// If more than one, print the number and pluralise
|
||||||
// i.e. (a) 3 daggers
|
// i.e. (a) 3 daggers
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item_count);
|
ctx.print_color(x, y, fg, RGB::named(BLACK), item_count);
|
||||||
x += 2;
|
x += 2;
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item.display_name.plural.to_string());
|
ctx.print_color(x, y, fg, RGB::named(BLACK), item.display_name.plural.to_string());
|
||||||
let this_width = x - initial_x + (item.display_name.plural.len() as i32);
|
let this_width = x - initial_x + (item.display_name.plural.len() as i32);
|
||||||
width = if width > this_width { width } else { this_width };
|
width = if width > this_width { width } else { this_width };
|
||||||
} else {
|
} else {
|
||||||
if item.display_name.singular.to_lowercase().ends_with("s") {
|
if item.display_name.singular.to_lowercase().ends_with("s") {
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), "some");
|
ctx.print_color(x, y, fg, RGB::named(BLACK), "some");
|
||||||
x += 5;
|
x += 5;
|
||||||
} else if
|
} else if
|
||||||
['a', 'e', 'i', 'o', 'u'].iter().any(|&v| item.display_name.singular.to_lowercase().starts_with(v))
|
['a', 'e', 'i', 'o', 'u']
|
||||||
|
.iter()
|
||||||
|
.any(|&v| item.display_name.singular.to_lowercase().starts_with(v))
|
||||||
{
|
{
|
||||||
// If one and starts with a vowel, print 'an'
|
// If one and starts with a vowel, print 'an'
|
||||||
// i.e. (a) an apple
|
// i.e. (a) an apple
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), "an");
|
ctx.print_color(x, y, fg, RGB::named(BLACK), "an");
|
||||||
x += 3;
|
x += 3;
|
||||||
} else {
|
} else {
|
||||||
// If one and not a vowel, print 'a'
|
// If one and not a vowel, print 'a'
|
||||||
// i.e. (a) a dagger
|
// i.e. (a) a dagger
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), "a");
|
ctx.print_color(x, y, fg, RGB::named(BLACK), "a");
|
||||||
x += 2;
|
x += 2;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item.display_name.singular.to_string());
|
ctx.print_color(x, y, fg, RGB::named(BLACK), item.display_name.singular.to_string());
|
||||||
let this_width = x - initial_x + (item.display_name.singular.len() as i32);
|
let this_width = x - initial_x + (item.display_name.singular.len() as i32);
|
||||||
width = if width > this_width { width } else { this_width };
|
width = if width > this_width { width } else { this_width };
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +577,9 @@ pub fn get_max_inventory_width(inventory: &PlayerInventory) -> i32 {
|
||||||
if count <= &1 {
|
if count <= &1 {
|
||||||
if item.display_name.singular == item.display_name.plural {
|
if item.display_name.singular == item.display_name.plural {
|
||||||
this_width += 4; // "some".len
|
this_width += 4; // "some".len
|
||||||
} else if ['a', 'e', 'i', 'o', 'u'].iter().any(|&v| item.display_name.singular.starts_with(v)) {
|
} else if
|
||||||
|
['a', 'e', 'i', 'o', 'u'].iter().any(|&v| item.display_name.singular.starts_with(v))
|
||||||
|
{
|
||||||
this_width += 2; // "an".len
|
this_width += 2; // "an".len
|
||||||
} else {
|
} else {
|
||||||
this_width += 1; // "a".len
|
this_width += 1; // "a".len
|
||||||
|
|
@ -492,7 +602,10 @@ pub fn obfuscate_name(
|
||||||
dm: &MasterDungeonMap,
|
dm: &MasterDungeonMap,
|
||||||
wand: Option<&ReadStorage<Charges>>
|
wand: Option<&ReadStorage<Charges>>
|
||||||
) -> (String, String) {
|
) -> (String, String) {
|
||||||
let (mut singular, mut plural) = ("nameless item (bug)".to_string(), "nameless items (bug)".to_string());
|
let (mut singular, mut plural) = (
|
||||||
|
"nameless item (bug)".to_string(),
|
||||||
|
"nameless items (bug)".to_string(),
|
||||||
|
);
|
||||||
if let Some(name) = names.get(item) {
|
if let Some(name) = names.get(item) {
|
||||||
if magic_items.get(item).is_some() {
|
if magic_items.get(item).is_some() {
|
||||||
if dm.identified_items.contains(&name.name) {
|
if dm.identified_items.contains(&name.name) {
|
||||||
|
|
@ -510,7 +623,10 @@ pub fn obfuscate_name(
|
||||||
} else if let Some(obfuscated) = obfuscated_names.get(item) {
|
} else if let Some(obfuscated) = obfuscated_names.get(item) {
|
||||||
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
|
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
|
||||||
} else {
|
} else {
|
||||||
(singular, plural) = ("unid magic item".to_string(), "unid magic items".to_string());
|
(singular, plural) = (
|
||||||
|
"unid magic item".to_string(),
|
||||||
|
"unid magic items".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(singular, plural) = (name.name.clone(), name.plural.clone());
|
(singular, plural) = (name.name.clone(), name.plural.clone());
|
||||||
|
|
@ -534,7 +650,10 @@ pub fn obfuscate_name(
|
||||||
|
|
||||||
// Outside the ECS
|
// Outside the ECS
|
||||||
pub fn obfuscate_name_ecs(ecs: &World, item: Entity) -> (String, String) {
|
pub fn obfuscate_name_ecs(ecs: &World, item: Entity) -> (String, String) {
|
||||||
let (mut singular, mut plural) = ("nameless item (bug)".to_string(), "nameless items (bug)".to_string());
|
let (mut singular, mut plural) = (
|
||||||
|
"nameless item (bug)".to_string(),
|
||||||
|
"nameless items (bug)".to_string(),
|
||||||
|
);
|
||||||
if let Some(name) = ecs.read_storage::<Name>().get(item) {
|
if let Some(name) = ecs.read_storage::<Name>().get(item) {
|
||||||
if ecs.read_storage::<MagicItem>().get(item).is_some() {
|
if ecs.read_storage::<MagicItem>().get(item).is_some() {
|
||||||
let dm = ecs.fetch::<MasterDungeonMap>();
|
let dm = ecs.fetch::<MasterDungeonMap>();
|
||||||
|
|
@ -550,7 +669,10 @@ pub fn obfuscate_name_ecs(ecs: &World, item: Entity) -> (String, String) {
|
||||||
} else if let Some(obfuscated) = ecs.read_storage::<ObfuscatedName>().get(item) {
|
} else if let Some(obfuscated) = ecs.read_storage::<ObfuscatedName>().get(item) {
|
||||||
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
|
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
|
||||||
} else {
|
} else {
|
||||||
(singular, plural) = ("unid magic item".to_string(), "unid magic items".to_string());
|
(singular, plural) = (
|
||||||
|
"unid magic item".to_string(),
|
||||||
|
"unid magic items".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(singular, plural) = (name.name.clone(), name.plural.clone());
|
(singular, plural) = (name.name.clone(), name.plural.clone());
|
||||||
|
|
@ -592,7 +714,11 @@ pub fn unobf_name_ecs(ecs: &World, item: Entity) -> (String, String) {
|
||||||
/// Gets renderable colour as tuple of u8
|
/// Gets renderable colour as tuple of u8
|
||||||
pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity) -> (u8, u8, u8) {
|
pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity) -> (u8, u8, u8) {
|
||||||
return if let Some(renderable) = renderables.get(entity) {
|
return if let Some(renderable) = renderables.get(entity) {
|
||||||
((renderable.fg.r * 255.0) as u8, (renderable.fg.g * 255.0) as u8, (renderable.fg.b * 255.0) as u8)
|
(
|
||||||
|
(renderable.fg.r * 255.0) as u8,
|
||||||
|
(renderable.fg.g * 255.0) as u8,
|
||||||
|
(renderable.fg.b * 255.0) as u8,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
WHITE
|
WHITE
|
||||||
};
|
};
|
||||||
|
|
@ -601,7 +727,11 @@ pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity)
|
||||||
/// Gets renderable colour as tuple of u8
|
/// Gets renderable colour as tuple of u8
|
||||||
pub fn renderable_colour_ecs(ecs: &World, entity: Entity) -> (u8, u8, u8) {
|
pub fn renderable_colour_ecs(ecs: &World, entity: Entity) -> (u8, u8, u8) {
|
||||||
return if let Some(renderable) = ecs.read_storage::<Renderable>().get(entity) {
|
return if let Some(renderable) = ecs.read_storage::<Renderable>().get(entity) {
|
||||||
((renderable.fg.r * 255.0) as u8, (renderable.fg.g * 255.0) as u8, (renderable.fg.b * 255.0) as u8)
|
(
|
||||||
|
(renderable.fg.r * 255.0) as u8,
|
||||||
|
(renderable.fg.g * 255.0) as u8,
|
||||||
|
(renderable.fg.b * 255.0) as u8,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
WHITE
|
WHITE
|
||||||
};
|
};
|
||||||
|
|
@ -653,17 +783,17 @@ pub fn item_colour(item: Entity, beatitudes: &ReadStorage<Beatitude>) -> (u8, u8
|
||||||
return WHITE;
|
return WHITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
pub fn show_help(ctx: &mut BTerm) -> YesNoResult {
|
||||||
let mut x = 3;
|
let mut x = 3;
|
||||||
let mut y = 12;
|
let mut y = 12;
|
||||||
let height = 22;
|
let height = 22;
|
||||||
let width = 25;
|
let width = 25;
|
||||||
ctx.draw_box(x, y, width, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width, height, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), " Controls ");
|
ctx.print_color(x + 3, y, RGB::named(YELLOW), RGB::named(BLACK), " Controls ");
|
||||||
ctx.print_color(x + 3, y + height, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), " ESC/? to close ");
|
ctx.print_color(x + 3, y + height, RGB::named(YELLOW), RGB::named(BLACK), " ESC/? to close ");
|
||||||
x += 2;
|
x += 2;
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "MOVE COMMANDS");
|
ctx.print_color(x, y, RGB::named(GREEN), RGB::named(BLACK), "MOVE COMMANDS");
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print(x, y, "y k u 7 8 9 > down");
|
ctx.print(x, y, "y k u 7 8 9 > down");
|
||||||
ctx.print(x, y + 1, " \\|/ \\|/");
|
ctx.print(x, y + 1, " \\|/ \\|/");
|
||||||
|
|
@ -671,7 +801,7 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
||||||
ctx.print(x, y + 3, " /|\\ /|\\");
|
ctx.print(x, y + 3, " /|\\ /|\\");
|
||||||
ctx.print(x, y + 4, "b j n 1 2 3 . wait");
|
ctx.print(x, y + 4, "b j n 1 2 3 . wait");
|
||||||
y += 7;
|
y += 7;
|
||||||
ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "OBJECT INTERACTION");
|
ctx.print_color(x, y, RGB::named(GREEN), RGB::named(BLACK), "OBJECT INTERACTION");
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print(x, y, "g get d drop");
|
ctx.print(x, y, "g get d drop");
|
||||||
y += 1;
|
y += 1;
|
||||||
|
|
@ -681,7 +811,7 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.print(x, y, "f force x farlook");
|
ctx.print(x, y, "f force x farlook");
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "MOUSE CONTROL");
|
ctx.print_color(x, y, RGB::named(GREEN), RGB::named(BLACK), "MOUSE CONTROL");
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print(x, y, "hover for tooltips");
|
ctx.print(x, y, "hover for tooltips");
|
||||||
|
|
||||||
|
|
@ -766,7 +896,7 @@ pub fn get_player_inventory(ecs: &World) -> PlayerInventory {
|
||||||
return player_inventory;
|
return player_inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
pub fn show_inventory(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
|
||||||
let player_inventory = get_player_inventory(&gs.ecs);
|
let player_inventory = get_player_inventory(&gs.ecs);
|
||||||
let count = player_inventory.len();
|
let count = player_inventory.len();
|
||||||
|
|
||||||
|
|
@ -779,12 +909,12 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||||
"You can't use items on the overmap [Esc.]"
|
"You can't use items on the overmap [Esc.]"
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), message);
|
ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(WHITE), RGB::named(BLACK), message);
|
||||||
|
|
||||||
let x = 1 + x_offset;
|
let x = 1 + x_offset;
|
||||||
let y = 3 + y_offset;
|
let y = 3 + y_offset;
|
||||||
let width = get_max_inventory_width(&player_inventory);
|
let width = get_max_inventory_width(&player_inventory);
|
||||||
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
print_options(&player_inventory, x + 1, y + 1, ctx);
|
print_options(&player_inventory, x + 1, y + 1, ctx);
|
||||||
|
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
|
|
@ -796,7 +926,10 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||||
let selection = letter_to_option::letter_to_option(key, ctx.shift);
|
let selection = letter_to_option::letter_to_option(key, ctx.shift);
|
||||||
if selection > -1 && selection < (count as i32) {
|
if selection > -1 && selection < (count as i32) {
|
||||||
if on_overmap {
|
if on_overmap {
|
||||||
gamelog::Logger::new().append("You can't use items on the overmap.").log();
|
gamelog::Logger
|
||||||
|
::new()
|
||||||
|
.append("You can't use items on the overmap.")
|
||||||
|
.log();
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
ItemMenuResult::Selected,
|
ItemMenuResult::Selected,
|
||||||
|
|
@ -815,21 +948,25 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
pub fn drop_item_menu(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
|
||||||
let player_inventory = get_player_inventory(&gs.ecs);
|
let player_inventory = get_player_inventory(&gs.ecs);
|
||||||
let count = player_inventory.len();
|
let count = player_inventory.len();
|
||||||
|
|
||||||
let (x_offset, y_offset) = (1, 10);
|
let (x_offset, y_offset) = (1, 10);
|
||||||
|
|
||||||
let on_overmap = gs.ecs.fetch::<Map>().overmap;
|
let on_overmap = gs.ecs.fetch::<Map>().overmap;
|
||||||
let message = if !on_overmap { "Drop what? [aA-zZ][Esc.]" } else { "You can't drop items on the overmap [Esc.]" };
|
let message = if !on_overmap {
|
||||||
|
"Drop what? [aA-zZ][Esc.]"
|
||||||
|
} else {
|
||||||
|
"You can't drop items on the overmap [Esc.]"
|
||||||
|
};
|
||||||
|
|
||||||
ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), message);
|
ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(WHITE), RGB::named(BLACK), message);
|
||||||
|
|
||||||
let x = 1 + x_offset;
|
let x = 1 + x_offset;
|
||||||
let y = 3 + y_offset;
|
let y = 3 + y_offset;
|
||||||
let width = get_max_inventory_width(&player_inventory);
|
let width = get_max_inventory_width(&player_inventory);
|
||||||
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
print_options(&player_inventory, x + 1, y + 1, ctx);
|
print_options(&player_inventory, x + 1, y + 1, ctx);
|
||||||
|
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
|
|
@ -838,10 +975,13 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||||
_ => {
|
_ => {
|
||||||
let selection = rltk::letter_to_option(key);
|
let selection = letter_to_option(key);
|
||||||
if selection > -1 && selection < (count as i32) {
|
if selection > -1 && selection < (count as i32) {
|
||||||
if on_overmap {
|
if on_overmap {
|
||||||
gamelog::Logger::new().append("You can't drop items on the overmap.").log();
|
gamelog::Logger
|
||||||
|
::new()
|
||||||
|
.append("You can't drop items on the overmap.")
|
||||||
|
.log();
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
ItemMenuResult::Selected,
|
ItemMenuResult::Selected,
|
||||||
|
|
@ -860,7 +1000,7 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
pub fn remove_item_menu(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
|
||||||
let player_entity = gs.ecs.fetch::<Entity>();
|
let player_entity = gs.ecs.fetch::<Entity>();
|
||||||
let backpack = gs.ecs.read_storage::<Equipped>();
|
let backpack = gs.ecs.read_storage::<Equipped>();
|
||||||
let entities = gs.ecs.entities();
|
let entities = gs.ecs.entities();
|
||||||
|
|
@ -872,14 +1012,16 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"Unequip what? [aA-zZ][Esc.]"
|
"Unequip what? [aA-zZ][Esc.]"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut equippable: Vec<(Entity, String)> = Vec::new();
|
let mut equippable: Vec<(Entity, String)> = Vec::new();
|
||||||
let mut width = 2;
|
let mut width = 2;
|
||||||
for (entity, _pack) in (&entities, &backpack).join().filter(|item| item.1.owner == *player_entity) {
|
for (entity, _pack) in (&entities, &backpack)
|
||||||
|
.join()
|
||||||
|
.filter(|item| item.1.owner == *player_entity) {
|
||||||
let this_name = &obfuscate_name_ecs(&gs.ecs, entity).0;
|
let this_name = &obfuscate_name_ecs(&gs.ecs, entity).0;
|
||||||
let this_width = 5 + this_name.len();
|
let this_width = 5 + this_name.len();
|
||||||
width = if width > this_width { width } else { this_width };
|
width = if width > this_width { width } else { this_width };
|
||||||
|
|
@ -889,7 +1031,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||||
let x = 1 + x_offset;
|
let x = 1 + x_offset;
|
||||||
let mut y = 3 + y_offset;
|
let mut y = 3 + y_offset;
|
||||||
|
|
||||||
ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
y += 1;
|
y += 1;
|
||||||
|
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
|
|
@ -898,12 +1040,12 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||||
let (mut fg, glyph) = if let Some(renderable) = renderables.get(*e) {
|
let (mut fg, glyph) = if let Some(renderable) = renderables.get(*e) {
|
||||||
(renderable.fg, renderable.glyph)
|
(renderable.fg, renderable.glyph)
|
||||||
} else {
|
} else {
|
||||||
(RGB::named(rltk::WHITE), rltk::to_cp437('-'))
|
(RGB::named(WHITE), to_cp437('-'))
|
||||||
};
|
};
|
||||||
ctx.set(x + 1, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
ctx.set(x + 1, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType));
|
||||||
ctx.set(x + 3, y, fg, RGB::named(rltk::BLACK), glyph);
|
ctx.set(x + 3, y, fg, RGB::named(BLACK), glyph);
|
||||||
fg = RGB::named(item_colour_ecs(&gs.ecs, *e));
|
fg = RGB::named(item_colour_ecs(&gs.ecs, *e));
|
||||||
ctx.print_color(x + 5, y, fg, RGB::named(rltk::BLACK), name);
|
ctx.print_color(x + 5, y, fg, RGB::named(BLACK), name);
|
||||||
y += 1;
|
y += 1;
|
||||||
j += 1;
|
j += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -914,7 +1056,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||||
_ => {
|
_ => {
|
||||||
let selection = rltk::letter_to_option(key);
|
let selection = letter_to_option(key);
|
||||||
if selection > -1 && selection < (count as i32) {
|
if selection > -1 && selection < (count as i32) {
|
||||||
return (ItemMenuResult::Selected, Some(equippable[selection as usize].0));
|
return (ItemMenuResult::Selected, Some(equippable[selection as usize].0));
|
||||||
}
|
}
|
||||||
|
|
@ -936,7 +1078,7 @@ pub enum TargetResult {
|
||||||
|
|
||||||
pub fn ranged_target(
|
pub fn ranged_target(
|
||||||
gs: &mut State,
|
gs: &mut State,
|
||||||
ctx: &mut Rltk,
|
ctx: &mut BTerm,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
range: i32,
|
range: i32,
|
||||||
|
|
@ -950,8 +1092,8 @@ pub fn ranged_target(
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"Targeting which tile? [mouse input]"
|
"Targeting which tile? [mouse input]"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -961,11 +1103,16 @@ pub fn ranged_target(
|
||||||
if let Some(visible) = visible {
|
if let Some(visible) = visible {
|
||||||
// We have a viewshed
|
// We have a viewshed
|
||||||
for idx in visible.visible_tiles.iter() {
|
for idx in visible.visible_tiles.iter() {
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
let distance = DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
||||||
if distance <= (range as f32) {
|
if distance <= (range as f32) {
|
||||||
let screen_x = idx.x - min_x;
|
let screen_x = idx.x - min_x;
|
||||||
let screen_y = idx.y - min_y;
|
let screen_y = idx.y - min_y;
|
||||||
if screen_x > 1 && screen_x < max_x - min_x - 1 && screen_y > 1 && screen_y < max_y - min_y - 1 {
|
if
|
||||||
|
screen_x > 1 &&
|
||||||
|
screen_x < max_x - min_x - 1 &&
|
||||||
|
screen_y > 1 &&
|
||||||
|
screen_y < max_y - min_y - 1
|
||||||
|
{
|
||||||
ctx.set_bg(screen_x + x_offset, screen_y + y_offset, TARGETING_VALID_COL);
|
ctx.set_bg(screen_x + x_offset, screen_y + y_offset, TARGETING_VALID_COL);
|
||||||
available_cells.push(idx);
|
available_cells.push(idx);
|
||||||
}
|
}
|
||||||
|
|
@ -977,7 +1124,10 @@ pub fn ranged_target(
|
||||||
|
|
||||||
// Draw mouse cursor
|
// Draw mouse cursor
|
||||||
let mouse_pos = (x, y);
|
let mouse_pos = (x, y);
|
||||||
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = camera::get_screen_bounds(&gs.ecs, ctx);
|
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = camera::get_screen_bounds(
|
||||||
|
&gs.ecs,
|
||||||
|
ctx
|
||||||
|
);
|
||||||
let (screen_x, screen_y) = (69, 41);
|
let (screen_x, screen_y) = (69, 41);
|
||||||
let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32));
|
let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32));
|
||||||
let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32));
|
let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32));
|
||||||
|
|
@ -994,7 +1144,7 @@ pub fn ranged_target(
|
||||||
}
|
}
|
||||||
let mut result = (TargetResult::NoResponse { x, y }, None);
|
let mut result = (TargetResult::NoResponse { x, y }, None);
|
||||||
if valid_target {
|
if valid_target {
|
||||||
let path = rltk::line2d(
|
let path = line2d(
|
||||||
LineAlg::Bresenham,
|
LineAlg::Bresenham,
|
||||||
Point::new(player_pos.x, player_pos.y),
|
Point::new(player_pos.x, player_pos.y),
|
||||||
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)
|
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)
|
||||||
|
|
@ -1014,12 +1164,14 @@ pub fn ranged_target(
|
||||||
if aoe > 0 {
|
if aoe > 0 {
|
||||||
// We adjust for camera position when getting FOV, but then we need to adjust back
|
// We adjust for camera position when getting FOV, but then we need to adjust back
|
||||||
// when iterating through the tiles themselves, by taking away min_x/min_y.
|
// when iterating through the tiles themselves, by taking away min_x/min_y.
|
||||||
let mut blast_tiles = rltk::field_of_view(
|
let mut blast_tiles = field_of_view(
|
||||||
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1),
|
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1),
|
||||||
aoe,
|
aoe,
|
||||||
&*map
|
&*map
|
||||||
);
|
);
|
||||||
blast_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
blast_tiles.retain(
|
||||||
|
|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1
|
||||||
|
);
|
||||||
for tile in blast_tiles.iter() {
|
for tile in blast_tiles.iter() {
|
||||||
let bg = if available_cells.contains(&tile) {
|
let bg = if available_cells.contains(&tile) {
|
||||||
let col1 = TARGETING_AOE_COL;
|
let col1 = TARGETING_AOE_COL;
|
||||||
|
|
@ -1040,13 +1192,16 @@ pub fn ranged_target(
|
||||||
Some(key) =>
|
Some(key) =>
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::Return => {
|
VirtualKeyCode::Return => {
|
||||||
return (TargetResult::Selected, Some(Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)));
|
return (
|
||||||
|
TargetResult::Selected,
|
||||||
|
Some(Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => result,
|
_ => result,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::RED));
|
ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(RED));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = match ctx.key {
|
result = match ctx.key {
|
||||||
|
|
@ -1085,7 +1240,7 @@ pub enum MainMenuResult {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
pub fn main_menu(gs: &mut State, ctx: &mut BTerm) -> MainMenuResult {
|
||||||
let save_exists = super::saveload_system::does_save_exist();
|
let save_exists = super::saveload_system::does_save_exist();
|
||||||
let runstate = gs.ecs.fetch::<RunState>();
|
let runstate = gs.ecs.fetch::<RunState>();
|
||||||
let assets = gs.ecs.fetch::<RexAssets>();
|
let assets = gs.ecs.fetch::<RexAssets>();
|
||||||
|
|
@ -1099,34 +1254,34 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
||||||
height -= 1;
|
height -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.draw_box_double(x, y - 4, 13, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box_double(x, y - 4, 13, height, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
ctx.print_color(x + 3, y - 2, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "RUST-RL!");
|
ctx.print_color(x + 3, y - 2, RGB::named(YELLOW), RGB::named(BLACK), "RUST-RL!");
|
||||||
|
|
||||||
if let RunState::MainMenu { menu_selection: selection } = *runstate {
|
if let RunState::MainMenu { menu_selection: selection } = *runstate {
|
||||||
if save_exists {
|
if save_exists {
|
||||||
if selection == MainMenuSelection::LoadGame {
|
if selection == MainMenuSelection::LoadGame {
|
||||||
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
|
ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "[");
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "continue");
|
ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "continue");
|
||||||
ctx.print_color(x + 11, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "]");
|
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
|
||||||
} else {
|
} else {
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "continue");
|
ctx.print_color(x + 3, y, RGB::named(WHITE), RGB::named(BLACK), "continue");
|
||||||
}
|
}
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
if selection == MainMenuSelection::NewGame {
|
if selection == MainMenuSelection::NewGame {
|
||||||
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
|
ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "[");
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "new game");
|
ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "new game");
|
||||||
ctx.print_color(x + 11, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "]");
|
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
|
||||||
} else {
|
} else {
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "new game");
|
ctx.print_color(x + 3, y, RGB::named(WHITE), RGB::named(BLACK), "new game");
|
||||||
}
|
}
|
||||||
y += 1;
|
y += 1;
|
||||||
if selection == MainMenuSelection::Quit {
|
if selection == MainMenuSelection::Quit {
|
||||||
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
|
ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "[");
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "goodbye!");
|
ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "goodbye!");
|
||||||
ctx.print_color(x + 11, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "]");
|
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
|
||||||
} else {
|
} else {
|
||||||
ctx.print_color(x + 5, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "quit");
|
ctx.print_color(x + 5, y, RGB::named(WHITE), RGB::named(BLACK), "quit");
|
||||||
}
|
}
|
||||||
|
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
|
|
@ -1142,7 +1297,9 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
||||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame };
|
return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame };
|
||||||
}
|
}
|
||||||
VirtualKeyCode::L => {
|
VirtualKeyCode::L => {
|
||||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::LoadGame };
|
return MainMenuResult::NoSelection {
|
||||||
|
selected: MainMenuSelection::LoadGame,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => {
|
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => {
|
||||||
let mut new_selection;
|
let mut new_selection;
|
||||||
|
|
@ -1199,18 +1356,18 @@ pub enum YesNoResult {
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
pub fn game_over(ctx: &mut BTerm) -> YesNoResult {
|
||||||
let mut x = 3;
|
let mut x = 3;
|
||||||
let mut y = 12;
|
let mut y = 12;
|
||||||
let width = 45;
|
let width = 45;
|
||||||
let height = 20;
|
let height = 20;
|
||||||
ctx.draw_box(x, y, width, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
|
ctx.draw_box(x, y, width, height, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
ctx.print_color(x + 3, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "You died!");
|
ctx.print_color(x + 3, y, RGB::named(YELLOW), RGB::named(BLACK), "You died!");
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x + 3,
|
x + 3,
|
||||||
y + height,
|
y + height,
|
||||||
RGB::named(rltk::YELLOW),
|
RGB::named(YELLOW),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
" Write a morgue file? [y/n] "
|
" Write a morgue file? [y/n] "
|
||||||
);
|
);
|
||||||
x += 2;
|
x += 2;
|
||||||
|
|
@ -1218,20 +1375,23 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::GREEN),
|
RGB::named(GREEN),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!("You survived for {} turns.", crate::gamelog::get_event_count(EVENT::COUNT_TURN))
|
format!("You survived for {} turns.", crate::gamelog::get_event_count(EVENT::COUNT_TURN))
|
||||||
);
|
);
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), format!("And in the process, you"));
|
ctx.print_color(x, y, RGB::named(GREEN), RGB::named(BLACK), format!("And in the process, you"));
|
||||||
y += 1;
|
y += 1;
|
||||||
if crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) > 0 {
|
if crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) > 0 {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x + 1,
|
x + 1,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!("- changed floor {} times", crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR))
|
format!(
|
||||||
|
"- changed floor {} times",
|
||||||
|
crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1239,8 +1399,8 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x + 1,
|
x + 1,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!(
|
format!(
|
||||||
"- kicked {} time(s), breaking {} object(s)",
|
"- kicked {} time(s), breaking {} object(s)",
|
||||||
crate::gamelog::get_event_count(EVENT::COUNT_KICK),
|
crate::gamelog::get_event_count(EVENT::COUNT_KICK),
|
||||||
|
|
@ -1253,9 +1413,12 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x + 1,
|
x + 1,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!("- slew {} other creature(s)", crate::gamelog::get_event_count(EVENT::COUNT_KILLED))
|
format!(
|
||||||
|
"- slew {} other creature(s)",
|
||||||
|
crate::gamelog::get_event_count(EVENT::COUNT_KILLED)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1263,9 +1426,12 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
x + 1,
|
x + 1,
|
||||||
y,
|
y,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP))
|
format!(
|
||||||
|
"- forgot the controls {} time(s)",
|
||||||
|
crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,24 @@ use super::{
|
||||||
ItemMenuResult,
|
ItemMenuResult,
|
||||||
UniqueInventoryItem,
|
UniqueInventoryItem,
|
||||||
};
|
};
|
||||||
use crate::{ gamelog, Beatitude, Entity, Equipped, InBackpack, Item, Name, Renderable, states::state::*, BUC };
|
use crate::{
|
||||||
use rltk::prelude::*;
|
gamelog,
|
||||||
|
Beatitude,
|
||||||
|
Entity,
|
||||||
|
Equipped,
|
||||||
|
InBackpack,
|
||||||
|
Item,
|
||||||
|
Name,
|
||||||
|
Renderable,
|
||||||
|
states::state::*,
|
||||||
|
BUC,
|
||||||
|
};
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// Handles the Remove Curse menu.
|
/// Handles the Remove Curse menu.
|
||||||
pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
|
||||||
let player_entity = gs.ecs.fetch::<Entity>();
|
let player_entity = gs.ecs.fetch::<Entity>();
|
||||||
let equipped = gs.ecs.read_storage::<Equipped>();
|
let equipped = gs.ecs.read_storage::<Equipped>();
|
||||||
let backpack = gs.ecs.read_storage::<InBackpack>();
|
let backpack = gs.ecs.read_storage::<InBackpack>();
|
||||||
|
|
@ -24,7 +35,9 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
||||||
let renderables = gs.ecs.read_storage::<Renderable>();
|
let renderables = gs.ecs.read_storage::<Renderable>();
|
||||||
|
|
||||||
let build_cursed_iterator = || {
|
let build_cursed_iterator = || {
|
||||||
(&entities, &items, &beatitudes, &renderables, &names).join().filter(|(item_entity, _i, b, _r, _n)| {
|
(&entities, &items, &beatitudes, &renderables, &names)
|
||||||
|
.join()
|
||||||
|
.filter(|(item_entity, _i, b, _r, _n)| {
|
||||||
// Set all items to FALSE initially.
|
// Set all items to FALSE initially.
|
||||||
let mut keep = false;
|
let mut keep = false;
|
||||||
// If found in the player's backpack, set to TRUE
|
// If found in the player's backpack, set to TRUE
|
||||||
|
|
@ -76,7 +89,9 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
||||||
let mut player_inventory: super::PlayerInventory = BTreeMap::new();
|
let mut player_inventory: super::PlayerInventory = BTreeMap::new();
|
||||||
for (entity, _i, _b, renderable, name) in build_cursed_iterator() {
|
for (entity, _i, _b, renderable, name) in build_cursed_iterator() {
|
||||||
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
|
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
|
||||||
let beatitude_status = if let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity) {
|
let beatitude_status = if
|
||||||
|
let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity)
|
||||||
|
{
|
||||||
match beatitude.buc {
|
match beatitude.buc {
|
||||||
BUC::Blessed => 1,
|
BUC::Blessed => 1,
|
||||||
BUC::Uncursed => 2,
|
BUC::Uncursed => 2,
|
||||||
|
|
@ -108,8 +123,8 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
1 + x_offset,
|
1 + x_offset,
|
||||||
1 + y_offset,
|
1 + y_offset,
|
||||||
RGB::named(rltk::WHITE),
|
RGB::named(WHITE),
|
||||||
RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
"Decurse which item? [aA-zZ][Esc.]"
|
"Decurse which item? [aA-zZ][Esc.]"
|
||||||
);
|
);
|
||||||
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
||||||
|
|
@ -121,7 +136,7 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
||||||
match key {
|
match key {
|
||||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||||
_ => {
|
_ => {
|
||||||
let selection = rltk::letter_to_option(key);
|
let selection = letter_to_option(key);
|
||||||
if selection > -1 && selection < (count as i32) {
|
if selection > -1 && selection < (count as i32) {
|
||||||
let item = player_inventory
|
let item = player_inventory
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,18 @@
|
||||||
use super::{ camera::get_screen_bounds, Attributes, Hidden, Map, Name, Pools, Position, Renderable, Rltk, World, RGB };
|
use super::{
|
||||||
|
camera::get_screen_bounds,
|
||||||
|
Attributes,
|
||||||
|
Hidden,
|
||||||
|
Map,
|
||||||
|
Name,
|
||||||
|
Pools,
|
||||||
|
Position,
|
||||||
|
Renderable,
|
||||||
|
World,
|
||||||
|
RGB,
|
||||||
|
};
|
||||||
use crate::TileType;
|
use crate::TileType;
|
||||||
use crate::data::ids::*;
|
use crate::data::ids::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
struct Tooltip {
|
struct Tooltip {
|
||||||
|
|
@ -33,8 +44,15 @@ impl Tooltip {
|
||||||
fn height(&self) -> i32 {
|
fn height(&self) -> i32 {
|
||||||
return (self.lines.len() as i32) + 2i32;
|
return (self.lines.len() as i32) + 2i32;
|
||||||
}
|
}
|
||||||
fn render(&self, ctx: &mut Rltk, x: i32, y: i32) {
|
fn render(&self, ctx: &mut BTerm, x: i32, y: i32) {
|
||||||
ctx.draw_box(x, y, self.width() - 1, self.height() - 1, RGB::named(WHITE), RGB::named(BLACK));
|
ctx.draw_box(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
self.width() - 1,
|
||||||
|
self.height() - 1,
|
||||||
|
RGB::named(WHITE),
|
||||||
|
RGB::named(BLACK)
|
||||||
|
);
|
||||||
for (i, s) in self.lines.iter().enumerate() {
|
for (i, s) in self.lines.iter().enumerate() {
|
||||||
ctx.print_color(x + 1, y + (i as i32) + 1, s.1, RGB::named(BLACK), &s.0);
|
ctx.print_color(x + 1, y + (i as i32) + 1, s.1, RGB::named(BLACK), &s.0);
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +60,7 @@ impl Tooltip {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk, xy: Option<(i32, i32)>) {
|
pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) {
|
||||||
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx);
|
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx);
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let names = ecs.read_storage::<Name>();
|
let names = ecs.read_storage::<Name>();
|
||||||
|
|
@ -143,7 +161,7 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk, xy: Option<(i32, i32)>) {
|
||||||
|
|
||||||
if tooltips.is_empty() { return ; }
|
if tooltips.is_empty() { return ; }
|
||||||
|
|
||||||
let white = RGB::named(rltk::WHITE);
|
let white = RGB::named(WHITE);
|
||||||
|
|
||||||
let arrow;
|
let arrow;
|
||||||
let arrow_x;
|
let arrow_x;
|
||||||
|
|
@ -157,7 +175,7 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk, xy: Option<(i32, i32)>) {
|
||||||
arrow = to_cp437('←');
|
arrow = to_cp437('←');
|
||||||
arrow_x = mouse_pos.0 + 1;
|
arrow_x = mouse_pos.0 + 1;
|
||||||
}
|
}
|
||||||
ctx.set(arrow_x, arrow_y, white, RGB::named(rltk::BLACK), arrow);
|
ctx.set(arrow_x, arrow_y, white, RGB::named(BLACK), arrow);
|
||||||
|
|
||||||
let mut total_height = 0;
|
let mut total_height = 0;
|
||||||
for t in tooltips.iter() {
|
for t in tooltips.iter() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
use super::{ effects::{ add_effect, EffectType, Targets }, gamelog, Clock, HungerClock, HungerState, TakingTurn };
|
use super::{
|
||||||
use rltk::prelude::*;
|
effects::{ add_effect, EffectType, Targets },
|
||||||
|
gamelog,
|
||||||
|
Clock,
|
||||||
|
HungerClock,
|
||||||
|
HungerState,
|
||||||
|
TakingTurn,
|
||||||
|
};
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
|
||||||
|
|
@ -69,11 +76,18 @@ impl<'a> System<'a> for HungerSystem {
|
||||||
let initial_state = hunger_clock.state;
|
let initial_state = hunger_clock.state;
|
||||||
hunger_clock.state = get_hunger_state(hunger_clock.duration);
|
hunger_clock.state = get_hunger_state(hunger_clock.duration);
|
||||||
if hunger_clock.state == HungerState::Starving {
|
if hunger_clock.state == HungerState::Starving {
|
||||||
add_effect(None, EffectType::Damage { amount: 1 }, Targets::Entity { target: entity });
|
add_effect(
|
||||||
|
None,
|
||||||
|
EffectType::Damage { amount: 1 },
|
||||||
|
Targets::Entity { target: entity }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if CONFIG.logging.log_ticks && entity == *player_entity {
|
if CONFIG.logging.log_ticks && entity == *player_entity {
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!("HUNGER SYSTEM: Ticked for player entity. [clock: {}]", hunger_clock.duration)
|
format!(
|
||||||
|
"HUNGER SYSTEM: Ticked for player entity. [clock: {}]",
|
||||||
|
hunger_clock.duration
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if hunger_clock.state == initial_state {
|
if hunger_clock.state == initial_state {
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ use crate::{
|
||||||
ObfuscatedName,
|
ObfuscatedName,
|
||||||
Position,
|
Position,
|
||||||
WantsToPickupItem,
|
WantsToPickupItem,
|
||||||
Renderable,
|
|
||||||
};
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::messages;
|
use crate::data::messages;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct ItemCollectionSystem {}
|
pub struct ItemCollectionSystem {}
|
||||||
|
|
||||||
|
|
@ -52,7 +52,9 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
||||||
|
|
||||||
for pickup in wants_pickup.join() {
|
for pickup in wants_pickup.join() {
|
||||||
positions.remove(pickup.item);
|
positions.remove(pickup.item);
|
||||||
backpack.insert(pickup.item, InBackpack { owner: pickup.collected_by }).expect("Unable to pickup item.");
|
backpack
|
||||||
|
.insert(pickup.item, InBackpack { owner: pickup.collected_by })
|
||||||
|
.expect("Unable to pickup item.");
|
||||||
equipment_changed
|
equipment_changed
|
||||||
.insert(pickup.collected_by, EquipmentChanged {})
|
.insert(pickup.collected_by, EquipmentChanged {})
|
||||||
.expect("Unable to insert EquipmentChanged.");
|
.expect("Unable to insert EquipmentChanged.");
|
||||||
|
|
@ -76,7 +78,7 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
||||||
).0
|
).0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period()
|
.period()
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::messages;
|
use crate::data::messages;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct ItemDropSystem {}
|
pub struct ItemDropSystem {}
|
||||||
|
|
||||||
|
|
@ -52,7 +53,9 @@ impl<'a> System<'a> for ItemDropSystem {
|
||||||
) = data;
|
) = data;
|
||||||
|
|
||||||
for (entity, to_drop) in (&entities, &wants_drop).join() {
|
for (entity, to_drop) in (&entities, &wants_drop).join() {
|
||||||
equipment_changed.insert(entity, EquipmentChanged {}).expect("Unable to insert EquipmentChanged.");
|
equipment_changed
|
||||||
|
.insert(entity, EquipmentChanged {})
|
||||||
|
.expect("Unable to insert EquipmentChanged.");
|
||||||
let mut dropper_pos: Position = Position { x: 0, y: 0 };
|
let mut dropper_pos: Position = Position { x: 0, y: 0 };
|
||||||
{
|
{
|
||||||
let dropped_pos = positions.get(entity).unwrap();
|
let dropped_pos = positions.get(entity).unwrap();
|
||||||
|
|
@ -83,7 +86,7 @@ impl<'a> System<'a> for ItemDropSystem {
|
||||||
).0
|
).0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period()
|
.period()
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::messages;
|
use crate::data::messages;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct ItemEquipSystem {}
|
pub struct ItemEquipSystem {}
|
||||||
|
|
||||||
|
|
@ -66,7 +67,11 @@ impl<'a> System<'a> for ItemEquipSystem {
|
||||||
// Remove any items target has in item's slot
|
// Remove any items target has in item's slot
|
||||||
let mut can_equip = true;
|
let mut can_equip = true;
|
||||||
let mut to_unequip: Vec<Entity> = Vec::new();
|
let mut to_unequip: Vec<Entity> = Vec::new();
|
||||||
for (item_entity, already_equipped, _name) in (&entities, &equipped, &names).join() {
|
for (item_entity, already_equipped, _name) in (
|
||||||
|
&entities,
|
||||||
|
&equipped,
|
||||||
|
&names,
|
||||||
|
).join() {
|
||||||
if already_equipped.owner == target && already_equipped.slot == target_slot {
|
if already_equipped.owner == target && already_equipped.slot == target_slot {
|
||||||
if let Some(beatitude) = beatitudes.get(item_entity) {
|
if let Some(beatitude) = beatitudes.get(item_entity) {
|
||||||
if beatitude.buc == BUC::Cursed {
|
if beatitude.buc == BUC::Cursed {
|
||||||
|
|
@ -85,7 +90,7 @@ impl<'a> System<'a> for ItemEquipSystem {
|
||||||
None
|
None
|
||||||
).0
|
).0
|
||||||
)
|
)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.append("!");
|
.append("!");
|
||||||
identified_beatitude
|
identified_beatitude
|
||||||
.insert(item_entity, IdentifiedBeatitude {})
|
.insert(item_entity, IdentifiedBeatitude {})
|
||||||
|
|
@ -101,15 +106,25 @@ impl<'a> System<'a> for ItemEquipSystem {
|
||||||
}
|
}
|
||||||
for item in to_unequip.iter() {
|
for item in to_unequip.iter() {
|
||||||
equipped.remove(*item);
|
equipped.remove(*item);
|
||||||
backpack.insert(*item, InBackpack { owner: target }).expect("Unable to insert backpack");
|
backpack
|
||||||
|
.insert(*item, InBackpack { owner: target })
|
||||||
|
.expect("Unable to insert backpack");
|
||||||
if target == *player_entity {
|
if target == *player_entity {
|
||||||
logger = logger
|
logger = logger
|
||||||
.append(messages::YOU_REMOVE_ITEM)
|
.append(messages::YOU_REMOVE_ITEM)
|
||||||
.colour(item_colour(*item, &beatitudes))
|
.colour(item_colour(*item, &beatitudes))
|
||||||
.append_n(
|
.append_n(
|
||||||
obfuscate_name(*item, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None).0
|
obfuscate_name(
|
||||||
|
*item,
|
||||||
|
&names,
|
||||||
|
&magic_items,
|
||||||
|
&obfuscated_names,
|
||||||
|
&beatitudes,
|
||||||
|
&dm,
|
||||||
|
None
|
||||||
|
).0
|
||||||
)
|
)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period();
|
.period();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +149,7 @@ impl<'a> System<'a> for ItemEquipSystem {
|
||||||
None
|
None
|
||||||
).0
|
).0
|
||||||
)
|
)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period();
|
.period();
|
||||||
logger.log();
|
logger.log();
|
||||||
identified_items
|
identified_items
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
WantsToRemoveItem,
|
WantsToRemoveItem,
|
||||||
BUC,
|
BUC,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::messages;
|
use crate::data::messages;
|
||||||
|
|
||||||
|
|
@ -99,7 +99,9 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backpack.insert(to_remove.item, InBackpack { owner: entity }).expect("Unable to insert backpack");
|
backpack
|
||||||
|
.insert(to_remove.item, InBackpack { owner: entity })
|
||||||
|
.expect("Unable to insert backpack");
|
||||||
}
|
}
|
||||||
|
|
||||||
wants_remove.clear();
|
wants_remove.clear();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// src/lib.rs
|
// src/lib.rs
|
||||||
// 31-Aug-2023
|
// 31-Aug-2023
|
||||||
|
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
|
|
|
||||||
18
src/main.rs
18
src/main.rs
|
|
@ -1,19 +1,19 @@
|
||||||
use rust_rl::*;
|
use rust_rl::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator };
|
use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
const DISPLAYWIDTH: i32 = 105;
|
const DISPLAYWIDTH: i32 = 105;
|
||||||
const DISPLAYHEIGHT: i32 = 56;
|
const DISPLAYHEIGHT: i32 = 56;
|
||||||
|
|
||||||
fn main() -> rltk::BError {
|
fn main() -> BError {
|
||||||
// Embedded resources for use in wasm build
|
// Embedded resources for use in wasm build
|
||||||
const CURSES_14_16_BYTES: &[u8] = include_bytes!("../resources/curses14x16.png");
|
const CURSES_14_16_BYTES: &[u8] = include_bytes!("../resources/curses14x16.png");
|
||||||
rltk::embedding::EMBED.lock().add_resource("resources/curses14x16.png".to_string(), CURSES_14_16_BYTES);
|
EMBED.lock().add_resource("resources/curses14x16.png".to_string(), CURSES_14_16_BYTES);
|
||||||
|
|
||||||
//rltk::link_resource!(CURSES14X16, "../resources/curses_14x16.png");
|
//link_resource!(CURSES14X16, "../resources/curses_14x16.png");
|
||||||
|
|
||||||
let mut context = RltkBuilder::new()
|
let mut context = BTermBuilder::new()
|
||||||
.with_title("rust-rl")
|
.with_title("rust-rl")
|
||||||
.with_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT)
|
.with_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT)
|
||||||
.with_font("curses14x16.png", 14, 16)
|
.with_font("curses14x16.png", 14, 16)
|
||||||
|
|
@ -26,7 +26,9 @@ fn main() -> rltk::BError {
|
||||||
|
|
||||||
let mut gs = State {
|
let mut gs = State {
|
||||||
ecs: World::new(),
|
ecs: World::new(),
|
||||||
mapgen_next_state: Some(RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame }),
|
mapgen_next_state: Some(RunState::MainMenu {
|
||||||
|
menu_selection: gui::MainMenuSelection::NewGame,
|
||||||
|
}),
|
||||||
mapgen_index: 0,
|
mapgen_index: 0,
|
||||||
mapgen_history: Vec::new(),
|
mapgen_history: Vec::new(),
|
||||||
mapgen_timer: 0.0,
|
mapgen_timer: 0.0,
|
||||||
|
|
@ -115,7 +117,7 @@ fn main() -> rltk::BError {
|
||||||
raws::load_raws();
|
raws::load_raws();
|
||||||
|
|
||||||
// Insert calls
|
// Insert calls
|
||||||
gs.ecs.insert(rltk::RandomNumberGenerator::new());
|
gs.ecs.insert(RandomNumberGenerator::new());
|
||||||
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
||||||
gs.ecs.insert(Map::new(true, 1, 64, 64, 0, "New Map", "N", 0)); // Map
|
gs.ecs.insert(Map::new(true, 1, 64, 64, 0, "New Map", "N", 0)); // Map
|
||||||
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
||||||
|
|
@ -130,5 +132,5 @@ fn main() -> rltk::BError {
|
||||||
gamelog::record_event(data::events::EVENT::LEVEL(1));
|
gamelog::record_event(data::events::EVENT::LEVEL(1));
|
||||||
gs.generate_world_map(1, TileType::Floor);
|
gs.generate_world_map(1, TileType::Floor);
|
||||||
|
|
||||||
rltk::main_loop(context, gs)
|
main_loop(context, gs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{ Map, TileType };
|
use super::{ Map, TileType };
|
||||||
use crate::{ gamelog, map_builders, OtherLevelPosition, Position, Telepath, Viewshed };
|
use crate::{ gamelog, map_builders, OtherLevelPosition, Position, Telepath, Viewshed };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use serde::{ Deserialize, Serialize };
|
use serde::{ Deserialize, Serialize };
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::{ HashMap, HashSet };
|
use std::collections::{ HashMap, HashSet };
|
||||||
|
|
@ -61,7 +61,11 @@ impl MasterDungeonMap {
|
||||||
|
|
||||||
fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String {
|
fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String {
|
||||||
let len = 4 + rng.roll_dice(1, 6);
|
let len = 4 + rng.roll_dice(1, 6);
|
||||||
let space_at_i = if len > 6 && rng.roll_dice(1, 2) == 1 { rng.roll_dice(1, len - 6) + 3 } else { -1 };
|
let space_at_i = if len > 6 && rng.roll_dice(1, 2) == 1 {
|
||||||
|
rng.roll_dice(1, len - 6) + 3
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
};
|
||||||
let offset = rng.roll_dice(1, 2) - 1;
|
let offset = rng.roll_dice(1, 2) - 1;
|
||||||
let mut name = "".to_string();
|
let mut name = "".to_string();
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
|
|
@ -142,7 +146,9 @@ const POTION_ADJECTIVES: &[&str] = &[
|
||||||
fn make_potion_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
fn make_potion_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
||||||
loop {
|
loop {
|
||||||
let mut name: String =
|
let mut name: String =
|
||||||
POTION_ADJECTIVES[(rng.roll_dice(1, POTION_ADJECTIVES.len() as i32) as usize) - 1].to_string();
|
POTION_ADJECTIVES[
|
||||||
|
(rng.roll_dice(1, POTION_ADJECTIVES.len() as i32) as usize) - 1
|
||||||
|
].to_string();
|
||||||
name += " ";
|
name += " ";
|
||||||
name += POTION_COLOURS[(rng.roll_dice(1, POTION_COLOURS.len() as i32) as usize) - 1];
|
name += POTION_COLOURS[(rng.roll_dice(1, POTION_COLOURS.len() as i32) as usize) - 1];
|
||||||
name += " potion";
|
name += " potion";
|
||||||
|
|
@ -178,7 +184,8 @@ const WAND_TYPES: &[&str] = &[
|
||||||
|
|
||||||
fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
||||||
loop {
|
loop {
|
||||||
let mut name: String = WAND_TYPES[(rng.roll_dice(1, WAND_TYPES.len() as i32) as usize) - 1].to_string();
|
let mut name: String =
|
||||||
|
WAND_TYPES[(rng.roll_dice(1, WAND_TYPES.len() as i32) as usize) - 1].to_string();
|
||||||
name += " wand";
|
name += " wand";
|
||||||
|
|
||||||
if !used_names.contains(&name) {
|
if !used_names.contains(&name) {
|
||||||
|
|
@ -227,8 +234,9 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32, dest_tile: TileType)
|
||||||
}
|
}
|
||||||
possible_destinations.push(((map.width * map.height) as usize) / 2); // Centre of map
|
possible_destinations.push(((map.width * map.height) as usize) / 2); // Centre of map
|
||||||
}
|
}
|
||||||
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let idx = possible_destinations[(rng.roll_dice(1, possible_destinations.len() as i32) as usize) - 1];
|
let idx =
|
||||||
|
possible_destinations[(rng.roll_dice(1, possible_destinations.len() as i32) as usize) - 1];
|
||||||
let mut player_position = ecs.write_resource::<Point>();
|
let mut player_position = ecs.write_resource::<Point>();
|
||||||
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
|
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
|
||||||
let mut position_components = ecs.write_storage::<Position>();
|
let mut position_components = ecs.write_storage::<Position>();
|
||||||
|
|
@ -253,7 +261,7 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32, dest_tile: TileType)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transition_to_new_map(ecs: &mut World, new_id: i32, _dest_tile: TileType) -> Vec<Map> {
|
fn transition_to_new_map(ecs: &mut World, new_id: i32, _dest_tile: TileType) -> Vec<Map> {
|
||||||
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
// Might need this to fallback to 1, but if player
|
// Might need this to fallback to 1, but if player
|
||||||
// level isn't found at all, there's a bigger concern
|
// level isn't found at all, there's a bigger concern
|
||||||
// concern than just this function not working.
|
// concern than just this function not working.
|
||||||
|
|
@ -346,7 +354,9 @@ pub fn thaw_entities(ecs: &mut World) {
|
||||||
let mut pos_to_delete: Vec<Entity> = Vec::new();
|
let mut pos_to_delete: Vec<Entity> = Vec::new();
|
||||||
for (entity, pos) in (&entities, &other_positions).join() {
|
for (entity, pos) in (&entities, &other_positions).join() {
|
||||||
if entity != *player_entity && pos.id == map_id {
|
if entity != *player_entity && pos.id == map_id {
|
||||||
positions.insert(entity, Position { x: pos.x, y: pos.y }).expect("Failed to insert OtherLevelPosition");
|
positions
|
||||||
|
.insert(entity, Position { x: pos.x, y: pos.y })
|
||||||
|
.expect("Failed to insert OtherLevelPosition");
|
||||||
pos_to_delete.push(entity);
|
pos_to_delete.push(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
use crate::{ config::CONFIG, gamelog, raws, spawner, Clock, Map, RandomNumberGenerator, TakingTurn };
|
use crate::{
|
||||||
|
config::CONFIG,
|
||||||
|
gamelog,
|
||||||
|
raws,
|
||||||
|
spawner,
|
||||||
|
Clock,
|
||||||
|
Map,
|
||||||
|
RandomNumberGenerator,
|
||||||
|
TakingTurn,
|
||||||
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
|
||||||
const TRY_SPAWN_CHANCE: i32 = 70;
|
const TRY_SPAWN_CHANCE: i32 = 70;
|
||||||
|
|
@ -15,7 +25,7 @@ pub fn maybe_map_message(ecs: &mut World) {
|
||||||
{
|
{
|
||||||
let clock = ecs.read_storage::<Clock>();
|
let clock = ecs.read_storage::<Clock>();
|
||||||
let turns = ecs.read_storage::<TakingTurn>();
|
let turns = ecs.read_storage::<TakingTurn>();
|
||||||
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
for (_c, _t) in (&clock, &turns).join() {
|
for (_c, _t) in (&clock, &turns).join() {
|
||||||
if rng.roll_dice(1, FEATURE_MESSAGE_CHANCE) == 1 {
|
if rng.roll_dice(1, FEATURE_MESSAGE_CHANCE) == 1 {
|
||||||
maybe_message = true;
|
maybe_message = true;
|
||||||
|
|
@ -42,7 +52,7 @@ pub fn try_spawn_interval(ecs: &mut World) {
|
||||||
}
|
}
|
||||||
let clock = ecs.read_storage::<Clock>();
|
let clock = ecs.read_storage::<Clock>();
|
||||||
let turns = ecs.read_storage::<TakingTurn>();
|
let turns = ecs.read_storage::<TakingTurn>();
|
||||||
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
for (_c, _t) in (&clock, &turns).join() {
|
for (_c, _t) in (&clock, &turns).join() {
|
||||||
if rng.roll_dice(1, TRY_SPAWN_CHANCE) == 1 {
|
if rng.roll_dice(1, TRY_SPAWN_CHANCE) == 1 {
|
||||||
try_spawn = true;
|
try_spawn = true;
|
||||||
|
|
@ -51,7 +61,7 @@ pub fn try_spawn_interval(ecs: &mut World) {
|
||||||
}
|
}
|
||||||
if try_spawn {
|
if try_spawn {
|
||||||
if CONFIG.logging.log_spawning {
|
if CONFIG.logging.log_spawning {
|
||||||
rltk::console::log("SPAWNINFO: Trying spawn.");
|
console::log("SPAWNINFO: Trying spawn.");
|
||||||
}
|
}
|
||||||
spawn_random_mob_in_free_nonvisible_tile(ecs);
|
spawn_random_mob_in_free_nonvisible_tile(ecs);
|
||||||
}
|
}
|
||||||
|
|
@ -61,11 +71,11 @@ fn spawn_random_mob_in_free_nonvisible_tile(ecs: &mut World) {
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let mut available_tiles = populate_unblocked_nonvisible(&map);
|
let mut available_tiles = populate_unblocked_nonvisible(&map);
|
||||||
let player_level = gamelog::get_event_count(EVENT::COUNT_LEVEL);
|
let player_level = gamelog::get_event_count(EVENT::COUNT_LEVEL);
|
||||||
rltk::console::log(player_level);
|
console::log(player_level);
|
||||||
let difficulty = (map.difficulty + player_level) / 2;
|
let difficulty = (map.difficulty + player_level) / 2;
|
||||||
if available_tiles.len() == 0 {
|
if available_tiles.len() == 0 {
|
||||||
if CONFIG.logging.log_spawning {
|
if CONFIG.logging.log_spawning {
|
||||||
rltk::console::log("SPAWNINFO: No free tiles; not spawning anything..");
|
console::log("SPAWNINFO: No free tiles; not spawning anything..");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +94,7 @@ fn spawn_random_mob_in_free_nonvisible_tile(ecs: &mut World) {
|
||||||
// For every idx in the spawn list, spawn mob.
|
// For every idx in the spawn list, spawn mob.
|
||||||
for idx in spawn_locations {
|
for idx in spawn_locations {
|
||||||
if CONFIG.logging.log_spawning {
|
if CONFIG.logging.log_spawning {
|
||||||
rltk::console::log(format!("SPAWNINFO: Spawning {} at {}, {}.", key, idx.0, idx.1));
|
console::log(format!("SPAWNINFO: Spawning {} at {}, {}.", key, idx.0, idx.1));
|
||||||
}
|
}
|
||||||
raws::spawn_named_entity(
|
raws::spawn_named_entity(
|
||||||
&raws::RAWS.lock().unwrap(),
|
&raws::RAWS.lock().unwrap(),
|
||||||
|
|
@ -109,8 +119,12 @@ fn populate_unblocked_nonvisible(map: &Map) -> Vec<usize> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Picks a random index from a vector of indexes, and removes it from the vector.
|
/// Picks a random index from a vector of indexes, and removes it from the vector.
|
||||||
fn get_random_idx_from_tiles(rng: &mut rltk::RandomNumberGenerator, area: &mut Vec<usize>) -> usize {
|
fn get_random_idx_from_tiles(rng: &mut RandomNumberGenerator, area: &mut Vec<usize>) -> usize {
|
||||||
let idx = if area.len() == 1 { 0usize } else { (rng.roll_dice(1, area.len() as i32) - 1) as usize };
|
let idx = if area.len() == 1 {
|
||||||
|
0usize
|
||||||
|
} else {
|
||||||
|
(rng.roll_dice(1, area.len() as i32) - 1) as usize
|
||||||
|
};
|
||||||
area.remove(idx);
|
area.remove(idx);
|
||||||
return area[idx];
|
return area[idx];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use serde::{ Deserialize, Serialize };
|
use serde::{ Deserialize, Serialize };
|
||||||
use std::collections::{ HashSet, HashMap };
|
use std::collections::{ HashSet, HashMap };
|
||||||
mod tiletype;
|
mod tiletype;
|
||||||
|
|
@ -8,7 +8,11 @@ pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval };
|
||||||
pub mod dungeon;
|
pub mod dungeon;
|
||||||
pub use dungeon::{ level_transition, MasterDungeonMap };
|
pub use dungeon::{ level_transition, MasterDungeonMap };
|
||||||
pub mod themes;
|
pub mod themes;
|
||||||
use super::data::visuals::{ BRIGHTEN_FG_COLOUR_BY, GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP };
|
use super::data::visuals::{
|
||||||
|
BRIGHTEN_FG_COLOUR_BY,
|
||||||
|
GLOBAL_OFFSET_MIN_CLAMP,
|
||||||
|
GLOBAL_OFFSET_MAX_CLAMP,
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: If the map size gets too small, entities stop being rendered starting from the right.
|
// FIXME: If the map size gets too small, entities stop being rendered starting from the right.
|
||||||
// i.e. on a map size of 40*40, only entities to the left of the player are rendered.
|
// i.e. on a map size of 40*40, only entities to the left of the player are rendered.
|
||||||
|
|
@ -63,7 +67,7 @@ impl Map {
|
||||||
lit_tiles: vec![true; map_tile_count], // NYI: Light sources. Once those exist, we can set this to false.
|
lit_tiles: vec![true; map_tile_count], // NYI: Light sources. Once those exist, we can set this to false.
|
||||||
telepath_tiles: vec![false; map_tile_count],
|
telepath_tiles: vec![false; map_tile_count],
|
||||||
colour_offset: vec![((0.0, 0.0, 0.0), (0.0, 0.0, 0.0)); map_tile_count],
|
colour_offset: vec![((0.0, 0.0, 0.0), (0.0, 0.0, 0.0)); map_tile_count],
|
||||||
additional_fg_offset: rltk::RGB::from_u8(
|
additional_fg_offset: RGB::from_u8(
|
||||||
BRIGHTEN_FG_COLOUR_BY as u8,
|
BRIGHTEN_FG_COLOUR_BY as u8,
|
||||||
BRIGHTEN_FG_COLOUR_BY as u8,
|
BRIGHTEN_FG_COLOUR_BY as u8,
|
||||||
BRIGHTEN_FG_COLOUR_BY as u8
|
BRIGHTEN_FG_COLOUR_BY as u8
|
||||||
|
|
@ -78,7 +82,7 @@ impl Map {
|
||||||
view_blocked: HashSet::new(),
|
view_blocked: HashSet::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rng = rltk::RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
|
|
||||||
for idx in 0..map.colour_offset.len() {
|
for idx in 0..map.colour_offset.len() {
|
||||||
map.colour_offset[idx].0 = (
|
map.colour_offset[idx].0 = (
|
||||||
|
|
@ -134,12 +138,12 @@ impl BaseMap for Map {
|
||||||
let w = self.width as usize;
|
let w = self.width as usize;
|
||||||
let p1 = Point::new(idx1 % w, idx1 / w);
|
let p1 = Point::new(idx1 % w, idx1 / w);
|
||||||
let p2 = Point::new(idx2 % w, idx2 / w);
|
let p2 = Point::new(idx2 % w, idx2 / w);
|
||||||
rltk::DistanceAlg::Pythagoras.distance2d(p1, p2)
|
DistanceAlg::Pythagoras.distance2d(p1, p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate every possible exit from a given tile in a cardinal direction, and return it as a vector.
|
/// Evaluate every possible exit from a given tile in a cardinal direction, and return it as a vector.
|
||||||
fn get_available_exits(&self, idx: usize) -> rltk::SmallVec<[(usize, f32); 10]> {
|
fn get_available_exits(&self, idx: usize) -> SmallVec<[(usize, f32); 10]> {
|
||||||
let mut exits = rltk::SmallVec::new();
|
let mut exits = SmallVec::new();
|
||||||
let x = (idx as i32) % self.width;
|
let x = (idx as i32) % self.width;
|
||||||
let y = (idx as i32) / self.width;
|
let y = (idx as i32) / self.width;
|
||||||
let w = self.width as usize;
|
let w = self.width as usize;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use super::{ Map, Point, TileType };
|
||||||
use crate::data::visuals::*;
|
use crate::data::visuals::*;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
use crate::data::ids::*;
|
use crate::data::ids::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use std::ops::{ Add, Mul };
|
use std::ops::{ Add, Mul };
|
||||||
|
|
||||||
/// Gets the renderables for a tile, with darkening/offset/post-processing/etc. Passing a val for "debug" will ignore viewshed.
|
/// Gets the renderables for a tile, with darkening/offset/post-processing/etc. Passing a val for "debug" will ignore viewshed.
|
||||||
|
|
@ -11,7 +11,7 @@ pub fn get_tile_renderables_for_id(
|
||||||
map: &Map,
|
map: &Map,
|
||||||
other_pos: Option<Point>,
|
other_pos: Option<Point>,
|
||||||
debug: Option<bool>
|
debug: Option<bool>
|
||||||
) -> (rltk::FontCharType, RGB, RGB) {
|
) -> (FontCharType, RGB, RGB) {
|
||||||
let coloured_bg = CONFIG.visuals.use_coloured_tile_bg;
|
let coloured_bg = CONFIG.visuals.use_coloured_tile_bg;
|
||||||
|
|
||||||
let (glyph, mut fg, mut bg, fg_offset, bg_offset) = match map.id {
|
let (glyph, mut fg, mut bg, fg_offset, bg_offset) = match map.id {
|
||||||
|
|
@ -78,8 +78,8 @@ pub fn get_tile_renderables_for_id(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>) -> (rltk::FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
|
pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>) -> (FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
|
||||||
let glyph: rltk::FontCharType;
|
let glyph: FontCharType;
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
let mut fg: RGB = RGB::new();
|
let mut fg: RGB = RGB::new();
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
|
|
@ -88,25 +88,25 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>)
|
||||||
let mut bg_offsets: (i32, i32, i32) = (-1, -1, -1);
|
let mut bg_offsets: (i32, i32, i32) = (-1, -1, -1);
|
||||||
|
|
||||||
match map.tiles[idx] {
|
match map.tiles[idx] {
|
||||||
TileType::Floor => { glyph = rltk::to_cp437(FLOOR_GLYPH); fg = RGB::named(FLOOR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = FLOOR_OFFSETS; }
|
TileType::Floor => { glyph = to_cp437(FLOOR_GLYPH); fg = RGB::named(FLOOR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = FLOOR_OFFSETS; }
|
||||||
TileType::WoodFloor => { glyph = rltk::to_cp437(WOOD_FLOOR_GLYPH); bg = RGB::named(WOOD_FLOOR_COLOUR); offsets = WOOD_FLOOR_OFFSETS; }
|
TileType::WoodFloor => { glyph = to_cp437(WOOD_FLOOR_GLYPH); bg = RGB::named(WOOD_FLOOR_COLOUR); offsets = WOOD_FLOOR_OFFSETS; }
|
||||||
TileType::Fence => { glyph = rltk::to_cp437(FENCE_GLYPH); fg = RGB::named(FENCE_FG_COLOUR); bg = RGB::named(FENCE_COLOUR); offsets = FENCE_OFFSETS; }
|
TileType::Fence => { glyph = to_cp437(FENCE_GLYPH); fg = RGB::named(FENCE_FG_COLOUR); bg = RGB::named(FENCE_COLOUR); offsets = FENCE_OFFSETS; }
|
||||||
TileType::Wall => { let x = idx as i32 % map.width; let y = idx as i32 / map.width; glyph = wall_glyph(&*map, x, y, debug); fg = RGB::named(WALL_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = WALL_OFFSETS; bg_offsets = DEFAULT_BG_OFFSETS }
|
TileType::Wall => { let x = idx as i32 % map.width; let y = idx as i32 / map.width; glyph = wall_glyph(&*map, x, y, debug); fg = RGB::named(WALL_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = WALL_OFFSETS; bg_offsets = DEFAULT_BG_OFFSETS }
|
||||||
TileType::DownStair => { glyph = rltk::to_cp437(DOWN_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = STAIR_OFFSETS;}
|
TileType::DownStair => { glyph = to_cp437(DOWN_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = STAIR_OFFSETS;}
|
||||||
TileType::UpStair => { glyph = rltk::to_cp437(UP_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = STAIR_OFFSETS; }
|
TileType::UpStair => { glyph = to_cp437(UP_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = STAIR_OFFSETS; }
|
||||||
TileType::Bridge => { glyph = rltk::to_cp437(BRIDGE_GLYPH); bg = RGB::named(BRIDGE_COLOUR); offsets = BRIDGE_OFFSETS; }
|
TileType::Bridge => { glyph = to_cp437(BRIDGE_GLYPH); bg = RGB::named(BRIDGE_COLOUR); offsets = BRIDGE_OFFSETS; }
|
||||||
TileType::Gravel => { glyph = rltk::to_cp437(GRAVEL_GLYPH); bg = RGB::named(GRAVEL_COLOUR); offsets = GRAVEL_OFFSETS;}
|
TileType::Gravel => { glyph = to_cp437(GRAVEL_GLYPH); bg = RGB::named(GRAVEL_COLOUR); offsets = GRAVEL_OFFSETS;}
|
||||||
TileType::Road => { glyph = rltk::to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); offsets = ROAD_OFFSETS;}
|
TileType::Road => { glyph = to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); offsets = ROAD_OFFSETS;}
|
||||||
TileType::Grass => { glyph = rltk::to_cp437(GRASS_GLYPH); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
|
TileType::Grass => { glyph = to_cp437(GRASS_GLYPH); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
|
||||||
TileType::Foliage => { glyph = rltk::to_cp437(FOLIAGE_GLYPH); bg = RGB::named(FOLIAGE_COLOUR); offsets = FOLIAGE_OFFSETS; }
|
TileType::Foliage => { glyph = to_cp437(FOLIAGE_GLYPH); bg = RGB::named(FOLIAGE_COLOUR); offsets = FOLIAGE_OFFSETS; }
|
||||||
TileType::HeavyFoliage => { glyph = rltk::to_cp437(HEAVY_FOLIAGE_GLYPH); bg = RGB::named(HEAVY_FOLIAGE_COLOUR); offsets = HEAVY_FOLIAGE_OFFSETS; }
|
TileType::HeavyFoliage => { glyph = to_cp437(HEAVY_FOLIAGE_GLYPH); bg = RGB::named(HEAVY_FOLIAGE_COLOUR); offsets = HEAVY_FOLIAGE_OFFSETS; }
|
||||||
TileType::Sand => { glyph = rltk::to_cp437(SAND_GLYPH); bg = RGB::named(SAND_COLOUR); offsets = SAND_OFFSETS; }
|
TileType::Sand => { glyph = to_cp437(SAND_GLYPH); bg = RGB::named(SAND_COLOUR); offsets = SAND_OFFSETS; }
|
||||||
TileType::ShallowWater => { glyph = rltk::to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); offsets = SHALLOW_WATER_OFFSETS; }
|
TileType::ShallowWater => { glyph = to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); offsets = SHALLOW_WATER_OFFSETS; }
|
||||||
TileType::DeepWater => { glyph = rltk::to_cp437(DEEP_WATER_GLYPH); bg = RGB::named(DEEP_WATER_COLOUR); offsets = DEEP_WATER_OFFSETS; }
|
TileType::DeepWater => { glyph = to_cp437(DEEP_WATER_GLYPH); bg = RGB::named(DEEP_WATER_COLOUR); offsets = DEEP_WATER_OFFSETS; }
|
||||||
TileType::Bars => { glyph = rltk::to_cp437(BARS_GLYPH); fg = RGB::named(BARS_COLOUR); bg = RGB::named(FLOOR_COLOUR); }
|
TileType::Bars => { glyph = to_cp437(BARS_GLYPH); fg = RGB::named(BARS_COLOUR); bg = RGB::named(FLOOR_COLOUR); }
|
||||||
TileType::ImpassableMountain => { glyph = rltk::to_cp437(IMPASSABLE_MOUNTAIN_GLYPH); bg = RGB::named(IMPASSABLE_MOUNTAIN_COLOUR); offsets = IMPASSABLE_MOUNTAIN_OFFSETS }
|
TileType::ImpassableMountain => { glyph = to_cp437(IMPASSABLE_MOUNTAIN_GLYPH); bg = RGB::named(IMPASSABLE_MOUNTAIN_COLOUR); offsets = IMPASSABLE_MOUNTAIN_OFFSETS }
|
||||||
TileType::ToOvermap(_) => { glyph = rltk::to_cp437(TO_OVERMAP_GLYPH); fg = RGB::named(TO_OVERMAP_COLOUR); bg = RGB::named(GRASS_COLOUR); }
|
TileType::ToOvermap(_) => { glyph = to_cp437(TO_OVERMAP_GLYPH); fg = RGB::named(TO_OVERMAP_COLOUR); bg = RGB::named(GRASS_COLOUR); }
|
||||||
TileType::ToLocal(_) => { glyph = rltk::to_cp437(TO_TOWN_GLYPH); fg = RGB::named(TO_TOWN_COLOUR); bg = RGB::named(GRASS_COLOUR); }
|
TileType::ToLocal(_) => { glyph = to_cp437(TO_TOWN_GLYPH); fg = RGB::named(TO_TOWN_COLOUR); bg = RGB::named(GRASS_COLOUR); }
|
||||||
}
|
}
|
||||||
if bg_offsets == (-1, -1, -1) {
|
if bg_offsets == (-1, -1, -1) {
|
||||||
bg_offsets = offsets;
|
bg_offsets = offsets;
|
||||||
|
|
@ -115,7 +115,7 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option<bool>) -> (rltk::FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
|
fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option<bool>) -> (FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
|
||||||
let glyph;
|
let glyph;
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
let mut fg = RGB::new();
|
let mut fg = RGB::new();
|
||||||
|
|
@ -125,9 +125,9 @@ fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option<bool>) -> (r
|
||||||
let mut bg_offsets: (i32, i32, i32) = (-1, -1, -1);
|
let mut bg_offsets: (i32, i32, i32) = (-1, -1, -1);
|
||||||
|
|
||||||
match map.tiles[idx] {
|
match map.tiles[idx] {
|
||||||
TileType::Wall => { glyph = rltk::to_cp437(FOREST_WALL_GLYPH); fg = RGB::named(FOREST_WALL_COLOUR); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
|
TileType::Wall => { glyph = to_cp437(FOREST_WALL_GLYPH); fg = RGB::named(FOREST_WALL_COLOUR); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
|
||||||
TileType::Road => { glyph = rltk::to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); }
|
TileType::Road => { glyph = to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); }
|
||||||
TileType::ShallowWater => { glyph = rltk::to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); offsets = SHALLOW_WATER_OFFSETS; }
|
TileType::ShallowWater => { glyph = to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); offsets = SHALLOW_WATER_OFFSETS; }
|
||||||
_ => { (glyph, fg, _, offsets, _) = get_default_theme_renderables(idx, map, debug); bg = RGB::named(GRASS_COLOUR); bg_offsets = GRASS_OFFSETS; }
|
_ => { (glyph, fg, _, offsets, _) = get_default_theme_renderables(idx, map, debug); bg = RGB::named(GRASS_COLOUR); bg_offsets = GRASS_OFFSETS; }
|
||||||
}
|
}
|
||||||
if bg_offsets == (-1, -1, -1) {
|
if bg_offsets == (-1, -1, -1) {
|
||||||
|
|
@ -142,7 +142,7 @@ fn is_revealed_and_wall(map: &Map, x: i32, y: i32, debug: Option<bool>) -> bool
|
||||||
(if debug.is_none() { map.revealed_tiles[idx] } else { true })
|
(if debug.is_none() { map.revealed_tiles[idx] } else { true })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> rltk::FontCharType {
|
fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> FontCharType {
|
||||||
if
|
if
|
||||||
x < 1 ||
|
x < 1 ||
|
||||||
x > map.width - 2 ||
|
x > map.width - 2 ||
|
||||||
|
|
@ -315,15 +315,15 @@ pub fn add_i32_offsets(rgb: RGB, offsets: (f32, f32, f32)) -> RGB {
|
||||||
let g = rgb.g + (offsets.1 as f32) / 255.0;
|
let g = rgb.g + (offsets.1 as f32) / 255.0;
|
||||||
let b = rgb.b + (offsets.2 as f32) / 255.0;
|
let b = rgb.b + (offsets.2 as f32) / 255.0;
|
||||||
|
|
||||||
return rltk::RGB::from_f32(r, g, b);
|
return RGB::from_f32(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiply_by_float(rgb: rltk::RGB, offsets: (f32, f32, f32)) -> RGB {
|
pub fn multiply_by_float(rgb: RGB, offsets: (f32, f32, f32)) -> RGB {
|
||||||
let r = rgb.r * offsets.0;
|
let r = rgb.r * offsets.0;
|
||||||
let g = rgb.g * offsets.1;
|
let g = rgb.g * offsets.1;
|
||||||
let b = rgb.b * offsets.2;
|
let b = rgb.b * offsets.2;
|
||||||
|
|
||||||
return rltk::RGB::from_f32(r, g, b);
|
return RGB::from_f32(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn darken_by_distance(pos: Point, other_pos: Point) -> f32 {
|
fn darken_by_distance(pos: Point, other_pos: Point) -> f32 {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Position };
|
use super::{ BuilderMap, MetaMapBuilder, Position };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum XStart {
|
pub enum XStart {
|
||||||
|
|
@ -21,7 +22,7 @@ pub struct AreaStartingPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for AreaStartingPosition {
|
impl MetaMapBuilder for AreaStartingPosition {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -64,9 +65,12 @@ impl AreaStartingPosition {
|
||||||
if crate::tile_walkable(*tiletype) {
|
if crate::tile_walkable(*tiletype) {
|
||||||
available_floors.push((
|
available_floors.push((
|
||||||
idx,
|
idx,
|
||||||
rltk::DistanceAlg::PythagorasSquared.distance2d(
|
DistanceAlg::PythagorasSquared.distance2d(
|
||||||
rltk::Point::new((idx as i32) % build_data.map.width, (idx as i32) / build_data.map.width),
|
Point::new(
|
||||||
rltk::Point::new(seed_x, seed_y)
|
(idx as i32) % build_data.map.width,
|
||||||
|
(idx as i32) / build_data.map.width
|
||||||
|
),
|
||||||
|
Point::new(seed_x, seed_y)
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, InitialMapBuilder, Rect, TileType };
|
use super::{ BuilderMap, InitialMapBuilder, Rect, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct BspDungeonBuilder {
|
pub struct BspDungeonBuilder {
|
||||||
rects: Vec<Rect>,
|
rects: Vec<Rect>,
|
||||||
|
|
@ -7,7 +7,7 @@ pub struct BspDungeonBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for BspDungeonBuilder {
|
impl InitialMapBuilder for BspDungeonBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ draw_corridor, BuilderMap, InitialMapBuilder, Rect, TileType };
|
use super::{ draw_corridor, BuilderMap, InitialMapBuilder, Rect, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
const MIN_ROOM_SIZE: i32 = 8;
|
const MIN_ROOM_SIZE: i32 = 8;
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ pub struct BspInteriorBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for BspInteriorBuilder {
|
impl InitialMapBuilder for BspInteriorBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, InitialMapBuilder, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, InitialMapBuilder, MetaMapBuilder, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct CellularAutomataBuilder {
|
pub struct CellularAutomataBuilder {
|
||||||
floor_tile: TileType,
|
floor_tile: TileType,
|
||||||
|
|
@ -7,14 +7,14 @@ pub struct CellularAutomataBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for CellularAutomataBuilder {
|
impl InitialMapBuilder for CellularAutomataBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for CellularAutomataBuilder {
|
impl MetaMapBuilder for CellularAutomataBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, _rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.apply_iteration(build_data);
|
self.apply_iteration(build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,16 +69,28 @@ impl CellularAutomataBuilder {
|
||||||
if build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Wall {
|
if build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Wall {
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx - ((build_data.map.width as usize) - 1)] == TileType::Wall {
|
if
|
||||||
|
build_data.map.tiles[idx - ((build_data.map.width as usize) - 1)] ==
|
||||||
|
TileType::Wall
|
||||||
|
{
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx - ((build_data.map.width as usize) + 1)] == TileType::Wall {
|
if
|
||||||
|
build_data.map.tiles[idx - ((build_data.map.width as usize) + 1)] ==
|
||||||
|
TileType::Wall
|
||||||
|
{
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx + ((build_data.map.width as usize) - 1)] == TileType::Wall {
|
if
|
||||||
|
build_data.map.tiles[idx + ((build_data.map.width as usize) - 1)] ==
|
||||||
|
TileType::Wall
|
||||||
|
{
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx + ((build_data.map.width as usize) + 1)] == TileType::Wall {
|
if
|
||||||
|
build_data.map.tiles[idx + ((build_data.map.width as usize) + 1)] ==
|
||||||
|
TileType::Wall
|
||||||
|
{
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use crate::tile_walkable;
|
use crate::tile_walkable;
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct CullUnreachable {}
|
pub struct CullUnreachable {}
|
||||||
|
|
||||||
impl MetaMapBuilder for CullUnreachable {
|
impl MetaMapBuilder for CullUnreachable {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ impl CullUnreachable {
|
||||||
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
|
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
|
||||||
build_data.map.populate_blocked();
|
build_data.map.populate_blocked();
|
||||||
let map_starts: Vec<usize> = vec![start_idx];
|
let map_starts: Vec<usize> = vec![start_idx];
|
||||||
let dijkstra_map = rltk::DijkstraMap::new(
|
let dijkstra_map = DijkstraMap::new(
|
||||||
build_data.map.width as usize,
|
build_data.map.width as usize,
|
||||||
build_data.map.height as usize,
|
build_data.map.height as usize,
|
||||||
&map_starts,
|
&map_starts,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use crate::tile_walkable;
|
use crate::tile_walkable;
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct DistantExit {}
|
pub struct DistantExit {}
|
||||||
|
|
||||||
impl MetaMapBuilder for DistantExit {
|
impl MetaMapBuilder for DistantExit {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ impl DistantExit {
|
||||||
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
|
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
|
||||||
build_data.map.populate_blocked();
|
build_data.map.populate_blocked();
|
||||||
let map_starts: Vec<usize> = vec![start_idx];
|
let map_starts: Vec<usize> = vec![start_idx];
|
||||||
let dijkstra_map = rltk::DijkstraMap::new(
|
let dijkstra_map = DijkstraMap::new(
|
||||||
build_data.map.width as usize,
|
build_data.map.width as usize,
|
||||||
build_data.map.height as usize,
|
build_data.map.height as usize,
|
||||||
&map_starts,
|
&map_starts,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
|
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -18,14 +18,14 @@ pub struct DLABuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for DLABuilder {
|
impl InitialMapBuilder for DLABuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for DLABuilder {
|
impl MetaMapBuilder for DLABuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,10 @@ impl DLABuilder {
|
||||||
#[allow(clippy::map_entry)]
|
#[allow(clippy::map_entry)]
|
||||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
// Carve a starting seed
|
// Carve a starting seed
|
||||||
let starting_position = Position { x: build_data.map.width / 2, y: build_data.map.height / 2 };
|
let starting_position = Position {
|
||||||
|
x: build_data.map.width / 2,
|
||||||
|
y: build_data.map.height / 2,
|
||||||
|
};
|
||||||
let start_idx = build_data.map.xy_idx(starting_position.x, starting_position.y);
|
let start_idx = build_data.map.xy_idx(starting_position.x, starting_position.y);
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
build_data.map.tiles[start_idx] = TileType::Floor;
|
build_data.map.tiles[start_idx] = TileType::Floor;
|
||||||
|
|
@ -189,10 +192,10 @@ impl DLABuilder {
|
||||||
let mut prev_y = digger_y;
|
let mut prev_y = digger_y;
|
||||||
let mut digger_idx = build_data.map.xy_idx(digger_x, digger_y);
|
let mut digger_idx = build_data.map.xy_idx(digger_x, digger_y);
|
||||||
|
|
||||||
let mut path = rltk::line2d(
|
let mut path = line2d(
|
||||||
rltk::LineAlg::Bresenham,
|
LineAlg::Bresenham,
|
||||||
rltk::Point::new(digger_x, digger_y),
|
Point::new(digger_x, digger_y),
|
||||||
rltk::Point::new(starting_position.x, starting_position.y)
|
Point::new(starting_position.x, starting_position.y)
|
||||||
);
|
);
|
||||||
|
|
||||||
while build_data.map.tiles[digger_idx] == TileType::Wall && !path.is_empty() {
|
while build_data.map.tiles[digger_idx] == TileType::Wall && !path.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct DoorPlacement {}
|
pub struct DoorPlacement {}
|
||||||
|
|
||||||
impl MetaMapBuilder for DoorPlacement {
|
impl MetaMapBuilder for DoorPlacement {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.doors(rng, build_data);
|
self.doors(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,11 @@ impl DoorPlacement {
|
||||||
// There are no corridors - scan for possible places
|
// There are no corridors - scan for possible places
|
||||||
let tiles = build_data.map.tiles.clone();
|
let tiles = build_data.map.tiles.clone();
|
||||||
for (i, tile) in tiles.iter().enumerate() {
|
for (i, tile) in tiles.iter().enumerate() {
|
||||||
if *tile == TileType::Floor && self.door_possible(build_data, i) && rng.roll_dice(1, 6) == 1 {
|
if
|
||||||
|
*tile == TileType::Floor &&
|
||||||
|
self.door_possible(build_data, i) &&
|
||||||
|
rng.roll_dice(1, 6) == 1
|
||||||
|
{
|
||||||
build_data.spawn_list.push((i, "door".to_string()));
|
build_data.spawn_list.push((i, "door".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
|
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -22,14 +22,14 @@ pub struct DrunkardsWalkBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for DrunkardsWalkBuilder {
|
impl InitialMapBuilder for DrunkardsWalkBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for DrunkardsWalkBuilder {
|
impl MetaMapBuilder for DrunkardsWalkBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,10 @@ impl DrunkardsWalkBuilder {
|
||||||
|
|
||||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
// Set a central starting point
|
// Set a central starting point
|
||||||
let starting_position = Position { x: build_data.map.width / 2, y: build_data.map.height / 2 };
|
let starting_position = Position {
|
||||||
|
x: build_data.map.width / 2,
|
||||||
|
y: build_data.map.height / 2,
|
||||||
|
};
|
||||||
let start_idx = build_data.map.xy_idx(starting_position.x, starting_position.y);
|
let start_idx = build_data.map.xy_idx(starting_position.x, starting_position.y);
|
||||||
build_data.map.tiles[start_idx] = TileType::Floor;
|
build_data.map.tiles[start_idx] = TileType::Floor;
|
||||||
|
|
||||||
|
|
@ -144,7 +147,13 @@ impl DrunkardsWalkBuilder {
|
||||||
if build_data.map.tiles[drunk_idx] == TileType::Wall {
|
if build_data.map.tiles[drunk_idx] == TileType::Wall {
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
paint(&mut build_data.map, self.settings.symmetry, self.settings.brush_size, drunk_x, drunk_y);
|
paint(
|
||||||
|
&mut build_data.map,
|
||||||
|
self.settings.symmetry,
|
||||||
|
self.settings.brush_size,
|
||||||
|
drunk_x,
|
||||||
|
drunk_y
|
||||||
|
);
|
||||||
build_data.map.tiles[drunk_idx] = TileType::DownStair;
|
build_data.map.tiles[drunk_idx] = TileType::DownStair;
|
||||||
|
|
||||||
let stagger_direction = rng.roll_dice(1, 4);
|
let stagger_direction = rng.roll_dice(1, 4);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use crate::tile_walkable;
|
use crate::tile_walkable;
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct FillEdges {
|
pub struct FillEdges {
|
||||||
fill_with: TileType,
|
fill_with: TileType,
|
||||||
|
|
@ -9,7 +9,7 @@ pub struct FillEdges {
|
||||||
|
|
||||||
impl MetaMapBuilder for FillEdges {
|
impl MetaMapBuilder for FillEdges {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.fill_edges(rng, build_data);
|
self.fill_edges(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct Foliage {
|
pub struct Foliage {
|
||||||
start_tile: TileType,
|
start_tile: TileType,
|
||||||
|
|
@ -8,7 +8,7 @@ pub struct Foliage {
|
||||||
|
|
||||||
impl MetaMapBuilder for Foliage {
|
impl MetaMapBuilder for Foliage {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.apply(rng, build_data);
|
self.apply(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ use super::{
|
||||||
YStart,
|
YStart,
|
||||||
Foliage,
|
Foliage,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use crate::data::names::*;
|
use crate::data::names::*;
|
||||||
|
|
||||||
pub fn forest_builder(
|
pub fn forest_builder(
|
||||||
new_id: i32,
|
new_id: i32,
|
||||||
_rng: &mut rltk::RandomNumberGenerator,
|
_rng: &mut RandomNumberGenerator,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
difficulty: i32,
|
difficulty: i32,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ BuilderMap, InitialMapBuilder, Map, TileType };
|
use super::{ BuilderMap, InitialMapBuilder, Map, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct MazeBuilder {}
|
pub struct MazeBuilder {}
|
||||||
|
|
||||||
impl InitialMapBuilder for MazeBuilder {
|
impl InitialMapBuilder for MazeBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,14 @@ struct Grid<'a> {
|
||||||
|
|
||||||
impl<'a> Grid<'a> {
|
impl<'a> Grid<'a> {
|
||||||
fn new(width: i32, height: i32, rng: &mut RandomNumberGenerator) -> Grid {
|
fn new(width: i32, height: i32, rng: &mut RandomNumberGenerator) -> Grid {
|
||||||
let mut grid = Grid { width, height, cells: Vec::new(), backtrace: Vec::new(), current: 0, rng };
|
let mut grid = Grid {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
cells: Vec::new(),
|
||||||
|
backtrace: Vec::new(),
|
||||||
|
current: 0,
|
||||||
|
rng,
|
||||||
|
};
|
||||||
|
|
||||||
for row in 0..height {
|
for row in 0..height {
|
||||||
for column in 0..width {
|
for column in 0..width {
|
||||||
|
|
@ -122,7 +129,9 @@ impl<'a> Grid<'a> {
|
||||||
if neighbors.len() == 1 {
|
if neighbors.len() == 1 {
|
||||||
return Some(neighbors[0]);
|
return Some(neighbors[0]);
|
||||||
} else {
|
} else {
|
||||||
return Some(neighbors[(self.rng.roll_dice(1, neighbors.len() as i32) - 1) as usize]);
|
return Some(
|
||||||
|
neighbors[(self.rng.roll_dice(1, neighbors.len() as i32) - 1) as usize]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -141,7 +150,9 @@ impl<'a> Grid<'a> {
|
||||||
// __lower_part__ __higher_part_
|
// __lower_part__ __higher_part_
|
||||||
// / \ / \
|
// / \ / \
|
||||||
// --------cell1------ | cell2-----------
|
// --------cell1------ | cell2-----------
|
||||||
let (lower_part, higher_part) = self.cells.split_at_mut(std::cmp::max(self.current, next));
|
let (lower_part, higher_part) = self.cells.split_at_mut(
|
||||||
|
std::cmp::max(self.current, next)
|
||||||
|
);
|
||||||
let cell1 = &mut lower_part[std::cmp::min(self.current, next)];
|
let cell1 = &mut lower_part[std::cmp::min(self.current, next)];
|
||||||
let cell2 = &mut higher_part[0];
|
let cell2 = &mut higher_part[0];
|
||||||
cell1.remove_walls(cell2);
|
cell1.remove_walls(cell2);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use super::{ spawner, Map, Position, Rect, TileType };
|
use super::{ spawner, Map, Position, Rect, TileType };
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
mod bsp_dungeon;
|
mod bsp_dungeon;
|
||||||
use bsp_dungeon::BspDungeonBuilder;
|
use bsp_dungeon::BspDungeonBuilder;
|
||||||
mod bsp_interior;
|
mod bsp_interior;
|
||||||
|
|
@ -143,7 +145,7 @@ impl BuilderChain {
|
||||||
self.builders.push(metabuilder);
|
self.builders.push(metabuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator) {
|
pub fn build_map(&mut self, rng: &mut RandomNumberGenerator) {
|
||||||
match &mut self.starter {
|
match &mut self.starter {
|
||||||
None => panic!("Cannot run a map builder chain without a starting build system"),
|
None => panic!("Cannot run a map builder chain without a starting build system"),
|
||||||
Some(starter) => {
|
Some(starter) => {
|
||||||
|
|
@ -165,20 +167,20 @@ impl BuilderChain {
|
||||||
spawner::spawn_entity(ecs, &(&entity.0, &entity.1));
|
spawner::spawn_entity(ecs, &(&entity.0, &entity.1));
|
||||||
}
|
}
|
||||||
if CONFIG.logging.log_spawning {
|
if CONFIG.logging.log_spawning {
|
||||||
rltk::console::log(format!("DEBUGINFO: SPAWNED ENTITIES = {:?}", spawned_entities));
|
console::log(format!("DEBUGINFO: SPAWNED ENTITIES = {:?}", spawned_entities));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait InitialMapBuilder {
|
pub trait InitialMapBuilder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap);
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MetaMapBuilder {
|
pub trait MetaMapBuilder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap);
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_start_position(rng: &mut rltk::RandomNumberGenerator) -> (XStart, YStart) {
|
fn random_start_position(rng: &mut RandomNumberGenerator) -> (XStart, YStart) {
|
||||||
let x;
|
let x;
|
||||||
let xroll = rng.roll_dice(1, 3);
|
let xroll = rng.roll_dice(1, 3);
|
||||||
match xroll {
|
match xroll {
|
||||||
|
|
@ -210,11 +212,7 @@ fn random_start_position(rng: &mut rltk::RandomNumberGenerator) -> (XStart, YSta
|
||||||
(x, y)
|
(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_room_builder(
|
fn random_room_builder(rng: &mut RandomNumberGenerator, builder: &mut BuilderChain, end: bool) {
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
|
||||||
builder: &mut BuilderChain,
|
|
||||||
end: bool
|
|
||||||
) {
|
|
||||||
let build_roll = rng.roll_dice(1, 3);
|
let build_roll = rng.roll_dice(1, 3);
|
||||||
// Start with a room builder.
|
// Start with a room builder.
|
||||||
match build_roll {
|
match build_roll {
|
||||||
|
|
@ -296,7 +294,7 @@ fn random_room_builder(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_shape_builder(
|
fn random_shape_builder(
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
builder: &mut BuilderChain,
|
builder: &mut BuilderChain,
|
||||||
end: bool
|
end: bool
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
|
@ -368,7 +366,7 @@ pub enum BuildType {
|
||||||
|
|
||||||
pub fn random_builder(
|
pub fn random_builder(
|
||||||
new_id: i32,
|
new_id: i32,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
difficulty: i32,
|
difficulty: i32,
|
||||||
|
|
@ -377,7 +375,7 @@ pub fn random_builder(
|
||||||
end: bool,
|
end: bool,
|
||||||
build_type: BuildType
|
build_type: BuildType
|
||||||
) -> BuilderChain {
|
) -> BuilderChain {
|
||||||
rltk::console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
|
console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
|
||||||
let mut builder = BuilderChain::new(
|
let mut builder = BuilderChain::new(
|
||||||
false,
|
false,
|
||||||
new_id,
|
new_id,
|
||||||
|
|
@ -441,7 +439,7 @@ pub fn random_builder(
|
||||||
|
|
||||||
pub fn level_builder(
|
pub fn level_builder(
|
||||||
new_id: i32,
|
new_id: i32,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
initial_player_level: i32
|
initial_player_level: i32
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ spawner, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, TileType };
|
use super::{ spawner, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
pub mod prefab_levels;
|
pub mod prefab_levels;
|
||||||
pub mod prefab_sections;
|
pub mod prefab_sections;
|
||||||
pub mod prefab_vaults;
|
pub mod prefab_vaults;
|
||||||
|
|
@ -25,14 +25,14 @@ pub struct PrefabBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for PrefabBuilder {
|
impl MetaMapBuilder for PrefabBuilder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InitialMapBuilder for PrefabBuilder {
|
impl InitialMapBuilder for PrefabBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,8 @@ impl PrefabBuilder {
|
||||||
|
|
||||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
PrefabMode::Overmap => self.load_ascii_map(&prefab_levels::OVERMAP, rng, build_data, true),
|
PrefabMode::Overmap =>
|
||||||
|
self.load_ascii_map(&prefab_levels::OVERMAP, rng, build_data, true),
|
||||||
PrefabMode::Constant { level } => self.load_ascii_map(&level, rng, build_data, false),
|
PrefabMode::Constant { level } => self.load_ascii_map(&level, rng, build_data, false),
|
||||||
PrefabMode::Sectional { section } => self.apply_sectional(§ion, rng, build_data),
|
PrefabMode::Sectional { section } => self.apply_sectional(§ion, rng, build_data),
|
||||||
PrefabMode::RoomVaults => self.apply_room_vaults(rng, build_data),
|
PrefabMode::RoomVaults => self.apply_room_vaults(rng, build_data),
|
||||||
|
|
@ -73,7 +74,13 @@ impl PrefabBuilder {
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_to_map(&mut self, ch: char, idx: usize, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn char_to_map(
|
||||||
|
&mut self,
|
||||||
|
ch: char,
|
||||||
|
idx: usize,
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
build_data: &mut BuilderMap
|
||||||
|
) {
|
||||||
let difficulty = (build_data.map.difficulty + build_data.initial_player_level) / 2;
|
let difficulty = (build_data.map.difficulty + build_data.initial_player_level) / 2;
|
||||||
match ch {
|
match ch {
|
||||||
' ' => {
|
' ' => {
|
||||||
|
|
@ -123,7 +130,10 @@ impl PrefabBuilder {
|
||||||
}
|
}
|
||||||
'!' => {
|
'!' => {
|
||||||
build_data.map.tiles[idx] = TileType::Floor;
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
build_data.spawn_list.push((idx, spawner::potion_table(Some(difficulty)).roll(rng)));
|
build_data.spawn_list.push((
|
||||||
|
idx,
|
||||||
|
spawner::potion_table(Some(difficulty)).roll(rng),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
'/' => {
|
'/' => {
|
||||||
build_data.map.tiles[idx] = TileType::Floor;
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
|
|
@ -131,14 +141,20 @@ impl PrefabBuilder {
|
||||||
}
|
}
|
||||||
'?' => {
|
'?' => {
|
||||||
build_data.map.tiles[idx] = TileType::Floor;
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
build_data.spawn_list.push((idx, spawner::scroll_table(Some(difficulty)).roll(rng)));
|
build_data.spawn_list.push((
|
||||||
|
idx,
|
||||||
|
spawner::scroll_table(Some(difficulty)).roll(rng),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
')' => {
|
')' => {
|
||||||
build_data.map.tiles[idx] = TileType::Floor;
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
build_data.spawn_list.push((idx, spawner::equipment_table(Some(difficulty)).roll(rng)));
|
build_data.spawn_list.push((
|
||||||
|
idx,
|
||||||
|
spawner::equipment_table(Some(difficulty)).roll(rng),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
rltk::console::log(format!("Unknown glyph '{}' when loading prefab", ch as u8 as char));
|
console::log(format!("Unknown glyph '{}' when loading prefab", ch as u8 as char));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,14 +201,19 @@ impl PrefabBuilder {
|
||||||
build_data.map.tiles[idx] = TileType::ToLocal(ID_INFINITE);
|
build_data.map.tiles[idx] = TileType::ToLocal(ID_INFINITE);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
rltk::console::log(format!("Unknown glyph '{}' when loading overmap", ch as u8 as char));
|
console::log(format!("Unknown glyph '{}' when loading overmap", ch as u8 as char));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn load_rex_map(&mut self, path: &str, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn load_rex_map(
|
||||||
let xp_file = rltk::rex::XpFile::from_resource(path).unwrap();
|
&mut self,
|
||||||
|
path: &str,
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
build_data: &mut BuilderMap
|
||||||
|
) {
|
||||||
|
let xp_file = rex::XpFile::from_resource(path).unwrap();
|
||||||
|
|
||||||
for layer in &xp_file.layers {
|
for layer in &xp_file.layers {
|
||||||
for y in 0..layer.height {
|
for y in 0..layer.height {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ spawner, BuilderMap, MetaMapBuilder };
|
use super::{ spawner, BuilderMap, MetaMapBuilder };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomBasedSpawner {}
|
pub struct RoomBasedSpawner {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomBasedSpawner {
|
impl MetaMapBuilder for RoomBasedSpawner {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, TileType };
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomBasedStairs {}
|
pub struct RoomBasedStairs {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomBasedStairs {
|
impl MetaMapBuilder for RoomBasedStairs {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Position };
|
use super::{ BuilderMap, MetaMapBuilder, Position };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomBasedStartingPosition {}
|
pub struct RoomBasedStartingPosition {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomBasedStartingPosition {
|
impl MetaMapBuilder for RoomBasedStartingPosition {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomCornerRounder {}
|
pub struct RoomCornerRounder {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomCornerRounder {
|
impl MetaMapBuilder for RoomCornerRounder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomDrawer {}
|
pub struct RoomDrawer {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomDrawer {
|
impl MetaMapBuilder for RoomDrawer {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -29,14 +29,11 @@ impl RoomDrawer {
|
||||||
fn circle(&mut self, build_data: &mut BuilderMap, room: &Rect) {
|
fn circle(&mut self, build_data: &mut BuilderMap, room: &Rect) {
|
||||||
let radius = (i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32) / 2.0;
|
let radius = (i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32) / 2.0;
|
||||||
let center = room.center();
|
let center = room.center();
|
||||||
let center_pt = rltk::Point::new(center.x, center.y);
|
let center_pt = Point::new(center.x, center.y);
|
||||||
for y in room.y1..=room.y2 {
|
for y in room.y1..=room.y2 {
|
||||||
for x in room.x1..=room.x2 {
|
for x in room.x1..=room.x2 {
|
||||||
let idx = build_data.map.xy_idx(x, y);
|
let idx = build_data.map.xy_idx(x, y);
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance = DistanceAlg::Pythagoras.distance2d(center_pt, Point::new(x, y));
|
||||||
center_pt,
|
|
||||||
rltk::Point::new(x, y)
|
|
||||||
);
|
|
||||||
if
|
if
|
||||||
idx > 0 &&
|
idx > 0 &&
|
||||||
idx < ((build_data.map.width * build_data.map.height - 1) as usize) &&
|
idx < ((build_data.map.width * build_data.map.height - 1) as usize) &&
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ paint, BuilderMap, MetaMapBuilder, Rect, Symmetry, TileType };
|
use super::{ paint, BuilderMap, MetaMapBuilder, Rect, Symmetry, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct RoomExploder {}
|
pub struct RoomExploder {}
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomExploder {
|
impl MetaMapBuilder for RoomExploder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Rect };
|
use super::{ BuilderMap, MetaMapBuilder, Rect };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum RoomSort {
|
pub enum RoomSort {
|
||||||
|
|
@ -16,7 +16,7 @@ pub struct RoomSorter {
|
||||||
|
|
||||||
impl MetaMapBuilder for RoomSorter {
|
impl MetaMapBuilder for RoomSorter {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.sorter(rng, build_data);
|
self.sorter(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,21 +50,18 @@ impl RoomSorter {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.sort_by(|a, b| b.y2.cmp(&a.y2)),
|
.sort_by(|a, b| b.y2.cmp(&a.y2)),
|
||||||
RoomSort::CENTRAL => {
|
RoomSort::CENTRAL => {
|
||||||
let map_centre = rltk::Point::new(
|
let map_centre = Point::new(build_data.map.width / 2, build_data.map.height / 2);
|
||||||
build_data.map.width / 2,
|
|
||||||
build_data.map.height / 2
|
|
||||||
);
|
|
||||||
build_data.rooms
|
build_data.rooms
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.sort_by(|a: &Rect, b: &Rect| {
|
.sort_by(|a: &Rect, b: &Rect| {
|
||||||
let a_centre_pt = rltk::Point::new(a.center().x, a.center().y);
|
let a_centre_pt = Point::new(a.center().x, a.center().y);
|
||||||
let b_centre_pt = rltk::Point::new(b.center().x, b.center().y);
|
let b_centre_pt = Point::new(b.center().x, b.center().y);
|
||||||
let distance_a = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance_a = DistanceAlg::Pythagoras.distance2d(
|
||||||
a_centre_pt,
|
a_centre_pt,
|
||||||
map_centre
|
map_centre
|
||||||
);
|
);
|
||||||
let distance_b = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance_b = DistanceAlg::Pythagoras.distance2d(
|
||||||
b_centre_pt,
|
b_centre_pt,
|
||||||
map_centre
|
map_centre
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::data::messages::{
|
||||||
FEATURE_BARRACKS_ORC,
|
FEATURE_BARRACKS_ORC,
|
||||||
};
|
};
|
||||||
use crate::raws;
|
use crate::raws;
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
|
|
@ -22,7 +22,7 @@ pub struct ThemeRooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaMapBuilder for ThemeRooms {
|
impl MetaMapBuilder for ThemeRooms {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +173,7 @@ fn roll_until_fail(rng: &mut RandomNumberGenerator, target: i32) -> i32 {
|
||||||
loop {
|
loop {
|
||||||
if rng.roll_dice(1, 100) <= target - accumulator {
|
if rng.roll_dice(1, 100) <= target - accumulator {
|
||||||
accumulator += 1;
|
accumulator += 1;
|
||||||
rltk::console::log(accumulator);
|
console::log(accumulator);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub struct BresenhamCorridors {}
|
pub struct BresenhamCorridors {}
|
||||||
|
|
||||||
impl MetaMapBuilder for BresenhamCorridors {
|
impl MetaMapBuilder for BresenhamCorridors {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.corridors(rng, build_data);
|
self.corridors(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,12 +30,12 @@ impl BresenhamCorridors {
|
||||||
for (i, room) in rooms.iter().enumerate() {
|
for (i, room) in rooms.iter().enumerate() {
|
||||||
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
||||||
let room_centre = room.center();
|
let room_centre = room.center();
|
||||||
let room_centre_pt = rltk::Point::new(room_centre.x, room_centre.y);
|
let room_centre_pt = Point::new(room_centre.x, room_centre.y);
|
||||||
for (j, other_room) in rooms.iter().enumerate() {
|
for (j, other_room) in rooms.iter().enumerate() {
|
||||||
if i != j && !connected.contains(&j) {
|
if i != j && !connected.contains(&j) {
|
||||||
let other_centre = other_room.center();
|
let other_centre = other_room.center();
|
||||||
let other_centre_pt = rltk::Point::new(other_centre.x, other_centre.y);
|
let other_centre_pt = Point::new(other_centre.x, other_centre.y);
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance = DistanceAlg::Pythagoras.distance2d(
|
||||||
room_centre_pt,
|
room_centre_pt,
|
||||||
other_centre_pt
|
other_centre_pt
|
||||||
);
|
);
|
||||||
|
|
@ -46,10 +46,10 @@ impl BresenhamCorridors {
|
||||||
if !room_distance.is_empty() {
|
if !room_distance.is_empty() {
|
||||||
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||||
let dest_centre = rooms[room_distance[0].0].center();
|
let dest_centre = rooms[room_distance[0].0].center();
|
||||||
let line = rltk::line2d(
|
let line = line2d(
|
||||||
rltk::LineAlg::Bresenham,
|
LineAlg::Bresenham,
|
||||||
room_centre_pt,
|
room_centre_pt,
|
||||||
rltk::Point::new(dest_centre.x, dest_centre.y)
|
Point::new(dest_centre.x, dest_centre.y)
|
||||||
);
|
);
|
||||||
let mut corridor = Vec::new();
|
let mut corridor = Vec::new();
|
||||||
for cell in line.iter() {
|
for cell in line.iter() {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
|
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct BspCorridors {}
|
pub struct BspCorridors {}
|
||||||
|
|
||||||
impl MetaMapBuilder for BspCorridors {
|
impl MetaMapBuilder for BspCorridors {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.corridors(rng, build_data);
|
self.corridors(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,8 +30,10 @@ impl BspCorridors {
|
||||||
let next_room = rooms[i + 1];
|
let next_room = rooms[i + 1];
|
||||||
let start_x = room.x1 + (rng.roll_dice(1, i32::abs(room.x1 - room.x2)) - 1);
|
let start_x = room.x1 + (rng.roll_dice(1, i32::abs(room.x1 - room.x2)) - 1);
|
||||||
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 =
|
||||||
let end_y = next_room.y1 + (rng.roll_dice(1, i32::abs(next_room.y1 - next_room.y2)) - 1);
|
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 corridor = 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);
|
corridors.push(corridor);
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{ apply_horizontal_tunnel, apply_vertical_tunnel, BuilderMap, MetaMapBuilder, Rect };
|
use super::{ apply_horizontal_tunnel, apply_vertical_tunnel, BuilderMap, MetaMapBuilder, Rect };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct DoglegCorridors {}
|
pub struct DoglegCorridors {}
|
||||||
|
|
||||||
impl MetaMapBuilder for DoglegCorridors {
|
impl MetaMapBuilder for DoglegCorridors {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.corridors(rng, build_data);
|
self.corridors(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
|
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub struct NearestCorridors {}
|
pub struct NearestCorridors {}
|
||||||
|
|
||||||
impl MetaMapBuilder for NearestCorridors {
|
impl MetaMapBuilder for NearestCorridors {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.corridors(rng, build_data);
|
self.corridors(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,12 +30,12 @@ impl NearestCorridors {
|
||||||
for (i, room) in rooms.iter().enumerate() {
|
for (i, room) in rooms.iter().enumerate() {
|
||||||
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
let mut room_distance: Vec<(usize, f32)> = Vec::new();
|
||||||
let room_centre = room.center();
|
let room_centre = room.center();
|
||||||
let room_centre_pt = rltk::Point::new(room_centre.x, room_centre.y);
|
let room_centre_pt = Point::new(room_centre.x, room_centre.y);
|
||||||
for (j, other_room) in rooms.iter().enumerate() {
|
for (j, other_room) in rooms.iter().enumerate() {
|
||||||
if i != j && !connected.contains(&j) {
|
if i != j && !connected.contains(&j) {
|
||||||
let other_centre = other_room.center();
|
let other_centre = other_room.center();
|
||||||
let other_centre_pt = rltk::Point::new(other_centre.x, other_centre.y);
|
let other_centre_pt = Point::new(other_centre.x, other_centre.y);
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
|
let distance = DistanceAlg::Pythagoras.distance2d(
|
||||||
room_centre_pt,
|
room_centre_pt,
|
||||||
other_centre_pt
|
other_centre_pt
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ spawner, BuilderMap, MetaMapBuilder };
|
use super::{ spawner, BuilderMap, MetaMapBuilder };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct CorridorSpawner {}
|
pub struct CorridorSpawner {}
|
||||||
|
|
||||||
impl MetaMapBuilder for CorridorSpawner {
|
impl MetaMapBuilder for CorridorSpawner {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use super::{
|
||||||
generate_voronoi_spawn_regions, remove_unreachable_areas_returning_most_distant, spawner, Map, MapBuilder,
|
generate_voronoi_spawn_regions, remove_unreachable_areas_returning_most_distant, spawner, Map, MapBuilder,
|
||||||
Position, TileType, SHOW_MAPGEN,
|
Position, TileType, SHOW_MAPGEN,
|
||||||
};
|
};
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, InitialMapBuilder, Rect };
|
use super::{ BuilderMap, InitialMapBuilder, Rect };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct SimpleMapBuilder {
|
pub struct SimpleMapBuilder {
|
||||||
room_params: (i32, i32, i32),
|
room_params: (i32, i32, i32),
|
||||||
|
|
@ -7,7 +7,7 @@ pub struct SimpleMapBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for SimpleMapBuilder {
|
impl InitialMapBuilder for SimpleMapBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build_rooms(rng, build_data);
|
self.build_rooms(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
use super::{ BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType, FillEdges };
|
use super::{ BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType, FillEdges };
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use crate::data::names::*;
|
use crate::data::names::*;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub fn town_builder(
|
pub fn town_builder(
|
||||||
new_id: i32,
|
new_id: i32,
|
||||||
_rng: &mut rltk::RandomNumberGenerator,
|
_rng: &mut RandomNumberGenerator,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
difficulty: i32,
|
difficulty: i32,
|
||||||
initial_player_level: i32
|
initial_player_level: i32
|
||||||
) -> BuilderChain {
|
) -> BuilderChain {
|
||||||
rltk::console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
|
console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
|
||||||
let mut chain = BuilderChain::new(
|
let mut chain = BuilderChain::new(
|
||||||
false,
|
false,
|
||||||
new_id,
|
new_id,
|
||||||
|
|
@ -32,7 +33,7 @@ pub struct TownBuilder {}
|
||||||
|
|
||||||
impl InitialMapBuilder for TownBuilder {
|
impl InitialMapBuilder for TownBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build_map(rng, build_data);
|
self.build_map(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +53,7 @@ impl TownBuilder {
|
||||||
return Box::new(TownBuilder {});
|
return Box::new(TownBuilder {});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
pub fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
// Make visible for snapshot
|
// Make visible for snapshot
|
||||||
for t in build_data.map.visible_tiles.iter_mut() {
|
for t in build_data.map.visible_tiles.iter_mut() {
|
||||||
*t = true;
|
*t = true;
|
||||||
|
|
@ -64,8 +65,20 @@ impl TownBuilder {
|
||||||
let (mut available_building_tiles, wall_gap_y) = self.town_walls(rng, build_data);
|
let (mut available_building_tiles, wall_gap_y) = self.town_walls(rng, build_data);
|
||||||
let mut buildings = self.buildings(rng, build_data, &mut available_building_tiles);
|
let mut buildings = self.buildings(rng, build_data, &mut available_building_tiles);
|
||||||
let doors = self.add_doors(rng, build_data, &mut buildings, wall_gap_y);
|
let doors = self.add_doors(rng, build_data, &mut buildings, wall_gap_y);
|
||||||
self.path_from_tiles_to_nearest_tiletype(build_data, &doors, TileType::Road, TileType::Road, true);
|
self.path_from_tiles_to_nearest_tiletype(
|
||||||
self.path_from_tiles_to_nearest_tiletype(build_data, &piers, TileType::Road, TileType::Road, false);
|
build_data,
|
||||||
|
&doors,
|
||||||
|
TileType::Road,
|
||||||
|
TileType::Road,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
self.path_from_tiles_to_nearest_tiletype(
|
||||||
|
build_data,
|
||||||
|
&piers,
|
||||||
|
TileType::Road,
|
||||||
|
TileType::Road,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// Spawn entities
|
// Spawn entities
|
||||||
let building_size = self.sort_buildings(&buildings);
|
let building_size = self.sort_buildings(&buildings);
|
||||||
|
|
@ -81,7 +94,10 @@ impl TownBuilder {
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_buildings(&mut self, buildings: &[(i32, i32, i32, i32)]) -> Vec<(usize, i32, BuildingTag)> {
|
fn sort_buildings(
|
||||||
|
&mut self,
|
||||||
|
buildings: &[(i32, i32, i32, i32)]
|
||||||
|
) -> Vec<(usize, i32, BuildingTag)> {
|
||||||
// Sort buildings by size, defaulting them to Unassigned buildings
|
// Sort buildings by size, defaulting them to Unassigned buildings
|
||||||
let mut building_size: Vec<(usize, i32, BuildingTag)> = Vec::new();
|
let mut building_size: Vec<(usize, i32, BuildingTag)> = Vec::new();
|
||||||
for (i, building) in buildings.iter().enumerate() {
|
for (i, building) in buildings.iter().enumerate() {
|
||||||
|
|
@ -105,7 +121,7 @@ impl TownBuilder {
|
||||||
|
|
||||||
fn building_factory(
|
fn building_factory(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
buildings: &[(i32, i32, i32, i32)],
|
buildings: &[(i32, i32, i32, i32)],
|
||||||
building_index: &[(usize, i32, BuildingTag)]
|
building_index: &[(usize, i32, BuildingTag)]
|
||||||
|
|
@ -124,7 +140,7 @@ impl TownBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_dockers(&mut self, build_data: &mut BuilderMap, rng: &mut rltk::RandomNumberGenerator) {
|
fn spawn_dockers(&mut self, build_data: &mut BuilderMap, rng: &mut RandomNumberGenerator) {
|
||||||
for (idx, tt) in build_data.map.tiles.iter().enumerate() {
|
for (idx, tt) in build_data.map.tiles.iter().enumerate() {
|
||||||
if *tt == TileType::Bridge && rng.roll_dice(1, 20) == 1 {
|
if *tt == TileType::Bridge && rng.roll_dice(1, 20) == 1 {
|
||||||
let roll = rng.roll_dice(1, 2);
|
let roll = rng.roll_dice(1, 2);
|
||||||
|
|
@ -139,7 +155,7 @@ impl TownBuilder {
|
||||||
fn spawn_townsfolk(
|
fn spawn_townsfolk(
|
||||||
&mut self,
|
&mut self,
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
available_building_tiles: &mut HashSet<usize>
|
available_building_tiles: &mut HashSet<usize>
|
||||||
) {
|
) {
|
||||||
for idx in available_building_tiles.iter() {
|
for idx in available_building_tiles.iter() {
|
||||||
|
|
@ -176,7 +192,7 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
to_place: &mut Vec<&str>,
|
to_place: &mut Vec<&str>,
|
||||||
avoid_tile: usize
|
avoid_tile: usize
|
||||||
) {
|
) {
|
||||||
|
|
@ -201,9 +217,12 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
let player_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
let player_idx = build_data.map.xy_idx(
|
||||||
|
building.0 + building.2 / 2,
|
||||||
|
building.1 + building.3 / 2
|
||||||
|
);
|
||||||
|
|
||||||
// Place other items
|
// Place other items
|
||||||
let mut to_place: Vec<&str> = vec![
|
let mut to_place: Vec<&str> = vec![
|
||||||
|
|
@ -224,7 +243,7 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
let mut to_place: Vec<&str> = vec![
|
let mut to_place: Vec<&str> = vec![
|
||||||
"npc_priest",
|
"npc_priest",
|
||||||
|
|
@ -244,10 +263,13 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
// Place exit
|
// Place exit
|
||||||
let exit_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
let exit_idx = build_data.map.xy_idx(
|
||||||
|
building.0 + building.2 / 2,
|
||||||
|
building.1 + building.3 / 2
|
||||||
|
);
|
||||||
build_data.map.tiles[exit_idx] = TileType::DownStair;
|
build_data.map.tiles[exit_idx] = TileType::DownStair;
|
||||||
let mut to_place: Vec<&str> = vec!["npc_miner", "npc_miner", "npc_guard", "prop_chair"];
|
let mut to_place: Vec<&str> = vec!["npc_miner", "npc_miner", "npc_guard", "prop_chair"];
|
||||||
self.random_building_spawn(building, build_data, rng, &mut to_place, exit_idx)
|
self.random_building_spawn(building, build_data, rng, &mut to_place, exit_idx)
|
||||||
|
|
@ -257,9 +279,15 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
let mut to_place: Vec<&str> = vec!["prop_bed", "prop_table", "dog_little", "prop_chair", "prop_chair"];
|
let mut to_place: Vec<&str> = vec![
|
||||||
|
"prop_bed",
|
||||||
|
"prop_table",
|
||||||
|
"dog_little",
|
||||||
|
"prop_chair",
|
||||||
|
"prop_chair"
|
||||||
|
];
|
||||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,9 +295,14 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
let mut to_place: Vec<&str> = vec!["npc_townsperson", "prop_bed", "prop_table", "prop_chair"];
|
let mut to_place: Vec<&str> = vec![
|
||||||
|
"npc_townsperson",
|
||||||
|
"prop_bed",
|
||||||
|
"prop_table",
|
||||||
|
"prop_chair"
|
||||||
|
];
|
||||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,7 +310,7 @@ impl TownBuilder {
|
||||||
&mut self,
|
&mut self,
|
||||||
building: &(i32, i32, i32, i32),
|
building: &(i32, i32, i32, i32),
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
let mut to_place: Vec<&str> = vec!["rat", "rat", "rat", "prop_table", "prop_chair"];
|
let mut to_place: Vec<&str> = vec!["rat", "rat", "rat", "prop_table", "prop_chair"];
|
||||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||||
|
|
@ -291,7 +324,11 @@ impl TownBuilder {
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn water_and_piers(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) -> Vec<usize> {
|
fn water_and_piers(
|
||||||
|
&mut self,
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
build_data: &mut BuilderMap
|
||||||
|
) -> Vec<usize> {
|
||||||
let mut n = (rng.roll_dice(1, 65535) as f32) / 65535f32;
|
let mut n = (rng.roll_dice(1, 65535) as f32) / 65535f32;
|
||||||
let mut water_width: Vec<i32> = Vec::new();
|
let mut water_width: Vec<i32> = Vec::new();
|
||||||
let variance = 5;
|
let variance = 5;
|
||||||
|
|
@ -300,7 +337,8 @@ impl TownBuilder {
|
||||||
let sand_width = shallow_width + 4;
|
let sand_width = shallow_width + 4;
|
||||||
|
|
||||||
for y in 0..build_data.height {
|
for y in 0..build_data.height {
|
||||||
let n_water = ((f32::sin(n) * (variance as f32)) as i32) + minimum_width + rng.roll_dice(1, 2);
|
let n_water =
|
||||||
|
((f32::sin(n) * (variance as f32)) as i32) + minimum_width + rng.roll_dice(1, 2);
|
||||||
water_width.push(n_water);
|
water_width.push(n_water);
|
||||||
n += 0.1;
|
n += 0.1;
|
||||||
for x in 0..n_water {
|
for x in 0..n_water {
|
||||||
|
|
@ -374,7 +412,7 @@ impl TownBuilder {
|
||||||
|
|
||||||
fn town_walls(
|
fn town_walls(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
build_data: &mut BuilderMap
|
build_data: &mut BuilderMap
|
||||||
) -> (HashSet<usize>, i32) {
|
) -> (HashSet<usize>, i32) {
|
||||||
let mut available_building_tiles: HashSet<usize> = HashSet::new();
|
let mut available_building_tiles: HashSet<usize> = HashSet::new();
|
||||||
|
|
@ -385,7 +423,10 @@ impl TownBuilder {
|
||||||
const HALF_PATH_THICKNESS: i32 = 3;
|
const HALF_PATH_THICKNESS: i32 = 3;
|
||||||
|
|
||||||
let wall_gap_y =
|
let wall_gap_y =
|
||||||
build_data.height / 2 + rng.roll_dice(1, PATH_OFFSET_FROM_CENTRE * 2) - 1 - PATH_OFFSET_FROM_CENTRE;
|
build_data.height / 2 +
|
||||||
|
rng.roll_dice(1, PATH_OFFSET_FROM_CENTRE * 2) -
|
||||||
|
1 -
|
||||||
|
PATH_OFFSET_FROM_CENTRE;
|
||||||
|
|
||||||
for y in BORDER..build_data.height - BORDER {
|
for y in BORDER..build_data.height - BORDER {
|
||||||
if !(y > wall_gap_y - HALF_PATH_THICKNESS && y < wall_gap_y + HALF_PATH_THICKNESS) {
|
if !(y > wall_gap_y - HALF_PATH_THICKNESS && y < wall_gap_y + HALF_PATH_THICKNESS) {
|
||||||
|
|
@ -438,7 +479,7 @@ impl TownBuilder {
|
||||||
|
|
||||||
fn buildings(
|
fn buildings(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
available_building_tiles: &mut HashSet<usize>
|
available_building_tiles: &mut HashSet<usize>
|
||||||
) -> Vec<(i32, i32, i32, i32)> {
|
) -> Vec<(i32, i32, i32, i32)> {
|
||||||
|
|
@ -452,7 +493,9 @@ impl TownBuilder {
|
||||||
const MAX_BUILDING_SIZE: i32 = 10;
|
const MAX_BUILDING_SIZE: i32 = 10;
|
||||||
|
|
||||||
while n_buildings < REQUIRED_BUILDINGS {
|
while n_buildings < REQUIRED_BUILDINGS {
|
||||||
let bx = rng.roll_dice(1, build_data.map.width - OFFSET_FROM_LEFT - BORDER) + OFFSET_FROM_LEFT;
|
let bx =
|
||||||
|
rng.roll_dice(1, build_data.map.width - OFFSET_FROM_LEFT - BORDER) +
|
||||||
|
OFFSET_FROM_LEFT;
|
||||||
let by = rng.roll_dice(1, build_data.map.height) - BORDER;
|
let by = rng.roll_dice(1, build_data.map.height) - BORDER;
|
||||||
let bw = rng.roll_dice(1, MAX_BUILDING_SIZE - MIN_BUILDING_SIZE) + MIN_BUILDING_SIZE;
|
let bw = rng.roll_dice(1, MAX_BUILDING_SIZE - MIN_BUILDING_SIZE) + MIN_BUILDING_SIZE;
|
||||||
let bh = rng.roll_dice(1, MAX_BUILDING_SIZE - MIN_BUILDING_SIZE) + MIN_BUILDING_SIZE;
|
let bh = rng.roll_dice(1, MAX_BUILDING_SIZE - MIN_BUILDING_SIZE) + MIN_BUILDING_SIZE;
|
||||||
|
|
@ -500,10 +543,16 @@ impl TownBuilder {
|
||||||
if build_data.map.tiles[idx + 1] != TileType::WoodFloor {
|
if build_data.map.tiles[idx + 1] != TileType::WoodFloor {
|
||||||
neighbours += 1;
|
neighbours += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx - (build_data.width as usize)] != TileType::WoodFloor {
|
if
|
||||||
|
build_data.map.tiles[idx - (build_data.width as usize)] !=
|
||||||
|
TileType::WoodFloor
|
||||||
|
{
|
||||||
neighbours += 1;
|
neighbours += 1;
|
||||||
}
|
}
|
||||||
if build_data.map.tiles[idx + (build_data.width as usize)] != TileType::WoodFloor {
|
if
|
||||||
|
build_data.map.tiles[idx + (build_data.width as usize)] !=
|
||||||
|
TileType::WoodFloor
|
||||||
|
{
|
||||||
neighbours += 1;
|
neighbours += 1;
|
||||||
}
|
}
|
||||||
if neighbours > 0 {
|
if neighbours > 0 {
|
||||||
|
|
@ -520,7 +569,7 @@ impl TownBuilder {
|
||||||
|
|
||||||
fn add_doors(
|
fn add_doors(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
buildings: &mut Vec<(i32, i32, i32, i32)>,
|
buildings: &mut Vec<(i32, i32, i32, i32)>,
|
||||||
wall_gap_y: i32
|
wall_gap_y: i32
|
||||||
|
|
@ -556,23 +605,26 @@ impl TownBuilder {
|
||||||
build_data.map.populate_blocked();
|
build_data.map.populate_blocked();
|
||||||
for tile_idx in tiles.iter() {
|
for tile_idx in tiles.iter() {
|
||||||
let mut nearest_tiletype: Vec<(usize, f32)> = Vec::new();
|
let mut nearest_tiletype: Vec<(usize, f32)> = Vec::new();
|
||||||
let tile_pt = rltk::Point::new(
|
let tile_pt = Point::new(
|
||||||
(*tile_idx as i32) % (build_data.map.width as i32),
|
(*tile_idx as i32) % (build_data.map.width as i32),
|
||||||
(*tile_idx as i32) / (build_data.map.width as i32)
|
(*tile_idx as i32) / (build_data.map.width as i32)
|
||||||
);
|
);
|
||||||
for r in roads.iter() {
|
for r in roads.iter() {
|
||||||
nearest_tiletype.push((
|
nearest_tiletype.push((
|
||||||
*r,
|
*r,
|
||||||
rltk::DistanceAlg::Manhattan.distance2d(
|
DistanceAlg::Manhattan.distance2d(
|
||||||
tile_pt,
|
tile_pt,
|
||||||
rltk::Point::new((*r as i32) % build_data.map.width, (*r as i32) / build_data.map.width)
|
Point::new(
|
||||||
|
(*r as i32) % build_data.map.width,
|
||||||
|
(*r as i32) / build_data.map.width
|
||||||
|
)
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
nearest_tiletype.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
nearest_tiletype.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||||
|
|
||||||
let destination = nearest_tiletype[0].0;
|
let destination = nearest_tiletype[0].0;
|
||||||
let path = rltk::a_star_search(*tile_idx, destination, &mut build_data.map);
|
let path = a_star_search(*tile_idx, destination, &mut build_data.map);
|
||||||
if path.success {
|
if path.success {
|
||||||
for step in path.steps.iter() {
|
for step in path.steps.iter() {
|
||||||
let idx = *step as usize;
|
let idx = *step as usize;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, InitialMapBuilder, TileType };
|
use super::{ BuilderMap, InitialMapBuilder, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -16,7 +16,7 @@ pub struct VoronoiBuilder {
|
||||||
|
|
||||||
impl InitialMapBuilder for VoronoiBuilder {
|
impl InitialMapBuilder for VoronoiBuilder {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,20 +40,21 @@ impl VoronoiBuilder {
|
||||||
#[allow(clippy::map_entry)]
|
#[allow(clippy::map_entry)]
|
||||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
// Make a Voronoi diagram. We'll do this the hard way to learn about the technique!
|
// Make a Voronoi diagram. We'll do this the hard way to learn about the technique!
|
||||||
let mut voronoi_seeds: Vec<(usize, rltk::Point)> = Vec::new();
|
let mut voronoi_seeds: Vec<(usize, Point)> = Vec::new();
|
||||||
|
|
||||||
while voronoi_seeds.len() < self.n_seeds {
|
while voronoi_seeds.len() < self.n_seeds {
|
||||||
let vx = rng.roll_dice(1, build_data.map.width - 1);
|
let vx = rng.roll_dice(1, build_data.map.width - 1);
|
||||||
let vy = rng.roll_dice(1, build_data.map.height - 1);
|
let vy = rng.roll_dice(1, build_data.map.height - 1);
|
||||||
let vidx = build_data.map.xy_idx(vx, vy);
|
let vidx = build_data.map.xy_idx(vx, vy);
|
||||||
let candidate = (vidx, rltk::Point::new(vx, vy));
|
let candidate = (vidx, Point::new(vx, vy));
|
||||||
if !voronoi_seeds.contains(&candidate) {
|
if !voronoi_seeds.contains(&candidate) {
|
||||||
voronoi_seeds.push(candidate);
|
voronoi_seeds.push(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut voronoi_distance = vec![(0, 0.0f32); self.n_seeds];
|
let mut voronoi_distance = vec![(0, 0.0f32); self.n_seeds];
|
||||||
let mut voronoi_membership: Vec<i32> = vec![0; build_data.map.width as usize * build_data.map.height as usize];
|
let mut voronoi_membership: Vec<i32> =
|
||||||
|
vec![0; build_data.map.width as usize * build_data.map.height as usize];
|
||||||
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
|
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
|
||||||
let x = (i as i32) % build_data.map.width;
|
let x = (i as i32) % build_data.map.width;
|
||||||
let y = (i as i32) / build_data.map.width;
|
let y = (i as i32) / build_data.map.width;
|
||||||
|
|
@ -62,13 +63,16 @@ impl VoronoiBuilder {
|
||||||
let distance;
|
let distance;
|
||||||
match self.distance_algorithm {
|
match self.distance_algorithm {
|
||||||
DistanceAlgorithm::Pythagoras => {
|
DistanceAlgorithm::Pythagoras => {
|
||||||
distance = rltk::DistanceAlg::PythagorasSquared.distance2d(rltk::Point::new(x, y), pos.1);
|
distance = DistanceAlg::PythagorasSquared.distance2d(
|
||||||
|
Point::new(x, y),
|
||||||
|
pos.1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
DistanceAlgorithm::Manhattan => {
|
DistanceAlgorithm::Manhattan => {
|
||||||
distance = rltk::DistanceAlg::Manhattan.distance2d(rltk::Point::new(x, y), pos.1);
|
distance = DistanceAlg::Manhattan.distance2d(Point::new(x, y), pos.1);
|
||||||
}
|
}
|
||||||
DistanceAlgorithm::Chebyshev => {
|
DistanceAlgorithm::Chebyshev => {
|
||||||
distance = rltk::DistanceAlg::Chebyshev.distance2d(rltk::Point::new(x, y), pos.1);
|
distance = DistanceAlg::Chebyshev.distance2d(Point::new(x, y), pos.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
voronoi_distance[seed] = (seed, distance);
|
voronoi_distance[seed] = (seed, distance);
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use super::{ spawner, BuilderMap, MetaMapBuilder, TileType };
|
use super::{ spawner, BuilderMap, MetaMapBuilder };
|
||||||
use crate::tile_walkable;
|
use crate::tile_walkable;
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct VoronoiSpawning {}
|
pub struct VoronoiSpawning {}
|
||||||
|
|
||||||
impl MetaMapBuilder for VoronoiSpawning {
|
impl MetaMapBuilder for VoronoiSpawning {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,10 +20,10 @@ impl VoronoiSpawning {
|
||||||
#[allow(clippy::map_entry)]
|
#[allow(clippy::map_entry)]
|
||||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
let mut noise_areas: HashMap<i32, Vec<usize>> = HashMap::new();
|
let mut noise_areas: HashMap<i32, Vec<usize>> = HashMap::new();
|
||||||
let mut noise = rltk::FastNoise::seeded(rng.roll_dice(1, 65536) as u64);
|
let mut noise = FastNoise::seeded(rng.roll_dice(1, 65536) as u64);
|
||||||
noise.set_noise_type(rltk::NoiseType::Cellular);
|
noise.set_noise_type(NoiseType::Cellular);
|
||||||
noise.set_frequency(0.08);
|
noise.set_frequency(0.08);
|
||||||
noise.set_cellular_distance_function(rltk::CellularDistanceFunction::Manhattan);
|
noise.set_cellular_distance_function(CellularDistanceFunction::Manhattan);
|
||||||
|
|
||||||
for y in 1..build_data.map.height - 1 {
|
for y in 1..build_data.map.height - 1 {
|
||||||
for x in 1..build_data.map.width - 1 {
|
for x in 1..build_data.map.width - 1 {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
use super::{Map, MapChunk, TileType};
|
use super::{ Map, MapChunk, TileType };
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub fn build_patterns(map: &Map, chunk_size: i32, include_flipping: bool, dedupe: bool) -> Vec<Vec<TileType>> {
|
pub fn build_patterns(
|
||||||
|
map: &Map,
|
||||||
|
chunk_size: i32,
|
||||||
|
include_flipping: bool,
|
||||||
|
dedupe: bool
|
||||||
|
) -> Vec<Vec<TileType>> {
|
||||||
let chunks_x = map.width / chunk_size;
|
let chunks_x = map.width / chunk_size;
|
||||||
let chunks_y = map.height / chunk_size;
|
let chunks_y = map.height / chunk_size;
|
||||||
let mut patterns = Vec::new();
|
let mut patterns = Vec::new();
|
||||||
|
|
@ -49,16 +55,22 @@ pub fn build_patterns(map: &Map, chunk_size: i32, include_flipping: bool, dedupe
|
||||||
|
|
||||||
// Dedupe
|
// Dedupe
|
||||||
if dedupe {
|
if dedupe {
|
||||||
rltk::console::log(format!("Pre de-duplication, there are {} patterns.", patterns.len()));
|
console::log(format!("Pre de-duplication, there are {} patterns.", patterns.len()));
|
||||||
let set: HashSet<Vec<TileType>> = patterns.drain(..).collect(); // Dedupes
|
let set: HashSet<Vec<TileType>> = patterns.drain(..).collect(); // Dedupes
|
||||||
patterns.extend(set.into_iter());
|
patterns.extend(set.into_iter());
|
||||||
rltk::console::log(format!("There are {} patterns.", patterns.len()));
|
console::log(format!("There are {} patterns.", patterns.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_pattern_to_map(map: &mut Map, chunk: &MapChunk, chunk_size: i32, start_x: i32, start_y: i32) {
|
pub fn render_pattern_to_map(
|
||||||
|
map: &mut Map,
|
||||||
|
chunk: &MapChunk,
|
||||||
|
chunk_size: i32,
|
||||||
|
start_x: i32,
|
||||||
|
start_y: i32
|
||||||
|
) {
|
||||||
let mut i = 0usize;
|
let mut i = 0usize;
|
||||||
for tile_y in 0..chunk_size {
|
for tile_y in 0..chunk_size {
|
||||||
for tile_x in 0..chunk_size {
|
for tile_x in 0..chunk_size {
|
||||||
|
|
@ -70,25 +82,25 @@ pub fn render_pattern_to_map(map: &mut Map, chunk: &MapChunk, chunk_size: i32, s
|
||||||
}
|
}
|
||||||
for (x, northbound) in chunk.exits[0].iter().enumerate() {
|
for (x, northbound) in chunk.exits[0].iter().enumerate() {
|
||||||
if *northbound {
|
if *northbound {
|
||||||
let map_idx = map.xy_idx(start_x + x as i32, start_y);
|
let map_idx = map.xy_idx(start_x + (x as i32), start_y);
|
||||||
map.tiles[map_idx] = TileType::DownStair;
|
map.tiles[map_idx] = TileType::DownStair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (x, southbound) in chunk.exits[1].iter().enumerate() {
|
for (x, southbound) in chunk.exits[1].iter().enumerate() {
|
||||||
if *southbound {
|
if *southbound {
|
||||||
let map_idx = map.xy_idx(start_x + x as i32, start_y + chunk_size - 1);
|
let map_idx = map.xy_idx(start_x + (x as i32), start_y + chunk_size - 1);
|
||||||
map.tiles[map_idx] = TileType::DownStair;
|
map.tiles[map_idx] = TileType::DownStair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (x, westbound) in chunk.exits[2].iter().enumerate() {
|
for (x, westbound) in chunk.exits[2].iter().enumerate() {
|
||||||
if *westbound {
|
if *westbound {
|
||||||
let map_idx = map.xy_idx(start_x, start_y + x as i32);
|
let map_idx = map.xy_idx(start_x, start_y + (x as i32));
|
||||||
map.tiles[map_idx] = TileType::DownStair;
|
map.tiles[map_idx] = TileType::DownStair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (x, eastbound) in chunk.exits[3].iter().enumerate() {
|
for (x, eastbound) in chunk.exits[3].iter().enumerate() {
|
||||||
if *eastbound {
|
if *eastbound {
|
||||||
let map_idx = map.xy_idx(start_x + chunk_size - 1, start_y + x as i32);
|
let map_idx = map.xy_idx(start_x + chunk_size - 1, start_y + (x as i32));
|
||||||
map.tiles[map_idx] = TileType::DownStair;
|
map.tiles[map_idx] = TileType::DownStair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ BuilderMap, Map, MetaMapBuilder, TileType };
|
use super::{ BuilderMap, Map, MetaMapBuilder, TileType };
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::prelude::*;
|
||||||
mod common;
|
mod common;
|
||||||
use common::*;
|
use common::*;
|
||||||
mod constraints;
|
mod constraints;
|
||||||
|
|
@ -11,7 +11,7 @@ use solver::*;
|
||||||
pub struct WaveFunctionCollapseBuilder {}
|
pub struct WaveFunctionCollapseBuilder {}
|
||||||
|
|
||||||
impl MetaMapBuilder for WaveFunctionCollapseBuilder {
|
impl MetaMapBuilder for WaveFunctionCollapseBuilder {
|
||||||
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
self.build(rng, build_data);
|
self.build(rng, build_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,12 @@ impl WaveFunctionCollapseBuilder {
|
||||||
build_data.spawn_list.clear();
|
build_data.spawn_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_tile_gallery(&mut self, constraints: &[MapChunk], chunk_size: i32, build_data: &mut BuilderMap) {
|
fn render_tile_gallery(
|
||||||
|
&mut self,
|
||||||
|
constraints: &[MapChunk],
|
||||||
|
chunk_size: i32,
|
||||||
|
build_data: &mut BuilderMap
|
||||||
|
) {
|
||||||
build_data.map = Map::new(
|
build_data.map = Map::new(
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{Map, MapChunk};
|
use super::{ Map, MapChunk };
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
pub struct Solver {
|
pub struct Solver {
|
||||||
constraints: Vec<MapChunk>,
|
constraints: Vec<MapChunk>,
|
||||||
|
|
@ -16,7 +17,7 @@ impl Solver {
|
||||||
let chunks_x = (map.width / chunk_size) as usize;
|
let chunks_x = (map.width / chunk_size) as usize;
|
||||||
let chunks_y = (map.height / chunk_size) as usize;
|
let chunks_y = (map.height / chunk_size) as usize;
|
||||||
let mut remaining: Vec<(usize, i32)> = Vec::new();
|
let mut remaining: Vec<(usize, i32)> = Vec::new();
|
||||||
for i in 0..(chunks_x * chunks_y) {
|
for i in 0..chunks_x * chunks_y {
|
||||||
remaining.push((i, 0));
|
remaining.push((i, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ impl Solver {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chunk_idx(&self, x: usize, y: usize) -> usize {
|
fn chunk_idx(&self, x: usize, y: usize) -> usize {
|
||||||
return ((y * self.chunks_x) + x) as usize;
|
return (y * self.chunks_x + x) as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_neighbours(&self, chunk_x: usize, chunk_y: usize) -> i32 {
|
fn count_neighbours(&self, chunk_x: usize, chunk_y: usize) -> i32 {
|
||||||
|
|
@ -99,8 +100,11 @@ impl Solver {
|
||||||
self.remaining = remain_copy;
|
self.remaining = remain_copy;
|
||||||
|
|
||||||
// Pick a random chunk we haven't dealt with yet and get its index, remove from remaining list
|
// Pick a random chunk we haven't dealt with yet and get its index, remove from remaining list
|
||||||
let remaining_index =
|
let remaining_index = if !neighbours_exist {
|
||||||
if !neighbours_exist { (rng.roll_dice(1, self.remaining.len() as i32) - 1) as usize } else { 0usize };
|
(rng.roll_dice(1, self.remaining.len() as i32) - 1) as usize
|
||||||
|
} else {
|
||||||
|
0usize
|
||||||
|
};
|
||||||
let chunk_index = self.remaining[remaining_index].0;
|
let chunk_index = self.remaining[remaining_index].0;
|
||||||
self.remaining.remove(remaining_index);
|
self.remaining.remove(remaining_index);
|
||||||
|
|
||||||
|
|
@ -158,10 +162,10 @@ impl Solver {
|
||||||
// There is nothing nearby, so we can have anything!
|
// There is nothing nearby, so we can have anything!
|
||||||
let new_chunk_idx = (rng.roll_dice(1, self.constraints.len() as i32) - 1) as usize;
|
let new_chunk_idx = (rng.roll_dice(1, self.constraints.len() as i32) - 1) as usize;
|
||||||
self.chunks[chunk_index] = Some(new_chunk_idx);
|
self.chunks[chunk_index] = Some(new_chunk_idx);
|
||||||
let left_x = chunk_x as i32 * self.chunk_size as i32;
|
let left_x = (chunk_x as i32) * (self.chunk_size as i32);
|
||||||
let right_x = (chunk_x as i32 + 1) * self.chunk_size as i32;
|
let right_x = ((chunk_x as i32) + 1) * (self.chunk_size as i32);
|
||||||
let top_y = chunk_y as i32 * self.chunk_size as i32;
|
let top_y = (chunk_y as i32) * (self.chunk_size as i32);
|
||||||
let bottom_y = (chunk_y as i32 + 1) * self.chunk_size as i32;
|
let bottom_y = ((chunk_y as i32) + 1) * (self.chunk_size as i32);
|
||||||
|
|
||||||
let mut i: usize = 0;
|
let mut i: usize = 0;
|
||||||
for y in top_y..bottom_y {
|
for y in top_y..bottom_y {
|
||||||
|
|
@ -195,18 +199,21 @@ impl Solver {
|
||||||
}
|
}
|
||||||
|
|
||||||
if possible_options.is_empty() {
|
if possible_options.is_empty() {
|
||||||
rltk::console::log("Oh no! It's not possible!");
|
console::log("Oh no! It's not possible!");
|
||||||
self.possible = false;
|
self.possible = false;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
let new_chunk_idx =
|
let new_chunk_idx = if possible_options.len() == 1 {
|
||||||
if possible_options.len() == 1 { 0 } else { rng.roll_dice(1, possible_options.len() as i32) - 1 };
|
0
|
||||||
|
} else {
|
||||||
|
rng.roll_dice(1, possible_options.len() as i32) - 1
|
||||||
|
};
|
||||||
|
|
||||||
self.chunks[chunk_index] = Some(new_chunk_idx as usize);
|
self.chunks[chunk_index] = Some(new_chunk_idx as usize);
|
||||||
let left_x = chunk_x as i32 * self.chunk_size as i32;
|
let left_x = (chunk_x as i32) * (self.chunk_size as i32);
|
||||||
let right_x = (chunk_x as i32 + 1) * self.chunk_size as i32;
|
let right_x = ((chunk_x as i32) + 1) * (self.chunk_size as i32);
|
||||||
let top_y = chunk_y as i32 * self.chunk_size as i32;
|
let top_y = (chunk_y as i32) * (self.chunk_size as i32);
|
||||||
let bottom_y = (chunk_y as i32 + 1) * self.chunk_size as i32;
|
let bottom_y = ((chunk_y as i32) + 1) * (self.chunk_size as i32);
|
||||||
|
|
||||||
let mut i: usize = 0;
|
let mut i: usize = 0;
|
||||||
for y in top_y..bottom_y {
|
for y in top_y..bottom_y {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use super::{
|
||||||
WeaponAttribute,
|
WeaponAttribute,
|
||||||
config::CONFIG,
|
config::CONFIG,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct MeleeCombatSystem {}
|
pub struct MeleeCombatSystem {}
|
||||||
|
|
@ -50,7 +50,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
ReadStorage<'a, HungerClock>,
|
ReadStorage<'a, HungerClock>,
|
||||||
ReadStorage<'a, MultiAttack>,
|
ReadStorage<'a, MultiAttack>,
|
||||||
ReadStorage<'a, Blind>,
|
ReadStorage<'a, Blind>,
|
||||||
WriteExpect<'a, rltk::RandomNumberGenerator>,
|
WriteExpect<'a, RandomNumberGenerator>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
|
|
@ -194,7 +194,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
armour_ac_bonus += ac.amount;
|
armour_ac_bonus += ac.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let actual_armour_class = bac - attribute_ac_bonus - skill_ac_bonus - armour_ac_bonus;
|
let actual_armour_class =
|
||||||
|
bac - attribute_ac_bonus - skill_ac_bonus - armour_ac_bonus;
|
||||||
let mut armour_class_roll = actual_armour_class;
|
let mut armour_class_roll = actual_armour_class;
|
||||||
|
|
||||||
if actual_armour_class < 0 {
|
if actual_armour_class < 0 {
|
||||||
|
|
@ -205,13 +206,17 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monster attacks receive a +10 to-hit bonus against the player.
|
// Monster attacks receive a +10 to-hit bonus against the player.
|
||||||
let monster_v_player_bonus = if wants_melee.target == *player_entity { 10 } else { 0 };
|
let monster_v_player_bonus = if wants_melee.target == *player_entity {
|
||||||
|
10
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let target_number = monster_v_player_bonus + armour_class_roll + attacker_bonuses;
|
let target_number = monster_v_player_bonus + armour_class_roll + attacker_bonuses;
|
||||||
|
|
||||||
let target_name = names.get(wants_melee.target).unwrap();
|
let target_name = names.get(wants_melee.target).unwrap();
|
||||||
if CONFIG.logging.log_combat {
|
if CONFIG.logging.log_combat {
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!(
|
format!(
|
||||||
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} ({} + {}AC + {}to-hit)",
|
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} ({} + {}AC + {}to-hit)",
|
||||||
&name.name,
|
&name.name,
|
||||||
|
|
@ -228,8 +233,14 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
|
|
||||||
if d20 < target_number {
|
if d20 < target_number {
|
||||||
// Target hit!
|
// Target hit!
|
||||||
let base_damage = rng.roll_dice(weapon_info.damage_n_dice, weapon_info.damage_die_type);
|
let base_damage = rng.roll_dice(
|
||||||
let skill_damage_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
weapon_info.damage_n_dice,
|
||||||
|
weapon_info.damage_die_type
|
||||||
|
);
|
||||||
|
let skill_damage_bonus = gamesystem::skill_bonus(
|
||||||
|
Skill::Melee,
|
||||||
|
&*attacker_skills
|
||||||
|
);
|
||||||
let mut attribute_damage_bonus = weapon_info.damage_bonus;
|
let mut attribute_damage_bonus = weapon_info.damage_bonus;
|
||||||
match weapon_info.attribute {
|
match weapon_info.attribute {
|
||||||
WeaponAttribute::Dexterity => {
|
WeaponAttribute::Dexterity => {
|
||||||
|
|
@ -239,17 +250,23 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
||||||
}
|
}
|
||||||
WeaponAttribute::Finesse => {
|
WeaponAttribute::Finesse => {
|
||||||
if attacker_attributes.dexterity.bonus > attacker_attributes.strength.bonus {
|
if
|
||||||
|
attacker_attributes.dexterity.bonus >
|
||||||
|
attacker_attributes.strength.bonus
|
||||||
|
{
|
||||||
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
||||||
} else {
|
} else {
|
||||||
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut damage = i32::max(0, base_damage + skill_damage_bonus + attribute_damage_bonus);
|
let mut damage = i32::max(
|
||||||
|
0,
|
||||||
|
base_damage + skill_damage_bonus + attribute_damage_bonus
|
||||||
|
);
|
||||||
|
|
||||||
if CONFIG.logging.log_combat {
|
if CONFIG.logging.log_combat {
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!(
|
format!(
|
||||||
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
|
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
|
||||||
&name.name,
|
&name.name,
|
||||||
|
|
@ -267,7 +284,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
|
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
|
||||||
damage = i32::min(1, damage - ac_damage_reduction);
|
damage = i32::min(1, damage - ac_damage_reduction);
|
||||||
if CONFIG.logging.log_combat {
|
if CONFIG.logging.log_combat {
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!(
|
format!(
|
||||||
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
|
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
|
||||||
&target_name.name,
|
&target_name.name,
|
||||||
|
|
@ -321,7 +338,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if CONFIG.logging.log_combat {
|
if CONFIG.logging.log_combat {
|
||||||
rltk::console::log(format!("ATTACKLOG: {} *MISSED*", &name.name));
|
console::log(format!("ATTACKLOG: {} *MISSED*", &name.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos = positions.get(wants_melee.target);
|
let pos = positions.get(wants_melee.target);
|
||||||
|
|
@ -365,7 +382,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_natural_attacks(
|
fn get_natural_attacks(
|
||||||
rng: &mut rltk::RandomNumberGenerator,
|
rng: &mut RandomNumberGenerator,
|
||||||
nat: NaturalAttacks,
|
nat: NaturalAttacks,
|
||||||
multi_attack: bool,
|
multi_attack: bool,
|
||||||
attacks: &mut Vec<(MeleeWeapon, String)>
|
attacks: &mut Vec<(MeleeWeapon, String)>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use crate::gamelog;
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::gui::{ Class, Ancestry, unobf_name_ecs };
|
use crate::gui::{ Class, Ancestry, unobf_name_ecs };
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use rltk::to_char;
|
use to_char;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
|
||||||
|
|
@ -49,7 +49,14 @@ fn create_file_name(ecs: &World, morgue_dir: &str) -> String {
|
||||||
Ancestry::Catfolk => "catfolk",
|
Ancestry::Catfolk => "catfolk",
|
||||||
Ancestry::NULL => "NULL",
|
Ancestry::NULL => "NULL",
|
||||||
};
|
};
|
||||||
return format!("{}/lv{}-{}-{}-{}.txt", morgue_dir, &pool.level, &ancestry, &class, get_timestamp());
|
return format!(
|
||||||
|
"{}/lv{}-{}-{}-{}.txt",
|
||||||
|
morgue_dir,
|
||||||
|
&pool.level,
|
||||||
|
&ancestry,
|
||||||
|
&class,
|
||||||
|
get_timestamp()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_morgue_string(ecs: &World) -> String {
|
fn create_morgue_string(ecs: &World) -> String {
|
||||||
|
|
@ -165,7 +172,12 @@ fn draw_map(ecs: &World) -> String {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
glyph_u16 = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None, Some(true)).0;
|
glyph_u16 = crate::map::themes::get_tile_renderables_for_id(
|
||||||
|
idx,
|
||||||
|
&*map,
|
||||||
|
None,
|
||||||
|
Some(true)
|
||||||
|
).0;
|
||||||
}
|
}
|
||||||
let char = to_char((glyph_u16 & 0xff) as u8);
|
let char = to_char((glyph_u16 & 0xff) as u8);
|
||||||
result.push_str(&char.to_string());
|
result.push_str(&char.to_string());
|
||||||
|
|
@ -201,7 +213,11 @@ fn draw_equipment(ecs: &World) -> String {
|
||||||
EquipmentSlot::Back => "back -",
|
EquipmentSlot::Back => "back -",
|
||||||
EquipmentSlot::Neck => "neck -",
|
EquipmentSlot::Neck => "neck -",
|
||||||
};
|
};
|
||||||
let name = if item.1 != 1 { unobf_name_ecs(ecs, item.0).1 } else { unobf_name_ecs(ecs, item.0).0 };
|
let name = if item.1 != 1 {
|
||||||
|
unobf_name_ecs(ecs, item.0).1
|
||||||
|
} else {
|
||||||
|
unobf_name_ecs(ecs, item.0).0
|
||||||
|
};
|
||||||
result.push_str(&format!("{:>8} {}\n", slot, name));
|
result.push_str(&format!("{:>8} {}\n", slot, name));
|
||||||
}
|
}
|
||||||
result.push_str("\n");
|
result.push_str("\n");
|
||||||
|
|
@ -211,7 +227,11 @@ fn draw_equipment(ecs: &World) -> String {
|
||||||
fn draw_backpack(ecs: &World) -> String {
|
fn draw_backpack(ecs: &World) -> String {
|
||||||
// Get all of the player's backpack.
|
// Get all of the player's backpack.
|
||||||
let mut pack: HashMap<(String, String), (i32, Entity)> = HashMap::new();
|
let mut pack: HashMap<(String, String), (i32, Entity)> = HashMap::new();
|
||||||
for (entity, _bp, _n) in (&ecs.entities(), &ecs.read_storage::<InBackpack>(), &ecs.read_storage::<Name>())
|
for (entity, _bp, _n) in (
|
||||||
|
&ecs.entities(),
|
||||||
|
&ecs.read_storage::<InBackpack>(),
|
||||||
|
&ecs.read_storage::<Name>(),
|
||||||
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter(|item| item.1.owner == *ecs.fetch::<Entity>()) {
|
.filter(|item| item.1.owner == *ecs.fetch::<Entity>()) {
|
||||||
pack.entry(unobf_name_ecs(ecs, entity))
|
pack.entry(unobf_name_ecs(ecs, entity))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{ ParticleLifetime, Position, Renderable, Rltk };
|
use super::{ ParticleLifetime, Position, Renderable, BTerm };
|
||||||
use rltk::RGB;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME };
|
use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME };
|
||||||
|
|
||||||
|
|
@ -8,12 +8,12 @@ use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME }
|
||||||
// running through a list and removing the frame_time_ms from the
|
// running through a list and removing the frame_time_ms from the
|
||||||
// delay. When delay is <= 0, make a particle_builder.request for
|
// delay. When delay is <= 0, make a particle_builder.request for
|
||||||
// the particle.
|
// the particle.
|
||||||
pub fn particle_ticker(ecs: &mut World, ctx: &Rltk) {
|
pub fn particle_ticker(ecs: &mut World, ctx: &BTerm) {
|
||||||
cull_dead_particles(ecs, ctx);
|
cull_dead_particles(ecs, ctx);
|
||||||
create_delayed_particles(ecs, ctx);
|
create_delayed_particles(ecs, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cull_dead_particles(ecs: &mut World, ctx: &Rltk) {
|
fn cull_dead_particles(ecs: &mut World, ctx: &BTerm) {
|
||||||
let mut dead_particles: Vec<Entity> = Vec::new();
|
let mut dead_particles: Vec<Entity> = Vec::new();
|
||||||
{
|
{
|
||||||
// Age out particles
|
// Age out particles
|
||||||
|
|
@ -39,7 +39,7 @@ pub fn check_queue(ecs: &World) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_delayed_particles(ecs: &mut World, ctx: &Rltk) {
|
fn create_delayed_particles(ecs: &mut World, ctx: &BTerm) {
|
||||||
let mut particle_builder = ecs.write_resource::<ParticleBuilder>();
|
let mut particle_builder = ecs.write_resource::<ParticleBuilder>();
|
||||||
let mut handled_particles: Vec<ParticleRequest> = Vec::new();
|
let mut handled_particles: Vec<ParticleRequest> = Vec::new();
|
||||||
for delayed_particle in particle_builder.delayed_requests.iter_mut() {
|
for delayed_particle in particle_builder.delayed_requests.iter_mut() {
|
||||||
|
|
@ -76,11 +76,20 @@ fn create_delayed_particles(ecs: &mut World, ctx: &Rltk) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
particle_builder.delayed_requests.remove(index);
|
particle_builder.delayed_requests.remove(index);
|
||||||
let p = entities.create();
|
let p = entities.create();
|
||||||
positions.insert(p, Position { x: handled.x, y: handled.y }).expect("Could not insert position");
|
positions
|
||||||
|
.insert(p, Position { x: handled.x, y: handled.y })
|
||||||
|
.expect("Could not insert position");
|
||||||
renderables
|
renderables
|
||||||
.insert(p, Renderable { fg: handled.fg, bg: handled.bg, glyph: handled.glyph, render_order: 0 })
|
.insert(p, Renderable {
|
||||||
|
fg: handled.fg,
|
||||||
|
bg: handled.bg,
|
||||||
|
glyph: handled.glyph,
|
||||||
|
render_order: 0,
|
||||||
|
})
|
||||||
.expect("Could not insert renderables");
|
.expect("Could not insert renderables");
|
||||||
particles.insert(p, ParticleLifetime { lifetime_ms: handled.lifetime }).expect("Could not insert lifetime");
|
particles
|
||||||
|
.insert(p, ParticleLifetime { lifetime_ms: handled.lifetime })
|
||||||
|
.expect("Could not insert lifetime");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +99,7 @@ pub struct ParticleRequest {
|
||||||
y: i32,
|
y: i32,
|
||||||
fg: RGB,
|
fg: RGB,
|
||||||
bg: RGB,
|
bg: RGB,
|
||||||
glyph: rltk::FontCharType,
|
glyph: FontCharType,
|
||||||
lifetime: f32,
|
lifetime: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,11 +121,28 @@ impl ParticleBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a single particle request.
|
/// Makes a single particle request.
|
||||||
pub fn request(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32) {
|
pub fn request(
|
||||||
|
&mut self,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
fg: RGB,
|
||||||
|
bg: RGB,
|
||||||
|
glyph: FontCharType,
|
||||||
|
lifetime: f32
|
||||||
|
) {
|
||||||
self.requests.push(ParticleRequest { x, y, fg, bg, glyph, lifetime });
|
self.requests.push(ParticleRequest { x, y, fg, bg, glyph, lifetime });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delay(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32, delay: f32) {
|
pub fn delay(
|
||||||
|
&mut self,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
fg: RGB,
|
||||||
|
bg: RGB,
|
||||||
|
glyph: FontCharType,
|
||||||
|
lifetime: f32,
|
||||||
|
delay: f32
|
||||||
|
) {
|
||||||
self.delayed_requests.push(DelayedParticleRequest {
|
self.delayed_requests.push(DelayedParticleRequest {
|
||||||
delay: delay,
|
delay: delay,
|
||||||
particle: ParticleRequest { x, y, fg, bg, glyph, lifetime },
|
particle: ParticleRequest { x, y, fg, bg, glyph, lifetime },
|
||||||
|
|
@ -127,9 +153,9 @@ impl ParticleBuilder {
|
||||||
self.request(
|
self.request(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
rltk::RGB::named(rltk::ORANGE),
|
RGB::named(ORANGE),
|
||||||
rltk::RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
rltk::to_cp437('‼'),
|
to_cp437('‼'),
|
||||||
DEFAULT_PARTICLE_LIFETIME
|
DEFAULT_PARTICLE_LIFETIME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -138,9 +164,9 @@ impl ParticleBuilder {
|
||||||
self.request(
|
self.request(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
rltk::RGB::named(rltk::CYAN),
|
RGB::named(CYAN),
|
||||||
rltk::RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
rltk::to_cp437('‼'),
|
to_cp437('‼'),
|
||||||
DEFAULT_PARTICLE_LIFETIME
|
DEFAULT_PARTICLE_LIFETIME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -149,9 +175,9 @@ impl ParticleBuilder {
|
||||||
self.request(
|
self.request(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
rltk::RGB::named(rltk::CHOCOLATE),
|
RGB::named(CHOCOLATE),
|
||||||
rltk::RGB::named(rltk::BLACK),
|
RGB::named(BLACK),
|
||||||
rltk::to_cp437('‼'),
|
to_cp437('‼'),
|
||||||
SHORT_PARTICLE_LIFETIME
|
SHORT_PARTICLE_LIFETIME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -164,57 +190,97 @@ impl ParticleBuilder {
|
||||||
y: i32,
|
y: i32,
|
||||||
fg: RGB,
|
fg: RGB,
|
||||||
bg: RGB,
|
bg: RGB,
|
||||||
glyph: rltk::FontCharType,
|
glyph: FontCharType,
|
||||||
lifetime: f32,
|
lifetime: f32,
|
||||||
secondary_fg: RGB
|
secondary_fg: RGB
|
||||||
) {
|
) {
|
||||||
let eighth_l = lifetime / 8.0;
|
let eighth_l = lifetime / 8.0;
|
||||||
let quarter_l = eighth_l * 2.0;
|
let quarter_l = eighth_l * 2.0;
|
||||||
self.request(x, y, fg, bg, glyph, lifetime);
|
self.request(x, y, fg, bg, glyph, lifetime);
|
||||||
self.delay(x + 1, y + 1, secondary_fg.lerp(bg, 0.8), bg, rltk::to_cp437('/'), quarter_l, eighth_l);
|
self.delay(
|
||||||
self.delay(x + 1, y - 1, secondary_fg.lerp(bg, 0.6), bg, rltk::to_cp437('\\'), quarter_l, quarter_l);
|
x + 1,
|
||||||
self.delay(x - 1, y - 1, secondary_fg.lerp(bg, 0.2), bg, rltk::to_cp437('/'), quarter_l, eighth_l * 3.0);
|
y + 1,
|
||||||
self.delay(x - 1, y + 1, secondary_fg.lerp(bg, 0.4), bg, rltk::to_cp437('\\'), quarter_l, lifetime);
|
secondary_fg.lerp(bg, 0.8),
|
||||||
|
bg,
|
||||||
|
to_cp437('/'),
|
||||||
|
quarter_l,
|
||||||
|
eighth_l
|
||||||
|
);
|
||||||
|
self.delay(
|
||||||
|
x + 1,
|
||||||
|
y - 1,
|
||||||
|
secondary_fg.lerp(bg, 0.6),
|
||||||
|
bg,
|
||||||
|
to_cp437('\\'),
|
||||||
|
quarter_l,
|
||||||
|
quarter_l
|
||||||
|
);
|
||||||
|
self.delay(
|
||||||
|
x - 1,
|
||||||
|
y - 1,
|
||||||
|
secondary_fg.lerp(bg, 0.2),
|
||||||
|
bg,
|
||||||
|
to_cp437('/'),
|
||||||
|
quarter_l,
|
||||||
|
eighth_l * 3.0
|
||||||
|
);
|
||||||
|
self.delay(
|
||||||
|
x - 1,
|
||||||
|
y + 1,
|
||||||
|
secondary_fg.lerp(bg, 0.4),
|
||||||
|
bg,
|
||||||
|
to_cp437('\\'),
|
||||||
|
quarter_l,
|
||||||
|
lifetime
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes a rainbow particle request in the shape of an 'x'. Sort of.
|
// Makes a rainbow particle request in the shape of an 'x'. Sort of.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn request_rainbow_star(&mut self, x: i32, y: i32, glyph: rltk::FontCharType, lifetime: f32) {
|
pub fn request_rainbow_star(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) {
|
||||||
let bg = RGB::named(rltk::BLACK);
|
let bg = RGB::named(BLACK);
|
||||||
let eighth_l = lifetime / 8.0;
|
let eighth_l = lifetime / 8.0;
|
||||||
let quarter_l = eighth_l * 2.0;
|
let quarter_l = eighth_l * 2.0;
|
||||||
let half_l = quarter_l * 2.0;
|
let half_l = quarter_l * 2.0;
|
||||||
|
|
||||||
self.request(x, y, RGB::named(rltk::CYAN), bg, glyph, lifetime);
|
self.request(x, y, RGB::named(CYAN), bg, glyph, lifetime);
|
||||||
self.delay(x + 1, y + 1, RGB::named(rltk::RED), bg, rltk::to_cp437('\\'), half_l, eighth_l);
|
self.delay(x + 1, y + 1, RGB::named(RED), bg, to_cp437('\\'), half_l, eighth_l);
|
||||||
self.delay(x + 1, y - 1, RGB::named(rltk::ORANGE), bg, rltk::to_cp437('/'), half_l, quarter_l);
|
self.delay(x + 1, y - 1, RGB::named(ORANGE), bg, to_cp437('/'), half_l, quarter_l);
|
||||||
self.delay(x - 1, y - 1, RGB::named(rltk::GREEN), bg, rltk::to_cp437('\\'), half_l, eighth_l * 3.0);
|
self.delay(x - 1, y - 1, RGB::named(GREEN), bg, to_cp437('\\'), half_l, eighth_l * 3.0);
|
||||||
self.delay(x - 1, y + 1, RGB::named(rltk::YELLOW), bg, rltk::to_cp437('/'), half_l, half_l);
|
self.delay(x - 1, y + 1, RGB::named(YELLOW), bg, to_cp437('/'), half_l, half_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes a rainbow particle request. Sort of.
|
// Makes a rainbow particle request. Sort of.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn request_rainbow(&mut self, x: i32, y: i32, glyph: rltk::FontCharType, lifetime: f32) {
|
pub fn request_rainbow(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) {
|
||||||
let bg = RGB::named(rltk::BLACK);
|
let bg = RGB::named(BLACK);
|
||||||
let eighth_l = lifetime / 8.0;
|
let eighth_l = lifetime / 8.0;
|
||||||
|
|
||||||
self.request(x, y, RGB::named(rltk::RED), bg, glyph, eighth_l);
|
self.request(x, y, RGB::named(RED), bg, glyph, eighth_l);
|
||||||
self.delay(x, y, RGB::named(rltk::ORANGE), bg, glyph, eighth_l, eighth_l);
|
self.delay(x, y, RGB::named(ORANGE), bg, glyph, eighth_l, eighth_l);
|
||||||
self.delay(x, y, RGB::named(rltk::YELLOW), bg, glyph, eighth_l, eighth_l * 2.0);
|
self.delay(x, y, RGB::named(YELLOW), bg, glyph, eighth_l, eighth_l * 2.0);
|
||||||
self.delay(x, y, RGB::named(rltk::GREEN), bg, glyph, eighth_l, eighth_l * 3.0);
|
self.delay(x, y, RGB::named(GREEN), bg, glyph, eighth_l, eighth_l * 3.0);
|
||||||
self.delay(x, y, RGB::named(rltk::BLUE), bg, glyph, eighth_l, eighth_l * 4.0);
|
self.delay(x, y, RGB::named(BLUE), bg, glyph, eighth_l, eighth_l * 4.0);
|
||||||
self.delay(x, y, RGB::named(rltk::INDIGO), bg, glyph, eighth_l, eighth_l * 5.0);
|
self.delay(x, y, RGB::named(INDIGO), bg, glyph, eighth_l, eighth_l * 5.0);
|
||||||
self.delay(x, y, RGB::named(rltk::VIOLET), bg, glyph, eighth_l, eighth_l * 6.0);
|
self.delay(x, y, RGB::named(VIOLET), bg, glyph, eighth_l, eighth_l * 6.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a particle request in the shape of a +.
|
/// Makes a particle request in the shape of a +.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn request_plus(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32) {
|
pub fn request_plus(
|
||||||
|
&mut self,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
fg: RGB,
|
||||||
|
bg: RGB,
|
||||||
|
glyph: FontCharType,
|
||||||
|
lifetime: f32
|
||||||
|
) {
|
||||||
self.request(x, y, fg, bg, glyph, lifetime * 2.0);
|
self.request(x, y, fg, bg, glyph, lifetime * 2.0);
|
||||||
self.request(x + 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
|
self.request(x + 1, y, fg, bg, to_cp437('─'), lifetime);
|
||||||
self.request(x - 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
|
self.request(x - 1, y, fg, bg, to_cp437('─'), lifetime);
|
||||||
self.request(x, y + 1, fg, bg, rltk::to_cp437('│'), lifetime);
|
self.request(x, y + 1, fg, bg, to_cp437('│'), lifetime);
|
||||||
self.request(x, y - 1, fg, bg, rltk::to_cp437('│'), lifetime);
|
self.request(x, y - 1, fg, bg, to_cp437('│'), lifetime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,7 +301,9 @@ impl<'a> System<'a> for ParticleSpawnSystem {
|
||||||
|
|
||||||
for new_particle in particle_builder.requests.iter() {
|
for new_particle in particle_builder.requests.iter() {
|
||||||
let p = entities.create();
|
let p = entities.create();
|
||||||
positions.insert(p, Position { x: new_particle.x, y: new_particle.y }).expect("Could not insert position");
|
positions
|
||||||
|
.insert(p, Position { x: new_particle.x, y: new_particle.y })
|
||||||
|
.expect("Could not insert position");
|
||||||
renderables
|
renderables
|
||||||
.insert(p, Renderable {
|
.insert(p, Renderable {
|
||||||
fg: new_particle.fg,
|
fg: new_particle.fg,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ use super::{
|
||||||
Item,
|
Item,
|
||||||
Map,
|
Map,
|
||||||
Name,
|
Name,
|
||||||
ParticleBuilder,
|
|
||||||
Player,
|
Player,
|
||||||
Pools,
|
Pools,
|
||||||
Position,
|
Position,
|
||||||
|
|
@ -34,8 +33,7 @@ use super::{
|
||||||
get_dest,
|
get_dest,
|
||||||
Destination,
|
Destination,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode };
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::cmp::{ max, min };
|
use std::cmp::{ max, min };
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
|
@ -133,7 +131,7 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
|
||||||
std::mem::drop(renderables);
|
std::mem::drop(renderables);
|
||||||
let mut renderables = ecs.write_storage::<Renderable>();
|
let mut renderables = ecs.write_storage::<Renderable>();
|
||||||
let render_data = renderables.get_mut(potential_target).unwrap();
|
let render_data = renderables.get_mut(potential_target).unwrap();
|
||||||
render_data.glyph = rltk::to_cp437('+'); // Nethack open door, maybe just use '/' instead.
|
render_data.glyph = to_cp437('+'); // Nethack open door, maybe just use '/' instead.
|
||||||
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
|
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
|
||||||
}
|
}
|
||||||
result = RunState::Ticking;
|
result = RunState::Ticking;
|
||||||
|
|
@ -230,7 +228,7 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
|
||||||
std::mem::drop(renderables);
|
std::mem::drop(renderables);
|
||||||
let mut renderables = ecs.write_storage::<Renderable>();
|
let mut renderables = ecs.write_storage::<Renderable>();
|
||||||
let render_data = renderables.get_mut(potential_target).unwrap();
|
let render_data = renderables.get_mut(potential_target).unwrap();
|
||||||
render_data.glyph = rltk::to_cp437('▓'); // Nethack open door, maybe just use '/' instead.
|
render_data.glyph = to_cp437('▓'); // Nethack open door, maybe just use '/' instead.
|
||||||
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
|
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
|
||||||
}
|
}
|
||||||
result = RunState::Ticking;
|
result = RunState::Ticking;
|
||||||
|
|
@ -643,7 +641,7 @@ fn get_item(ecs: &mut World) -> RunState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_input(gs: &mut State, ctx: &mut Rltk, on_overmap: bool) -> RunState {
|
pub fn player_input(gs: &mut State, ctx: &mut BTerm, on_overmap: bool) -> RunState {
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
None => {
|
None => {
|
||||||
return RunState::AwaitingInput;
|
return RunState::AwaitingInput;
|
||||||
|
|
@ -878,7 +876,7 @@ pub fn auto_explore(ecs: &mut World) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = rltk::a_star_search(map.xy_idx(player_pos.x, player_pos.y), unexplored_tile.0, &*map);
|
let path = a_star_search(map.xy_idx(player_pos.x, player_pos.y), unexplored_tile.0, &*map);
|
||||||
if path.success && path.steps.len() > 1 {
|
if path.success && path.steps.len() > 1 {
|
||||||
let mut idx = map.xy_idx(player_pos.x, player_pos.y);
|
let mut idx = map.xy_idx(player_pos.x, player_pos.y);
|
||||||
map.blocked[idx] = false;
|
map.blocked[idx] = false;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use rltk::RandomNumberGenerator;
|
use bracket_lib::random::RandomNumberGenerator;
|
||||||
|
|
||||||
// FIXME: note to self,
|
// FIXME: note to self,
|
||||||
// passing around strings here is super inefficient, so this is
|
// passing around strings here is super inefficient, so this is
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ mod reaction_structs;
|
||||||
pub use reaction_structs::Reaction;
|
pub use reaction_structs::Reaction;
|
||||||
use reaction_structs::{ AncestryData, FactionData };
|
use reaction_structs::{ AncestryData, FactionData };
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref RAWS: Mutex<RawMaster> = Mutex::new(RawMaster::empty());
|
pub static ref RAWS: Mutex<RawMaster> = Mutex::new(RawMaster::empty());
|
||||||
|
|
@ -31,22 +32,22 @@ pub struct Raws {
|
||||||
pub ancestries: Vec<AncestryData>,
|
pub ancestries: Vec<AncestryData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
rltk::embedded_resource!(RAW_MOBS, "../../raws/mobs.json");
|
embedded_resource!(RAW_MOBS, "../../raws/mobs.json");
|
||||||
rltk::embedded_resource!(RAW_PROPS, "../../raws/props.json");
|
embedded_resource!(RAW_PROPS, "../../raws/props.json");
|
||||||
rltk::embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
||||||
rltk::embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
||||||
rltk::embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
||||||
rltk::embedded_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
embedded_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
||||||
|
|
||||||
pub fn load_raws() {
|
pub fn load_raws() {
|
||||||
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
|
link_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
rltk::link_resource!(RAW_MOBS, "../../raws/mobs.json");
|
link_resource!(RAW_MOBS, "../../raws/mobs.json");
|
||||||
rltk::link_resource!(RAW_PROPS, "../../raws/props.json");
|
link_resource!(RAW_PROPS, "../../raws/props.json");
|
||||||
rltk::link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
||||||
rltk::link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
||||||
rltk::link_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
link_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
||||||
rltk::link_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
link_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
||||||
|
|
||||||
let decoded_raws = get_decoded_raws();
|
let decoded_raws = get_decoded_raws();
|
||||||
RAWS.lock().unwrap().load(decoded_raws);
|
RAWS.lock().unwrap().load(decoded_raws);
|
||||||
|
|
@ -56,10 +57,18 @@ pub fn get_decoded_raws() -> Raws {
|
||||||
let items: Vec<Item> = ParseJson::parse_raws_into_vector("../../raws/items.json".to_string());
|
let items: Vec<Item> = ParseJson::parse_raws_into_vector("../../raws/items.json".to_string());
|
||||||
let mobs: Vec<Mob> = ParseJson::parse_raws_into_vector("../../raws/mobs.json".to_string());
|
let mobs: Vec<Mob> = ParseJson::parse_raws_into_vector("../../raws/mobs.json".to_string());
|
||||||
let props: Vec<Prop> = ParseJson::parse_raws_into_vector("../../raws/props.json".to_string());
|
let props: Vec<Prop> = ParseJson::parse_raws_into_vector("../../raws/props.json".to_string());
|
||||||
let spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector("../../raws/spawn_tables.json".to_string());
|
let spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector(
|
||||||
let loot_tables: Vec<LootTable> = ParseJson::parse_raws_into_vector("../../raws/loot_tables.json".to_string());
|
"../../raws/spawn_tables.json".to_string()
|
||||||
let factions: Vec<FactionData> = ParseJson::parse_raws_into_vector("../../raws/factions.json".to_string());
|
);
|
||||||
let ancestries: Vec<AncestryData> = ParseJson::parse_raws_into_vector("../../raws/ancestries.json".to_string());
|
let loot_tables: Vec<LootTable> = ParseJson::parse_raws_into_vector(
|
||||||
|
"../../raws/loot_tables.json".to_string()
|
||||||
|
);
|
||||||
|
let factions: Vec<FactionData> = ParseJson::parse_raws_into_vector(
|
||||||
|
"../../raws/factions.json".to_string()
|
||||||
|
);
|
||||||
|
let ancestries: Vec<AncestryData> = ParseJson::parse_raws_into_vector(
|
||||||
|
"../../raws/ancestries.json".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
return Raws { items, mobs, props, spawn_tables, loot_tables, factions, ancestries };
|
return Raws { items, mobs, props, spawn_tables, loot_tables, factions, ancestries };
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +80,7 @@ macro_rules! impl_ParseJson {
|
||||||
(for $($t:ty),+) => {
|
(for $($t:ty),+) => {
|
||||||
$(impl ParseJson for $t {
|
$(impl ParseJson for $t {
|
||||||
fn parse_raws_into_vector(path: String) -> $t {
|
fn parse_raws_into_vector(path: String) -> $t {
|
||||||
let raw_data = rltk::embedding::EMBED.lock().get_resource(path).unwrap();
|
let raw_data = EMBED.lock().get_resource(path).unwrap();
|
||||||
let raw_string = std::str::from_utf8(&raw_data).expect("Failed to convert UTF-8 to &str.");
|
let raw_string = std::str::from_utf8(&raw_data).expect("Failed to convert UTF-8 to &str.");
|
||||||
return serde_json::from_str(&raw_string).expect("Failed to convert &str to json");
|
return serde_json::from_str(&raw_string).expect("Failed to convert &str to json");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::random_table::RandomTable;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
use crate::data::visuals::BLOODSTAIN_COLOUR;
|
use crate::data::visuals::BLOODSTAIN_COLOUR;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{ MarkedBuilder, SimpleMarker };
|
use specs::saveload::{ MarkedBuilder, SimpleMarker };
|
||||||
use std::collections::{ HashMap, HashSet };
|
use std::collections::{ HashMap, HashSet };
|
||||||
|
|
@ -98,7 +98,7 @@ macro_rules! apply_flags {
|
||||||
"LARGE_GROUP" => {} // and don't need to apply a component.
|
"LARGE_GROUP" => {} // and don't need to apply a component.
|
||||||
"MULTIATTACK" => $eb = $eb.with(MultiAttack {}),
|
"MULTIATTACK" => $eb = $eb.with(MultiAttack {}),
|
||||||
"BLIND" => $eb = $eb.with(Blind {}),
|
"BLIND" => $eb = $eb.with(Blind {}),
|
||||||
_ => rltk::console::log(format!("Unrecognised flag: {}", flag.as_str())),
|
_ => console::log(format!("Unrecognised flag: {}", flag.as_str())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -203,13 +203,13 @@ impl RawMaster {
|
||||||
/// Checks a string against a HashSet, logging if a duplicate is found.
|
/// Checks a string against a HashSet, logging if a duplicate is found.
|
||||||
fn check_for_duplicate_entries(used_names: &HashSet<String>, id: &String) {
|
fn check_for_duplicate_entries(used_names: &HashSet<String>, id: &String) {
|
||||||
if used_names.contains(id) {
|
if used_names.contains(id) {
|
||||||
rltk::console::log(format!("DEBUGINFO: Duplicate ID found in raws [{}]", id));
|
console::log(format!("DEBUGINFO: Duplicate ID found in raws [{}]", id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Checks a string against a HashSet, logging if the string isn't found.
|
/// Checks a string against a HashSet, logging if the string isn't found.
|
||||||
fn check_for_unspecified_entity(used_names: &HashSet<String>, id: &String) {
|
fn check_for_unspecified_entity(used_names: &HashSet<String>, id: &String) {
|
||||||
if !used_names.contains(id) {
|
if !used_names.contains(id) {
|
||||||
rltk::console::log(format!("DEBUGINFO: Table references unspecified entity [{}]", id));
|
console::log(format!("DEBUGINFO: Table references unspecified entity [{}]", id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,8 +266,14 @@ pub fn spawn_named_item(
|
||||||
// -- DROP EVERYTHING THAT INVOLVES THE ECS BEFORE THIS POINT ---
|
// -- DROP EVERYTHING THAT INVOLVES THE ECS BEFORE THIS POINT ---
|
||||||
let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
||||||
|
|
||||||
eb = eb.with(Name { name: item_template.name.name.clone(), plural: item_template.name.plural.clone() });
|
eb = eb.with(Name {
|
||||||
eb = eb.with(Item { weight: item_template.weight.unwrap_or(0.0), value: item_template.value.unwrap_or(0.0) });
|
name: item_template.name.name.clone(),
|
||||||
|
plural: item_template.name.plural.clone(),
|
||||||
|
});
|
||||||
|
eb = eb.with(Item {
|
||||||
|
weight: item_template.weight.unwrap_or(0.0),
|
||||||
|
value: item_template.value.unwrap_or(0.0),
|
||||||
|
});
|
||||||
eb = spawn_position(pos, eb, key, raws);
|
eb = spawn_position(pos, eb, key, raws);
|
||||||
|
|
||||||
if let Some(renderable) = &item_template.renderable {
|
if let Some(renderable) = &item_template.renderable {
|
||||||
|
|
@ -379,7 +385,11 @@ pub fn spawn_named_mob(
|
||||||
eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
||||||
eb = spawn_position(pos, eb, key, raws);
|
eb = spawn_position(pos, eb, key, raws);
|
||||||
eb = eb.with(Name { name: mob_template.name.clone(), plural: mob_template.name.clone() });
|
eb = eb.with(Name { name: mob_template.name.clone(), plural: mob_template.name.clone() });
|
||||||
eb = eb.with(Viewshed { visible_tiles: Vec::new(), range: mob_template.vision_range as i32, dirty: true });
|
eb = eb.with(Viewshed {
|
||||||
|
visible_tiles: Vec::new(),
|
||||||
|
range: mob_template.vision_range as i32,
|
||||||
|
dirty: true,
|
||||||
|
});
|
||||||
if let Some(telepath) = &mob_template.telepathy_range {
|
if let Some(telepath) = &mob_template.telepathy_range {
|
||||||
eb = eb.with(Telepath { telepath_tiles: Vec::new(), range: *telepath, dirty: true });
|
eb = eb.with(Telepath { telepath_tiles: Vec::new(), range: *telepath, dirty: true });
|
||||||
}
|
}
|
||||||
|
|
@ -447,7 +457,11 @@ pub fn spawn_named_mob(
|
||||||
let speed = if mob_template.speed.is_some() { mob_template.speed.unwrap() } else { 12 };
|
let speed = if mob_template.speed.is_some() { mob_template.speed.unwrap() } else { 12 };
|
||||||
eb = eb.with(Energy { current: 0, speed: speed });
|
eb = eb.with(Energy { current: 0, speed: speed });
|
||||||
|
|
||||||
let base_mob_level = if mob_template.level.is_some() { mob_template.level.unwrap() } else { 0 };
|
let base_mob_level = if mob_template.level.is_some() {
|
||||||
|
mob_template.level.unwrap()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
let mut mob_level = base_mob_level;
|
let mut mob_level = base_mob_level;
|
||||||
// If the level difficulty is smaller than the mob's base level, subtract 1;
|
// If the level difficulty is smaller than the mob's base level, subtract 1;
|
||||||
// else, if the level difficulty is larger, add one-fifth of the difference
|
// else, if the level difficulty is larger, add one-fifth of the difference
|
||||||
|
|
@ -464,7 +478,7 @@ pub fn spawn_named_mob(
|
||||||
mob_level = i32::min(mob_level, (1.5 * (base_mob_level as f32)).trunc() as i32);
|
mob_level = i32::min(mob_level, (1.5 * (base_mob_level as f32)).trunc() as i32);
|
||||||
|
|
||||||
// Should really use existing RNG here
|
// Should really use existing RNG here
|
||||||
let mut rng = rltk::RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
let mob_hp = npc_hp_at_level(&mut rng, mob_con, mob_level);
|
let mob_hp = npc_hp_at_level(&mut rng, mob_con, mob_level);
|
||||||
let mob_mana = mana_at_level(&mut rng, mob_int, mob_level);
|
let mob_mana = mana_at_level(&mut rng, mob_int, mob_level);
|
||||||
let mob_bac = if mob_template.bac.is_some() { mob_template.bac.unwrap() } else { 10 };
|
let mob_bac = if mob_template.bac.is_some() { mob_template.bac.unwrap() } else { 10 };
|
||||||
|
|
@ -497,7 +511,7 @@ pub fn spawn_named_mob(
|
||||||
skills.skills.insert(Skill::Magic, *sk.1);
|
skills.skills.insert(Skill::Magic, *sk.1);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
rltk::console::log(format!("Unknown skill referenced: [{}]", sk.0));
|
console::log(format!("Unknown skill referenced: [{}]", sk.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -548,7 +562,7 @@ pub fn spawn_named_mob(
|
||||||
}
|
}
|
||||||
|
|
||||||
if CONFIG.logging.log_spawning {
|
if CONFIG.logging.log_spawning {
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!(
|
format!(
|
||||||
"SPAWNLOG: {} ({}HP, {}MANA, {}BAC) spawned at level {} ({}[base], {}[map difficulty], {}[player level]), worth {} XP",
|
"SPAWNLOG: {} ({}HP, {}MANA, {}BAC) spawned at level {} ({}[base], {}[map difficulty], {}[player level]), worth {} XP",
|
||||||
&mob_template.name,
|
&mob_template.name,
|
||||||
|
|
@ -569,7 +583,14 @@ pub fn spawn_named_mob(
|
||||||
// Build entity, then check for anything they're wearing
|
// Build entity, then check for anything they're wearing
|
||||||
if let Some(wielding) = &mob_template.equipped {
|
if let Some(wielding) = &mob_template.equipped {
|
||||||
for tag in wielding.iter() {
|
for tag in wielding.iter() {
|
||||||
spawn_named_entity(raws, ecs, tag, None, SpawnType::Equipped { by: new_mob }, map_difficulty);
|
spawn_named_entity(
|
||||||
|
raws,
|
||||||
|
ecs,
|
||||||
|
tag,
|
||||||
|
None,
|
||||||
|
SpawnType::Equipped { by: new_mob },
|
||||||
|
map_difficulty
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -578,7 +599,12 @@ pub fn spawn_named_mob(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_named_prop(raws: &RawMaster, ecs: &mut World, key: &str, pos: SpawnType) -> Option<Entity> {
|
pub fn spawn_named_prop(
|
||||||
|
raws: &RawMaster,
|
||||||
|
ecs: &mut World,
|
||||||
|
key: &str,
|
||||||
|
pos: SpawnType
|
||||||
|
) -> Option<Entity> {
|
||||||
if raws.prop_index.contains_key(key) {
|
if raws.prop_index.contains_key(key) {
|
||||||
// ENTITY BUILDER PREP
|
// ENTITY BUILDER PREP
|
||||||
let prop_template = &raws.raws.props[raws.prop_index[key]];
|
let prop_template = &raws.raws.props[raws.prop_index[key]];
|
||||||
|
|
@ -610,7 +636,12 @@ pub fn spawn_named_prop(raws: &RawMaster, ecs: &mut World, key: &str, pos: Spawn
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_position<'a>(pos: SpawnType, new_entity: EntityBuilder<'a>, tag: &str, raws: &RawMaster) -> EntityBuilder<'a> {
|
fn spawn_position<'a>(
|
||||||
|
pos: SpawnType,
|
||||||
|
new_entity: EntityBuilder<'a>,
|
||||||
|
tag: &str,
|
||||||
|
raws: &RawMaster
|
||||||
|
) -> EntityBuilder<'a> {
|
||||||
let mut eb = new_entity;
|
let mut eb = new_entity;
|
||||||
|
|
||||||
match pos {
|
match pos {
|
||||||
|
|
@ -629,11 +660,13 @@ fn spawn_position<'a>(pos: SpawnType, new_entity: EntityBuilder<'a>, tag: &str,
|
||||||
eb
|
eb
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_renderable_component(renderable: &super::item_structs::Renderable) -> crate::components::Renderable {
|
fn get_renderable_component(
|
||||||
|
renderable: &super::item_structs::Renderable
|
||||||
|
) -> crate::components::Renderable {
|
||||||
crate::components::Renderable {
|
crate::components::Renderable {
|
||||||
glyph: rltk::to_cp437(renderable.glyph.chars().next().unwrap()),
|
glyph: to_cp437(renderable.glyph.chars().next().unwrap()),
|
||||||
fg: rltk::RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
|
fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
|
||||||
bg: rltk::RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
|
bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
|
||||||
render_order: renderable.order,
|
render_order: renderable.order,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -668,7 +701,7 @@ pub fn table_by_name(raws: &RawMaster, key: &str, optional_difficulty: Option<i3
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rltk::console::log(
|
console::log(
|
||||||
format!(
|
format!(
|
||||||
"DEBUGINFO: Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}]. Returned debug entry.",
|
"DEBUGINFO: Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}]. Returned debug entry.",
|
||||||
key,
|
key,
|
||||||
|
|
@ -741,7 +774,11 @@ fn find_slot_for_equippable_item(tag: &str, raws: &RawMaster) -> EquipmentSlot {
|
||||||
panic!("Trying to equip {}, but it has no slot tag.", tag);
|
panic!("Trying to equip {}, but it has no slot tag.", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn roll_on_loot_table(raws: &RawMaster, rng: &mut RandomNumberGenerator, key: &str) -> Option<String> {
|
pub fn roll_on_loot_table(
|
||||||
|
raws: &RawMaster,
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
key: &str
|
||||||
|
) -> Option<String> {
|
||||||
if raws.loot_index.contains_key(key) {
|
if raws.loot_index.contains_key(key) {
|
||||||
console::log(format!("DEBUGINFO: Rolling on loot table: {}", key));
|
console::log(format!("DEBUGINFO: Rolling on loot table: {}", key));
|
||||||
let mut rt = RandomTable::new();
|
let mut rt = RandomTable::new();
|
||||||
|
|
@ -792,7 +829,11 @@ pub fn get_mob_spawn_type(raws: &RawMaster, key: &str) -> SpawnsAs {
|
||||||
return SpawnsAs::Single;
|
return SpawnsAs::Single;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mob_spawn_amount(rng: &mut RandomNumberGenerator, spawn_type: &SpawnsAs, player_level: i32) -> i32 {
|
pub fn get_mob_spawn_amount(
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
spawn_type: &SpawnsAs,
|
||||||
|
player_level: i32
|
||||||
|
) -> i32 {
|
||||||
let n = match spawn_type {
|
let n = match spawn_type {
|
||||||
// Single mobs always spawn alone.
|
// Single mobs always spawn alone.
|
||||||
SpawnsAs::Single => 1,
|
SpawnsAs::Single => 1,
|
||||||
|
|
@ -893,7 +934,11 @@ pub fn faction_reaction(this_faction: &str, other_faction: &str, raws: &RawMaste
|
||||||
return Reaction::Ignore;
|
return Reaction::Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ancestry_reaction(this_ancestry: Ancestry, other_ancestry: Ancestry, raws: &RawMaster) -> Option<Reaction> {
|
pub fn ancestry_reaction(
|
||||||
|
this_ancestry: Ancestry,
|
||||||
|
other_ancestry: Ancestry,
|
||||||
|
raws: &RawMaster
|
||||||
|
) -> Option<Reaction> {
|
||||||
if this_ancestry == other_ancestry {
|
if this_ancestry == other_ancestry {
|
||||||
return Some(Reaction::Ignore);
|
return Some(Reaction::Ignore);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use rltk::rex::XpFile;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
rltk::embedded_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
|
embedded_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
|
||||||
rltk::embedded_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
|
embedded_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
|
||||||
rltk::embedded_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
|
embedded_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
|
||||||
|
|
||||||
pub struct RexAssets {
|
pub struct RexAssets {
|
||||||
pub menu: XpFile,
|
pub menu: XpFile,
|
||||||
|
|
@ -11,9 +11,9 @@ pub struct RexAssets {
|
||||||
impl RexAssets {
|
impl RexAssets {
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
pub fn new() -> RexAssets {
|
pub fn new() -> RexAssets {
|
||||||
rltk::link_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
|
link_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
|
||||||
rltk::link_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
|
link_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
|
||||||
rltk::link_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
|
link_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
|
||||||
|
|
||||||
RexAssets { menu: XpFile::from_resource("../resources/title_image.xp").unwrap() }
|
RexAssets { menu: XpFile::from_resource("../resources/title_image.xp").unwrap() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use super::components::*;
|
use super::components::*;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use specs::error::NoError;
|
use specs::error::NoError;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{
|
use specs::saveload::{
|
||||||
|
|
@ -293,8 +294,8 @@ pub fn load_game(ecs: &mut World) {
|
||||||
crate::gamelog::restore_events(h.events.clone());
|
crate::gamelog::restore_events(h.events.clone());
|
||||||
}
|
}
|
||||||
for (e, _p, pos) in (&entities, &player, &position).join() {
|
for (e, _p, pos) in (&entities, &player, &position).join() {
|
||||||
let mut ppos = ecs.write_resource::<rltk::Point>();
|
let mut ppos = ecs.write_resource::<Point>();
|
||||||
*ppos = rltk::Point::new(pos.x, pos.y);
|
*ppos = Point::new(pos.x, pos.y);
|
||||||
let mut player_resource = ecs.write_resource::<Entity>();
|
let mut player_resource = ecs.write_resource::<Entity>();
|
||||||
*player_resource = e;
|
*player_resource = e;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ use super::{
|
||||||
SerializeMe,
|
SerializeMe,
|
||||||
Skill,
|
Skill,
|
||||||
Skills,
|
Skills,
|
||||||
TileType,
|
|
||||||
tile_walkable,
|
tile_walkable,
|
||||||
Viewshed,
|
Viewshed,
|
||||||
BlocksTile,
|
BlocksTile,
|
||||||
|
|
@ -30,7 +29,7 @@ use super::{
|
||||||
use crate::data::entity;
|
use crate::data::entity;
|
||||||
use crate::data::visuals::BLOODSTAIN_COLOUR;
|
use crate::data::visuals::BLOODSTAIN_COLOUR;
|
||||||
use crate::gamesystem::*;
|
use crate::gamesystem::*;
|
||||||
use rltk::{ RandomNumberGenerator, RGB };
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{ MarkedBuilder, SimpleMarker };
|
use specs::saveload::{ MarkedBuilder, SimpleMarker };
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -52,9 +51,9 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
.with(Position { x: player_x, y: player_y })
|
.with(Position { x: player_x, y: player_y })
|
||||||
.with(BlocksTile {})
|
.with(BlocksTile {})
|
||||||
.with(Renderable {
|
.with(Renderable {
|
||||||
glyph: rltk::to_cp437('@'),
|
glyph: to_cp437('@'),
|
||||||
fg: RGB::named(rltk::YELLOW),
|
fg: RGB::named(YELLOW),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(BLACK),
|
||||||
render_order: 0,
|
render_order: 0,
|
||||||
})
|
})
|
||||||
.with(Bleeds { colour: RGB::named(BLOODSTAIN_COLOUR) })
|
.with(Bleeds { colour: RGB::named(BLOODSTAIN_COLOUR) })
|
||||||
|
|
@ -132,7 +131,7 @@ pub fn spawn_region(
|
||||||
let difficulty = (map.difficulty + player_level) / 2;
|
let difficulty = (map.difficulty + player_level) / 2;
|
||||||
// If no area, log and return.
|
// If no area, log and return.
|
||||||
if areas.len() == 0 {
|
if areas.len() == 0 {
|
||||||
rltk::console::log("DEBUGINFO: No areas capable of spawning mobs!");
|
console::log("DEBUGINFO: No areas capable of spawning mobs!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get num of each entity type.
|
// Get num of each entity type.
|
||||||
|
|
@ -212,7 +211,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rltk::console::log(format!("WARNING: We don't know how to spawn [{}]!", spawn.1));
|
console::log(format!("WARNING: We don't know how to spawn [{}]!", spawn.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 scrolls : 3 potions : 1 equipment : 1 wand?
|
// 3 scrolls : 3 potions : 1 equipment : 1 wand?
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use super::runstate::RunState;
|
use super::runstate::RunState;
|
||||||
use crate::map::*;
|
use crate::map::*;
|
||||||
use crate::hunger_system;
|
use crate::hunger_system;
|
||||||
|
|
@ -125,7 +125,7 @@ impl State {
|
||||||
.append("You head to")
|
.append("You head to")
|
||||||
.colour(rgb_to_u8(get_local_col(id)))
|
.colour(rgb_to_u8(get_local_col(id)))
|
||||||
.append_n(&mapname)
|
.append_n(&mapname)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period()
|
.period()
|
||||||
.log();
|
.log();
|
||||||
gamelog::record_event(EVENT::CHANGED_FLOOR(mapname));
|
gamelog::record_event(EVENT::CHANGED_FLOOR(mapname));
|
||||||
|
|
@ -157,7 +157,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameState for State {
|
impl GameState for State {
|
||||||
fn tick(&mut self, ctx: &mut Rltk) {
|
fn tick(&mut self, ctx: &mut BTerm) {
|
||||||
let mut new_runstate;
|
let mut new_runstate;
|
||||||
{
|
{
|
||||||
let runstate = self.ecs.fetch::<RunState>();
|
let runstate = self.ecs.fetch::<RunState>();
|
||||||
|
|
@ -581,6 +581,6 @@ impl GameState for State {
|
||||||
|
|
||||||
damage_system::delete_the_dead(&mut self.ecs);
|
damage_system::delete_the_dead(&mut self.ecs);
|
||||||
|
|
||||||
let _ = rltk::render_draw_buffer(ctx);
|
let _ = render_draw_buffer(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use super::{
|
||||||
Renderable,
|
Renderable,
|
||||||
AOE,
|
AOE,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct TriggerSystem {}
|
pub struct TriggerSystem {}
|
||||||
|
|
@ -30,7 +30,8 @@ impl<'a> System<'a> for TriggerSystem {
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (map, mut entity_moved, position, entry_trigger, names, entities, aoes, renderables) = data;
|
let (map, mut entity_moved, position, entry_trigger, names, entities, aoes, renderables) =
|
||||||
|
data;
|
||||||
for (entity, mut _entity_moved, pos) in (&entities, &mut entity_moved, &position).join() {
|
for (entity, mut _entity_moved, pos) in (&entities, &mut entity_moved, &position).join() {
|
||||||
let idx = map.xy_idx(pos.x, pos.y);
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
crate::spatial::for_each_tile_content(idx, |entity_id| {
|
crate::spatial::for_each_tile_content(idx, |entity_id| {
|
||||||
|
|
@ -51,15 +52,21 @@ impl<'a> System<'a> for TriggerSystem {
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
add_effect(Some(entity_id), EffectType::TriggerFire { trigger: entity_id }, if
|
add_effect(
|
||||||
let Some(aoe) = aoes.get(entity_id)
|
Some(entity_id),
|
||||||
{
|
EffectType::TriggerFire { trigger: entity_id },
|
||||||
|
if let Some(aoe) = aoes.get(entity_id) {
|
||||||
Targets::TileList {
|
Targets::TileList {
|
||||||
targets: aoe_tiles(&*map, Point::new(pos.x, pos.y), aoe.radius),
|
targets: aoe_tiles(
|
||||||
|
&*map,
|
||||||
|
Point::new(pos.x, pos.y),
|
||||||
|
aoe.radius
|
||||||
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Targets::Tile { target: idx }
|
Targets::Tile { target: idx }
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ use super::{
|
||||||
Renderable,
|
Renderable,
|
||||||
gui::renderable_colour,
|
gui::renderable_colour,
|
||||||
};
|
};
|
||||||
use rltk::{ FieldOfViewAlg::SymmetricShadowcasting, Point };
|
use bracket_lib::prelude::*;
|
||||||
|
use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct VisibilitySystem {}
|
pub struct VisibilitySystem {}
|
||||||
|
|
@ -22,7 +23,7 @@ const BLIND_TELEPATHY_RANGE_MULTIPLIER: i32 = 3;
|
||||||
impl<'a> System<'a> for VisibilitySystem {
|
impl<'a> System<'a> for VisibilitySystem {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
WriteExpect<'a, Map>,
|
WriteExpect<'a, Map>,
|
||||||
WriteExpect<'a, rltk::RandomNumberGenerator>,
|
WriteExpect<'a, RandomNumberGenerator>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
WriteStorage<'a, Viewshed>,
|
WriteStorage<'a, Viewshed>,
|
||||||
WriteStorage<'a, Telepath>,
|
WriteStorage<'a, Telepath>,
|
||||||
|
|
@ -73,7 +74,7 @@ impl<'a> System<'a> for VisibilitySystem {
|
||||||
p.y >= 0 &&
|
p.y >= 0 &&
|
||||||
p.y < map.height &&
|
p.y < map.height &&
|
||||||
(map.lit_tiles[map.xy_idx(p.x, p.y)] == true ||
|
(map.lit_tiles[map.xy_idx(p.x, p.y)] == true ||
|
||||||
rltk::DistanceAlg::Pythagoras.distance2d(Point::new(p.x, p.y), origin) < 1.5)
|
DistanceAlg::Pythagoras.distance2d(Point::new(p.x, p.y), origin) < 1.5)
|
||||||
});
|
});
|
||||||
|
|
||||||
// If this is the player, reveal what they can see
|
// If this is the player, reveal what they can see
|
||||||
|
|
@ -99,7 +100,7 @@ impl<'a> System<'a> for VisibilitySystem {
|
||||||
.append("You spot a")
|
.append("You spot a")
|
||||||
.colour(renderable_colour(&renderables, e))
|
.colour(renderable_colour(&renderables, e))
|
||||||
.append_n(&name.name)
|
.append_n(&name.name)
|
||||||
.colour(rltk::WHITE)
|
.colour(WHITE)
|
||||||
.period()
|
.period()
|
||||||
.log();
|
.log();
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +121,9 @@ impl<'a> System<'a> for VisibilitySystem {
|
||||||
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
|
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
|
||||||
}
|
}
|
||||||
telepath.telepath_tiles = fast_fov(pos.x, pos.y, range);
|
telepath.telepath_tiles = fast_fov(pos.x, pos.y, range);
|
||||||
telepath.telepath_tiles.retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height);
|
telepath.telepath_tiles.retain(
|
||||||
|
|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height
|
||||||
|
);
|
||||||
|
|
||||||
// If this is the player, reveal what they can see
|
// If this is the player, reveal what they can see
|
||||||
let _p: Option<&Player> = player.get(ent);
|
let _p: Option<&Player> = player.get(ent);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue