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:
Llywelwyn 2023-09-05 02:23:31 +01:00
parent 455b8f2d80
commit 85efe13dc5
93 changed files with 1528 additions and 770 deletions

View file

@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rltk = { version = "^0.8.7", features = ["serde"] }
bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git", rev = "851f6f08675444fb6fa088b9e67bee9fd75554c6", features = ["serde"] }
regex = "1.3.6"
specs = { version = "0.16.1", features = ["serde"] }

View file

@ -1,5 +1,5 @@
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.
// Greyscale is significantly faster, but generally looks worse - the

View file

@ -1,5 +1,5 @@
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToApproach };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct ApproachAI {}
@ -39,7 +39,9 @@ impl<'a> System<'a> for ApproachAI {
&turns,
).join() {
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
} else {
continue;
@ -47,9 +49,12 @@ impl<'a> System<'a> for ApproachAI {
let mut path: Option<NavigationPath> = None;
let idx = map.xy_idx(pos.x, pos.y);
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 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);
}
}

View file

@ -1,5 +1,5 @@
use crate::{ Chasing, EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::HashMap;
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) {
let (mut turns, mut chasing, mut positions, mut map, mut viewsheds, mut telepaths, mut entity_moved, entities) =
data;
let (
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 end_chase: Vec<Entity> = Vec::new();
// 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 idx = map.xy_idx(pos.x, pos.y);
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 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);
}
}

View file

@ -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 bracket_lib::prelude::*;
// 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
@ -16,7 +27,7 @@ impl<'a> System<'a> for DefaultAI {
WriteStorage<'a, Viewshed>,
WriteStorage<'a, Telepath>,
WriteStorage<'a, EntityMoved>,
WriteExpect<'a, rltk::RandomNumberGenerator>,
WriteExpect<'a, RandomNumberGenerator>,
Entities<'a>,
);
@ -85,7 +96,9 @@ impl<'a> System<'a> for DefaultAI {
let idx = map.xy_idx(pos.x, pos.y);
pos.x = x;
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);
viewshed.dirty = true;
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) {
pos.x = (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);
crate::spatial::move_entity(entity, idx, new_idx);
viewshed.dirty = true;
@ -112,7 +127,7 @@ impl<'a> System<'a> for DefaultAI {
path.remove(0);
} else {
// 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(
(path[path.len() - 1] as i32) % map.width,
@ -121,7 +136,9 @@ impl<'a> System<'a> for DefaultAI {
&mut *map
);
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 {
@ -132,7 +149,7 @@ impl<'a> System<'a> for DefaultAI {
let target_y = rng.roll_dice(1, map.height - 2);
let idx = map.xy_idx(target_x, target_y);
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(target_x, target_y) as i32,
&mut *map

View file

@ -11,7 +11,7 @@ use crate::{
TakingTurn,
Confusion,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::config::CONFIG;
use crate::data::events::*;
@ -126,7 +126,7 @@ impl<'a> System<'a> for EnergySystem {
if entity == *player {
*runstate = RunState::AwaitingInput;
} else {
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
let distance = DistanceAlg::Pythagoras.distance2d(
*player_pos,
Point::new(pos.x, pos.y)
);

View file

@ -1,5 +1,5 @@
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToFlee };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct FleeAI {}
@ -39,7 +39,13 @@ impl<'a> System<'a> for FleeAI {
turn_done.push(entity);
let my_idx = map.xy_idx(pos.x, pos.y);
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);
if let Some(flee_target) = flee_target {
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.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");
}
}
}

View file

@ -1,5 +1,5 @@
use crate::{ gamelog, gui::renderable_colour, Name, Quips, Renderable, TakingTurn, Viewshed };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct QuipSystem {}
@ -19,8 +19,18 @@ impl<'a> System<'a> for QuipSystem {
fn run(&mut self, data: Self::SystemData) {
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() {
if !quip.available.is_empty() && viewshed.visible_tiles.contains(&player_pos) && rng.roll_dice(1, 6) == 1 {
for (entity, quip, name, viewshed, _turn) in (
&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 {
0
} else {

View file

@ -10,7 +10,7 @@ use crate::{
Item,
Prop,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::data::events::*;

View file

@ -12,7 +12,7 @@ use crate::{
WantsToApproach,
WantsToFlee,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::HashSet;
@ -81,10 +81,16 @@ impl<'a> System<'a> for VisibleAI {
}
reactions.sort_by(|(a, _, _), (b, _, _)| {
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 (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;
return dist_b_estimate.cmp(&dist_a_estimate);
});
@ -96,7 +102,9 @@ impl<'a> System<'a> for VisibleAI {
wants_to_approach
.insert(entity, WantsToApproach { idx: reaction.0 as i32 })
.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;
}
}
@ -108,7 +116,9 @@ impl<'a> System<'a> for VisibleAI {
}
}
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");
}
}
}

View file

@ -1,11 +1,11 @@
use super::{ Hidden, Map, Mind, Position, Prop, Renderable };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::ops::Mul;
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 map = ecs.fetch::<Map>();
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)
}
pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
let map = ecs.fetch::<Map>();
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);
}
} 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;
}
@ -112,14 +118,20 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
}
}
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 (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 {
let idx = map.xy_idx(tx, ty);
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);
}
} 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;
}

View file

@ -1,6 +1,6 @@
use crate::gui::Ancestry;
use crate::gui::Class;
use rltk::RGB;
use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize };
use specs::error::NoError;
use specs::prelude::*;
@ -40,7 +40,7 @@ pub struct OtherLevelPosition {
#[derive(Component, ConvertSaveload, Clone)]
pub struct Renderable {
pub glyph: rltk::FontCharType,
pub glyph: FontCharType,
pub fg: RGB,
pub bg: RGB,
pub render_order: i32,
@ -104,14 +104,14 @@ pub struct Mind {}
#[derive(Component, ConvertSaveload, Clone)]
pub struct Viewshed {
pub visible_tiles: Vec<rltk::Point>,
pub visible_tiles: Vec<Point>,
pub range: i32,
pub dirty: bool,
}
#[derive(Component, ConvertSaveload, Clone)]
pub struct Telepath {
pub telepath_tiles: Vec<rltk::Point>,
pub telepath_tiles: Vec<Point>,
pub range: i32,
pub dirty: bool,
}
@ -417,7 +417,7 @@ pub struct WantsToRemoveItem {
#[derive(Component, Debug, ConvertSaveload)]
pub struct WantsToUseItem {
pub item: Entity,
pub target: Option<rltk::Point>,
pub target: Option<Point>,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
@ -446,8 +446,8 @@ pub struct Charges {
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct SpawnParticleLine {
pub glyph: rltk::FontCharType,
pub tail_glyph: rltk::FontCharType,
pub glyph: FontCharType,
pub tail_glyph: FontCharType,
pub colour: RGB,
pub lifetime_ms: f32,
pub trail_colour: RGB,
@ -456,16 +456,16 @@ pub struct SpawnParticleLine {
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct SpawnParticleSimple {
pub glyph: rltk::FontCharType,
pub glyph: FontCharType,
pub colour: RGB,
pub lifetime_ms: f32,
}
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct SpawnParticleBurst {
pub glyph: rltk::FontCharType,
pub head_glyph: rltk::FontCharType,
pub tail_glyph: rltk::FontCharType,
pub glyph: FontCharType,
pub head_glyph: FontCharType,
pub tail_glyph: FontCharType,
pub colour: RGB,
pub lerp: RGB,
pub lifetime_ms: f32,

View file

@ -1,4 +1,4 @@
use rltk::prelude::*;
use bracket_lib::prelude::*;
use toml::Value;
use serde::{ Serialize, Deserialize };

View file

@ -12,7 +12,7 @@ use super::{
Renderable,
RunState,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::data::events;
@ -40,7 +40,7 @@ pub fn delete_the_dead(ecs: &mut World) {
.append("The")
.colour(renderable_colour(&renderables, entity))
.append(&victim_name.name)
.colour(rltk::WHITE)
.colour(WHITE)
.append("is destroyed!")
.log();
} else {
@ -49,7 +49,7 @@ pub fn delete_the_dead(ecs: &mut World) {
.append("The")
.colour(renderable_colour(&renderables, entity))
.append(&victim_name.name)
.colour(rltk::WHITE)
.colour(WHITE)
.append("dies!")
.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_spawn: Vec<(String, Position)> = Vec::new();
let entities = ecs.entities();

View file

@ -1,6 +1,6 @@
use super::names::*;
use super::visuals::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
pub const ID_OVERMAP: i32 = 1;

View file

@ -1,3 +1,5 @@
use bracket_lib::prelude::*;
// 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.
@ -15,8 +17,8 @@ pub const SHORT_PARTICLE_LIFETIME: f32 = 100.0; // in ms
pub const DEFAULT_PARTICLE_LIFETIME: f32 = 200.0;
pub const LONG_PARTICLE_LIFETIME: f32 = 300.0;
pub const TARGETING_CURSOR_COL: (u8, u8, u8) = rltk::GOLDENROD;
pub const TARGETING_LINE_COL: (u8, u8, u8) = rltk::LIGHTGOLDENROD;
pub const TARGETING_CURSOR_COL: (u8, u8, u8) = GOLDENROD;
pub const TARGETING_LINE_COL: (u8, u8, u8) = LIGHTGOLDENROD;
pub const TARGETING_AOE_COL: (u8, u8, u8) = (20, 20, 20);
pub const TARGETING_VALID_COL: (u8, u8, u8) = (10, 10, 10);

View file

@ -20,7 +20,7 @@ use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME };
use crate::data::messages::LEVELUP_PLAYER;
use crate::data::events::*;
use crate::data::messages::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {

View file

@ -1,6 +1,6 @@
use super::BUC;
use crate::spatial;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::VecDeque;
use std::sync::Mutex;

View file

@ -1,6 +1,6 @@
use super::{ add_effect, targeting, EffectSpawner, EffectType, Targets };
use crate::{ Map, ParticleBuilder, SpawnParticleBurst, SpawnParticleLine, SpawnParticleSimple };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
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 mut particle_builder = ecs.fetch_mut::<ParticleBuilder>();
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 {
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(start_pos) = targeting::find_item_position(ecs, entity) {
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.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 } => {
if let Some(end_pos) = targeting::entity_position(ecs, *target) {

View file

@ -1,5 +1,5 @@
use crate::{ Equipped, InBackpack, Map, Position };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
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;
}
pub fn aoe_tiles(map: &Map, target: rltk::Point, radius: i32) -> Vec<usize> {
let mut blast_tiles = rltk::field_of_view(target, radius, &*map);
pub fn aoe_tiles(map: &Map, target: Point, radius: i32) -> Vec<usize> {
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);
let mut result = Vec::new();
for t in blast_tiles.iter() {

View file

@ -36,7 +36,7 @@ use crate::{
Viewshed,
};
use crate::data::messages::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub fn item_trigger(source: Option<Entity>, item: Entity, target: &Targets, ecs: &mut World) {
// 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();
return;
}
gamelog::Logger::new().colour(rltk::YELLOW).append(NOCHARGES_WREST);
ecs.write_storage::<Consumable>().insert(item, Consumable {}).expect("Could not insert consumable");
gamelog::Logger::new().colour(YELLOW).append(NOCHARGES_WREST);
ecs.write_storage::<Consumable>()
.insert(item, Consumable {})
.expect("Could not insert consumable");
}
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
// 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.
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) {
beatitude.buc.clone()
} else {
@ -147,7 +154,11 @@ fn handle_restore_nutrition(
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() {
let mut runstate = ecs.fetch_mut::<RunState>();
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);
}
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(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.
} else {
// 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);
}
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) {
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
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,
_ => 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(
event.source,
EffectType::Healing { amount: roll, increment_max: get_noncursed(&event.buc) },
event.target.clone()
);
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;
}
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);
}
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) {
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
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)
.append(DAMAGE_PLAYER_HIT);
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::<Destructible>().get(target).is_some() {
logger = logger
@ -259,9 +293,17 @@ fn handle_damage(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Lo
}
#[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) {
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, false);
@ -272,7 +314,11 @@ fn select_single(ecs: &World, 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) {
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
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())
.map(|b| b.known)
.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()));
}
@ -313,14 +362,20 @@ fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::
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;
return (logger, true);
}
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) {
let mut to_decurse: Vec<Entity> = Vec::new();
match event.buc {
@ -338,7 +393,9 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
&ecs.read_storage::<Beatitude>(),
)
.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);
}
}
@ -367,7 +424,9 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
}
let mut beatitudes = ecs.write_storage::<Beatitude>();
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));
event.log = true;

View file

@ -1,6 +1,6 @@
use super::{ append_entry, LogFragment };
use crate::BUC;
use rltk::prelude::*;
use bracket_lib::prelude::*;
pub struct Logger {
current_colour: RGB,
@ -10,7 +10,7 @@ pub struct Logger {
impl Logger {
/// Creates a blank builder for making message log entries.
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.
@ -42,11 +42,23 @@ impl Logger {
pub fn buc<T: ToString>(mut self, buc: BUC, cursed: Option<T>, blessed: Option<T>) -> Self {
if buc == BUC::Cursed && cursed.is_some() {
self.fragments.push(LogFragment { colour: RGB::named(SALMON), text: cursed.unwrap().to_string() });
self.fragments.push(LogFragment { colour: self.current_colour, text: ". ".to_string() });
self.fragments.push(LogFragment {
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() {
self.fragments.push(LogFragment { colour: RGB::named(CYAN), text: blessed.unwrap().to_string() });
self.fragments.push(LogFragment { colour: self.current_colour, text: ". ".to_string() });
self.fragments.push(LogFragment {
colour: RGB::named(CYAN),
text: blessed.unwrap().to_string(),
});
self.fragments.push(LogFragment {
colour: self.current_colour,
text: ". ".to_string(),
});
}
return self;
}

View file

@ -1,5 +1,5 @@
use super::{ events, LogFragment, Logger };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use std::sync::Mutex;
lazy_static! {
@ -19,7 +19,13 @@ pub fn clear_log() {
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 x = pos.x;
// 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
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;
}
@ -80,7 +92,7 @@ pub fn setup_log() {
Logger::new()
.append("Welcome!")
.colour(rltk::CYAN)
.colour(CYAN)
.append_n("Press [?] at any time to view controls")
.period()
.log();

View file

@ -7,7 +7,7 @@ mod events;
pub use events::*;
use serde::{ Deserialize, Serialize };
use rltk::prelude::*;
use bracket_lib::prelude::*;
#[derive(Serialize, Deserialize, Clone)]
pub struct LogFragment {
pub colour: RGB,

View file

@ -2,7 +2,7 @@ use super::{ Skill, Skills };
use crate::gui::{ Ancestry, Class };
use crate::data::entity;
use crate::data::char_create::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use std::cmp::max;
/// 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.
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);
}
#[allow(dead_code)]
/// 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);
for _i in 0..level {
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.
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 {
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.
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);
}
/// 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;
for _i in 0..level {
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
#[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();
for _i in 0..4 {
rolls.push(rng.roll_dice(1, 6));

View file

@ -24,7 +24,7 @@ use crate::{
Telepath,
BUC,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize };
use specs::prelude::*;
use std::collections::HashMap;
@ -111,14 +111,14 @@ pub enum CharCreateResult {
}
/// 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 mut x = 2;
let mut y = 11;
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;
if let RunState::CharacterCreation { ancestry, class } = *runstate {
@ -269,9 +269,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
Ancestry::Dwarf => {
renderables
.insert(*player, Renderable {
glyph: rltk::to_cp437(DWARF_GLYPH),
glyph: to_cp437(DWARF_GLYPH),
fg: RGB::named(DWARF_COLOUR),
bg: RGB::named(rltk::BLACK),
bg: RGB::named(BLACK),
render_order: 0,
})
.expect("Unable to insert renderable component");
@ -280,9 +280,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
Ancestry::Elf => {
renderables
.insert(*player, Renderable {
glyph: rltk::to_cp437(ELF_GLYPH),
glyph: to_cp437(ELF_GLYPH),
fg: RGB::named(ELF_COLOUR),
bg: RGB::named(rltk::BLACK),
bg: RGB::named(BLACK),
render_order: 0,
})
.expect("Unable to insert renderable component");
@ -305,9 +305,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
Ancestry::Catfolk => {
renderables
.insert(*player, Renderable {
glyph: rltk::to_cp437(CATFOLK_GLYPH),
glyph: to_cp437(CATFOLK_GLYPH),
fg: RGB::named(CATFOLK_COLOUR),
bg: RGB::named(rltk::BLACK),
bg: RGB::named(BLACK),
render_order: 0,
})
.expect("Unable to insert renderable component");
@ -451,11 +451,11 @@ fn pick_random_table_item(
rng: &mut RandomNumberGenerator,
push_to: &mut Vec<String>,
table: &'static str,
dice: &'static str,
dice_str: &'static str,
difficulty: Option<i32>
) {
let (n, d, m) = raws::parse_dice_string(dice);
for _i in 0..rng.roll_dice(n, d) + m {
let dice = parse_dice_string(dice_str).expect("Error parsing dice");
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));
}
}

View file

@ -1,5 +1,5 @@
use super::State;
use rltk::prelude::*;
use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)]
pub enum CheatMenuResult {
@ -12,13 +12,13 @@ pub enum CheatMenuResult {
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);
ctx.print_color(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::RED),
RGB::named(rltk::BLACK),
RGB::named(RED),
RGB::named(BLACK),
"DEBUG MENU! [aA-zZ][Esc.]"
);
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 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;
// 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");
y += 1;
// 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");
y += 1;
// 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");
y += 1;
// 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");
y += 1;
// 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");
// Match keys
match ctx.key {

View file

@ -1,5 +1,5 @@
use super::{ State, RunState, tooltip::draw_tooltips, camera::get_screen_bounds };
use rltk::prelude::*;
use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)]
pub enum FarlookResult {
@ -10,7 +10,7 @@ pub enum FarlookResult {
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 (_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 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)));
return match ctx.key {

View file

@ -21,12 +21,12 @@ use crate::{
Renderable,
states::state::*,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::BTreeMap;
/// 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 equipped = gs.ecs.read_storage::<Equipped>();
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
(!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
.get(*item_entity)
.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();
for (entity, _i, renderable, name) in build_identify_iterator() {
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 {
BUC::Blessed => 1,
BUC::Uncursed => 2,
@ -125,8 +128,8 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
ctx.print_color(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
"Identify which item? [aA-zZ][Esc.]"
);
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 {
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) {
let item = player_inventory
.iter()

View file

@ -1,4 +1,4 @@
use rltk::prelude::*;
use bracket_lib::prelude::*;
pub fn letter_to_option(key: VirtualKeyCode, shift: bool) -> i32 {
if shift {

View file

@ -35,8 +35,13 @@ use super::{
data::ids::get_local_col,
};
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 rltk::prelude::*;
use crate::data::visuals::{
TARGETING_LINE_COL,
TARGETING_CURSOR_COL,
TARGETING_AOE_COL,
TARGETING_VALID_COL,
};
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::BTreeMap;
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.
#[allow(unused)]
pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
ctx.print_color_centered(15, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), question);
ctx.print_color_centered(17, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "(y)es or (n)o");
pub fn yes_no(ctx: &mut BTerm, question: String) -> Option<bool> {
ctx.print_color_centered(15, RGB::named(YELLOW), RGB::named(BLACK), question);
ctx.print_color_centered(17, RGB::named(CYAN), RGB::named(BLACK), "(y)es or (n)o");
match ctx.key {
None => None,
Some(key) =>
@ -70,7 +75,7 @@ pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
}
pub fn draw_lerping_bar(
ctx: &mut Rltk,
ctx: &mut BTerm,
sx: i32,
sy: i32,
width: i32,
@ -82,12 +87,12 @@ pub fn draw_lerping_bar(
let percent = (n as f32) / (max as f32);
let fill_width = (percent * (width as f32)) as i32;
let bg = empty_colour.lerp(full_colour, percent);
let fg = RGB::named(rltk::BLACK);
let fg = RGB::named(BLACK);
for x in 0..width {
if x <= fill_width {
ctx.print_color(sx + x, sy, fg, bg, " ");
} 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, "[");
@ -96,7 +101,7 @@ pub fn draw_lerping_bar(
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
let pools = ecs.read_storage::<Pools>();
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 burden = ecs.read_storage::<Burden>();
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_lerping_bar(
ctx,
@ -123,8 +134,8 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
22,
stats.mana.current,
stats.mana.max,
RGB::named(rltk::BLUE),
RGB::named(rltk::BLACK)
RGB::named(BLUE),
RGB::named(BLACK)
);
// Draw AC
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;
}
}
let armour_class = stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus;
ctx.print_color(26, 53, RGB::named(rltk::PINK), RGB::named(rltk::BLACK), "AC");
ctx.print_color(28, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), armour_class);
let armour_class =
stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus;
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
ctx.print_color(
26,
54,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
format!("XP{}/{}", stats.level, stats.xp)
);
// Draw attributes
let x = 38;
ctx.print_color(x, 53, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "STR");
ctx.print_color(x + 3, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.strength.base);
ctx.print_color(x + 7, 53, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "DEX");
ctx.print_color(x + 10, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.dexterity.base);
ctx.print_color(x + 14, 53, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "CON");
ctx.print_color(x + 17, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.constitution.base);
ctx.print_color(x, 54, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "INT");
ctx.print_color(x + 3, 54, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.intelligence.base);
ctx.print_color(x + 7, 54, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "WIS");
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 + 17, 54, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), attributes.charisma.base);
ctx.print_color(x, 53, RGB::named(RED), RGB::named(BLACK), "STR");
ctx.print_color(x + 3, 53, RGB::named(WHITE), RGB::named(BLACK), attributes.strength.base);
ctx.print_color(x + 7, 53, RGB::named(GREEN), RGB::named(BLACK), "DEX");
ctx.print_color(
x + 10,
53,
RGB::named(WHITE),
RGB::named(BLACK),
attributes.dexterity.base
);
ctx.print_color(x + 14, 53, RGB::named(ORANGE), RGB::named(BLACK), "CON");
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
match hunger.state {
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::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 => {
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 => {
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 => {
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
if let Some(burden) = burden.get(*player_entity) {
match burden.level {
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 => {
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 => {
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 {
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
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();
for (entity, _equipped, renderable) in (&entities, &equipped, &renderables)
.join()
@ -214,30 +286,37 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
}
let mut y = 1;
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;
for item in equipment {
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;
ctx.set(74, y, item.2, RGB::named(rltk::BLACK), item.3);
ctx.print_color(76, y, item.1, RGB::named(rltk::BLACK), &item.0);
ctx.print_color(76 + &item.0.len() + 1, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "(worn)");
ctx.set(74, y, item.2, RGB::named(BLACK), item.3);
ctx.print_color(76, y, item.1, RGB::named(BLACK), &item.0);
ctx.print_color(
76 + &item.0.len() + 1,
y,
RGB::named(WHITE),
RGB::named(BLACK),
"(worn)"
);
}
y += 2;
}
// 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(
81,
y,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
&format!(
"[{:.1}/{} lbs]",
stats.weight,
(attributes.strength.base + attributes.strength.modifiers) * CARRY_CAPACITY_PER_STRENGTH
(attributes.strength.base + attributes.strength.modifiers) *
CARRY_CAPACITY_PER_STRENGTH
)
);
y += 1;
@ -252,7 +331,13 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
y += 1;
let mut index = 1;
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(
74,
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) {
(renderable.fg, renderable.glyph)
} else {
(RGB::named(rltk::WHITE), rltk::to_cp437('-'))
(RGB::named(WHITE), to_cp437('-'))
};
seen_entities.push((
obfuscate_name_ecs(ecs, entity).0,
@ -311,38 +396,54 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
if !seen_entities.is_empty() {
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 {
y += 1;
ctx.set(72, y, entity.2, RGB::named(rltk::BLACK), entity.3);
ctx.print_color(74, y, entity.1, RGB::named(rltk::BLACK), entity.0);
ctx.set(72, y, entity.2, RGB::named(BLACK), entity.3);
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.
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
let map = ecs.fetch::<Map>();
let id = if map.depth > 0 { format!("{}{}", map.short_name, map.depth) } else { format!("{}", map.short_name) };
ctx.print_color_right(70, 54, get_local_col(map.id), RGB::named(rltk::BLACK), &id);
let id = if map.depth > 0 {
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
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.
ctx.draw_hollow_box(0, 0, 70, 8, RGB::named(rltk::WHITE), RGB::named(rltk::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, 52, 70, 3, RGB::named(rltk::WHITE), RGB::named(rltk::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(0, 0, 70, 8, RGB::named(WHITE), RGB::named(BLACK)); // Log 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(WHITE), RGB::named(BLACK)); // Stats box
ctx.draw_hollow_box(71, 0, 33, 55, RGB::named(WHITE), RGB::named(BLACK)); // Side box
tooltip::draw_tooltips(ecs, ctx, None);
}
pub fn get_input_direction(
ecs: &mut World,
ctx: &mut Rltk,
ctx: &mut BTerm,
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState
) -> RunState {
let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs, ctx);
@ -350,8 +451,8 @@ pub fn get_input_direction(
ctx.print_color(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
"In what direction? [0-9]/[YUHJKLBN]"
);
match ctx.key {
@ -403,7 +504,12 @@ pub enum ItemMenuResult {
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 initial_x: i32 = x;
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;
// Print the character required to access this item. i.e. (a)
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 {
// 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;
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;
let fg = RGB::from_u8(item.rgb.0, item.rgb.1, item.rgb.2);
if item_count > &1 {
// If more than one, print the number and pluralise
// 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;
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);
width = if width > this_width { width } else { this_width };
} else {
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;
} 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'
// 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;
} else {
// If one and not a vowel, print 'a'
// 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;
}
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);
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 item.display_name.singular == item.display_name.plural {
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
} else {
this_width += 1; // "a".len
@ -492,7 +602,10 @@ pub fn obfuscate_name(
dm: &MasterDungeonMap,
wand: Option<&ReadStorage<Charges>>
) -> (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 magic_items.get(item).is_some() {
if dm.identified_items.contains(&name.name) {
@ -510,7 +623,10 @@ pub fn obfuscate_name(
} else if let Some(obfuscated) = obfuscated_names.get(item) {
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
} 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 {
(singular, plural) = (name.name.clone(), name.plural.clone());
@ -534,7 +650,10 @@ pub fn obfuscate_name(
// Outside the ECS
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 ecs.read_storage::<MagicItem>().get(item).is_some() {
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) {
(singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone());
} 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 {
(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
pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity) -> (u8, u8, u8) {
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 {
WHITE
};
@ -601,7 +727,11 @@ pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity)
/// Gets renderable colour as tuple of u8
pub fn renderable_colour_ecs(ecs: &World, entity: Entity) -> (u8, u8, u8) {
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 {
WHITE
};
@ -653,17 +783,17 @@ pub fn item_colour(item: Entity, beatitudes: &ReadStorage<Beatitude>) -> (u8, u8
return WHITE;
}
pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
pub fn show_help(ctx: &mut BTerm) -> YesNoResult {
let mut x = 3;
let mut y = 12;
let height = 22;
let width = 25;
ctx.draw_box(x, y, width, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
ctx.print_color(x + 3, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), " Controls ");
ctx.print_color(x + 3, y + height, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), " ESC/? to close ");
ctx.draw_box(x, y, width, height, RGB::named(WHITE), RGB::named(BLACK));
ctx.print_color(x + 3, y, RGB::named(YELLOW), RGB::named(BLACK), " Controls ");
ctx.print_color(x + 3, y + height, RGB::named(YELLOW), RGB::named(BLACK), " ESC/? to close ");
x += 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;
ctx.print(x, y, "y k u 7 8 9 > down");
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 + 4, "b j n 1 2 3 . wait");
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;
ctx.print(x, y, "g get d drop");
y += 1;
@ -681,7 +811,7 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
y += 1;
ctx.print(x, y, "f force x farlook");
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;
ctx.print(x, y, "hover for tooltips");
@ -766,7 +896,7 @@ pub fn get_player_inventory(ecs: &World) -> PlayerInventory {
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 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.]"
};
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 y = 3 + y_offset;
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);
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);
if selection > -1 && selection < (count as i32) {
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 {
return (
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 count = player_inventory.len();
let (x_offset, y_offset) = (1, 10);
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 y = 3 + y_offset;
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);
match ctx.key {
@ -838,10 +975,13 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
match key {
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 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 {
return (
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 backpack = gs.ecs.read_storage::<Equipped>();
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(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
"Unequip what? [aA-zZ][Esc.]"
);
let mut equippable: Vec<(Entity, String)> = Vec::new();
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_width = 5 + this_name.len();
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 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;
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) {
(renderable.fg, renderable.glyph)
} 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 + 3, y, fg, RGB::named(rltk::BLACK), glyph);
ctx.set(x + 1, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType));
ctx.set(x + 3, y, fg, RGB::named(BLACK), glyph);
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;
j += 1;
}
@ -914,7 +1056,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
match key {
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) {
return (ItemMenuResult::Selected, Some(equippable[selection as usize].0));
}
@ -936,7 +1078,7 @@ pub enum TargetResult {
pub fn ranged_target(
gs: &mut State,
ctx: &mut Rltk,
ctx: &mut BTerm,
x: i32,
y: i32,
range: i32,
@ -950,8 +1092,8 @@ pub fn ranged_target(
ctx.print_color(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
"Targeting which tile? [mouse input]"
);
@ -961,11 +1103,16 @@ pub fn ranged_target(
if let Some(visible) = visible {
// We have a viewshed
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) {
let screen_x = idx.x - min_x;
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);
available_cells.push(idx);
}
@ -977,7 +1124,10 @@ pub fn ranged_target(
// Draw mouse cursor
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 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));
@ -994,7 +1144,7 @@ pub fn ranged_target(
}
let mut result = (TargetResult::NoResponse { x, y }, None);
if valid_target {
let path = rltk::line2d(
let path = line2d(
LineAlg::Bresenham,
Point::new(player_pos.x, player_pos.y),
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)
@ -1014,12 +1164,14 @@ pub fn ranged_target(
if aoe > 0 {
// 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.
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),
aoe,
&*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() {
let bg = if available_cells.contains(&tile) {
let col1 = TARGETING_AOE_COL;
@ -1040,13 +1192,16 @@ pub fn ranged_target(
Some(key) =>
match key {
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,
}
};
} 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 {
@ -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 runstate = gs.ecs.fetch::<RunState>();
let assets = gs.ecs.fetch::<RexAssets>();
@ -1099,34 +1254,34 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
height -= 1;
}
ctx.draw_box_double(x, y - 4, 13, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
ctx.print_color(x + 3, y - 2, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "RUST-RL!");
ctx.draw_box_double(x, y - 4, 13, height, RGB::named(WHITE), RGB::named(BLACK));
ctx.print_color(x + 3, y - 2, RGB::named(YELLOW), RGB::named(BLACK), "RUST-RL!");
if let RunState::MainMenu { menu_selection: selection } = *runstate {
if save_exists {
if selection == MainMenuSelection::LoadGame {
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "continue");
ctx.print_color(x + 11, 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(GREEN), RGB::named(BLACK), "continue");
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
} 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;
}
if selection == MainMenuSelection::NewGame {
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "new game");
ctx.print_color(x + 11, 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(GREEN), RGB::named(BLACK), "new game");
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
} 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;
if selection == MainMenuSelection::Quit {
ctx.print_color(x + 2, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "[");
ctx.print_color(x + 3, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "goodbye!");
ctx.print_color(x + 11, 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(GREEN), RGB::named(BLACK), "goodbye!");
ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]");
} 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 {
@ -1142,7 +1297,9 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame };
}
VirtualKeyCode::L => {
return MainMenuResult::NoSelection { selected: MainMenuSelection::LoadGame };
return MainMenuResult::NoSelection {
selected: MainMenuSelection::LoadGame,
};
}
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => {
let mut new_selection;
@ -1199,18 +1356,18 @@ pub enum YesNoResult {
No,
}
pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
pub fn game_over(ctx: &mut BTerm) -> YesNoResult {
let mut x = 3;
let mut y = 12;
let width = 45;
let height = 20;
ctx.draw_box(x, y, width, height, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
ctx.print_color(x + 3, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "You died!");
ctx.draw_box(x, y, width, height, RGB::named(WHITE), RGB::named(BLACK));
ctx.print_color(x + 3, y, RGB::named(YELLOW), RGB::named(BLACK), "You died!");
ctx.print_color(
x + 3,
y + height,
RGB::named(rltk::YELLOW),
RGB::named(rltk::BLACK),
RGB::named(YELLOW),
RGB::named(BLACK),
" Write a morgue file? [y/n] "
);
x += 2;
@ -1218,20 +1375,23 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
ctx.print_color(
x,
y,
RGB::named(rltk::GREEN),
RGB::named(rltk::BLACK),
RGB::named(GREEN),
RGB::named(BLACK),
format!("You survived for {} turns.", crate::gamelog::get_event_count(EVENT::COUNT_TURN))
);
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;
if crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) > 0 {
ctx.print_color(
x + 1,
y,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
format!("- changed floor {} times", crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR))
RGB::named(WHITE),
RGB::named(BLACK),
format!(
"- changed floor {} times",
crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR)
)
);
y += 1;
}
@ -1239,8 +1399,8 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
ctx.print_color(
x + 1,
y,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
format!(
"- kicked {} time(s), breaking {} object(s)",
crate::gamelog::get_event_count(EVENT::COUNT_KICK),
@ -1253,9 +1413,12 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
ctx.print_color(
x + 1,
y,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
format!("- slew {} other creature(s)", crate::gamelog::get_event_count(EVENT::COUNT_KILLED))
RGB::named(WHITE),
RGB::named(BLACK),
format!(
"- slew {} other creature(s)",
crate::gamelog::get_event_count(EVENT::COUNT_KILLED)
)
);
y += 1;
}
@ -1263,9 +1426,12 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
ctx.print_color(
x + 1,
y,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP))
RGB::named(WHITE),
RGB::named(BLACK),
format!(
"- forgot the controls {} time(s)",
crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP)
)
);
}

View file

@ -7,13 +7,24 @@ use super::{
ItemMenuResult,
UniqueInventoryItem,
};
use crate::{ gamelog, Beatitude, Entity, Equipped, InBackpack, Item, Name, Renderable, states::state::*, BUC };
use rltk::prelude::*;
use crate::{
gamelog,
Beatitude,
Entity,
Equipped,
InBackpack,
Item,
Name,
Renderable,
states::state::*,
BUC,
};
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::BTreeMap;
/// 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 equipped = gs.ecs.read_storage::<Equipped>();
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 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.
let mut keep = false;
// 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();
for (entity, _i, _b, renderable, name) in build_cursed_iterator() {
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 {
BUC::Blessed => 1,
BUC::Uncursed => 2,
@ -108,8 +123,8 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
ctx.print_color(
1 + x_offset,
1 + y_offset,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
RGB::named(WHITE),
RGB::named(BLACK),
"Decurse which item? [aA-zZ][Esc.]"
);
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 {
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) {
let item = player_inventory
.iter()

View file

@ -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::data::ids::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
struct Tooltip {
@ -33,8 +44,15 @@ impl Tooltip {
fn height(&self) -> i32 {
return (self.lines.len() as i32) + 2i32;
}
fn render(&self, ctx: &mut Rltk, x: i32, y: i32) {
ctx.draw_box(x, y, self.width() - 1, self.height() - 1, RGB::named(WHITE), RGB::named(BLACK));
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)
);
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);
}
@ -42,7 +60,7 @@ impl Tooltip {
}
#[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 map = ecs.fetch::<Map>();
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 ; }
let white = RGB::named(rltk::WHITE);
let white = RGB::named(WHITE);
let arrow;
let arrow_x;
@ -157,7 +175,7 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk, xy: Option<(i32, i32)>) {
arrow = to_cp437('←');
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;
for t in tooltips.iter() {

View file

@ -1,5 +1,12 @@
use super::{ effects::{ add_effect, EffectType, Targets }, gamelog, Clock, HungerClock, HungerState, TakingTurn };
use rltk::prelude::*;
use super::{
effects::{ add_effect, EffectType, Targets },
gamelog,
Clock,
HungerClock,
HungerState,
TakingTurn,
};
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::config::CONFIG;
@ -69,11 +76,18 @@ impl<'a> System<'a> for HungerSystem {
let initial_state = hunger_clock.state;
hunger_clock.state = get_hunger_state(hunger_clock.duration);
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 {
rltk::console::log(
format!("HUNGER SYSTEM: Ticked for player entity. [clock: {}]", hunger_clock.duration)
console::log(
format!(
"HUNGER SYSTEM: Ticked for player entity. [clock: {}]",
hunger_clock.duration
)
);
}
if hunger_clock.state == initial_state {

View file

@ -12,10 +12,10 @@ use crate::{
ObfuscatedName,
Position,
WantsToPickupItem,
Renderable,
};
use specs::prelude::*;
use crate::data::messages;
use bracket_lib::prelude::*;
pub struct ItemCollectionSystem {}
@ -52,7 +52,9 @@ impl<'a> System<'a> for ItemCollectionSystem {
for pickup in wants_pickup.join() {
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
.insert(pickup.collected_by, EquipmentChanged {})
.expect("Unable to insert EquipmentChanged.");
@ -76,7 +78,7 @@ impl<'a> System<'a> for ItemCollectionSystem {
).0
)
)
.colour(rltk::WHITE)
.colour(WHITE)
.period()
.log();
}

View file

@ -15,6 +15,7 @@ use crate::{
};
use specs::prelude::*;
use crate::data::messages;
use bracket_lib::prelude::*;
pub struct ItemDropSystem {}
@ -52,7 +53,9 @@ impl<'a> System<'a> for ItemDropSystem {
) = data;
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 dropped_pos = positions.get(entity).unwrap();
@ -83,7 +86,7 @@ impl<'a> System<'a> for ItemDropSystem {
).0
)
)
.colour(rltk::WHITE)
.colour(WHITE)
.period()
.log();
}

View file

@ -17,6 +17,7 @@ use crate::{
};
use specs::prelude::*;
use crate::data::messages;
use bracket_lib::prelude::*;
pub struct ItemEquipSystem {}
@ -66,7 +67,11 @@ impl<'a> System<'a> for ItemEquipSystem {
// Remove any items target has in item's slot
let mut can_equip = true;
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 let Some(beatitude) = beatitudes.get(item_entity) {
if beatitude.buc == BUC::Cursed {
@ -85,7 +90,7 @@ impl<'a> System<'a> for ItemEquipSystem {
None
).0
)
.colour(rltk::WHITE)
.colour(WHITE)
.append("!");
identified_beatitude
.insert(item_entity, IdentifiedBeatitude {})
@ -101,15 +106,25 @@ impl<'a> System<'a> for ItemEquipSystem {
}
for item in to_unequip.iter() {
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 {
logger = logger
.append(messages::YOU_REMOVE_ITEM)
.colour(item_colour(*item, &beatitudes))
.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();
}
}
@ -134,7 +149,7 @@ impl<'a> System<'a> for ItemEquipSystem {
None
).0
)
.colour(rltk::WHITE)
.colour(WHITE)
.period();
logger.log();
identified_items

View file

@ -11,7 +11,7 @@ use crate::{
WantsToRemoveItem,
BUC,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::data::messages;
@ -99,7 +99,9 @@ impl<'a> System<'a> for ItemRemoveSystem {
.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();

View file

@ -1,7 +1,7 @@
// src/lib.rs
// 31-Aug-2023
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
extern crate serde;

View file

@ -1,19 +1,19 @@
use rust_rl::*;
use specs::prelude::*;
use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator };
use rltk::prelude::*;
use bracket_lib::prelude::*;
const DISPLAYWIDTH: i32 = 105;
const DISPLAYHEIGHT: i32 = 56;
fn main() -> rltk::BError {
fn main() -> BError {
// Embedded resources for use in wasm build
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_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT)
.with_font("curses14x16.png", 14, 16)
@ -26,7 +26,9 @@ fn main() -> rltk::BError {
let mut gs = State {
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_history: Vec::new(),
mapgen_timer: 0.0,
@ -115,7 +117,7 @@ fn main() -> rltk::BError {
raws::load_raws();
// 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::new(true, 1, 64, 64, 0, "New Map", "N", 0)); // Map
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));
gs.generate_world_map(1, TileType::Floor);
rltk::main_loop(context, gs)
main_loop(context, gs)
}

View file

@ -1,6 +1,6 @@
use super::{ Map, TileType };
use crate::{ gamelog, map_builders, OtherLevelPosition, Position, Telepath, Viewshed };
use rltk::prelude::*;
use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize };
use specs::prelude::*;
use std::collections::{ HashMap, HashSet };
@ -61,7 +61,11 @@ impl MasterDungeonMap {
fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String {
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 mut name = "".to_string();
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 {
loop {
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 += POTION_COLOURS[(rng.roll_dice(1, POTION_COLOURS.len() as i32) as usize) - 1];
name += " potion";
@ -178,7 +184,8 @@ const WAND_TYPES: &[&str] = &[
fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
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";
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
}
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
let idx = possible_destinations[(rng.roll_dice(1, possible_destinations.len() as i32) as usize) - 1];
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
let idx =
possible_destinations[(rng.roll_dice(1, possible_destinations.len() as i32) as usize) - 1];
let mut player_position = ecs.write_resource::<Point>();
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
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> {
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
// level isn't found at all, there's a bigger concern
// 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();
for (entity, pos) in (&entities, &other_positions).join() {
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);
}
}

View file

@ -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 bracket_lib::prelude::*;
use crate::data::events::*;
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 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() {
if rng.roll_dice(1, FEATURE_MESSAGE_CHANCE) == 1 {
maybe_message = true;
@ -42,7 +52,7 @@ pub fn try_spawn_interval(ecs: &mut World) {
}
let clock = ecs.read_storage::<Clock>();
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() {
if rng.roll_dice(1, TRY_SPAWN_CHANCE) == 1 {
try_spawn = true;
@ -51,7 +61,7 @@ pub fn try_spawn_interval(ecs: &mut World) {
}
if try_spawn {
if CONFIG.logging.log_spawning {
rltk::console::log("SPAWNINFO: Trying spawn.");
console::log("SPAWNINFO: Trying spawn.");
}
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 mut available_tiles = populate_unblocked_nonvisible(&map);
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;
if available_tiles.len() == 0 {
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;
}
@ -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 idx in spawn_locations {
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::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.
fn get_random_idx_from_tiles(rng: &mut rltk::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 };
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
};
area.remove(idx);
return area[idx];
}

View file

@ -1,4 +1,4 @@
use rltk::prelude::*;
use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize };
use std::collections::{ HashSet, HashMap };
mod tiletype;
@ -8,7 +8,11 @@ pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval };
pub mod dungeon;
pub use dungeon::{ level_transition, MasterDungeonMap };
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.
// 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.
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],
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
@ -78,7 +82,7 @@ impl Map {
view_blocked: HashSet::new(),
};
let mut rng = rltk::RandomNumberGenerator::new();
let mut rng = RandomNumberGenerator::new();
for idx in 0..map.colour_offset.len() {
map.colour_offset[idx].0 = (
@ -134,12 +138,12 @@ impl BaseMap for Map {
let w = self.width as usize;
let p1 = Point::new(idx1 % w, idx1 / 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.
fn get_available_exits(&self, idx: usize) -> rltk::SmallVec<[(usize, f32); 10]> {
let mut exits = rltk::SmallVec::new();
fn get_available_exits(&self, idx: usize) -> SmallVec<[(usize, f32); 10]> {
let mut exits = SmallVec::new();
let x = (idx as i32) % self.width;
let y = (idx as i32) / self.width;
let w = self.width as usize;

View file

@ -2,7 +2,7 @@ use super::{ Map, Point, TileType };
use crate::data::visuals::*;
use crate::config::CONFIG;
use crate::data::ids::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
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.
@ -11,7 +11,7 @@ pub fn get_tile_renderables_for_id(
map: &Map,
other_pos: Option<Point>,
debug: Option<bool>
) -> (rltk::FontCharType, RGB, RGB) {
) -> (FontCharType, RGB, RGB) {
let coloured_bg = CONFIG.visuals.use_coloured_tile_bg;
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]
pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>) -> (rltk::FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
let glyph: rltk::FontCharType;
pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>) -> (FontCharType, RGB, RGB, (i32, i32, i32), (i32, i32, i32)) {
let glyph: FontCharType;
#[allow(unused_assignments)]
let mut fg: RGB = RGB::new();
#[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);
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::WoodFloor => { glyph = rltk::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::Floor => { glyph = to_cp437(FLOOR_GLYPH); fg = RGB::named(FLOOR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = FLOOR_OFFSETS; }
TileType::WoodFloor => { glyph = to_cp437(WOOD_FLOOR_GLYPH); bg = RGB::named(WOOD_FLOOR_COLOUR); offsets = WOOD_FLOOR_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::DownStair => { glyph = rltk::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::Bridge => { glyph = rltk::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::Road => { glyph = rltk::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::Foliage => { glyph = rltk::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::Sand => { glyph = rltk::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::DeepWater => { glyph = rltk::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::ImpassableMountain => { glyph = rltk::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::ToLocal(_) => { glyph = rltk::to_cp437(TO_TOWN_GLYPH); fg = RGB::named(TO_TOWN_COLOUR); bg = RGB::named(GRASS_COLOUR); }
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 = to_cp437(UP_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); offsets = STAIR_OFFSETS; }
TileType::Bridge => { glyph = to_cp437(BRIDGE_GLYPH); bg = RGB::named(BRIDGE_COLOUR); offsets = BRIDGE_OFFSETS; }
TileType::Gravel => { glyph = to_cp437(GRAVEL_GLYPH); bg = RGB::named(GRAVEL_COLOUR); offsets = GRAVEL_OFFSETS;}
TileType::Road => { glyph = to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); offsets = ROAD_OFFSETS;}
TileType::Grass => { glyph = to_cp437(GRASS_GLYPH); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
TileType::Foliage => { glyph = to_cp437(FOLIAGE_GLYPH); bg = RGB::named(FOLIAGE_COLOUR); offsets = FOLIAGE_OFFSETS; }
TileType::HeavyFoliage => { glyph = to_cp437(HEAVY_FOLIAGE_GLYPH); bg = RGB::named(HEAVY_FOLIAGE_COLOUR); offsets = HEAVY_FOLIAGE_OFFSETS; }
TileType::Sand => { glyph = to_cp437(SAND_GLYPH); bg = RGB::named(SAND_COLOUR); offsets = SAND_OFFSETS; }
TileType::ShallowWater => { glyph = to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); offsets = SHALLOW_WATER_OFFSETS; }
TileType::DeepWater => { glyph = to_cp437(DEEP_WATER_GLYPH); bg = RGB::named(DEEP_WATER_COLOUR); offsets = DEEP_WATER_OFFSETS; }
TileType::Bars => { glyph = to_cp437(BARS_GLYPH); fg = RGB::named(BARS_COLOUR); bg = RGB::named(FLOOR_COLOUR); }
TileType::ImpassableMountain => { glyph = to_cp437(IMPASSABLE_MOUNTAIN_GLYPH); bg = RGB::named(IMPASSABLE_MOUNTAIN_COLOUR); offsets = IMPASSABLE_MOUNTAIN_OFFSETS }
TileType::ToOvermap(_) => { glyph = to_cp437(TO_OVERMAP_GLYPH); fg = RGB::named(TO_OVERMAP_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) {
bg_offsets = offsets;
@ -115,7 +115,7 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>)
}
#[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;
#[allow(unused_assignments)]
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);
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::Road => { glyph = rltk::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::Wall => { glyph = to_cp437(FOREST_WALL_GLYPH); fg = RGB::named(FOREST_WALL_COLOUR); bg = RGB::named(GRASS_COLOUR); offsets = GRASS_OFFSETS; }
TileType::Road => { glyph = to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); }
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; }
}
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 })
}
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
x < 1 ||
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 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 g = rgb.g * offsets.1;
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 {

View file

@ -1,5 +1,6 @@
use super::{ BuilderMap, MetaMapBuilder, Position };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use bracket_lib::prelude::*;
#[allow(dead_code)]
pub enum XStart {
@ -21,7 +22,7 @@ pub struct 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);
}
}
@ -64,9 +65,12 @@ impl AreaStartingPosition {
if crate::tile_walkable(*tiletype) {
available_floors.push((
idx,
rltk::DistanceAlg::PythagorasSquared.distance2d(
rltk::Point::new((idx as i32) % build_data.map.width, (idx as i32) / build_data.map.width),
rltk::Point::new(seed_x, seed_y)
DistanceAlg::PythagorasSquared.distance2d(
Point::new(
(idx as i32) % build_data.map.width,
(idx as i32) / build_data.map.width
),
Point::new(seed_x, seed_y)
),
));
}

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, InitialMapBuilder, Rect, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct BspDungeonBuilder {
rects: Vec<Rect>,
@ -7,7 +7,7 @@ pub struct BspDungeonBuilder {
impl InitialMapBuilder for BspDungeonBuilder {
#[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);
}
}

View file

@ -1,5 +1,5 @@
use super::{ draw_corridor, BuilderMap, InitialMapBuilder, Rect, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
const MIN_ROOM_SIZE: i32 = 8;
@ -9,7 +9,7 @@ pub struct BspInteriorBuilder {
impl InitialMapBuilder for BspInteriorBuilder {
#[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);
}
}

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, InitialMapBuilder, MetaMapBuilder, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct CellularAutomataBuilder {
floor_tile: TileType,
@ -7,14 +7,14 @@ pub struct CellularAutomataBuilder {
impl InitialMapBuilder for CellularAutomataBuilder {
#[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);
}
}
impl MetaMapBuilder for CellularAutomataBuilder {
#[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);
}
}
@ -69,16 +69,28 @@ impl CellularAutomataBuilder {
if build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Wall {
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;
}
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;
}
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;
}
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;
}

View file

@ -1,11 +1,11 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use crate::tile_walkable;
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}
@ -21,7 +21,7 @@ impl CullUnreachable {
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
build_data.map.populate_blocked();
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.height as usize,
&map_starts,

View file

@ -1,11 +1,11 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use crate::tile_walkable;
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}
@ -21,7 +21,7 @@ impl DistantExit {
let start_idx = build_data.map.xy_idx(starting_pos.x, starting_pos.y);
build_data.map.populate_blocked();
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.height as usize,
&map_starts,

View file

@ -1,5 +1,5 @@
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)]
#[allow(dead_code)]
@ -18,14 +18,14 @@ pub struct DLABuilder {
impl InitialMapBuilder for DLABuilder {
#[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);
}
}
impl MetaMapBuilder for DLABuilder {
#[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);
}
}
@ -94,7 +94,10 @@ impl DLABuilder {
#[allow(clippy::map_entry)]
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
// 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);
build_data.take_snapshot();
build_data.map.tiles[start_idx] = TileType::Floor;
@ -189,10 +192,10 @@ impl DLABuilder {
let mut prev_y = digger_y;
let mut digger_idx = build_data.map.xy_idx(digger_x, digger_y);
let mut path = rltk::line2d(
rltk::LineAlg::Bresenham,
rltk::Point::new(digger_x, digger_y),
rltk::Point::new(starting_position.x, starting_position.y)
let mut path = line2d(
LineAlg::Bresenham,
Point::new(digger_x, digger_y),
Point::new(starting_position.x, starting_position.y)
);
while build_data.map.tiles[digger_idx] == TileType::Wall && !path.is_empty() {

View file

@ -1,11 +1,11 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct DoorPlacement {}
impl MetaMapBuilder for DoorPlacement {
#[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);
}
}
@ -30,7 +30,11 @@ impl DoorPlacement {
// There are no corridors - scan for possible places
let tiles = build_data.map.tiles.clone();
for (i, tile) in tiles.iter().enumerate() {
if *tile == TileType::Floor && self.door_possible(build_data, i) && rng.roll_dice(1, 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()));
}
}

View file

@ -1,5 +1,5 @@
use super::{ paint, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, Symmetry, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)]
#[allow(dead_code)]
@ -22,14 +22,14 @@ pub struct DrunkardsWalkBuilder {
impl InitialMapBuilder for DrunkardsWalkBuilder {
#[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);
}
}
impl MetaMapBuilder for DrunkardsWalkBuilder {
#[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);
}
}
@ -107,7 +107,10 @@ impl DrunkardsWalkBuilder {
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
// 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);
build_data.map.tiles[start_idx] = TileType::Floor;
@ -144,7 +147,13 @@ impl DrunkardsWalkBuilder {
if build_data.map.tiles[drunk_idx] == TileType::Wall {
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;
let stagger_direction = rng.roll_dice(1, 4);

View file

@ -1,6 +1,6 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use crate::tile_walkable;
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct FillEdges {
fill_with: TileType,
@ -9,7 +9,7 @@ pub struct FillEdges {
impl MetaMapBuilder for FillEdges {
#[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);
}
}

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct Foliage {
start_tile: TileType,
@ -8,7 +8,7 @@ pub struct Foliage {
impl MetaMapBuilder for Foliage {
#[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);
}
}

View file

@ -11,12 +11,12 @@ use super::{
YStart,
Foliage,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use crate::data::names::*;
pub fn forest_builder(
new_id: i32,
_rng: &mut rltk::RandomNumberGenerator,
_rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
difficulty: i32,

View file

@ -1,11 +1,11 @@
use super::{ BuilderMap, InitialMapBuilder, Map, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct MazeBuilder {}
impl InitialMapBuilder for MazeBuilder {
#[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);
}
}
@ -75,7 +75,14 @@ struct Grid<'a> {
impl<'a> Grid<'a> {
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 column in 0..width {
@ -122,7 +129,9 @@ impl<'a> Grid<'a> {
if neighbors.len() == 1 {
return Some(neighbors[0]);
} 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
@ -141,7 +150,9 @@ impl<'a> Grid<'a> {
// __lower_part__ __higher_part_
// / \ / \
// --------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 cell2 = &mut higher_part[0];
cell1.remove_walls(cell2);

View file

@ -1,4 +1,6 @@
use super::{ spawner, Map, Position, Rect, TileType };
use bracket_lib::prelude::*;
mod bsp_dungeon;
use bsp_dungeon::BspDungeonBuilder;
mod bsp_interior;
@ -143,7 +145,7 @@ impl BuilderChain {
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 {
None => panic!("Cannot run a map builder chain without a starting build system"),
Some(starter) => {
@ -165,20 +167,20 @@ impl BuilderChain {
spawner::spawn_entity(ecs, &(&entity.0, &entity.1));
}
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 {
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 {
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 xroll = rng.roll_dice(1, 3);
match xroll {
@ -210,11 +212,7 @@ fn random_start_position(rng: &mut rltk::RandomNumberGenerator) -> (XStart, YSta
(x, y)
}
fn random_room_builder(
rng: &mut rltk::RandomNumberGenerator,
builder: &mut BuilderChain,
end: bool
) {
fn random_room_builder(rng: &mut RandomNumberGenerator, builder: &mut BuilderChain, end: bool) {
let build_roll = rng.roll_dice(1, 3);
// Start with a room builder.
match build_roll {
@ -296,7 +294,7 @@ fn random_room_builder(
}
fn random_shape_builder(
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
builder: &mut BuilderChain,
end: bool
) -> bool {
@ -368,7 +366,7 @@ pub enum BuildType {
pub fn random_builder(
new_id: i32,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
difficulty: i32,
@ -377,7 +375,7 @@ pub fn random_builder(
end: bool,
build_type: BuildType
) -> 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(
false,
new_id,
@ -441,7 +439,7 @@ pub fn random_builder(
pub fn level_builder(
new_id: i32,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
initial_player_level: i32

View file

@ -1,5 +1,5 @@
use super::{ spawner, BuilderMap, InitialMapBuilder, MetaMapBuilder, Position, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub mod prefab_levels;
pub mod prefab_sections;
pub mod prefab_vaults;
@ -25,14 +25,14 @@ pub struct 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);
}
}
impl InitialMapBuilder for PrefabBuilder {
#[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);
}
}
@ -65,7 +65,8 @@ impl PrefabBuilder {
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
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::Sectional { section } => self.apply_sectional(&section, rng, build_data),
PrefabMode::RoomVaults => self.apply_room_vaults(rng, build_data),
@ -73,7 +74,13 @@ impl PrefabBuilder {
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;
match ch {
' ' => {
@ -123,7 +130,10 @@ impl PrefabBuilder {
}
'!' => {
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;
@ -131,14 +141,20 @@ impl PrefabBuilder {
}
'?' => {
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.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);
}
_ => {
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)]
fn load_rex_map(&mut self, path: &str, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
let xp_file = rltk::rex::XpFile::from_resource(path).unwrap();
fn load_rex_map(
&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 y in 0..layer.height {

View file

@ -1,10 +1,10 @@
use super::{ spawner, BuilderMap, MetaMapBuilder };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -1,10 +1,10 @@
use super::{ BuilderMap, MetaMapBuilder, TileType };
use rltk::prelude::*;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -1,10 +1,10 @@
use super::{ BuilderMap, MetaMapBuilder, Position };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -1,10 +1,10 @@
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -1,10 +1,10 @@
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}
@ -29,14 +29,11 @@ impl RoomDrawer {
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 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 x in room.x1..=room.x2 {
let idx = build_data.map.xy_idx(x, y);
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
center_pt,
rltk::Point::new(x, y)
);
let distance = DistanceAlg::Pythagoras.distance2d(center_pt, Point::new(x, y));
if
idx > 0 &&
idx < ((build_data.map.width * build_data.map.height - 1) as usize) &&

View file

@ -1,10 +1,10 @@
use super::{ paint, BuilderMap, MetaMapBuilder, Rect, Symmetry, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, MetaMapBuilder, Rect };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
#[allow(dead_code)]
pub enum RoomSort {
@ -16,7 +16,7 @@ pub struct RoomSorter {
impl MetaMapBuilder for RoomSorter {
#[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);
}
}
@ -50,21 +50,18 @@ impl RoomSorter {
.unwrap()
.sort_by(|a, b| b.y2.cmp(&a.y2)),
RoomSort::CENTRAL => {
let map_centre = rltk::Point::new(
build_data.map.width / 2,
build_data.map.height / 2
);
let map_centre = Point::new(build_data.map.width / 2, build_data.map.height / 2);
build_data.rooms
.as_mut()
.unwrap()
.sort_by(|a: &Rect, b: &Rect| {
let a_centre_pt = rltk::Point::new(a.center().x, a.center().y);
let b_centre_pt = rltk::Point::new(b.center().x, b.center().y);
let distance_a = rltk::DistanceAlg::Pythagoras.distance2d(
let a_centre_pt = Point::new(a.center().x, a.center().y);
let b_centre_pt = Point::new(b.center().x, b.center().y);
let distance_a = DistanceAlg::Pythagoras.distance2d(
a_centre_pt,
map_centre
);
let distance_b = rltk::DistanceAlg::Pythagoras.distance2d(
let distance_b = DistanceAlg::Pythagoras.distance2d(
b_centre_pt,
map_centre
);

View file

@ -7,7 +7,7 @@ use crate::data::messages::{
FEATURE_BARRACKS_ORC,
};
use crate::raws;
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use std::collections::HashSet;
pub enum Theme {
@ -22,7 +22,7 @@ pub struct 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);
}
}
@ -173,7 +173,7 @@ fn roll_until_fail(rng: &mut RandomNumberGenerator, target: i32) -> i32 {
loop {
if rng.roll_dice(1, 100) <= target - accumulator {
accumulator += 1;
rltk::console::log(accumulator);
console::log(accumulator);
} else {
break;
}

View file

@ -1,12 +1,12 @@
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use std::collections::HashSet;
pub struct BresenhamCorridors {}
impl MetaMapBuilder for BresenhamCorridors {
#[allow(dead_code)]
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
self.corridors(rng, build_data);
}
}
@ -30,12 +30,12 @@ impl BresenhamCorridors {
for (i, room) in rooms.iter().enumerate() {
let mut room_distance: Vec<(usize, f32)> = Vec::new();
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() {
if i != j && !connected.contains(&j) {
let other_centre = other_room.center();
let other_centre_pt = rltk::Point::new(other_centre.x, other_centre.y);
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
let other_centre_pt = Point::new(other_centre.x, other_centre.y);
let distance = DistanceAlg::Pythagoras.distance2d(
room_centre_pt,
other_centre_pt
);
@ -46,10 +46,10 @@ impl BresenhamCorridors {
if !room_distance.is_empty() {
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
let dest_centre = rooms[room_distance[0].0].center();
let line = rltk::line2d(
rltk::LineAlg::Bresenham,
let line = line2d(
LineAlg::Bresenham,
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();
for cell in line.iter() {

View file

@ -1,11 +1,11 @@
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct BspCorridors {}
impl MetaMapBuilder for BspCorridors {
#[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);
}
}
@ -30,8 +30,10 @@ impl BspCorridors {
let next_room = rooms[i + 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 end_x = next_room.x1 + (rng.roll_dice(1, i32::abs(next_room.x1 - next_room.x2)) - 1);
let end_y = next_room.y1 + (rng.roll_dice(1, i32::abs(next_room.y1 - next_room.y2)) - 1);
let end_x =
next_room.x1 + (rng.roll_dice(1, i32::abs(next_room.x1 - next_room.x2)) - 1);
let end_y =
next_room.y1 + (rng.roll_dice(1, i32::abs(next_room.y1 - next_room.y2)) - 1);
let corridor = draw_corridor(&mut build_data.map, start_x, start_y, end_x, end_y);
corridors.push(corridor);
build_data.take_snapshot();

View file

@ -1,11 +1,11 @@
use super::{ apply_horizontal_tunnel, apply_vertical_tunnel, BuilderMap, MetaMapBuilder, Rect };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct DoglegCorridors {}
impl MetaMapBuilder for DoglegCorridors {
#[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);
}
}

View file

@ -1,12 +1,12 @@
use super::{ draw_corridor, BuilderMap, MetaMapBuilder, Rect };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use std::collections::HashSet;
pub struct NearestCorridors {}
impl MetaMapBuilder for NearestCorridors {
#[allow(dead_code)]
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
self.corridors(rng, build_data);
}
}
@ -30,12 +30,12 @@ impl NearestCorridors {
for (i, room) in rooms.iter().enumerate() {
let mut room_distance: Vec<(usize, f32)> = Vec::new();
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() {
if i != j && !connected.contains(&j) {
let other_centre = other_room.center();
let other_centre_pt = rltk::Point::new(other_centre.x, other_centre.y);
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
let other_centre_pt = Point::new(other_centre.x, other_centre.y);
let distance = DistanceAlg::Pythagoras.distance2d(
room_centre_pt,
other_centre_pt
);

View file

@ -1,10 +1,10 @@
use super::{ spawner, BuilderMap, MetaMapBuilder };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct 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);
}
}

View file

@ -2,7 +2,7 @@ use super::{
generate_voronoi_spawn_regions, remove_unreachable_areas_returning_most_distant, spawner, Map, MapBuilder,
Position, TileType, SHOW_MAPGEN,
};
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::HashMap;

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, InitialMapBuilder, Rect };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
pub struct SimpleMapBuilder {
room_params: (i32, i32, i32),
@ -7,7 +7,7 @@ pub struct SimpleMapBuilder {
impl InitialMapBuilder for SimpleMapBuilder {
#[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);
}
}

View file

@ -1,16 +1,17 @@
use super::{ BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType, FillEdges };
use std::collections::HashSet;
use crate::data::names::*;
use bracket_lib::prelude::*;
pub fn town_builder(
new_id: i32,
_rng: &mut rltk::RandomNumberGenerator,
_rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
difficulty: i32,
initial_player_level: i32
) -> 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(
false,
new_id,
@ -32,7 +33,7 @@ pub struct TownBuilder {}
impl InitialMapBuilder for TownBuilder {
#[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);
}
}
@ -52,7 +53,7 @@ impl 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
for t in build_data.map.visible_tiles.iter_mut() {
*t = true;
@ -64,8 +65,20 @@ impl TownBuilder {
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 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(build_data, &piers, TileType::Road, TileType::Road, false);
self.path_from_tiles_to_nearest_tiletype(
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
let building_size = self.sort_buildings(&buildings);
@ -81,7 +94,10 @@ impl TownBuilder {
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
let mut building_size: Vec<(usize, i32, BuildingTag)> = Vec::new();
for (i, building) in buildings.iter().enumerate() {
@ -105,7 +121,7 @@ impl TownBuilder {
fn building_factory(
&mut self,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap,
buildings: &[(i32, i32, i32, i32)],
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() {
if *tt == TileType::Bridge && rng.roll_dice(1, 20) == 1 {
let roll = rng.roll_dice(1, 2);
@ -139,7 +155,7 @@ impl TownBuilder {
fn spawn_townsfolk(
&mut self,
build_data: &mut BuilderMap,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
available_building_tiles: &mut HashSet<usize>
) {
for idx in available_building_tiles.iter() {
@ -176,7 +192,7 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
build_data: &mut BuilderMap,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
to_place: &mut Vec<&str>,
avoid_tile: usize
) {
@ -201,9 +217,12 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
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
let mut to_place: Vec<&str> = vec![
@ -224,7 +243,7 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
build_data: &mut BuilderMap,
rng: &mut rltk::RandomNumberGenerator
rng: &mut RandomNumberGenerator
) {
let mut to_place: Vec<&str> = vec![
"npc_priest",
@ -244,10 +263,13 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
build_data: &mut BuilderMap,
rng: &mut rltk::RandomNumberGenerator
rng: &mut RandomNumberGenerator
) {
// 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;
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)
@ -257,9 +279,15 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
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);
}
@ -267,9 +295,14 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
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);
}
@ -277,7 +310,7 @@ impl TownBuilder {
&mut self,
building: &(i32, i32, i32, i32),
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"];
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
@ -291,7 +324,11 @@ impl TownBuilder {
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 water_width: Vec<i32> = Vec::new();
let variance = 5;
@ -300,7 +337,8 @@ impl TownBuilder {
let sand_width = shallow_width + 4;
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);
n += 0.1;
for x in 0..n_water {
@ -374,7 +412,7 @@ impl TownBuilder {
fn town_walls(
&mut self,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap
) -> (HashSet<usize>, i32) {
let mut available_building_tiles: HashSet<usize> = HashSet::new();
@ -385,7 +423,10 @@ impl TownBuilder {
const HALF_PATH_THICKNESS: i32 = 3;
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 {
if !(y > wall_gap_y - HALF_PATH_THICKNESS && y < wall_gap_y + HALF_PATH_THICKNESS) {
@ -438,7 +479,7 @@ impl TownBuilder {
fn buildings(
&mut self,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap,
available_building_tiles: &mut HashSet<usize>
) -> Vec<(i32, i32, i32, i32)> {
@ -452,7 +493,9 @@ impl TownBuilder {
const MAX_BUILDING_SIZE: i32 = 10;
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 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;
@ -500,10 +543,16 @@ impl TownBuilder {
if build_data.map.tiles[idx + 1] != TileType::WoodFloor {
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;
}
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;
}
if neighbours > 0 {
@ -520,7 +569,7 @@ impl TownBuilder {
fn add_doors(
&mut self,
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap,
buildings: &mut Vec<(i32, i32, i32, i32)>,
wall_gap_y: i32
@ -556,23 +605,26 @@ impl TownBuilder {
build_data.map.populate_blocked();
for tile_idx in tiles.iter() {
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)
);
for r in roads.iter() {
nearest_tiletype.push((
*r,
rltk::DistanceAlg::Manhattan.distance2d(
DistanceAlg::Manhattan.distance2d(
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());
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 {
for step in path.steps.iter() {
let idx = *step as usize;

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, InitialMapBuilder, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)]
#[allow(dead_code)]
@ -16,7 +16,7 @@ pub struct VoronoiBuilder {
impl InitialMapBuilder for VoronoiBuilder {
#[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);
}
}
@ -40,20 +40,21 @@ impl VoronoiBuilder {
#[allow(clippy::map_entry)]
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!
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 {
let vx = rng.roll_dice(1, build_data.map.width - 1);
let vy = rng.roll_dice(1, build_data.map.height - 1);
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) {
voronoi_seeds.push(candidate);
}
}
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() {
let x = (i as i32) % build_data.map.width;
let y = (i as i32) / build_data.map.width;
@ -62,13 +63,16 @@ impl VoronoiBuilder {
let distance;
match self.distance_algorithm {
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 => {
distance = rltk::DistanceAlg::Manhattan.distance2d(rltk::Point::new(x, y), pos.1);
distance = DistanceAlg::Manhattan.distance2d(Point::new(x, y), pos.1);
}
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);

View file

@ -1,12 +1,12 @@
use super::{ spawner, BuilderMap, MetaMapBuilder, TileType };
use super::{ spawner, BuilderMap, MetaMapBuilder };
use crate::tile_walkable;
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
use std::collections::HashMap;
pub struct 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);
}
}
@ -20,10 +20,10 @@ impl VoronoiSpawning {
#[allow(clippy::map_entry)]
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
let mut noise_areas: HashMap<i32, Vec<usize>> = HashMap::new();
let mut noise = rltk::FastNoise::seeded(rng.roll_dice(1, 65536) as u64);
noise.set_noise_type(rltk::NoiseType::Cellular);
let mut noise = FastNoise::seeded(rng.roll_dice(1, 65536) as u64);
noise.set_noise_type(NoiseType::Cellular);
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 x in 1..build_data.map.width - 1 {

View file

@ -1,7 +1,13 @@
use super::{ Map, MapChunk, TileType };
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_y = map.height / chunk_size;
let mut patterns = Vec::new();
@ -49,16 +55,22 @@ pub fn build_patterns(map: &Map, chunk_size: i32, include_flipping: bool, dedupe
// 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
patterns.extend(set.into_iter());
rltk::console::log(format!("There are {} patterns.", patterns.len()));
console::log(format!("There are {} patterns.", patterns.len()));
}
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;
for tile_y 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() {
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;
}
}
for (x, southbound) in chunk.exits[1].iter().enumerate() {
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;
}
}
for (x, westbound) in chunk.exits[2].iter().enumerate() {
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;
}
}
for (x, eastbound) in chunk.exits[3].iter().enumerate() {
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;
}
}

View file

@ -1,5 +1,5 @@
use super::{ BuilderMap, Map, MetaMapBuilder, TileType };
use rltk::RandomNumberGenerator;
use bracket_lib::prelude::*;
mod common;
use common::*;
mod constraints;
@ -11,7 +11,7 @@ use solver::*;
pub struct 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);
}
}
@ -54,7 +54,12 @@ impl WaveFunctionCollapseBuilder {
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(
false,
0,

View file

@ -1,5 +1,6 @@
use super::{ Map, MapChunk };
use std::collections::HashSet;
use bracket_lib::prelude::*;
pub struct Solver {
constraints: Vec<MapChunk>,
@ -16,7 +17,7 @@ impl Solver {
let chunks_x = (map.width / chunk_size) as usize;
let chunks_y = (map.height / chunk_size) as usize;
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));
}
@ -32,7 +33,7 @@ impl Solver {
}
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 {
@ -99,8 +100,11 @@ impl Solver {
self.remaining = remain_copy;
// Pick a random chunk we haven't dealt with yet and get its index, remove from remaining list
let remaining_index =
if !neighbours_exist { (rng.roll_dice(1, self.remaining.len() as i32) - 1) as usize } else { 0usize };
let remaining_index = if !neighbours_exist {
(rng.roll_dice(1, self.remaining.len() as i32) - 1) as usize
} else {
0usize
};
let chunk_index = self.remaining[remaining_index].0;
self.remaining.remove(remaining_index);
@ -158,10 +162,10 @@ impl Solver {
// 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;
self.chunks[chunk_index] = Some(new_chunk_idx);
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 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 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 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 mut i: usize = 0;
for y in top_y..bottom_y {
@ -195,18 +199,21 @@ impl Solver {
}
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;
return true;
} else {
let new_chunk_idx =
if possible_options.len() == 1 { 0 } else { rng.roll_dice(1, possible_options.len() as i32) - 1 };
let new_chunk_idx = if possible_options.len() == 1 {
0
} else {
rng.roll_dice(1, possible_options.len() as i32) - 1
};
self.chunks[chunk_index] = Some(new_chunk_idx as usize);
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 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 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 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 mut i: usize = 0;
for y in top_y..bottom_y {

View file

@ -25,7 +25,7 @@ use super::{
WeaponAttribute,
config::CONFIG,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct MeleeCombatSystem {}
@ -50,7 +50,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
ReadStorage<'a, HungerClock>,
ReadStorage<'a, MultiAttack>,
ReadStorage<'a, Blind>,
WriteExpect<'a, rltk::RandomNumberGenerator>,
WriteExpect<'a, RandomNumberGenerator>,
);
fn run(&mut self, data: Self::SystemData) {
@ -194,7 +194,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
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;
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.
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_name = names.get(wants_melee.target).unwrap();
if CONFIG.logging.log_combat {
rltk::console::log(
console::log(
format!(
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} ({} + {}AC + {}to-hit)",
&name.name,
@ -228,8 +233,14 @@ impl<'a> System<'a> for MeleeCombatSystem {
if d20 < target_number {
// Target hit!
let base_damage = rng.roll_dice(weapon_info.damage_n_dice, weapon_info.damage_die_type);
let skill_damage_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
let base_damage = rng.roll_dice(
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;
match weapon_info.attribute {
WeaponAttribute::Dexterity => {
@ -239,17 +250,23 @@ impl<'a> System<'a> for MeleeCombatSystem {
attribute_damage_bonus += attacker_attributes.strength.bonus;
}
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;
} else {
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 {
rltk::console::log(
console::log(
format!(
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
&name.name,
@ -267,7 +284,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
damage = i32::min(1, damage - ac_damage_reduction);
if CONFIG.logging.log_combat {
rltk::console::log(
console::log(
format!(
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
&target_name.name,
@ -321,7 +338,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
}
} else {
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);
@ -365,7 +382,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
}
fn get_natural_attacks(
rng: &mut rltk::RandomNumberGenerator,
rng: &mut RandomNumberGenerator,
nat: NaturalAttacks,
multi_attack: bool,
attacks: &mut Vec<(MeleeWeapon, String)>

View file

@ -6,8 +6,8 @@ use crate::gamelog;
use crate::components::*;
use crate::gui::{ Class, Ancestry, unobf_name_ecs };
use specs::prelude::*;
use rltk::prelude::*;
use rltk::to_char;
use bracket_lib::prelude::*;
use to_char;
use std::collections::HashMap;
use crate::data::events::*;
@ -49,7 +49,14 @@ fn create_file_name(ecs: &World, morgue_dir: &str) -> String {
Ancestry::Catfolk => "catfolk",
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 {
@ -165,7 +172,12 @@ fn draw_map(ecs: &World) -> String {
}
});
} 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);
result.push_str(&char.to_string());
@ -201,7 +213,11 @@ fn draw_equipment(ecs: &World) -> String {
EquipmentSlot::Back => "back -",
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("\n");
@ -211,7 +227,11 @@ fn draw_equipment(ecs: &World) -> String {
fn draw_backpack(ecs: &World) -> String {
// Get all of the player's backpack.
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()
.filter(|item| item.1.owner == *ecs.fetch::<Entity>()) {
pack.entry(unobf_name_ecs(ecs, entity))

View file

@ -1,5 +1,5 @@
use super::{ ParticleLifetime, Position, Renderable, Rltk };
use rltk::RGB;
use super::{ ParticleLifetime, Position, Renderable, BTerm };
use bracket_lib::prelude::*;
use specs::prelude::*;
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
// delay. When delay is <= 0, make a particle_builder.request for
// 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);
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();
{
// Age out particles
@ -39,7 +39,7 @@ pub fn check_queue(ecs: &World) -> bool {
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 handled_particles: Vec<ParticleRequest> = Vec::new();
for delayed_particle in particle_builder.delayed_requests.iter_mut() {
@ -76,11 +76,20 @@ fn create_delayed_particles(ecs: &mut World, ctx: &Rltk) {
.unwrap();
particle_builder.delayed_requests.remove(index);
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
.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");
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,
fg: RGB,
bg: RGB,
glyph: rltk::FontCharType,
glyph: FontCharType,
lifetime: f32,
}
@ -112,11 +121,28 @@ impl ParticleBuilder {
}
/// 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 });
}
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 {
delay: delay,
particle: ParticleRequest { x, y, fg, bg, glyph, lifetime },
@ -127,9 +153,9 @@ impl ParticleBuilder {
self.request(
x,
y,
rltk::RGB::named(rltk::ORANGE),
rltk::RGB::named(rltk::BLACK),
rltk::to_cp437('‼'),
RGB::named(ORANGE),
RGB::named(BLACK),
to_cp437('‼'),
DEFAULT_PARTICLE_LIFETIME
);
}
@ -138,9 +164,9 @@ impl ParticleBuilder {
self.request(
x,
y,
rltk::RGB::named(rltk::CYAN),
rltk::RGB::named(rltk::BLACK),
rltk::to_cp437('‼'),
RGB::named(CYAN),
RGB::named(BLACK),
to_cp437('‼'),
DEFAULT_PARTICLE_LIFETIME
);
}
@ -149,9 +175,9 @@ impl ParticleBuilder {
self.request(
x,
y,
rltk::RGB::named(rltk::CHOCOLATE),
rltk::RGB::named(rltk::BLACK),
rltk::to_cp437('‼'),
RGB::named(CHOCOLATE),
RGB::named(BLACK),
to_cp437('‼'),
SHORT_PARTICLE_LIFETIME
);
}
@ -164,57 +190,97 @@ impl ParticleBuilder {
y: i32,
fg: RGB,
bg: RGB,
glyph: rltk::FontCharType,
glyph: FontCharType,
lifetime: f32,
secondary_fg: RGB
) {
let eighth_l = lifetime / 8.0;
let quarter_l = eighth_l * 2.0;
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(x + 1, y - 1, secondary_fg.lerp(bg, 0.6), bg, rltk::to_cp437('\\'), quarter_l, quarter_l);
self.delay(x - 1, y - 1, secondary_fg.lerp(bg, 0.2), bg, rltk::to_cp437('/'), quarter_l, eighth_l * 3.0);
self.delay(x - 1, y + 1, secondary_fg.lerp(bg, 0.4), bg, rltk::to_cp437('\\'), quarter_l, lifetime);
self.delay(
x + 1,
y + 1,
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.
#[allow(dead_code)]
pub fn request_rainbow_star(&mut self, x: i32, y: i32, glyph: rltk::FontCharType, lifetime: f32) {
let bg = RGB::named(rltk::BLACK);
pub fn request_rainbow_star(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) {
let bg = RGB::named(BLACK);
let eighth_l = lifetime / 8.0;
let quarter_l = eighth_l * 2.0;
let half_l = quarter_l * 2.0;
self.request(x, y, RGB::named(rltk::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(rltk::ORANGE), bg, rltk::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(rltk::YELLOW), bg, rltk::to_cp437('/'), half_l, half_l);
self.request(x, y, RGB::named(CYAN), bg, glyph, lifetime);
self.delay(x + 1, y + 1, RGB::named(RED), bg, to_cp437('\\'), half_l, eighth_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(GREEN), bg, to_cp437('\\'), half_l, eighth_l * 3.0);
self.delay(x - 1, y + 1, RGB::named(YELLOW), bg, to_cp437('/'), half_l, half_l);
}
// Makes a rainbow particle request. Sort of.
#[allow(dead_code)]
pub fn request_rainbow(&mut self, x: i32, y: i32, glyph: rltk::FontCharType, lifetime: f32) {
let bg = RGB::named(rltk::BLACK);
pub fn request_rainbow(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) {
let bg = RGB::named(BLACK);
let eighth_l = lifetime / 8.0;
self.request(x, y, RGB::named(rltk::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(rltk::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(rltk::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(rltk::VIOLET), bg, glyph, eighth_l, eighth_l * 6.0);
self.request(x, y, RGB::named(RED), bg, glyph, eighth_l);
self.delay(x, y, RGB::named(ORANGE), bg, glyph, eighth_l, eighth_l);
self.delay(x, y, RGB::named(YELLOW), bg, glyph, eighth_l, eighth_l * 2.0);
self.delay(x, y, RGB::named(GREEN), bg, glyph, eighth_l, eighth_l * 3.0);
self.delay(x, y, RGB::named(BLUE), bg, glyph, eighth_l, eighth_l * 4.0);
self.delay(x, y, RGB::named(INDIGO), bg, glyph, eighth_l, eighth_l * 5.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 +.
#[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 + 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
self.request(x - 1, y, fg, bg, rltk::to_cp437('─'), lifetime);
self.request(x, y + 1, fg, bg, rltk::to_cp437('│'), lifetime);
self.request(x, y - 1, fg, bg, rltk::to_cp437('│'), lifetime);
self.request(x + 1, y, fg, bg, to_cp437('─'), lifetime);
self.request(x - 1, y, fg, bg, to_cp437('─'), lifetime);
self.request(x, y + 1, fg, bg, 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() {
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
.insert(p, Renderable {
fg: new_particle.fg,

View file

@ -19,7 +19,6 @@ use super::{
Item,
Map,
Name,
ParticleBuilder,
Player,
Pools,
Position,
@ -34,8 +33,7 @@ use super::{
get_dest,
Destination,
};
use rltk::prelude::*;
use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode };
use bracket_lib::prelude::*;
use specs::prelude::*;
use std::cmp::{ max, min };
use crate::data::events::*;
@ -133,7 +131,7 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
std::mem::drop(renderables);
let mut renderables = ecs.write_storage::<Renderable>();
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));
}
result = RunState::Ticking;
@ -230,7 +228,7 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
std::mem::drop(renderables);
let mut renderables = ecs.write_storage::<Renderable>();
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));
}
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 {
None => {
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 {
let mut idx = map.xy_idx(player_pos.x, player_pos.y);
map.blocked[idx] = false;

View file

@ -1,4 +1,4 @@
use rltk::RandomNumberGenerator;
use bracket_lib::random::RandomNumberGenerator;
// FIXME: note to self,
// passing around strings here is super inefficient, so this is

View file

@ -15,6 +15,7 @@ mod reaction_structs;
pub use reaction_structs::Reaction;
use reaction_structs::{ AncestryData, FactionData };
use std::sync::Mutex;
use bracket_lib::prelude::*;
lazy_static! {
pub static ref RAWS: Mutex<RawMaster> = Mutex::new(RawMaster::empty());
@ -31,22 +32,22 @@ pub struct Raws {
pub ancestries: Vec<AncestryData>,
}
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
rltk::embedded_resource!(RAW_MOBS, "../../raws/mobs.json");
rltk::embedded_resource!(RAW_PROPS, "../../raws/props.json");
rltk::embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
rltk::embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
rltk::embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
rltk::embedded_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
embedded_resource!(RAW_ITEMS, "../../raws/items.json");
embedded_resource!(RAW_MOBS, "../../raws/mobs.json");
embedded_resource!(RAW_PROPS, "../../raws/props.json");
embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
embedded_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
pub fn load_raws() {
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
rltk::link_resource!(RAW_MOBS, "../../raws/mobs.json");
rltk::link_resource!(RAW_PROPS, "../../raws/props.json");
rltk::link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
rltk::link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
rltk::link_resource!(RAW_FACTIONS, "../../raws/factions.json");
rltk::link_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
link_resource!(RAW_ITEMS, "../../raws/items.json");
link_resource!(RAW_MOBS, "../../raws/mobs.json");
link_resource!(RAW_PROPS, "../../raws/props.json");
link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
link_resource!(RAW_FACTIONS, "../../raws/factions.json");
link_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
let decoded_raws = get_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 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 spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector("../../raws/spawn_tables.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());
let spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector(
"../../raws/spawn_tables.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 };
}
@ -71,7 +80,7 @@ macro_rules! impl_ParseJson {
(for $($t:ty),+) => {
$(impl ParseJson for $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.");
return serde_json::from_str(&raw_string).expect("Failed to convert &str to json");
}

View file

@ -6,7 +6,7 @@ use crate::random_table::RandomTable;
use crate::config::CONFIG;
use crate::data::visuals::BLOODSTAIN_COLOUR;
use regex::Regex;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use specs::saveload::{ MarkedBuilder, SimpleMarker };
use std::collections::{ HashMap, HashSet };
@ -98,7 +98,7 @@ macro_rules! apply_flags {
"LARGE_GROUP" => {} // and don't need to apply a component.
"MULTIATTACK" => $eb = $eb.with(MultiAttack {}),
"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.
fn check_for_duplicate_entries(used_names: &HashSet<String>, id: &String) {
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.
fn check_for_unspecified_entity(used_names: &HashSet<String>, id: &String) {
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 ---
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(Item { weight: item_template.weight.unwrap_or(0.0), value: item_template.value.unwrap_or(0.0) });
eb = eb.with(Name {
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);
if let Some(renderable) = &item_template.renderable {
@ -379,7 +385,11 @@ pub fn spawn_named_mob(
eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
eb = spawn_position(pos, eb, key, raws);
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 {
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 };
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;
// 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
@ -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);
// 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_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 };
@ -497,7 +511,7 @@ pub fn spawn_named_mob(
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 {
rltk::console::log(
console::log(
format!(
"SPAWNLOG: {} ({}HP, {}MANA, {}BAC) spawned at level {} ({}[base], {}[map difficulty], {}[player level]), worth {} XP",
&mob_template.name,
@ -569,7 +583,14 @@ pub fn spawn_named_mob(
// Build entity, then check for anything they're wearing
if let Some(wielding) = &mob_template.equipped {
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
}
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) {
// ENTITY BUILDER PREP
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
}
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;
match pos {
@ -629,11 +660,13 @@ fn spawn_position<'a>(pos: SpawnType, new_entity: EntityBuilder<'a>, tag: &str,
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 {
glyph: rltk::to_cp437(renderable.glyph.chars().next().unwrap()),
fg: rltk::RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
bg: rltk::RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
glyph: to_cp437(renderable.glyph.chars().next().unwrap()),
fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
render_order: renderable.order,
}
}
@ -668,7 +701,7 @@ pub fn table_by_name(raws: &RawMaster, key: &str, optional_difficulty: Option<i3
return rt;
}
}
rltk::console::log(
console::log(
format!(
"DEBUGINFO: Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}]. Returned debug entry.",
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);
}
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) {
console::log(format!("DEBUGINFO: Rolling on loot table: {}", key));
let mut rt = RandomTable::new();
@ -792,7 +829,11 @@ pub fn get_mob_spawn_type(raws: &RawMaster, key: &str) -> SpawnsAs {
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 {
// Single mobs always spawn alone.
SpawnsAs::Single => 1,
@ -893,7 +934,11 @@ pub fn faction_reaction(this_faction: &str, other_faction: &str, raws: &RawMaste
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 {
return Some(Reaction::Ignore);
} else {

View file

@ -1,8 +1,8 @@
use rltk::rex::XpFile;
use bracket_lib::prelude::*;
rltk::embedded_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
rltk::embedded_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
rltk::embedded_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
embedded_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
embedded_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
embedded_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
pub struct RexAssets {
pub menu: XpFile,
@ -11,9 +11,9 @@ pub struct RexAssets {
impl RexAssets {
#[allow(clippy::new_without_default)]
pub fn new() -> RexAssets {
rltk::link_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
rltk::link_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
rltk::link_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
link_resource!(TITLEIMAGE_105_56_BYTES, "../resources/title_image.xp");
link_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp");
link_resource!(WFC_POPULATED, "../resources/wfc-populated.xp");
RexAssets { menu: XpFile::from_resource("../resources/title_image.xp").unwrap() }
}

View file

@ -1,4 +1,5 @@
use super::components::*;
use bracket_lib::prelude::*;
use specs::error::NoError;
use specs::prelude::*;
use specs::saveload::{
@ -293,8 +294,8 @@ pub fn load_game(ecs: &mut World) {
crate::gamelog::restore_events(h.events.clone());
}
for (e, _p, pos) in (&entities, &player, &position).join() {
let mut ppos = ecs.write_resource::<rltk::Point>();
*ppos = rltk::Point::new(pos.x, pos.y);
let mut ppos = ecs.write_resource::<Point>();
*ppos = Point::new(pos.x, pos.y);
let mut player_resource = ecs.write_resource::<Entity>();
*player_resource = e;
}

View file

@ -21,7 +21,6 @@ use super::{
SerializeMe,
Skill,
Skills,
TileType,
tile_walkable,
Viewshed,
BlocksTile,
@ -30,7 +29,7 @@ use super::{
use crate::data::entity;
use crate::data::visuals::BLOODSTAIN_COLOUR;
use crate::gamesystem::*;
use rltk::{ RandomNumberGenerator, RGB };
use bracket_lib::prelude::*;
use specs::prelude::*;
use specs::saveload::{ MarkedBuilder, SimpleMarker };
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(BlocksTile {})
.with(Renderable {
glyph: rltk::to_cp437('@'),
fg: RGB::named(rltk::YELLOW),
bg: RGB::named(rltk::BLACK),
glyph: to_cp437('@'),
fg: RGB::named(YELLOW),
bg: RGB::named(BLACK),
render_order: 0,
})
.with(Bleeds { colour: RGB::named(BLOODSTAIN_COLOUR) })
@ -132,7 +131,7 @@ pub fn spawn_region(
let difficulty = (map.difficulty + player_level) / 2;
// If no area, log and return.
if areas.len() == 0 {
rltk::console::log("DEBUGINFO: No areas capable of spawning mobs!");
console::log("DEBUGINFO: No areas capable of spawning mobs!");
return;
}
// Get num of each entity type.
@ -212,7 +211,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
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?

View file

@ -1,5 +1,5 @@
use specs::prelude::*;
use rltk::prelude::*;
use bracket_lib::prelude::*;
use super::runstate::RunState;
use crate::map::*;
use crate::hunger_system;
@ -125,7 +125,7 @@ impl State {
.append("You head to")
.colour(rgb_to_u8(get_local_col(id)))
.append_n(&mapname)
.colour(rltk::WHITE)
.colour(WHITE)
.period()
.log();
gamelog::record_event(EVENT::CHANGED_FLOOR(mapname));
@ -157,7 +157,7 @@ impl State {
}
impl GameState for State {
fn tick(&mut self, ctx: &mut Rltk) {
fn tick(&mut self, ctx: &mut BTerm) {
let mut new_runstate;
{
let runstate = self.ecs.fetch::<RunState>();
@ -581,6 +581,6 @@ impl GameState for State {
damage_system::delete_the_dead(&mut self.ecs);
let _ = rltk::render_draw_buffer(ctx);
let _ = render_draw_buffer(ctx);
}
}

View file

@ -11,7 +11,7 @@ use super::{
Renderable,
AOE,
};
use rltk::prelude::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct TriggerSystem {}
@ -30,7 +30,8 @@ impl<'a> System<'a> for TriggerSystem {
);
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() {
let idx = map.xy_idx(pos.x, pos.y);
crate::spatial::for_each_tile_content(idx, |entity_id| {
@ -51,15 +52,21 @@ impl<'a> System<'a> for TriggerSystem {
.log();
}
}
add_effect(Some(entity_id), EffectType::TriggerFire { trigger: entity_id }, if
let Some(aoe) = aoes.get(entity_id)
{
add_effect(
Some(entity_id),
EffectType::TriggerFire { trigger: entity_id },
if let Some(aoe) = aoes.get(entity_id) {
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 {
Targets::Tile { target: idx }
});
}
);
}
}
}

View file

@ -12,7 +12,8 @@ use super::{
Renderable,
gui::renderable_colour,
};
use rltk::{ FieldOfViewAlg::SymmetricShadowcasting, Point };
use bracket_lib::prelude::*;
use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting;
use specs::prelude::*;
pub struct VisibilitySystem {}
@ -22,7 +23,7 @@ const BLIND_TELEPATHY_RANGE_MULTIPLIER: i32 = 3;
impl<'a> System<'a> for VisibilitySystem {
type SystemData = (
WriteExpect<'a, Map>,
WriteExpect<'a, rltk::RandomNumberGenerator>,
WriteExpect<'a, RandomNumberGenerator>,
Entities<'a>,
WriteStorage<'a, Viewshed>,
WriteStorage<'a, Telepath>,
@ -73,7 +74,7 @@ impl<'a> System<'a> for VisibilitySystem {
p.y >= 0 &&
p.y < map.height &&
(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
@ -99,7 +100,7 @@ impl<'a> System<'a> for VisibilitySystem {
.append("You spot a")
.colour(renderable_colour(&renderables, e))
.append_n(&name.name)
.colour(rltk::WHITE)
.colour(WHITE)
.period()
.log();
}
@ -120,7 +121,9 @@ impl<'a> System<'a> for VisibilitySystem {
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
}
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
let _p: Option<&Player> = player.get(ent);