overmap travel - needs refactoring urgently, but it works for now
This commit is contained in:
parent
00dea1a55e
commit
e1eae7efaf
15 changed files with 150 additions and 110 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::data::entity::*;
|
use crate::data::entity::*;
|
||||||
use crate::{ Burden, BurdenLevel, Clock, Energy, Name, Position, RunState, TakingTurn };
|
use crate::{ Burden, BurdenLevel, Clock, Energy, Name, Position, RunState, Map, TakingTurn };
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
|
@ -12,6 +12,7 @@ const TURN_COST: i32 = NORMAL_SPEED * TURN_COST_MULTIPLIER;
|
||||||
impl<'a> System<'a> for EnergySystem {
|
impl<'a> System<'a> for EnergySystem {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
ReadExpect<'a, Map>,
|
||||||
ReadStorage<'a, Clock>,
|
ReadStorage<'a, Clock>,
|
||||||
WriteStorage<'a, Energy>,
|
WriteStorage<'a, Energy>,
|
||||||
ReadStorage<'a, Burden>,
|
ReadStorage<'a, Burden>,
|
||||||
|
|
@ -27,6 +28,7 @@ impl<'a> System<'a> for EnergySystem {
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (
|
let (
|
||||||
|
map,
|
||||||
clock,
|
clock,
|
||||||
mut energies,
|
mut energies,
|
||||||
burdens,
|
burdens,
|
||||||
|
|
@ -62,15 +64,16 @@ impl<'a> System<'a> for EnergySystem {
|
||||||
for (entity, energy, pos) in (&entities, &mut energies, &positions).join() {
|
for (entity, energy, pos) in (&entities, &mut energies, &positions).join() {
|
||||||
let burden_modifier = if let Some(burden) = burdens.get(entity) {
|
let burden_modifier = if let Some(burden) = burdens.get(entity) {
|
||||||
match burden.level {
|
match burden.level {
|
||||||
BurdenLevel::Burdened => 0.75,
|
BurdenLevel::Burdened => SPEED_MOD_BURDENED,
|
||||||
BurdenLevel::Strained => 0.5,
|
BurdenLevel::Strained => SPEED_MOD_STRAINED,
|
||||||
BurdenLevel::Overloaded => 0.25,
|
BurdenLevel::Overloaded => SPEED_MOD_OVERLOADED,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
};
|
};
|
||||||
|
let overmap_mod = if map.overmap { SPEED_MOD_OVERMAP_TRAVEL } else { 1.0 };
|
||||||
// Every entity has a POTENTIAL equal to their speed.
|
// Every entity has a POTENTIAL equal to their speed.
|
||||||
let mut energy_potential: i32 = ((energy.speed as f32) * burden_modifier) as i32;
|
let mut energy_potential: i32 = ((energy.speed as f32) * burden_modifier * overmap_mod) as i32;
|
||||||
// Increment current energy by NORMAL_SPEED for every
|
// Increment current energy by NORMAL_SPEED for every
|
||||||
// whole number of NORMAL_SPEEDS in their POTENTIAL.
|
// whole number of NORMAL_SPEEDS in their POTENTIAL.
|
||||||
while energy_potential >= NORMAL_SPEED {
|
while energy_potential >= NORMAL_SPEED {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
pub const DEFAULT_VIEWSHED_STANDARD: i32 = 16; // Standard viewshed radius for almost all entities.
|
pub const DEFAULT_VIEWSHED_STANDARD: i32 = 16; // Standard viewshed radius for almost all entities.
|
||||||
pub const CARRY_CAPACITY_PER_STRENGTH: i32 = 8; // How much weight can be carried per point of strength.
|
pub const CARRY_CAPACITY_PER_STRENGTH: i32 = 8; // How much weight can be carried per point of strength.
|
||||||
pub const NORMAL_SPEED: i32 = 12; // Normal speed for almost all entities.
|
pub const NORMAL_SPEED: i32 = 12; // Normal speed for almost all entities.
|
||||||
|
pub const SPEED_MOD_BURDENED: f32 = 0.75;
|
||||||
|
pub const SPEED_MOD_STRAINED: f32 = 0.5;
|
||||||
|
pub const SPEED_MOD_OVERLOADED: f32 = 0.25;
|
||||||
|
pub const SPEED_MOD_OVERMAP_TRAVEL: f32 = 0.33;
|
||||||
pub const TURN_COST_MULTIPLIER: i32 = 4; // How many ticks for NORMAL_SPEED to get a turn.
|
pub const TURN_COST_MULTIPLIER: i32 = 4; // How many ticks for NORMAL_SPEED to get a turn.
|
||||||
pub const ATTR_BONUS_0: i32 = 10; // At this value, the attribute bonus is 0.
|
pub const ATTR_BONUS_0: i32 = 10; // At this value, the attribute bonus is 0.
|
||||||
pub const ATTR_NEEDED_PER_POINT: i32 = 2; // How many points +- ATTR_BONUS_0 are needed per +- 1 bonus.
|
pub const ATTR_NEEDED_PER_POINT: i32 = 2; // How many points +- ATTR_BONUS_0 are needed per +- 1 bonus.
|
||||||
|
|
|
||||||
6
src/data/ids.rs
Normal file
6
src/data/ids.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
pub const ID_PREVIOUS_LEVEL: i32 = -5;
|
||||||
|
pub const ID_NEXT_LEVEL: i32 = -6;
|
||||||
|
|
||||||
|
pub const ID_OVERMAP: i32 = 1;
|
||||||
|
pub const ID_TOWN: i32 = 10;
|
||||||
|
pub const ID_TOWN2: i32 = ID_TOWN + 1;
|
||||||
|
|
@ -3,3 +3,4 @@ pub mod visuals;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod char_create;
|
pub mod char_create;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
|
pub mod ids;
|
||||||
|
|
|
||||||
|
|
@ -76,3 +76,9 @@ pub const IMPASSABLE_MOUNTAIN_GLYPH: char = '▲';
|
||||||
|
|
||||||
// FOREST THEME
|
// FOREST THEME
|
||||||
pub const FOREST_WALL_GLYPH: char = '♣';
|
pub const FOREST_WALL_GLYPH: char = '♣';
|
||||||
|
|
||||||
|
// Overmap/transition stuff
|
||||||
|
pub const TO_OVERMAP_GLYPH: char = '<';
|
||||||
|
pub const TO_OVERMAP_COLOUR: (u8, u8, u8) = (205, 127, 50);
|
||||||
|
pub const TO_TOWN_GLYPH: char = 'o';
|
||||||
|
pub const TO_TOWN_COLOUR: (u8, u8, u8) = (205, 127, 50);
|
||||||
|
|
|
||||||
38
src/main.rs
38
src/main.rs
|
|
@ -70,8 +70,9 @@ pub enum RunState {
|
||||||
},
|
},
|
||||||
SaveGame,
|
SaveGame,
|
||||||
GameOver,
|
GameOver,
|
||||||
NextLevel,
|
|
||||||
PreviousLevel,
|
PreviousLevel,
|
||||||
|
NextLevel,
|
||||||
|
GoToLevel(i32, Option<TileType>),
|
||||||
HelpScreen,
|
HelpScreen,
|
||||||
MagicMapReveal {
|
MagicMapReveal {
|
||||||
row: i32,
|
row: i32,
|
||||||
|
|
@ -89,12 +90,12 @@ pub struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
fn generate_world_map(&mut self, new_id: i32, offset: i32) {
|
fn generate_world_map(&mut self, new_id: i32, offset: i32, from_tile: Option<TileType>) {
|
||||||
// Visualisation stuff
|
// Visualisation stuff
|
||||||
self.mapgen_index = 0;
|
self.mapgen_index = 0;
|
||||||
self.mapgen_timer = 0.0;
|
self.mapgen_timer = 0.0;
|
||||||
self.mapgen_history.clear();
|
self.mapgen_history.clear();
|
||||||
let map_building_info = map::level_transition(&mut self.ecs, new_id, offset);
|
let map_building_info = map::level_transition(&mut self.ecs, new_id, offset, from_tile);
|
||||||
if let Some(history) = map_building_info {
|
if let Some(history) = map_building_info {
|
||||||
self.mapgen_history = history;
|
self.mapgen_history = history;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -171,7 +172,17 @@ impl State {
|
||||||
default_move_ai.run_now(&self.ecs);
|
default_move_ai.run_now(&self.ecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn goto_level(&mut self, offset: i32) {
|
fn goto_id(&mut self, id: i32, from_tile: Option<TileType>) {
|
||||||
|
let current_id;
|
||||||
|
{
|
||||||
|
let worldmap_resource = self.ecs.fetch::<Map>();
|
||||||
|
current_id = worldmap_resource.id;
|
||||||
|
}
|
||||||
|
let offset = id - current_id;
|
||||||
|
self.goto_level(offset, from_tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn goto_level(&mut self, offset: i32, from_tile: Option<TileType>) {
|
||||||
// Build new map + place player
|
// Build new map + place player
|
||||||
let current_id;
|
let current_id;
|
||||||
{
|
{
|
||||||
|
|
@ -187,7 +198,7 @@ impl State {
|
||||||
}
|
}
|
||||||
// Freeze the current level
|
// Freeze the current level
|
||||||
map::dungeon::freeze_entities(&mut self.ecs);
|
map::dungeon::freeze_entities(&mut self.ecs);
|
||||||
self.generate_world_map(current_id + offset, offset);
|
self.generate_world_map(current_id + offset, offset, from_tile);
|
||||||
let mapname = self.ecs.fetch::<Map>().name.clone();
|
let mapname = self.ecs.fetch::<Map>().name.clone();
|
||||||
gamelog::Logger::new().append("You head to").npc_name_n(mapname).period().log();
|
gamelog::Logger::new().append("You head to").npc_name_n(mapname).period().log();
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +221,7 @@ impl State {
|
||||||
}
|
}
|
||||||
// Replace map list
|
// Replace map list
|
||||||
self.ecs.insert(map::dungeon::MasterDungeonMap::new());
|
self.ecs.insert(map::dungeon::MasterDungeonMap::new());
|
||||||
self.generate_world_map(1, 0);
|
self.generate_world_map(1, 0, None);
|
||||||
|
|
||||||
gamelog::setup_log();
|
gamelog::setup_log();
|
||||||
gamelog::record_event(EVENT::LEVEL(1));
|
gamelog::record_event(EVENT::LEVEL(1));
|
||||||
|
|
@ -299,12 +310,12 @@ impl GameState for State {
|
||||||
}
|
}
|
||||||
gui::CheatMenuResult::NoResponse => {}
|
gui::CheatMenuResult::NoResponse => {}
|
||||||
gui::CheatMenuResult::Ascend => {
|
gui::CheatMenuResult::Ascend => {
|
||||||
self.goto_level(-1);
|
self.goto_level(-1, Some(TileType::UpStair));
|
||||||
self.mapgen_next_state = Some(RunState::PreRun);
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
new_runstate = RunState::MapGeneration;
|
new_runstate = RunState::MapGeneration;
|
||||||
}
|
}
|
||||||
gui::CheatMenuResult::Descend => {
|
gui::CheatMenuResult::Descend => {
|
||||||
self.goto_level(1);
|
self.goto_level(1, Some(TileType::DownStair));
|
||||||
self.mapgen_next_state = Some(RunState::PreRun);
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
new_runstate = RunState::MapGeneration;
|
new_runstate = RunState::MapGeneration;
|
||||||
}
|
}
|
||||||
|
|
@ -524,12 +535,17 @@ impl GameState for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::NextLevel => {
|
RunState::NextLevel => {
|
||||||
self.goto_level(1);
|
self.goto_level(1, Some(TileType::DownStair));
|
||||||
self.mapgen_next_state = Some(RunState::PreRun);
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
new_runstate = RunState::MapGeneration;
|
new_runstate = RunState::MapGeneration;
|
||||||
}
|
}
|
||||||
RunState::PreviousLevel => {
|
RunState::PreviousLevel => {
|
||||||
self.goto_level(-1);
|
self.goto_level(-1, Some(TileType::UpStair));
|
||||||
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
|
new_runstate = RunState::MapGeneration;
|
||||||
|
}
|
||||||
|
RunState::GoToLevel(id, from_tile) => {
|
||||||
|
self.goto_id(id, from_tile);
|
||||||
self.mapgen_next_state = Some(RunState::PreRun);
|
self.mapgen_next_state = Some(RunState::PreRun);
|
||||||
new_runstate = RunState::MapGeneration;
|
new_runstate = RunState::MapGeneration;
|
||||||
}
|
}
|
||||||
|
|
@ -734,7 +750,7 @@ fn main() -> rltk::BError {
|
||||||
|
|
||||||
gamelog::setup_log();
|
gamelog::setup_log();
|
||||||
gamelog::record_event(EVENT::LEVEL(1));
|
gamelog::record_event(EVENT::LEVEL(1));
|
||||||
gs.generate_world_map(1, 0);
|
gs.generate_world_map(1, 0, None);
|
||||||
|
|
||||||
rltk::main_loop(context, gs)
|
rltk::main_loop(context, gs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use serde::{ Deserialize, Serialize };
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::{ HashMap, HashSet };
|
use std::collections::{ HashMap, HashSet };
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
use crate::data::ids::*;
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct MasterDungeonMap {
|
pub struct MasterDungeonMap {
|
||||||
|
|
@ -188,12 +189,12 @@ fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<Stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn level_transition(ecs: &mut World, new_id: i32, offset: i32) -> Option<Vec<Map>> {
|
pub fn level_transition(ecs: &mut World, new_id: i32, offset: i32, from_tile: Option<TileType>) -> Option<Vec<Map>> {
|
||||||
// Obtain master
|
// Obtain master
|
||||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||||
if dungeon_master.get_map(new_id).is_some() {
|
if dungeon_master.get_map(new_id).is_some() {
|
||||||
std::mem::drop(dungeon_master);
|
std::mem::drop(dungeon_master);
|
||||||
transition_to_existing_map(ecs, new_id, offset);
|
transition_to_existing_map(ecs, new_id, offset, from_tile);
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
std::mem::drop(dungeon_master);
|
std::mem::drop(dungeon_master);
|
||||||
|
|
@ -201,20 +202,36 @@ pub fn level_transition(ecs: &mut World, new_id: i32, offset: i32) -> Option<Vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32) {
|
fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32, from_tile: Option<TileType>) {
|
||||||
let mut dungeon_master = ecs.write_resource::<MasterDungeonMap>();
|
let mut dungeon_master = ecs.write_resource::<MasterDungeonMap>();
|
||||||
// Unwrapping here panics if new_id isn't present. But this should
|
// Unwrapping here panics if new_id isn't present. But this should
|
||||||
// never be called without new_id being present by level_transition.
|
// never be called without new_id being present by level_transition.
|
||||||
let map = dungeon_master.get_map(new_id).unwrap();
|
let map = dungeon_master.get_map(new_id).unwrap();
|
||||||
let mut worldmap_resource = ecs.write_resource::<Map>();
|
let mut worldmap_resource = ecs.write_resource::<Map>();
|
||||||
// Store new state of old map
|
|
||||||
dungeon_master.store_map(&worldmap_resource);
|
|
||||||
let player_entity = ecs.fetch::<Entity>();
|
let player_entity = ecs.fetch::<Entity>();
|
||||||
// Find down stairs, place player
|
// Find down stairs, place player
|
||||||
|
let dest_tile = if from_tile.is_some() {
|
||||||
|
match from_tile.unwrap() {
|
||||||
|
TileType::UpStair => TileType::DownStair,
|
||||||
|
TileType::DownStair => TileType::UpStair,
|
||||||
|
TileType::ToTown => TileType::ToOvermap,
|
||||||
|
TileType::ToOvermap => {
|
||||||
|
match worldmap_resource.id {
|
||||||
|
ID_TOWN => TileType::ToTown,
|
||||||
|
_ => panic!("Tried to transition to overmap from somewhere unaccounted for!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => if offset < 0 { TileType::DownStair } else { TileType::UpStair }
|
||||||
|
}
|
||||||
|
} else if offset < 0 {
|
||||||
|
TileType::DownStair
|
||||||
|
} else {
|
||||||
|
TileType::UpStair
|
||||||
|
};
|
||||||
|
|
||||||
let w = map.width;
|
let w = map.width;
|
||||||
let stair_type = if offset < 0 { TileType::DownStair } else { TileType::UpStair };
|
|
||||||
for (idx, tt) in map.tiles.iter().enumerate() {
|
for (idx, tt) in map.tiles.iter().enumerate() {
|
||||||
if *tt == stair_type {
|
if *tt == dest_tile {
|
||||||
let mut player_position = ecs.write_resource::<Point>();
|
let mut player_position = ecs.write_resource::<Point>();
|
||||||
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
|
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
|
||||||
let mut position_components = ecs.write_storage::<Position>();
|
let mut position_components = ecs.write_storage::<Position>();
|
||||||
|
|
@ -225,6 +242,7 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dungeon_master.store_map(&worldmap_resource);
|
||||||
*worldmap_resource = map;
|
*worldmap_resource = map;
|
||||||
// Dirtify viewsheds (forces refresh)
|
// Dirtify viewsheds (forces refresh)
|
||||||
let mut viewshed_components = ecs.write_storage::<Viewshed>();
|
let mut viewshed_components = ecs.write_storage::<Viewshed>();
|
||||||
|
|
@ -248,18 +266,23 @@ fn transition_to_new_map(ecs: &mut World, new_id: i32) -> Vec<Map> {
|
||||||
let mut builder = map_builders::level_builder(new_id, &mut rng, 100, 50, player_level);
|
let mut builder = map_builders::level_builder(new_id, &mut rng, 100, 50, player_level);
|
||||||
builder.build_map(&mut rng);
|
builder.build_map(&mut rng);
|
||||||
std::mem::drop(rng);
|
std::mem::drop(rng);
|
||||||
if new_id > 1 {
|
|
||||||
if let Some(pos) = &builder.build_data.starting_position {
|
|
||||||
let up_idx = builder.build_data.map.xy_idx(pos.x, pos.y);
|
|
||||||
builder.build_data.map.tiles[up_idx] = TileType::UpStair;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mapgen_history = builder.build_data.history.clone();
|
let mapgen_history = builder.build_data.history.clone();
|
||||||
let player_start;
|
let player_start;
|
||||||
let old_map: Map;
|
let old_map: Map;
|
||||||
{
|
{
|
||||||
let mut worldmap_resource = ecs.write_resource::<Map>();
|
let mut worldmap_resource = ecs.write_resource::<Map>();
|
||||||
old_map = worldmap_resource.clone();
|
old_map = worldmap_resource.clone();
|
||||||
|
if !old_map.overmap {
|
||||||
|
if let Some(pos) = &builder.build_data.starting_position {
|
||||||
|
let up_idx = builder.build_data.map.xy_idx(pos.x, pos.y);
|
||||||
|
builder.build_data.map.tiles[up_idx] = TileType::UpStair;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(pos) = &builder.build_data.starting_position {
|
||||||
|
let down_idx = builder.build_data.map.xy_idx(pos.x, pos.y);
|
||||||
|
builder.build_data.map.tiles[down_idx] = TileType::ToOvermap;
|
||||||
|
}
|
||||||
|
}
|
||||||
*worldmap_resource = builder.build_data.map.clone();
|
*worldmap_resource = builder.build_data.map.clone();
|
||||||
// Unwrap so we get a CTD if there's no starting pos.
|
// Unwrap so we get a CTD if there's no starting pos.
|
||||||
player_start = builder.build_data.starting_position.as_mut().unwrap().clone();
|
player_start = builder.build_data.starting_position.as_mut().unwrap().clone();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use super::{ Map, Point, TileType };
|
use super::{ Map, Point, TileType };
|
||||||
use crate::data::visuals::*;
|
use crate::data::visuals::*;
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
use crate::data::ids::*;
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use std::ops::{ Add, Mul };
|
use std::ops::{ Add, Mul };
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ pub fn get_tile_renderables_for_id(
|
||||||
debug: Option<bool>
|
debug: Option<bool>
|
||||||
) -> (rltk::FontCharType, RGB, RGB) {
|
) -> (rltk::FontCharType, RGB, RGB) {
|
||||||
let (glyph, mut fg, mut bg, offsets, bg_main_col) = match map.id {
|
let (glyph, mut fg, mut bg, offsets, bg_main_col) = match map.id {
|
||||||
3 => get_forest_theme_renderables(idx, map, debug),
|
ID_TOWN2 => get_forest_theme_renderables(idx, map, debug),
|
||||||
_ => get_default_theme_renderables(idx, map, debug),
|
_ => get_default_theme_renderables(idx, map, debug),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,6 +88,8 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>)
|
||||||
TileType::DeepWater => { glyph = rltk::to_cp437(DEEP_WATER_GLYPH); bg = RGB::named(DEEP_WATER_COLOUR); offsets = DEEP_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::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::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(DEFAULT_BG_COLOUR); bg_main_col = false; }
|
||||||
|
TileType::ToTown => { glyph = rltk::to_cp437(TO_TOWN_GLYPH); fg = RGB::named(TO_TOWN_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); bg_main_col = false; }
|
||||||
}
|
}
|
||||||
return (glyph, fg, bg, offsets, bg_main_col);
|
return (glyph, fg, bg, offsets, bg_main_col);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,23 +23,15 @@ pub enum TileType {
|
||||||
// Stairs (changes floor)
|
// Stairs (changes floor)
|
||||||
DownStair,
|
DownStair,
|
||||||
UpStair,
|
UpStair,
|
||||||
|
// To/From Overmap - ids are in src/data/ids.rs, are used in try_change_level() in src/player.rs
|
||||||
|
ToOvermap,
|
||||||
|
ToTown,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tile_walkable(tt: TileType) -> bool {
|
pub fn tile_walkable(tt: TileType) -> bool {
|
||||||
match tt {
|
match tt {
|
||||||
| TileType::Floor
|
TileType::ImpassableMountain | TileType::Wall | TileType::DeepWater | TileType::Fence | TileType::Bars => false,
|
||||||
| TileType::WoodFloor
|
_ => true,
|
||||||
| TileType::Gravel
|
|
||||||
| TileType::Road
|
|
||||||
| TileType::Grass
|
|
||||||
| TileType::Foliage
|
|
||||||
| TileType::HeavyFoliage
|
|
||||||
| TileType::Sand
|
|
||||||
| TileType::ShallowWater
|
|
||||||
| TileType::Bridge
|
|
||||||
| TileType::DownStair
|
|
||||||
| TileType::UpStair => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ use common::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use voronoi_spawning::VoronoiSpawning;
|
use voronoi_spawning::VoronoiSpawning;
|
||||||
use super::config::CONFIG;
|
use super::config::CONFIG;
|
||||||
|
use super::data::ids::*;
|
||||||
//use wfc::WaveFunctionCollapseBuilder;
|
//use wfc::WaveFunctionCollapseBuilder;
|
||||||
mod room_exploder;
|
mod room_exploder;
|
||||||
use room_exploder::RoomExploder;
|
use room_exploder::RoomExploder;
|
||||||
|
|
@ -318,7 +319,7 @@ fn random_shape_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Bui
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overmap_builder() -> BuilderChain {
|
fn overmap_builder() -> BuilderChain {
|
||||||
let mut builder = BuilderChain::new(true, 1, 69, 41, 0, "the world", 1);
|
let mut builder = BuilderChain::new(true, ID_OVERMAP, 69, 41, 0, "the world", 1);
|
||||||
builder.start_with(PrefabBuilder::overmap());
|
builder.start_with(PrefabBuilder::overmap());
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
@ -385,9 +386,9 @@ pub fn level_builder(
|
||||||
// TODO: With difficulty and ID/depth decoupled, this can be used for branches later.
|
// TODO: With difficulty and ID/depth decoupled, this can be used for branches later.
|
||||||
let difficulty = new_id;
|
let difficulty = new_id;
|
||||||
match new_id {
|
match new_id {
|
||||||
1 => overmap_builder(),
|
ID_OVERMAP => overmap_builder(),
|
||||||
2 => town_builder(new_id, rng, width, height, 0, initial_player_level),
|
ID_TOWN => town_builder(new_id, rng, width, height, 0, initial_player_level),
|
||||||
3 => forest_builder(new_id, rng, width, height, 1, initial_player_level),
|
ID_TOWN2 => forest_builder(new_id, rng, width, height, 1, initial_player_level),
|
||||||
_ => random_builder(new_id, rng, width, height, difficulty, initial_player_level),
|
_ => random_builder(new_id, rng, width, height, difficulty, initial_player_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,9 @@ impl PrefabBuilder {
|
||||||
'^' => {
|
'^' => {
|
||||||
build_data.map.tiles[idx] = TileType::ImpassableMountain;
|
build_data.map.tiles[idx] = TileType::ImpassableMountain;
|
||||||
}
|
}
|
||||||
|
'1' => {
|
||||||
|
build_data.map.tiles[idx] = TileType::ToTown;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
rltk::console::log(format!("Unknown glyph '{}' when loading overmap", ch as u8 as char));
|
rltk::console::log(format!("Unknown glyph '{}' when loading overmap", ch as u8 as char));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
~~~~~~~~~.................~~~.......~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
~~~~~~~~...........................~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
~~~~~~~............................~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
~~~~....~..........................~~~~~~~~~~~~~.....~~~~~~~
|
|
||||||
~~~....~...........................~..~~~~~~~~~~......~~~~~~
|
|
||||||
~~~.................~.................~~~~~~~~~........~...~
|
|
||||||
~~~.................~.......................................
|
|
||||||
~~~~........................................................
|
|
||||||
~~~~~~......................................................
|
|
||||||
~~~~~~..................................~...................
|
|
||||||
~~~~~........~~.........................~...................
|
|
||||||
~~~~~......~~~.~............................................
|
|
||||||
~~~~.......~~..~...........................................~
|
|
||||||
~~~........~...............................................~
|
|
||||||
~~~~......~...............................................~~
|
|
||||||
~~~~~......................................................~
|
|
||||||
~~~~~...~................~..................................
|
|
||||||
~~~~~~~~~~~............~~~..................................
|
|
||||||
~~~~~~~~~~...........~..~...................................
|
|
||||||
~~~~~~~~~~~............~....................................
|
|
||||||
~~~~~~~~~..............~....................................
|
|
||||||
~~~~~~~~.............~~...................................~~
|
|
||||||
~~~~~~~..............~.....................................~
|
|
||||||
~~~~~......................................................~
|
|
||||||
~~~~~.................~~...................................~
|
|
||||||
~~~~..................~.~~~.................................
|
|
||||||
~~~~..............~.......~.................................
|
|
||||||
~.................~~..................~~....................
|
|
||||||
~...............~..~..................~~~...................
|
|
||||||
..~......~~~~~~~~.....~~~.............~~....................
|
|
||||||
..~~.....~~~~~~~~~~...~~~...................................
|
|
||||||
..~~~~~~~~~~~~~~~~..~~~~~~..................................
|
|
||||||
....~~~~~~~~~~~~...~~~~~~~..............~~~~................
|
|
||||||
........~~~~~~~~..........~.~....~......~......~.......~....
|
|
||||||
~...~...~~~~~~~~...........................................~
|
|
||||||
...~~.......~~~~............................................
|
|
||||||
...............~............................................
|
|
||||||
.................................~..........................
|
|
||||||
~~...............................~~.....~...................
|
|
||||||
~~~..............................~~.........................
|
|
||||||
~~~......................................~~~.~~~~...........
|
|
||||||
|
|
@ -93,7 +93,7 @@ const OVERMAP_TEMPLATE: &str =
|
||||||
^^^^^^^........................≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.....≈
|
^^^^^^^........................≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.....≈
|
||||||
^^^^^^^^........@..............≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈....≈
|
^^^^^^^^........@..............≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈....≈
|
||||||
^^^^^^^^..................≈...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈...≈≈≈...≈≈≈≈≈≈≈≈.≈≈
|
^^^^^^^^..................≈...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈...≈≈≈...≈≈≈≈≈≈≈≈.≈≈
|
||||||
^^^^^^^^^.............>...≈≈....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈....≈≈......≈≈≈≈≈≈≈≈≈
|
^^^^^^^^^.............1...≈≈....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈....≈≈......≈≈≈≈≈≈≈≈≈
|
||||||
^^^^^^^^^........≈≈≈≈...≈≈≈≈....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈..≈≈≈......≈≈≈≈≈≈≈≈≈
|
^^^^^^^^^........≈≈≈≈...≈≈≈≈....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈..≈≈≈......≈≈≈≈≈≈≈≈≈
|
||||||
^^^^^^^^^^......≈≈≈≈≈≈≈≈≈≈≈≈≈..≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈
|
^^^^^^^^^^......≈≈≈≈≈≈≈≈≈≈≈≈≈..≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈
|
||||||
^^^^^^^^^^.....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈≈
|
^^^^^^^^^^.....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈≈
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,11 @@ impl TownBuilder {
|
||||||
self.spawn_dockers(build_data, rng);
|
self.spawn_dockers(build_data, rng);
|
||||||
self.spawn_townsfolk(build_data, rng, &mut available_building_tiles);
|
self.spawn_townsfolk(build_data, rng, &mut available_building_tiles);
|
||||||
|
|
||||||
|
build_data.starting_position = Some(Position {
|
||||||
|
x: build_data.width - 2,
|
||||||
|
y: wall_gap_y,
|
||||||
|
});
|
||||||
|
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,11 +191,6 @@ impl TownBuilder {
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
rng: &mut rltk::RandomNumberGenerator
|
rng: &mut rltk::RandomNumberGenerator
|
||||||
) {
|
) {
|
||||||
// Place player
|
|
||||||
build_data.starting_position = Some(Position {
|
|
||||||
x: building.0 + building.2 / 2,
|
|
||||||
y: building.1 + building.3 / 2,
|
|
||||||
});
|
|
||||||
let player_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
let player_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
||||||
|
|
||||||
// Place other items
|
// Place other items
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode };
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::cmp::{ max, min };
|
use std::cmp::{ max, min };
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
use crate::data::ids::*;
|
||||||
|
|
||||||
pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
|
pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
|
||||||
let mut positions = ecs.write_storage::<Position>();
|
let mut positions = ecs.write_storage::<Position>();
|
||||||
|
|
@ -529,20 +530,28 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
||||||
// id
|
// id
|
||||||
VirtualKeyCode::Period => {
|
VirtualKeyCode::Period => {
|
||||||
if ctx.shift {
|
if ctx.shift {
|
||||||
if !try_next_level(&mut gs.ecs) {
|
let (id, from_tile) = try_next_level(&mut gs.ecs);
|
||||||
|
if from_tile.is_none() {
|
||||||
return RunState::AwaitingInput;
|
return RunState::AwaitingInput;
|
||||||
|
} else if id == ID_NEXT_LEVEL {
|
||||||
|
return RunState::NextLevel;
|
||||||
}
|
}
|
||||||
return RunState::NextLevel; // > to descend
|
return RunState::GoToLevel(id, from_tile);
|
||||||
} else {
|
} else {
|
||||||
return skip_turn(&mut gs.ecs); // (Wait a turn)
|
return skip_turn(&mut gs.ecs); // (Wait a turn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VirtualKeyCode::Comma => {
|
VirtualKeyCode::Comma => {
|
||||||
if ctx.shift {
|
if ctx.shift {
|
||||||
if !try_previous_level(&mut gs.ecs) {
|
let (id, from_tile) = try_prev_level(&mut gs.ecs);
|
||||||
|
if from_tile.is_none() {
|
||||||
return RunState::AwaitingInput;
|
return RunState::AwaitingInput;
|
||||||
|
} else if id == ID_PREVIOUS_LEVEL {
|
||||||
|
return RunState::PreviousLevel;
|
||||||
}
|
}
|
||||||
return RunState::PreviousLevel; // < to ascend
|
return RunState::GoToLevel(id, from_tile);
|
||||||
|
} else {
|
||||||
|
return skip_turn(&mut gs.ecs); // (Wait a turn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VirtualKeyCode::Slash => {
|
VirtualKeyCode::Slash => {
|
||||||
|
|
@ -591,27 +600,41 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
||||||
return RunState::AwaitingInput;
|
return RunState::AwaitingInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_next_level(ecs: &mut World) -> bool {
|
fn try_next_level(ecs: &mut World) -> (i32, Option<TileType>) {
|
||||||
let player_pos = ecs.fetch::<Point>();
|
let player_pos = ecs.fetch::<Point>();
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let player_idx = map.xy_idx(player_pos.x, player_pos.y);
|
let player_idx = map.xy_idx(player_pos.x, player_pos.y);
|
||||||
if map.tiles[player_idx] == TileType::DownStair {
|
let this_tile = map.tiles[player_idx];
|
||||||
return true;
|
match this_tile {
|
||||||
} else {
|
TileType::DownStair => {
|
||||||
gamelog::Logger::new().append("You don't see a way down from here.").log();
|
return (ID_NEXT_LEVEL, Some(this_tile));
|
||||||
return false;
|
}
|
||||||
|
TileType::ToTown => {
|
||||||
|
return (ID_TOWN, Some(this_tile));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
gamelog::Logger::new().append("You don't see a way down from here.").log();
|
||||||
|
return (0, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_previous_level(ecs: &mut World) -> bool {
|
fn try_prev_level(ecs: &mut World) -> (i32, Option<TileType>) {
|
||||||
let player_pos = ecs.fetch::<Point>();
|
let player_pos = ecs.fetch::<Point>();
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let player_idx = map.xy_idx(player_pos.x, player_pos.y);
|
let player_idx = map.xy_idx(player_pos.x, player_pos.y);
|
||||||
if map.tiles[player_idx] == TileType::UpStair {
|
let this_tile = map.tiles[player_idx];
|
||||||
return true;
|
match this_tile {
|
||||||
} else {
|
TileType::UpStair => {
|
||||||
gamelog::Logger::new().append("You don't see a way up from here.").log();
|
return (ID_PREVIOUS_LEVEL, Some(this_tile));
|
||||||
return false;
|
}
|
||||||
|
TileType::ToOvermap => {
|
||||||
|
return (ID_OVERMAP, Some(this_tile));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
gamelog::Logger::new().append("You don't see a way out from here.").log();
|
||||||
|
return (0, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue