huge refactor of overmap-local map travel

This commit is contained in:
Llywelwyn 2023-08-27 16:21:15 +01:00
parent 02be487334
commit 8e3ed5cead
9 changed files with 103 additions and 145 deletions

View file

@ -189,60 +189,55 @@ fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<Stri
}
}
pub fn level_transition(ecs: &mut World, new_id: i32, offset: i32, from_tile: Option<TileType>) -> Option<Vec<Map>> {
pub fn level_transition(ecs: &mut World, new_id: i32, dest_tile: TileType) -> Option<Vec<Map>> {
// Obtain master
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
if dungeon_master.get_map(new_id).is_some() {
std::mem::drop(dungeon_master);
transition_to_existing_map(ecs, new_id, offset, from_tile);
transition_to_existing_map(ecs, new_id, dest_tile);
return None;
} else {
std::mem::drop(dungeon_master);
return Some(transition_to_new_map(ecs, new_id));
return Some(transition_to_new_map(ecs, new_id, dest_tile));
}
}
fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32, from_tile: Option<TileType>) {
fn transition_to_existing_map(ecs: &mut World, new_id: i32, dest_tile: TileType) {
let mut dungeon_master = ecs.write_resource::<MasterDungeonMap>();
// Unwrapping here panics if new_id isn't present. But this should
// never be called without new_id being present by level_transition.
let map = dungeon_master.get_map(new_id).unwrap();
let mut worldmap_resource = ecs.write_resource::<Map>();
let player_entity = ecs.fetch::<Entity>();
// 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,
ID_INFINITE => TileType::ToInfinite,
_ => 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 mut possible_destinations: Vec<usize> = Vec::new();
for (idx, tt) in map.tiles.iter().enumerate() {
if *tt == dest_tile {
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>();
let player_pos_component = position_components.get_mut(*player_entity);
if let Some(player_pos_component) = player_pos_component {
player_pos_component.x = (idx as i32) % w;
player_pos_component.y = (idx as i32) / w;
}
possible_destinations.push(idx);
}
}
if possible_destinations.is_empty() {
console::log("WARNING: No destination tiles found on map transition.");
match dest_tile {
TileType::DownStair => console::log("DESTINATION: DownStair"),
TileType::UpStair => console::log("DESTINATION: UpStair"),
TileType::ToOvermap(id) => console::log(format!("DESTINATION: ToOvermap({})", id)),
TileType::ToLocal(id) => console::log(format!("DESTINATION: ToLocal({})", id)),
_ => console::log("DESTINATION: Unknown"),
}
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 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>();
let player_pos_component = position_components.get_mut(*player_entity);
if let Some(player_pos_component) = player_pos_component {
player_pos_component.x = (idx as i32) % w;
player_pos_component.y = (idx as i32) / w;
}
dungeon_master.store_map(&worldmap_resource);
*worldmap_resource = map;
// Dirtify viewsheds (forces refresh)
@ -258,7 +253,7 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32, from_ti
}
}
fn transition_to_new_map(ecs: &mut World, new_id: i32) -> Vec<Map> {
fn transition_to_new_map(ecs: &mut World, new_id: i32, _dest_tile: TileType) -> Vec<Map> {
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
// Might need this to fallback to 1, but if player
// level isn't found at all, there's a bigger concern
@ -280,11 +275,6 @@ fn transition_to_new_map(ecs: &mut World, new_id: i32) -> Vec<Map> {
let up_idx = builder.build_data.map.xy_idx(pos.x, pos.y);
builder.build_data.map.tiles[up_idx] = TileType::UpStair;
}
} else if old_map.overmap && !builder.build_data.map.overmap {
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();
// Unwrap so we get a CTD if there's no starting pos.

View file

@ -2,7 +2,7 @@ use rltk::{ Algorithm2D, BaseMap, Point };
use serde::{ Deserialize, Serialize };
use std::collections::HashSet;
mod tiletype;
pub use tiletype::{ tile_cost, tile_opaque, tile_walkable, TileType };
pub use tiletype::{ tile_cost, tile_opaque, tile_walkable, TileType, get_dest, Destination };
mod interval_spawning_system;
pub use interval_spawning_system::try_spawn_interval;
pub mod dungeon;

View file

@ -88,9 +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::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(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; }
TileType::ToInfinite => { glyph = rltk::to_cp437(TO_INFINITE_GLYPH); fg = RGB::named(TO_INFINITE_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); bg_main_col = true; }
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::ToLocal(_) => { 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);
}

View file

@ -24,18 +24,15 @@ pub enum TileType {
DownStair,
UpStair,
// To/From Overmap - ids are in src/data/ids.rs, are used in try_change_level() in src/player.rs
ToOvermap,
ToTown,
ToInfinite,
ToOvermap(i32),
ToLocal(i32),
}
pub fn tile_walkable(tt: TileType) -> bool {
match tt {
TileType::ImpassableMountain | TileType::Wall | TileType::DeepWater | TileType::Fence | TileType::Bars => false,
_ => true,
}
}
pub fn tile_opaque(tt: TileType) -> bool {
match tt {
TileType::ImpassableMountain => true,
@ -43,7 +40,6 @@ pub fn tile_opaque(tt: TileType) -> bool {
_ => false,
}
}
pub fn tile_cost(tt: TileType) -> f32 {
match tt {
TileType::Road => 0.5,
@ -52,3 +48,29 @@ pub fn tile_cost(tt: TileType) -> f32 {
_ => 1.0,
}
}
pub fn get_dest(this_tile: TileType, backtracking: bool) -> Destination {
let result = if !backtracking {
match this_tile {
// If on downstair, GOTO next level, and end up on an upstair
TileType::DownStair => Destination::NextLevel,
// If on overmap ToLocal tile, GOTO local map, and end up on an overmap ToOvermap tile with corresponding ID
TileType::ToLocal(id) => Destination::ToOvermap(id),
_ => Destination::None,
}
} else {
match this_tile {
TileType::UpStair => Destination::PreviousLevel,
TileType::ToOvermap(id) => Destination::ToLocal(id),
_ => Destination::None,
}
};
return result;
}
pub enum Destination {
PreviousLevel,
NextLevel,
ToOvermap(i32),
ToLocal(i32),
None,
}