Merge branch 'master' into switching_to_draw_batches
This commit is contained in:
commit
441b22439f
119 changed files with 1851 additions and 3612 deletions
|
|
@ -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 {}
|
||||
|
|
@ -7,7 +7,6 @@ pub struct ApproachAI {}
|
|||
impl<'a> System<'a> for ApproachAI {
|
||||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
WriteExpect<'a, RandomNumberGenerator>,
|
||||
WriteStorage<'a, TakingTurn>,
|
||||
WriteStorage<'a, WantsToApproach>,
|
||||
WriteStorage<'a, Position>,
|
||||
|
|
@ -20,7 +19,6 @@ impl<'a> System<'a> for ApproachAI {
|
|||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut rng,
|
||||
mut turns,
|
||||
mut wants_to_approach,
|
||||
mut positions,
|
||||
|
|
@ -50,7 +48,7 @@ impl<'a> System<'a> for ApproachAI {
|
|||
let mut curr_abs_diff = 100;
|
||||
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() ||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ use crate::{
|
|||
Map,
|
||||
TakingTurn,
|
||||
Confusion,
|
||||
Intrinsics,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use crate::config::CONFIG;
|
||||
use crate::data::events::*;
|
||||
|
|
@ -36,6 +37,7 @@ impl<'a> System<'a> for EnergySystem {
|
|||
ReadStorage<'a, Name>,
|
||||
ReadExpect<'a, Point>,
|
||||
ReadStorage<'a, Confusion>,
|
||||
ReadStorage<'a, Intrinsics>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
|
|
@ -53,6 +55,7 @@ impl<'a> System<'a> for EnergySystem {
|
|||
names,
|
||||
player_pos,
|
||||
confusion,
|
||||
intrinsics,
|
||||
) = data;
|
||||
// If not ticking, do nothing.
|
||||
if *runstate != RunState::Ticking {
|
||||
|
|
@ -68,7 +71,7 @@ impl<'a> System<'a> for EnergySystem {
|
|||
.insert(entity, TakingTurn {})
|
||||
.expect("Unable to insert turn for turn counter.");
|
||||
energy.current -= TURN_COST;
|
||||
crate::gamelog::record_event(EVENT::TURN(1));
|
||||
crate::gamelog::record_event(EVENT::Turn(1));
|
||||
// Handle spawning mobs each turn
|
||||
if CONFIG.logging.log_ticks {
|
||||
console::log(
|
||||
|
|
@ -87,20 +90,14 @@ impl<'a> System<'a> for EnergySystem {
|
|||
&positions,
|
||||
!&confusion,
|
||||
).join() {
|
||||
let burden_modifier = if let Some(burden) = burdens.get(entity) {
|
||||
match burden.level {
|
||||
BurdenLevel::Burdened => SPEED_MOD_BURDENED,
|
||||
BurdenLevel::Strained => SPEED_MOD_STRAINED,
|
||||
BurdenLevel::Overloaded => SPEED_MOD_OVERLOADED,
|
||||
}
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let overmap_mod = if map.overmap { SPEED_MOD_OVERMAP_TRAVEL } else { 1.0 };
|
||||
let burden_modifier = get_burden_modifier(&burdens, entity);
|
||||
let overmap_mod = get_overmap_modifier(&map);
|
||||
let intrinsic_speed = get_intrinsic_speed(&intrinsics, entity);
|
||||
// Every entity has a POTENTIAL equal to their speed.
|
||||
let mut energy_potential: i32 = ((energy.speed as f32) *
|
||||
burden_modifier *
|
||||
overmap_mod) as i32;
|
||||
overmap_mod *
|
||||
intrinsic_speed) as i32;
|
||||
// Increment current energy by NORMAL_SPEED for every
|
||||
// whole number of NORMAL_SPEEDS in their POTENTIAL.
|
||||
while energy_potential >= NORMAL_SPEED {
|
||||
|
|
@ -121,37 +118,61 @@ impl<'a> System<'a> for EnergySystem {
|
|||
// has enough energy, they take a turn and decrement their energy
|
||||
// by TURN_COST. If the current entity is the player, await input.
|
||||
if energy.current >= TURN_COST {
|
||||
let mut my_turn = true;
|
||||
energy.current -= TURN_COST;
|
||||
if entity == *player {
|
||||
*runstate = RunState::AwaitingInput;
|
||||
} else {
|
||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(
|
||||
*player_pos,
|
||||
Point::new(pos.x, pos.y)
|
||||
);
|
||||
if distance > 20.0 {
|
||||
my_turn = false;
|
||||
}
|
||||
} else if cull_turn_by_distance(&player_pos, pos) {
|
||||
continue;
|
||||
}
|
||||
if my_turn {
|
||||
turns.insert(entity, TakingTurn {}).expect("Unable to insert turn.");
|
||||
if CONFIG.logging.log_ticks {
|
||||
let name = if let Some(name) = names.get(entity) {
|
||||
&name.name
|
||||
} else {
|
||||
"Unknown entity"
|
||||
};
|
||||
console::log(
|
||||
format!(
|
||||
"ENERGY SYSTEM: {} granted a turn. [leftover energy: {}].",
|
||||
name,
|
||||
energy.current
|
||||
)
|
||||
);
|
||||
}
|
||||
turns.insert(entity, TakingTurn {}).expect("Unable to insert turn.");
|
||||
if CONFIG.logging.log_ticks {
|
||||
let name = if let Some(name) = names.get(entity) {
|
||||
&name.name
|
||||
} else {
|
||||
"Unknown entity"
|
||||
};
|
||||
console::log(
|
||||
format!(
|
||||
"ENERGY SYSTEM: {} granted a turn. [leftover energy: {}].",
|
||||
name,
|
||||
energy.current
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_burden_modifier(burdens: &ReadStorage<Burden>, entity: Entity) -> f32 {
|
||||
return if let Some(burden) = burdens.get(entity) {
|
||||
match burden.level {
|
||||
BurdenLevel::Burdened => SPEED_MOD_BURDENED,
|
||||
BurdenLevel::Strained => SPEED_MOD_STRAINED,
|
||||
BurdenLevel::Overloaded => SPEED_MOD_OVERLOADED,
|
||||
}
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
}
|
||||
|
||||
fn get_overmap_modifier(map: &ReadExpect<Map>) -> f32 {
|
||||
return if map.overmap { SPEED_MOD_OVERMAP_TRAVEL } else { 1.0 };
|
||||
}
|
||||
|
||||
fn cull_turn_by_distance(player_pos: &Point, pos: &Position) -> bool {
|
||||
let distance = DistanceAlg::Pythagoras.distance2d(*player_pos, Point::new(pos.x, pos.y));
|
||||
if distance > 20.0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn get_intrinsic_speed(intrinsics: &ReadStorage<Intrinsics>, entity: Entity) -> f32 {
|
||||
if let Some(intrinsics) = intrinsics.get(entity) {
|
||||
if intrinsics.list.contains(&crate::Intrinsic::Speed) {
|
||||
return 4.0 / 3.0;
|
||||
}
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
Position,
|
||||
RandomNumberGenerator,
|
||||
TakingTurn,
|
||||
Intrinsics,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
use crate::data::events::*;
|
||||
|
|
@ -36,10 +37,24 @@ impl<'a> System<'a> for RegenSystem {
|
|||
ReadStorage<'a, HasClass>,
|
||||
ReadStorage<'a, Attributes>,
|
||||
WriteExpect<'a, RandomNumberGenerator>,
|
||||
ReadStorage<'a, Intrinsics>,
|
||||
ReadExpect<'a, Entity>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (clock, entities, positions, mut pools, turns, player, classes, attributes, mut rng) = data;
|
||||
let (
|
||||
clock,
|
||||
entities,
|
||||
positions,
|
||||
mut pools,
|
||||
turns,
|
||||
player,
|
||||
classes,
|
||||
attributes,
|
||||
mut rng,
|
||||
intrinsics,
|
||||
player_entity,
|
||||
) = data;
|
||||
let mut clock_turn = false;
|
||||
for (_e, _c, _t) in (&entities, &clock, &turns).join() {
|
||||
clock_turn = true;
|
||||
|
|
@ -56,19 +71,29 @@ impl<'a> System<'a> for RegenSystem {
|
|||
}
|
||||
// Player HP regen
|
||||
let level = gamelog::get_event_count(EVENT::COUNT_LEVEL);
|
||||
if current_turn % get_player_hp_regen_turn(level) == 0 {
|
||||
if
|
||||
current_turn % get_player_hp_regen_turn(level) == 0 ||
|
||||
intrinsics.get(*player_entity).unwrap().list.contains(&crate::Intrinsic::Regeneration)
|
||||
{
|
||||
for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, &player).join() {
|
||||
try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level));
|
||||
}
|
||||
}
|
||||
// Both MP regen
|
||||
for (e, _p, pool) in (&entities, &positions, &mut pools).join() {
|
||||
let is_wizard = if let Some(class) = classes.get(e) { class.name == Class::Wizard } else { false };
|
||||
let is_wizard = if let Some(class) = classes.get(e) {
|
||||
class.name == Class::Wizard
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let numerator = if is_wizard { WIZARD_MP_REGEN_MOD } else { NONWIZARD_MP_REGEN_MOD };
|
||||
let multiplier: f32 = (numerator as f32) / (MP_REGEN_DIVISOR as f32);
|
||||
let mp_regen_tick = (((MP_REGEN_BASE - pool.level) as f32) * multiplier) as i32;
|
||||
if current_turn % mp_regen_tick == 0 {
|
||||
try_mana_regen_tick(pool, rng.roll_dice(1, get_mana_regen_per_tick(e, &attributes)));
|
||||
try_mana_regen_tick(
|
||||
pool,
|
||||
rng.roll_dice(1, get_mana_regen_per_tick(e, &attributes))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
Item,
|
||||
Prop,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use crate::data::events::*;
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ impl<'a> System<'a> for TurnStatusSystem {
|
|||
.colour(WHITE)
|
||||
.append("are confused!");
|
||||
log = true;
|
||||
gamelog::record_event(EVENT::PLAYER_CONFUSED(1));
|
||||
gamelog::record_event(EVENT::PlayerConfused(1));
|
||||
} else {
|
||||
logger = logger
|
||||
.append("The")
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use super::{ Hidden, Map, Mind, Position, Prop, Renderable, Pools };
|
||||
use rltk::prelude::*;
|
||||
use super::{ Hidden, Map, Mind, Position, Prop, Renderable };
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use std::ops::Mul;
|
||||
use super::data::visuals::{ VIEWPORT_W, VIEWPORT_H };
|
||||
|
||||
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) = (VIEWPORT_W, VIEWPORT_H, 1, 10);
|
||||
|
|
@ -32,7 +32,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);
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
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::*;
|
||||
use specs::saveload::{ ConvertSaveload, Marker };
|
||||
use specs_derive::*;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{ HashMap, HashSet };
|
||||
|
||||
// Serialization helper code. We need to implement ConvertSaveload for each type that contains an
|
||||
// Entity.
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -316,6 +316,7 @@ pub enum WeaponAttribute {
|
|||
|
||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||
pub struct MeleeWeapon {
|
||||
pub damage_type: DamageType,
|
||||
pub attribute: WeaponAttribute,
|
||||
pub damage_n_dice: i32,
|
||||
pub damage_die_type: i32,
|
||||
|
|
@ -326,6 +327,7 @@ pub struct MeleeWeapon {
|
|||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct NaturalAttack {
|
||||
pub name: String,
|
||||
pub damage_type: DamageType,
|
||||
pub damage_n_dice: i32,
|
||||
pub damage_die_type: i32,
|
||||
pub damage_bonus: i32,
|
||||
|
|
@ -365,8 +367,74 @@ pub struct ProvidesHealing {
|
|||
pub modifier: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum DamageType {
|
||||
Physical,
|
||||
Magic, // e.g. magic missiles, silvered weapons
|
||||
Fire, // e.g. fireball
|
||||
Cold, // e.g. cone of cold
|
||||
Poison, // e.g. poison gas
|
||||
Forced, // Bypasses any immunities. e.g. Hunger ticks.
|
||||
}
|
||||
|
||||
impl DamageType {
|
||||
pub fn is_magic(&self) -> bool {
|
||||
match self {
|
||||
DamageType::Magic | DamageType::Fire | DamageType::Cold => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum DamageModifier {
|
||||
None,
|
||||
Weakness,
|
||||
Resistance,
|
||||
Immune,
|
||||
}
|
||||
|
||||
impl DamageModifier {
|
||||
const NONE_MOD: f32 = 1.0;
|
||||
const WEAK_MOD: f32 = 2.0;
|
||||
const RESIST_MOD: f32 = 0.5;
|
||||
const IMMUNE_MOD: f32 = 0.0;
|
||||
|
||||
pub fn multiplier(&self) -> f32 {
|
||||
match self {
|
||||
DamageModifier::None => Self::NONE_MOD,
|
||||
DamageModifier::Weakness => Self::WEAK_MOD,
|
||||
DamageModifier::Resistance => Self::RESIST_MOD,
|
||||
DamageModifier::Immune => Self::IMMUNE_MOD,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct HasDamageModifiers {
|
||||
pub modifiers: HashMap<DamageType, DamageModifier>,
|
||||
}
|
||||
|
||||
impl HasDamageModifiers {
|
||||
pub fn modifier(&self, damage_type: &DamageType) -> &DamageModifier {
|
||||
self.modifiers.get(damage_type).unwrap_or(&DamageModifier::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Intrinsic {
|
||||
Regeneration, // Regenerate 1 HP on every tick
|
||||
Speed, // 4/3x speed multiplier
|
||||
}
|
||||
|
||||
#[derive(Component, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Intrinsics {
|
||||
pub list: HashSet<Intrinsic>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
||||
pub struct InflictsDamage {
|
||||
pub damage_type: DamageType,
|
||||
pub n_dice: i32,
|
||||
pub sides: i32,
|
||||
pub modifier: i32,
|
||||
|
|
@ -417,7 +485,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 +514,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 +524,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,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use toml::Value;
|
||||
use serde::{ Serialize, Deserialize };
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -81,12 +81,15 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
}
|
||||
// For everything that died, increment the event log, and delete.
|
||||
for victim in dead {
|
||||
gamelog::record_event(events::EVENT::TURN(1));
|
||||
gamelog::record_event(events::EVENT::Turn(1));
|
||||
ecs.delete_entity(victim).expect("Unable to delete.");
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ use serde::{ Deserialize, Serialize };
|
|||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub enum EVENT {
|
||||
TURN(i32),
|
||||
LEVEL(i32),
|
||||
CHANGED_FLOOR(String),
|
||||
PLAYER_CONFUSED(i32),
|
||||
KICKED_SOMETHING(i32),
|
||||
BROKE_DOOR(i32),
|
||||
LOOKED_FOR_HELP(i32),
|
||||
KILLED(String),
|
||||
PLAYER_DIED(String),
|
||||
DISCOVERED(String),
|
||||
IDENTIFIED(String),
|
||||
Turn(i32),
|
||||
Level(i32),
|
||||
ChangedFloor(String),
|
||||
PlayerConfused(i32),
|
||||
KickedSomething(i32),
|
||||
BrokeDoor(i32),
|
||||
LookedForHelp(i32),
|
||||
Killed(String),
|
||||
PlayerDied(String),
|
||||
Discovered(String),
|
||||
Identified(String),
|
||||
}
|
||||
|
||||
impl EVENT {
|
||||
|
|
@ -20,8 +20,8 @@ impl EVENT {
|
|||
pub const COUNT_KILLED: &str = "killed";
|
||||
pub const COUNT_LEVEL: &str = "level";
|
||||
pub const COUNT_CHANGED_FLOOR: &str = "changed_floor";
|
||||
pub const COUNT_BROKE_DOOR: &str = "broke_door";
|
||||
pub const COUNT_PLAYER_CONFUSED: &str = "player_confused";
|
||||
pub const COUNT_BROKE_DOOR: &str = "BrokeDoor";
|
||||
pub const COUNT_PLAYER_CONFUSED: &str = "PlayerConfused";
|
||||
pub const COUNT_KICK: &str = "kick";
|
||||
pub const COUNT_LOOKED_FOR_HELP: &str = "looked_for_help";
|
||||
pub const COUNT_LOOKED_FOR_HELP: &str = "LookedForHelp";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::names::*;
|
||||
use super::visuals::*;
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
|
||||
pub const ID_OVERMAP: i32 = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub const YOU_REMOVE_ITEM_CURSED: &str = "You can't remove the";
|
|||
|
||||
/// Prefixes death message.
|
||||
pub const PLAYER_DIED: &str = "You died!";
|
||||
/// Death message specifiers. Appended after PLAYER_DIED.
|
||||
/// Death message specifiers. Appended after PlayerDied.
|
||||
pub const PLAYER_DIED_SUICIDE: &str = "You killed yourself";
|
||||
pub const PLAYER_DIED_NAMED_ATTACKER: &str = "You were killed by";
|
||||
pub const PLAYER_DIED_UNKNOWN: &str = "You were killed"; // Ultimately, this should never be used. Slowly include specific messages for any death.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
pub const VIEWPORT_W: i32 = 69;
|
||||
|
|
@ -17,8 +19,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,21 +14,29 @@ use crate::{
|
|||
HungerClock,
|
||||
HungerState,
|
||||
Bleeds,
|
||||
HasDamageModifiers,
|
||||
};
|
||||
use crate::gui::with_article;
|
||||
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) {
|
||||
let mut pools = ecs.write_storage::<Pools>();
|
||||
if let Some(target_pool) = pools.get_mut(target) {
|
||||
if !target_pool.god {
|
||||
if let EffectType::Damage { amount } = damage.effect_type {
|
||||
target_pool.hit_points.current -= amount;
|
||||
if let EffectType::Damage { amount, damage_type } = damage.effect_type {
|
||||
let mult = if
|
||||
let Some(modifiers) = ecs.read_storage::<HasDamageModifiers>().get(target)
|
||||
{
|
||||
modifiers.modifier(&damage_type).multiplier()
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
target_pool.hit_points.current -= ((amount as f32) * mult) as i32;
|
||||
let bleeders = ecs.read_storage::<Bleeds>();
|
||||
if let Some(bleeds) = bleeders.get(target) {
|
||||
add_effect(
|
||||
|
|
@ -221,12 +229,12 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
if let Some(source) = effect.source {
|
||||
// If the target was the player, game over, and record source of death.
|
||||
if target == *player {
|
||||
gamelog::record_event(EVENT::PLAYER_DIED(get_death_message(ecs, source)));
|
||||
gamelog::record_event(EVENT::PlayerDied(get_death_message(ecs, source)));
|
||||
return;
|
||||
} else {
|
||||
// If the player was the source, record the kill.
|
||||
if let Some(tar_name) = names.get(target) {
|
||||
gamelog::record_event(EVENT::KILLED(tar_name.name.clone()));
|
||||
gamelog::record_event(EVENT::Killed(tar_name.name.clone()));
|
||||
}
|
||||
}
|
||||
// Calc XP value of target.
|
||||
|
|
@ -246,7 +254,7 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
source_pools.level += 1;
|
||||
// If it was the PLAYER that levelled up:
|
||||
if ecs.read_storage::<Player>().get(source).is_some() {
|
||||
gamelog::record_event(EVENT::LEVEL(1));
|
||||
gamelog::record_event(EVENT::Level(1));
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append(LEVELUP_PLAYER)
|
||||
|
|
@ -328,11 +336,11 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
if target == *player {
|
||||
if let Some(hc) = ecs.read_storage::<HungerClock>().get(target) {
|
||||
if hc.state == HungerState::Starving {
|
||||
gamelog::record_event(EVENT::PLAYER_DIED("You starved to death!".to_string()));
|
||||
gamelog::record_event(EVENT::PlayerDied("You starved to death!".to_string()));
|
||||
}
|
||||
} else {
|
||||
gamelog::record_event(
|
||||
EVENT::PLAYER_DIED("You died from unknown causes!".to_string())
|
||||
EVENT::PlayerDied("You died from unknown causes!".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use super::BUC;
|
||||
use crate::spatial;
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Mutex;
|
||||
use crate::components::DamageType;
|
||||
|
||||
mod damage;
|
||||
mod hunger;
|
||||
|
|
@ -24,6 +25,7 @@ lazy_static! {
|
|||
pub enum EffectType {
|
||||
Damage {
|
||||
amount: i32,
|
||||
damage_type: DamageType,
|
||||
},
|
||||
Healing {
|
||||
amount: i32,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -30,13 +30,12 @@ use crate::{
|
|||
SingleActivation,
|
||||
BUC,
|
||||
GrantsSpell,
|
||||
KnownSpell,
|
||||
KnownSpells,
|
||||
Position,
|
||||
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 +46,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 +84,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 +153,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 +169,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) {
|
||||
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()) {
|
||||
fn handle_grant_spell(
|
||||
ecs: &mut World,
|
||||
event: &mut EventInfo,
|
||||
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())
|
||||
{
|
||||
// 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 +188,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 +200,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,11 +238,19 @@ 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;
|
||||
add_effect(event.source, EffectType::Damage { amount: roll }, event.target.clone());
|
||||
add_effect(
|
||||
event.source,
|
||||
EffectType::Damage { amount: roll, damage_type: damage_item.damage_type },
|
||||
event.target.clone()
|
||||
);
|
||||
for target in get_entity_targets(&event.target) {
|
||||
if ecs.read_storage::<Prop>().get(target).is_some() {
|
||||
continue;
|
||||
|
|
@ -232,7 +267,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 +296,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 +317,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 +352,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);
|
||||
let result =
|
||||
in_this_backpack &&
|
||||
(has_obfuscated_name || !already_identified || !known_beatitude);
|
||||
return result;
|
||||
}) {
|
||||
to_identify.push((e, name.name.clone()));
|
||||
}
|
||||
|
|
@ -313,14 +365,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 +396,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 +427,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::data::names::*;
|
|||
|
||||
lazy_static! {
|
||||
/// A count of each event that has happened over the run. i.e. "turns", "descended", "ascended"
|
||||
static ref EVENT_COUNTER: Mutex<HashMap<String, i32>> = Mutex::new(HashMap::new());
|
||||
pub static ref EVENT_COUNTER: Mutex<HashMap<String, i32>> = Mutex::new(HashMap::new());
|
||||
// A record of events that happened on a given turn. i.e. "Advanced to level 2".
|
||||
pub static ref EVENTS: Mutex<HashMap<u32, Vec<String>>> = Mutex::new(HashMap::new());
|
||||
// A record of floors visited, and monsters killed. Used to determine if an event is significant.
|
||||
|
|
@ -41,8 +41,9 @@ pub fn restore_events(events: HashMap<u32, Vec<String>>) {
|
|||
}
|
||||
/// Wipes all events - for starting a new game.
|
||||
pub fn clear_events() {
|
||||
EVENT_COUNTER.lock().unwrap().clear();
|
||||
EVENTS.lock().unwrap().clear();
|
||||
let (mut events, mut event_counts) = (EVENTS.lock().unwrap(), EVENT_COUNTER.lock().unwrap());
|
||||
events.clear();
|
||||
event_counts.clear();
|
||||
}
|
||||
|
||||
#[allow(unused_mut)]
|
||||
|
|
@ -73,12 +74,12 @@ pub fn record_event(event: EVENT) {
|
|||
let mut new_event: String = "unknown event".to_string();
|
||||
let mut significant_event = true;
|
||||
match event {
|
||||
EVENT::TURN(n) => {
|
||||
EVENT::Turn(n) => {
|
||||
modify_event_count(EVENT::COUNT_TURN, n);
|
||||
significant_event = false;
|
||||
}
|
||||
// If de-levelling is ever implemented, this needs refactoring (along with a lot of stuff).
|
||||
EVENT::LEVEL(n) => {
|
||||
EVENT::Level(n) => {
|
||||
modify_event_count(EVENT::COUNT_LEVEL, n);
|
||||
let new_lvl = get_event_count(EVENT::COUNT_LEVEL);
|
||||
if new_lvl == 1 {
|
||||
|
|
@ -87,7 +88,7 @@ pub fn record_event(event: EVENT) {
|
|||
new_event = format!("Advanced to level {}", new_lvl);
|
||||
}
|
||||
}
|
||||
EVENT::CHANGED_FLOOR(n) => {
|
||||
EVENT::ChangedFloor(n) => {
|
||||
modify_event_count(EVENT::COUNT_CHANGED_FLOOR, 1);
|
||||
if VISITED.lock().unwrap().contains(&n) {
|
||||
significant_event = false;
|
||||
|
|
@ -96,23 +97,23 @@ pub fn record_event(event: EVENT) {
|
|||
new_event = format!("Visited {} for the first time", n);
|
||||
}
|
||||
}
|
||||
EVENT::KICKED_SOMETHING(n) => {
|
||||
EVENT::KickedSomething(n) => {
|
||||
modify_event_count(EVENT::COUNT_KICK, n);
|
||||
significant_event = false;
|
||||
}
|
||||
EVENT::BROKE_DOOR(n) => {
|
||||
EVENT::BrokeDoor(n) => {
|
||||
modify_event_count(EVENT::COUNT_BROKE_DOOR, n);
|
||||
significant_event = false;
|
||||
}
|
||||
EVENT::PLAYER_CONFUSED(n) => {
|
||||
EVENT::PlayerConfused(n) => {
|
||||
modify_event_count(EVENT::COUNT_PLAYER_CONFUSED, n);
|
||||
significant_event = false;
|
||||
}
|
||||
EVENT::LOOKED_FOR_HELP(n) => {
|
||||
EVENT::LookedForHelp(n) => {
|
||||
modify_event_count(EVENT::COUNT_LOOKED_FOR_HELP, n);
|
||||
significant_event = false;
|
||||
}
|
||||
EVENT::KILLED(name) => {
|
||||
EVENT::Killed(name) => {
|
||||
modify_event_count(EVENT::COUNT_KILLED, 1);
|
||||
if KILLED.lock().unwrap().contains(&name) {
|
||||
significant_event = false;
|
||||
|
|
@ -121,13 +122,13 @@ pub fn record_event(event: EVENT) {
|
|||
new_event = format!("Killed your first {}", name);
|
||||
}
|
||||
}
|
||||
EVENT::DISCOVERED(name) => {
|
||||
EVENT::Discovered(name) => {
|
||||
new_event = format!("Discovered {}", name);
|
||||
}
|
||||
EVENT::IDENTIFIED(name) => {
|
||||
EVENT::Identified(name) => {
|
||||
new_event = format!("Identified {}", name);
|
||||
}
|
||||
EVENT::PLAYER_DIED(str) => {
|
||||
EVENT::PlayerDied(str) => {
|
||||
// Generating the String is handled in the death effect, to avoid passing the ecs here.
|
||||
new_event = format!("{}", str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -119,7 +119,7 @@ pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
|||
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 {
|
||||
|
|
@ -271,9 +271,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");
|
||||
|
|
@ -282,9 +282,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");
|
||||
|
|
@ -307,9 +307,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");
|
||||
|
|
@ -453,11 +453,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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
|
||||
pub fn letter_to_option(key: VirtualKeyCode, shift: bool) -> i32 {
|
||||
if shift {
|
||||
|
|
|
|||
112
src/gui/mod.rs
112
src/gui/mod.rs
|
|
@ -62,9 +62,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) =>
|
||||
|
|
@ -77,7 +77,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,
|
||||
|
|
@ -181,8 +181,8 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
ctx.print_color(
|
||||
26 * TEXT_FONT_MOD,
|
||||
54,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
RGB::named(WHITE),
|
||||
RGB::named(BLACK),
|
||||
format!("XP{}/{}", stats.level, stats.xp)
|
||||
);
|
||||
// Draw attributes
|
||||
|
|
@ -327,7 +327,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
}
|
||||
// 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()
|
||||
|
|
@ -472,7 +472,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,
|
||||
|
|
@ -587,7 +587,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
|
||||
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);
|
||||
|
|
@ -595,8 +595,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 {
|
||||
|
|
@ -681,14 +681,14 @@ pub fn print_options(
|
|||
|
||||
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,
|
||||
|
|
@ -701,7 +701,7 @@ pub fn print_options(
|
|||
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']
|
||||
|
|
@ -710,12 +710,12 @@ pub fn print_options(
|
|||
{
|
||||
// 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(
|
||||
|
|
@ -951,7 +951,7 @@ 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;
|
||||
|
|
@ -967,7 +967,7 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
|||
);
|
||||
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, " \\|/ \\|/");
|
||||
|
|
@ -975,7 +975,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;
|
||||
|
|
@ -985,7 +985,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");
|
||||
|
||||
|
|
@ -1139,7 +1139,7 @@ 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();
|
||||
|
||||
|
|
@ -1179,7 +1179,7 @@ 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
|
||||
|
|
@ -1204,7 +1204,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();
|
||||
|
|
@ -1216,8 +1216,8 @@ 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.]"
|
||||
);
|
||||
|
||||
|
|
@ -1235,7 +1235,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;
|
||||
|
|
@ -1244,7 +1244,7 @@ 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,
|
||||
|
|
@ -1255,7 +1255,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
|||
);
|
||||
ctx.set(x + 3, y, fg, RGB::named(rltk::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;
|
||||
}
|
||||
|
|
@ -1266,7 +1266,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));
|
||||
}
|
||||
|
|
@ -1288,7 +1288,7 @@ pub enum TargetResult {
|
|||
|
||||
pub fn ranged_target(
|
||||
gs: &mut State,
|
||||
ctx: &mut Rltk,
|
||||
ctx: &mut BTerm,
|
||||
x: i32,
|
||||
y: i32,
|
||||
range: i32,
|
||||
|
|
@ -1302,8 +1302,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]"
|
||||
);
|
||||
|
||||
|
|
@ -1313,7 +1313,7 @@ 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;
|
||||
|
|
@ -1354,7 +1354,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)
|
||||
|
|
@ -1374,7 +1374,7 @@ 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
|
||||
|
|
@ -1411,7 +1411,7 @@ pub fn ranged_target(
|
|||
}
|
||||
};
|
||||
} 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 {
|
||||
|
|
@ -1450,7 +1450,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>();
|
||||
|
|
@ -1464,8 +1464,8 @@ 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 {
|
||||
|
|
@ -1491,19 +1491,19 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||
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 {
|
||||
|
|
@ -1578,18 +1578,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;
|
||||
|
|
@ -1597,8 +1597,8 @@ 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;
|
||||
|
|
@ -1627,8 +1627,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),
|
||||
|
|
|
|||
|
|
@ -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,33 +35,35 @@ 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)| {
|
||||
// Set all items to FALSE initially.
|
||||
let mut keep = false;
|
||||
// If found in the player's backpack, set to TRUE
|
||||
if let Some(bp) = backpack.get(*item_entity) {
|
||||
if bp.owner == *player_entity {
|
||||
keep = true;
|
||||
(&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
|
||||
if let Some(bp) = backpack.get(*item_entity) {
|
||||
if bp.owner == *player_entity {
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If found in the player's equipslot, set to TRUE
|
||||
if let Some(equip) = equipped.get(*item_entity) {
|
||||
if equip.owner == *player_entity {
|
||||
keep = true;
|
||||
// If found in the player's equipslot, set to TRUE
|
||||
if let Some(equip) = equipped.get(*item_entity) {
|
||||
if equip.owner == *player_entity {
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it's not OUR item, RETURN FALSE.
|
||||
if !keep {
|
||||
return false;
|
||||
}
|
||||
// If it's identified as noncursed, RETURN FALSE.
|
||||
if b.known && b.buc != BUC::Cursed {
|
||||
return false;
|
||||
}
|
||||
// Otherwise, return: returns any items that are unidentified,
|
||||
// or identified as being cursed.
|
||||
return true;
|
||||
})
|
||||
// If it's not OUR item, RETURN FALSE.
|
||||
if !keep {
|
||||
return false;
|
||||
}
|
||||
// If it's identified as noncursed, RETURN FALSE.
|
||||
if b.known && b.buc != BUC::Cursed {
|
||||
return false;
|
||||
}
|
||||
// Otherwise, return: returns any items that are unidentified,
|
||||
// or identified as being cursed.
|
||||
return true;
|
||||
})
|
||||
};
|
||||
|
||||
// Build list of items to display
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ use super::{
|
|||
Pools,
|
||||
Position,
|
||||
Renderable,
|
||||
Rltk,
|
||||
World,
|
||||
RGB,
|
||||
};
|
||||
use crate::TileType;
|
||||
use crate::data::ids::*;
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
||||
struct Tooltip {
|
||||
|
|
@ -63,7 +62,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>();
|
||||
|
|
@ -164,7 +163,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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
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,
|
||||
DamageType,
|
||||
Intrinsics,
|
||||
};
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use crate::config::CONFIG;
|
||||
|
||||
|
|
@ -45,10 +54,11 @@ impl<'a> System<'a> for HungerSystem {
|
|||
ReadExpect<'a, Entity>,
|
||||
ReadStorage<'a, Clock>,
|
||||
ReadStorage<'a, TakingTurn>,
|
||||
ReadStorage<'a, Intrinsics>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (entities, mut hunger_clock, player_entity, turn_clock, turns) = data;
|
||||
let (entities, mut hunger_clock, player_entity, turn_clock, turns, intrinsics) = data;
|
||||
|
||||
// If the turn clock isn't taking a turn this tick, don't bother ticking hunger.
|
||||
let mut ticked = false;
|
||||
|
|
@ -64,16 +74,32 @@ impl<'a> System<'a> for HungerSystem {
|
|||
if hunger_clock.duration >= MAX_SATIATION {
|
||||
hunger_clock.duration = MAX_SATIATION;
|
||||
} else {
|
||||
hunger_clock.duration -= BASE_CLOCK_DECREMENT_PER_TURN;
|
||||
let mut modifier = 0;
|
||||
let intrinsic_regen = if let Some(i) = intrinsics.get(entity) {
|
||||
i.list.contains(&crate::Intrinsic::Regeneration)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if intrinsic_regen {
|
||||
modifier += 1;
|
||||
}
|
||||
hunger_clock.duration -= BASE_CLOCK_DECREMENT_PER_TURN + modifier;
|
||||
}
|
||||
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, damage_type: DamageType::Forced },
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
use crate::{ Beatitude, IdentifiedBeatitude, IdentifiedItem, Item, MasterDungeonMap, Name, ObfuscatedName, Player };
|
||||
use crate::{
|
||||
Beatitude,
|
||||
IdentifiedBeatitude,
|
||||
IdentifiedItem,
|
||||
Item,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Player,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
use crate::data::events::*;
|
||||
use crate::gamelog;
|
||||
|
|
@ -35,7 +44,7 @@ impl<'a> System<'a> for ItemIdentificationSystem {
|
|||
let tag = crate::raws::get_id_from_name(id.name.clone());
|
||||
if !dm.identified_items.contains(&id.name) && crate::raws::is_tag_magic(&tag) {
|
||||
if gamelog::get_event_count(EVENT::COUNT_TURN) != 1 {
|
||||
gamelog::record_event(EVENT::IDENTIFIED(id.name.clone()));
|
||||
gamelog::record_event(EVENT::Identified(id.name.clone()));
|
||||
}
|
||||
dm.identified_items.insert(id.name.clone());
|
||||
for (entity, _item, name) in (&entities, &items, &names).join() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// src/lib.rs
|
||||
// 31-Aug-2023
|
||||
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
extern crate serde;
|
||||
|
||||
|
|
|
|||
14
src/main.rs
14
src/main.rs
|
|
@ -1,12 +1,12 @@
|
|||
use rust_rl::*;
|
||||
use specs::prelude::*;
|
||||
use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator };
|
||||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
|
||||
const DISPLAYWIDTH: i32 = 100;
|
||||
const DISPLAYHEIGHT: i32 = 56;
|
||||
|
||||
fn main() -> rltk::BError {
|
||||
fn main() -> BError {
|
||||
// Embedded resources for use in wasm build
|
||||
const CURSES_16_16_BYTES: &[u8] = include_bytes!("../resources/curses16x16.png");
|
||||
const CURSES_8_16_BYTES: &[u8] = include_bytes!("../resources/curses8x16.png");
|
||||
|
|
@ -122,6 +122,8 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.register::<SpawnParticleSimple>();
|
||||
gs.ecs.register::<SpawnParticleBurst>();
|
||||
gs.ecs.register::<SpawnParticleLine>();
|
||||
gs.ecs.register::<HasDamageModifiers>();
|
||||
gs.ecs.register::<Intrinsics>();
|
||||
gs.ecs.register::<SimpleMarker<SerializeMe>>();
|
||||
gs.ecs.register::<SerializationHelper>();
|
||||
gs.ecs.register::<DMSerializationHelper>();
|
||||
|
|
@ -130,11 +132,11 @@ 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
|
||||
gs.ecs.insert(gui::Ancestry::Dwarf); // ancestry
|
||||
gs.ecs.insert(gui::Ancestry::Human); // ancestry
|
||||
let player_entity = spawner::player(&mut gs.ecs, 0, 0);
|
||||
gs.ecs.insert(player_entity); // Player entity
|
||||
gs.ecs.insert(RunState::MapGeneration {}); // RunState
|
||||
|
|
@ -142,8 +144,8 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.insert(rex_assets::RexAssets::new());
|
||||
|
||||
gamelog::setup_log();
|
||||
gamelog::record_event(data::events::EVENT::LEVEL(1));
|
||||
gamelog::record_event(data::events::EVENT::Level(1));
|
||||
gs.generate_world_map(1, TileType::Floor);
|
||||
|
||||
rltk::main_loop(context, gs)
|
||||
main_loop(context, gs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::{ Map, TileType };
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rltk::prelude::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use serde::{ Deserialize, Serialize };
|
||||
use std::collections::{ HashSet, HashMap };
|
||||
mod tiletype;
|
||||
|
|
@ -75,7 +75,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
|
||||
|
|
@ -90,7 +90,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 = (
|
||||
|
|
@ -146,12 +146,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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::{ BuilderMap, MetaMapBuilder, Position };
|
||||
use rltk::RandomNumberGenerator;
|
||||
use bracket_lib::prelude::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum XStart {
|
||||
|
|
@ -21,7 +21,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,15 +64,18 @@ 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)
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
if available_floors.is_empty() {
|
||||
panic!("No valid floors to start on");
|
||||
unreachable!("No valid floors to start on.");
|
||||
}
|
||||
|
||||
available_floors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -76,7 +76,7 @@ impl RoadExit {
|
|||
}
|
||||
}
|
||||
if available_floors.is_empty() {
|
||||
panic!("No valid floors to start on.");
|
||||
unreachable!("No valid floors to start on.");
|
||||
}
|
||||
available_floors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||
let end_x = (available_floors[0].0 as i32) % build_data.map.width;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -68,7 +70,7 @@ use forest::forest_builder;
|
|||
mod foliage;
|
||||
use foliage::Foliage;
|
||||
mod room_themer;
|
||||
use room_themer::{ Theme, ThemeRooms };
|
||||
use room_themer::ThemeRooms;
|
||||
|
||||
// Shared data to be passed around build chain
|
||||
pub struct BuilderMap {
|
||||
|
|
@ -135,7 +137,7 @@ impl BuilderChain {
|
|||
None => {
|
||||
self.starter = Some(starter);
|
||||
}
|
||||
Some(_) => panic!("You can only have one starting builder."),
|
||||
Some(_) => unreachable!("You can only have one starting builder."),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -143,9 +145,9 @@ 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"),
|
||||
None => unreachable!("Cannot run a map builder chain without a starting build system"),
|
||||
Some(starter) => {
|
||||
// Build the starting map
|
||||
starter.build_map(rng, &mut self.build_data);
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(§ion, 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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ impl RoomBasedSpawner {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
panic!("RoomBasedSpawner only works after rooms have been created");
|
||||
unreachable!("RoomBasedSpawner tried to run without any rooms.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ impl RoomBasedStairs {
|
|||
build_data.map.tiles[stairs_idx] = TileType::DownStair;
|
||||
build_data.take_snapshot();
|
||||
} else {
|
||||
panic!("RoomBasedStairs only works after rooms have been created");
|
||||
unreachable!("RoomBasedStairs tried to run without any rooms.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ impl RoomBasedStartingPosition {
|
|||
let start_pos = rooms[0].center();
|
||||
build_data.starting_position = Some(Position { x: start_pos.x, y: start_pos.y });
|
||||
} else {
|
||||
panic!("RoomBasedStartingPosition only works after rooms have been created");
|
||||
unreachable!("RoomBasedStartingPosition tried to run without any rooms.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ impl RoomCornerRounder {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("RoomCornerRounding requires a builder with rooms.");
|
||||
unreachable!("RoomCornerRounding tried to run without any rooms.");
|
||||
}
|
||||
|
||||
for room in rooms.iter() {
|
||||
|
|
|
|||
|
|
@ -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) &&
|
||||
|
|
@ -53,7 +50,7 @@ impl RoomDrawer {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("RoomDrawer require a builder with rooms");
|
||||
unreachable!("RoomDrawer tried to run without any rooms.");
|
||||
}
|
||||
|
||||
for room in rooms.iter() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ impl RoomExploder {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("RoomExploder requires a builder with rooms.");
|
||||
unreachable!("RoomExploder tried to run without any rooms.");
|
||||
}
|
||||
for room in rooms.iter() {
|
||||
let start = room.center();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ impl ThemeRooms {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("RoomCornerRounding requires a builder with rooms.");
|
||||
unreachable!("RoomCornerRounding tried to run without any rooms.");
|
||||
}
|
||||
|
||||
let count = roll_until_fail(rng, self.percent);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ impl BresenhamCorridors {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("BresenhamCorridors require a builder with room structures");
|
||||
unreachable!("BresenhamCorridors tried to run without any rooms.");
|
||||
}
|
||||
|
||||
let mut connected: HashSet<usize> = HashSet::new();
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ impl BspCorridors {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("BSP Corridors require a builder with room structures");
|
||||
unreachable!("BSP Corridors tried to run without any rooms.");
|
||||
}
|
||||
|
||||
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ impl DoglegCorridors {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("DoglegCorridors require a builder with rooms.");
|
||||
unreachable!("DoglegCorridors tried to run without any rooms.");
|
||||
}
|
||||
|
||||
let mut corridors: Vec<Vec<usize>> = Vec::new();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ impl NearestCorridors {
|
|||
if let Some(rooms_builder) = &build_data.rooms {
|
||||
rooms = rooms_builder.clone();
|
||||
} else {
|
||||
panic!("NearestCorridors requires a builder with rooms");
|
||||
unreachable!("NearestCorridors tried to run without any rooms.");
|
||||
}
|
||||
|
||||
let mut connected: HashSet<usize> = HashSet::new();
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ impl CorridorSpawner {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
panic!("CorridorSpawner only works after corridors have been created");
|
||||
unreachable!("CorridorSpawner tried to run without any corridors.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
use super::{Map, MapChunk, TileType};
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::{Map, MapChunk};
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
@ -123,6 +123,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
} else {
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
damage_type: crate::DamageType::Physical,
|
||||
attribute: WeaponAttribute::Strength,
|
||||
damage_n_dice: 1,
|
||||
damage_die_type: 4,
|
||||
|
|
@ -194,7 +195,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 +207,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 +234,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 +251,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 +285,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,
|
||||
|
|
@ -284,7 +302,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
}
|
||||
add_effect(
|
||||
Some(entity),
|
||||
EffectType::Damage { amount: damage },
|
||||
EffectType::Damage { amount: damage, damage_type: weapon_info.damage_type },
|
||||
Targets::Entity { target: wants_melee.target }
|
||||
);
|
||||
if entity == *player_entity {
|
||||
|
|
@ -321,7 +339,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 +383,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)>
|
||||
|
|
@ -375,6 +393,7 @@ fn get_natural_attacks(
|
|||
for a in nat.attacks.iter() {
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
damage_type: a.damage_type,
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: a.hit_bonus,
|
||||
damage_n_dice: a.damage_n_dice,
|
||||
|
|
@ -392,6 +411,7 @@ fn get_natural_attacks(
|
|||
};
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
damage_type: nat.attacks[attack_index].damage_type,
|
||||
attribute: WeaponAttribute::Strength,
|
||||
hit_bonus: nat.attacks[attack_index].hit_bonus,
|
||||
damage_n_dice: nat.attacks[attack_index].damage_n_dice,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use super::{
|
|||
Item,
|
||||
Map,
|
||||
Name,
|
||||
ParticleBuilder,
|
||||
Player,
|
||||
Pools,
|
||||
Position,
|
||||
|
|
@ -33,9 +32,9 @@ use super::{
|
|||
WantsToPickupItem,
|
||||
get_dest,
|
||||
Destination,
|
||||
DamageType,
|
||||
};
|
||||
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 +132,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 +229,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;
|
||||
|
|
@ -292,7 +291,7 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
if rng.roll_dice(1, 20) == 20 {
|
||||
add_effect(
|
||||
None,
|
||||
EffectType::Damage { amount: 1 },
|
||||
EffectType::Damage { amount: 1, damage_type: DamageType::Physical },
|
||||
Targets::Entity { target: entity }
|
||||
);
|
||||
gamelog::Logger
|
||||
|
|
@ -352,7 +351,7 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
destroyed_pos = Some(
|
||||
Point::new(pos.x + delta_x, pos.y + delta_y)
|
||||
);
|
||||
gamelog::record_event(EVENT::BROKE_DOOR(1));
|
||||
gamelog::record_event(EVENT::BrokeDoor(1));
|
||||
return false;
|
||||
// 66% chance of just kicking it.
|
||||
} else {
|
||||
|
|
@ -416,7 +415,7 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
ecs.delete_entity(destroyed_thing).expect("Unable to delete.");
|
||||
}
|
||||
|
||||
gamelog::record_event(EVENT::KICKED_SOMETHING(1));
|
||||
gamelog::record_event(EVENT::KickedSomething(1));
|
||||
return RunState::Ticking;
|
||||
}
|
||||
|
||||
|
|
@ -505,7 +504,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
|
|||
::new()
|
||||
.append("The")
|
||||
.colour(colour)
|
||||
.append_n(&name.name)
|
||||
.append(&name.name)
|
||||
.colour(WHITE)
|
||||
.append("is in your way.")
|
||||
.log();
|
||||
|
|
@ -643,7 +642,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 +877,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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ pub struct Mob {
|
|||
pub attacks: Option<Vec<NaturalAttack>>,
|
||||
pub attributes: Option<MobAttributes>,
|
||||
pub skills: Option<HashMap<String, i32>>,
|
||||
pub vision_range: i32,
|
||||
pub vision_range: Option<i32>,
|
||||
pub telepathy_range: Option<i32>,
|
||||
pub equipped: Option<Vec<String>>,
|
||||
pub loot: Option<LootTableInfo>,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use crate::gui::Ancestry;
|
|||
use crate::random_table::RandomTable;
|
||||
use crate::config::CONFIG;
|
||||
use crate::data::visuals::BLOODSTAIN_COLOUR;
|
||||
use regex::Regex;
|
||||
use rltk::prelude::*;
|
||||
use crate::data::entity::DEFAULT_VIEWSHED_STANDARD;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::prelude::*;
|
||||
use specs::saveload::{ MarkedBuilder, SimpleMarker };
|
||||
use std::collections::{ HashMap, HashSet };
|
||||
|
|
@ -19,13 +19,13 @@ macro_rules! apply_effects {
|
|||
let effect_name = effect.0.as_str();
|
||||
match effect_name {
|
||||
"heal" => {
|
||||
let (n_dice, sides, modifier) = parse_dice_string(effect.1.as_str());
|
||||
$eb = $eb.with(ProvidesHealing { n_dice, sides, modifier })
|
||||
let dice = parse_dice_string(effect.1.as_str()).expect("Failed to parse dice string");
|
||||
$eb = $eb.with(ProvidesHealing { n_dice: dice.n_dice, sides: dice.die_type, modifier: dice.bonus })
|
||||
}
|
||||
"ranged" => $eb = $eb.with(Ranged { range: effect.1.parse::<i32>().unwrap() }),
|
||||
"damage" => {
|
||||
let (n_dice, sides, modifier) = parse_dice_string(effect.1.as_str());
|
||||
$eb = $eb.with(InflictsDamage { n_dice, sides, modifier })
|
||||
let (damage_type, dice) = parse_damage_string(effect.1.as_str());
|
||||
$eb = $eb.with(InflictsDamage { damage_type, n_dice: dice.n_dice, sides: dice.die_type, modifier: dice.bonus })
|
||||
}
|
||||
"aoe" => $eb = $eb.with(AOE { radius: effect.1.parse::<i32>().unwrap() }),
|
||||
"confusion" => $eb = $eb.with(Confusion { turns: effect.1.parse::<i32>().unwrap() }),
|
||||
|
|
@ -44,6 +44,7 @@ macro_rules! apply_effects {
|
|||
/// flags are components that have no parameters to modify.
|
||||
macro_rules! apply_flags {
|
||||
($flags:expr, $eb:expr) => {
|
||||
let mut damage_modifiers: HashMap<DamageType, DamageModifier> = HashMap::new();
|
||||
for flag in $flags.iter() {
|
||||
match flag.as_str() {
|
||||
// --- PROP FLAGS BEGIN HERE ---
|
||||
|
|
@ -88,6 +89,22 @@ macro_rules! apply_flags {
|
|||
"NEUTRAL" => $eb = $eb.with(Faction { name: "neutral".to_string() }),
|
||||
"HERBIVORE" => $eb = $eb.with(Faction { name: "herbivore".to_string() }),
|
||||
"CARNIVORE" => $eb = $eb.with(Faction { name: "carnivore".to_string() }),
|
||||
// --- DAMAGE MODIFIERS ---
|
||||
"PHYS_IMMUNITY" => { damage_modifiers.insert(DamageType::Physical, DamageModifier::Immune); }
|
||||
"PHYS_WEAK" => { damage_modifiers.insert(DamageType::Physical, DamageModifier::Weakness); }
|
||||
"PHYS_RES" => { damage_modifiers.insert(DamageType::Physical, DamageModifier::Resistance); }
|
||||
"MAGIC_IMMUNITY" => { damage_modifiers.insert(DamageType::Magic, DamageModifier::Immune); }
|
||||
"MAGIC_WEAK" => { damage_modifiers.insert(DamageType::Magic, DamageModifier::Weakness); }
|
||||
"MAGIC_RES" => { damage_modifiers.insert(DamageType::Magic, DamageModifier::Resistance); }
|
||||
"FIRE_IMMUNITY" => { damage_modifiers.insert(DamageType::Fire, DamageModifier::Immune); }
|
||||
"FIRE_WEAK" => { damage_modifiers.insert(DamageType::Fire, DamageModifier::Weakness); }
|
||||
"FIRE_RES" => { damage_modifiers.insert(DamageType::Fire, DamageModifier::Resistance); }
|
||||
"COLD_IMMUNITY" => { damage_modifiers.insert(DamageType::Cold, DamageModifier::Immune); }
|
||||
"COLD_WEAK" => { damage_modifiers.insert(DamageType::Cold, DamageModifier::Weakness); }
|
||||
"COLD_RES" => { damage_modifiers.insert(DamageType::Cold, DamageModifier::Resistance); }
|
||||
"POISON_IMMUNITY" => { damage_modifiers.insert(DamageType::Poison, DamageModifier::Immune); }
|
||||
"POISON_WEAK" => { damage_modifiers.insert(DamageType::Poison, DamageModifier::Weakness); }
|
||||
"POISON_RES" => { damage_modifiers.insert(DamageType::Poison, DamageModifier::Resistance); }
|
||||
// --- MOVEMENT MODES --- ( defaults to WANDER )
|
||||
"STATIC" => $eb = $eb.with(MoveMode { mode: Movement::Static }),
|
||||
"RANDOM_PATH" => $eb = $eb.with(MoveMode { mode: Movement::RandomWaypoint { path: None } }),
|
||||
|
|
@ -98,9 +115,12 @@ 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())),
|
||||
}
|
||||
}
|
||||
if damage_modifiers.len() > 0 {
|
||||
$eb = $eb.with(HasDamageModifiers { modifiers: damage_modifiers });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -203,13 +223,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 +286,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 {
|
||||
|
|
@ -333,17 +359,18 @@ pub fn spawn_named_item(
|
|||
}
|
||||
|
||||
if let Some(weapon) = &item_template.equip {
|
||||
let (n_dice, die_type, bonus) = parse_dice_string(weapon.damage.as_str());
|
||||
let (damage_type, dice) = parse_damage_string(weapon.damage.as_str());
|
||||
let weapon_attribute = match weapon.flag.as_str() {
|
||||
"DEXTERITY" => WeaponAttribute::Dexterity,
|
||||
"FINESSE" => WeaponAttribute::Finesse,
|
||||
_ => WeaponAttribute::Strength,
|
||||
};
|
||||
let wpn = MeleeWeapon {
|
||||
damage_type,
|
||||
attribute: weapon_attribute,
|
||||
damage_n_dice: n_dice,
|
||||
damage_die_type: die_type,
|
||||
damage_bonus: bonus,
|
||||
damage_n_dice: dice.n_dice,
|
||||
damage_die_type: dice.die_type,
|
||||
damage_bonus: dice.bonus,
|
||||
hit_bonus: weapon.to_hit.unwrap_or(0),
|
||||
};
|
||||
eb = eb.with(wpn);
|
||||
|
|
@ -379,7 +406,15 @@ 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: if let Some(range) = mob_template.vision_range {
|
||||
range
|
||||
} else {
|
||||
DEFAULT_VIEWSHED_STANDARD
|
||||
},
|
||||
dirty: true,
|
||||
});
|
||||
if let Some(telepath) = &mob_template.telepathy_range {
|
||||
eb = eb.with(Telepath { telepath_tiles: Vec::new(), range: *telepath, dirty: true });
|
||||
}
|
||||
|
|
@ -447,7 +482,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 +503,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 +536,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -507,13 +546,14 @@ pub fn spawn_named_mob(
|
|||
if let Some(natural_attacks) = &mob_template.attacks {
|
||||
let mut natural = NaturalAttacks { attacks: Vec::new() };
|
||||
for na in natural_attacks.iter() {
|
||||
let (n, d, b) = parse_dice_string(&na.damage);
|
||||
let (damage_type, dice) = parse_damage_string(&na.damage);
|
||||
let attack = NaturalAttack {
|
||||
name: na.name.clone(),
|
||||
damage_type,
|
||||
hit_bonus: na.hit_bonus,
|
||||
damage_n_dice: n,
|
||||
damage_die_type: d,
|
||||
damage_bonus: b,
|
||||
damage_n_dice: dice.n_dice,
|
||||
damage_die_type: dice.die_type,
|
||||
damage_bonus: dice.bonus,
|
||||
};
|
||||
natural.attacks.push(attack);
|
||||
}
|
||||
|
|
@ -548,7 +588,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 +609,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 +625,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 +662,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 +686,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,19 +727,16 @@ pub fn table_by_name(raws: &RawMaster, key: &str, optional_difficulty: Option<i3
|
|||
return rt;
|
||||
}
|
||||
}
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"DEBUGINFO: Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}]. Returned debug entry.",
|
||||
key,
|
||||
difficulty,
|
||||
upper_bound,
|
||||
lower_bound
|
||||
)
|
||||
unreachable!(
|
||||
"Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}].",
|
||||
key,
|
||||
difficulty,
|
||||
upper_bound,
|
||||
lower_bound
|
||||
);
|
||||
return RandomTable::new().add("debug", 1);
|
||||
}
|
||||
|
||||
pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
|
||||
/*pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
|
||||
lazy_static! {
|
||||
static ref DICE_RE: Regex = Regex::new(r"(\d+)d(\d+)([\+\-]\d+)?").unwrap();
|
||||
}
|
||||
|
|
@ -699,11 +755,11 @@ pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
|
|||
}
|
||||
}
|
||||
(n_dice, die_type, die_bonus)
|
||||
}
|
||||
}*/
|
||||
|
||||
fn find_slot_for_equippable_item(tag: &str, raws: &RawMaster) -> EquipmentSlot {
|
||||
if !raws.item_index.contains_key(tag) {
|
||||
panic!("Trying to equip an unknown item: {}", tag);
|
||||
unreachable!("Tried to equip an unknown item: {}", tag);
|
||||
}
|
||||
let item_index = raws.item_index[tag];
|
||||
let item = &raws.raws.items[item_index];
|
||||
|
|
@ -738,10 +794,14 @@ fn find_slot_for_equippable_item(tag: &str, raws: &RawMaster) -> EquipmentSlot {
|
|||
}
|
||||
}
|
||||
}
|
||||
panic!("Trying to equip {}, but it has no slot tag.", tag);
|
||||
unreachable!("Tried 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 +852,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 +957,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 {
|
||||
|
|
@ -989,3 +1057,21 @@ fn parse_particle_burst(n: &str) -> SpawnParticleBurst {
|
|||
trail_lifetime_ms: tokens[7].parse::<f32>().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_damage_string(n: &str) -> (DamageType, DiceType) {
|
||||
let tokens: Vec<_> = n.split(';').collect();
|
||||
let damage_type = if tokens.len() > 1 {
|
||||
match tokens[1] {
|
||||
"physical" => DamageType::Physical,
|
||||
"magic" => DamageType::Magic,
|
||||
"fire" => DamageType::Fire,
|
||||
"cold" => DamageType::Cold,
|
||||
"poison" => DamageType::Poison,
|
||||
_ => unreachable!("Unrecognised damage type in raws: {}", tokens[1]),
|
||||
}
|
||||
} else {
|
||||
DamageType::Physical
|
||||
};
|
||||
let dice = parse_dice_string(tokens[0]).expect("Failed to parse dice string");
|
||||
return (damage_type, dice);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use super::components::*;
|
||||
use bracket_lib::prelude::*;
|
||||
use specs::error::NoError;
|
||||
use specs::prelude::*;
|
||||
use specs::saveload::{
|
||||
|
|
@ -87,12 +88,14 @@ pub fn save_game(ecs: &mut World) {
|
|||
GrantsXP,
|
||||
HasAncestry,
|
||||
HasClass,
|
||||
HasDamageModifiers,
|
||||
Hidden,
|
||||
HungerClock,
|
||||
IdentifiedBeatitude,
|
||||
IdentifiedItem,
|
||||
InBackpack,
|
||||
InflictsDamage,
|
||||
Intrinsics,
|
||||
Item,
|
||||
KnownSpells,
|
||||
LootTable,
|
||||
|
|
@ -217,12 +220,14 @@ pub fn load_game(ecs: &mut World) {
|
|||
GrantsXP,
|
||||
HasAncestry,
|
||||
HasClass,
|
||||
HasDamageModifiers,
|
||||
Hidden,
|
||||
HungerClock,
|
||||
IdentifiedBeatitude,
|
||||
IdentifiedItem,
|
||||
InBackpack,
|
||||
InflictsDamage,
|
||||
Intrinsics,
|
||||
Item,
|
||||
KnownSpells,
|
||||
LootTable,
|
||||
|
|
@ -293,8 +298,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,19 +21,20 @@ use super::{
|
|||
SerializeMe,
|
||||
Skill,
|
||||
Skills,
|
||||
TileType,
|
||||
tile_walkable,
|
||||
Viewshed,
|
||||
BlocksTile,
|
||||
Bleeds,
|
||||
HasDamageModifiers,
|
||||
Intrinsics,
|
||||
};
|
||||
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;
|
||||
use std::collections::{ HashMap, HashSet };
|
||||
|
||||
/// Spawns the player and returns his/her entity object.
|
||||
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||
|
|
@ -52,9 +53,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) })
|
||||
|
|
@ -87,7 +88,9 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
|||
weight: 0.0,
|
||||
god: false,
|
||||
})
|
||||
.with(EquipmentChanged {})
|
||||
.with(HasDamageModifiers { modifiers: HashMap::new() })
|
||||
.with(Intrinsics { list: HashSet::new() })
|
||||
.with(EquipmentChanged {}) // To force re-calc of equipment bonuses.
|
||||
.with(skills)
|
||||
.with(Energy { current: 0, speed: entity::NORMAL_SPEED })
|
||||
.marked::<SimpleMarker<SerializeMe>>()
|
||||
|
|
@ -132,7 +135,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 +215,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?
|
||||
|
|
|
|||
|
|
@ -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,10 +125,10 @@ 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));
|
||||
gamelog::record_event(EVENT::ChangedFloor(mapname));
|
||||
}
|
||||
|
||||
fn game_over_cleanup(&mut self) {
|
||||
|
|
@ -152,12 +152,12 @@ impl State {
|
|||
self.generate_world_map(1, TileType::Floor);
|
||||
|
||||
gamelog::setup_log();
|
||||
gamelog::record_event(EVENT::LEVEL(1));
|
||||
gamelog::record_event(EVENT::Level(1));
|
||||
}
|
||||
}
|
||||
|
||||
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>();
|
||||
|
|
@ -518,7 +518,7 @@ impl GameState for State {
|
|||
let result = gui::show_help(ctx);
|
||||
match result {
|
||||
gui::YesNoResult::Yes => {
|
||||
gamelog::record_event(EVENT::LOOKED_FOR_HELP(1));
|
||||
gamelog::record_event(EVENT::LookedForHelp(1));
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -591,6 +591,6 @@ impl GameState for State {
|
|||
|
||||
damage_system::delete_the_dead(&mut self.ecs);
|
||||
|
||||
let _ = rltk::render_draw_buffer(ctx);
|
||||
let _ = render_draw_buffer(ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use super::{
|
|||
Renderable,
|
||||
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)
|
||||
{
|
||||
Targets::TileList {
|
||||
targets: aoe_tiles(&*map, Point::new(pos.x, pos.y), aoe.radius),
|
||||
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
|
||||
),
|
||||
}
|
||||
} else {
|
||||
Targets::Tile { target: idx }
|
||||
}
|
||||
} else {
|
||||
Targets::Tile { target: idx }
|
||||
});
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ use super::{
|
|||
gui::renderable_colour,
|
||||
tile_blocks_telepathy,
|
||||
};
|
||||
use rltk::{ FieldOfViewAlg::SymmetricShadowcasting, Point };
|
||||
use bracket_lib::prelude::*;
|
||||
use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting;
|
||||
use specs::prelude::*;
|
||||
|
||||
pub struct VisibilitySystem {}
|
||||
|
|
@ -23,7 +24,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>,
|
||||
|
|
@ -74,8 +75,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
|
||||
|
|
@ -101,7 +101,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();
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
if let Some(_is_blind) = blind_entities.get(ent) {
|
||||
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
|
||||
}
|
||||
telepath.telepath_tiles = fast_fov(pos.x, pos.y, range, &map);
|
||||
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
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue