Refactor movement system, partially implement town portals
This commit is contained in:
parent
9132b6ae2f
commit
878ee5b480
@ -1,8 +1,8 @@
|
||||
use ::rltk::a_star_search;
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{EntityMoved, MyTurn, Position, Viewshed, WantsToApproach};
|
||||
use crate::{spatial, Map};
|
||||
use crate::components::{ApplyMove, MyTurn, Position, WantsToApproach};
|
||||
use crate::Map;
|
||||
|
||||
pub struct ApproachAI {}
|
||||
|
||||
@ -11,33 +11,18 @@ impl<'a> System<'a> for ApproachAI {
|
||||
type SystemData = (
|
||||
WriteStorage<'a, MyTurn>,
|
||||
WriteStorage<'a, WantsToApproach>,
|
||||
WriteStorage<'a, Position>,
|
||||
ReadStorage<'a, Position>,
|
||||
ReadExpect<'a, Map>,
|
||||
WriteStorage<'a, Viewshed>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, ApplyMove>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut turns,
|
||||
mut want_approach,
|
||||
mut positions,
|
||||
map,
|
||||
mut viewsheds,
|
||||
mut entity_moved,
|
||||
entities,
|
||||
) = data;
|
||||
let (mut turns, mut want_approach, positions, map, entities, mut apply_move) = data;
|
||||
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, mut pos, approach, mut viewshed, _myturn) in (
|
||||
&entities,
|
||||
&mut positions,
|
||||
&want_approach,
|
||||
&mut viewsheds,
|
||||
&turns,
|
||||
)
|
||||
.join()
|
||||
for (entity, pos, approach, _myturn) in
|
||||
(&entities, &positions, &want_approach, &turns).join()
|
||||
{
|
||||
turn_done.push(entity);
|
||||
|
||||
@ -48,16 +33,14 @@ impl<'a> System<'a> for ApproachAI {
|
||||
);
|
||||
|
||||
if path.success && path.steps.len() > 1 {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
pos.x = path.steps[1] as i32 % map.width;
|
||||
pos.y = path.steps[1] as i32 / map.width;
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to insert moved marker");
|
||||
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
spatial::move_entity(entity, idx, new_idx);
|
||||
viewshed.dirty = true;
|
||||
apply_move
|
||||
.insert(
|
||||
entity,
|
||||
ApplyMove {
|
||||
dest_idx: path.steps[1],
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intent to move.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ use std::collections::HashMap;
|
||||
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{Chasing, EntityMoved, MyTurn, Position, Viewshed};
|
||||
use crate::{spatial, Map};
|
||||
use crate::components::{ApplyMove, Chasing, MyTurn, Position};
|
||||
use crate::Map;
|
||||
|
||||
pub struct ChaseAI {}
|
||||
|
||||
@ -12,16 +12,14 @@ impl<'a> System<'a> for ChaseAI {
|
||||
type SystemData = (
|
||||
WriteStorage<'a, MyTurn>,
|
||||
WriteStorage<'a, Chasing>,
|
||||
WriteStorage<'a, Position>,
|
||||
ReadStorage<'a, Position>,
|
||||
ReadExpect<'a, Map>,
|
||||
WriteStorage<'a, Viewshed>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, ApplyMove>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (mut turns, mut chasing, mut positions, map, mut viewsheds, mut entity_moved, entities) =
|
||||
data;
|
||||
let (mut turns, mut chasing, positions, map, entities, mut apply_move) = data;
|
||||
|
||||
let mut targets: HashMap<Entity, (i32, i32)> = HashMap::new();
|
||||
let mut end_chase: Vec<Entity> = Vec::new();
|
||||
@ -39,9 +37,7 @@ impl<'a> System<'a> for ChaseAI {
|
||||
end_chase.clear();
|
||||
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, mut pos, _chase, mut viewshed, _myturn) in
|
||||
(&entities, &mut positions, &chasing, &mut viewsheds, &turns).join()
|
||||
{
|
||||
for (entity, pos, _chase, _myturn) in (&entities, &positions, &chasing, &turns).join() {
|
||||
turn_done.push(entity);
|
||||
let target_pos = targets[&entity];
|
||||
let path = ::rltk::a_star_search(
|
||||
@ -51,16 +47,14 @@ impl<'a> System<'a> for ChaseAI {
|
||||
);
|
||||
|
||||
if path.success && path.steps.len() > 1 && path.steps.len() < 15 {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
pos.x = path.steps[1] as i32 % map.width;
|
||||
pos.y = path.steps[1] as i32 / map.width;
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to insert movement marker");
|
||||
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
viewshed.dirty = true;
|
||||
spatial::move_entity(entity, idx, new_idx);
|
||||
apply_move
|
||||
.insert(
|
||||
entity,
|
||||
ApplyMove {
|
||||
dest_idx: path.steps[1],
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intent to move.");
|
||||
turn_done.push(entity);
|
||||
} else {
|
||||
end_chase.push(entity);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use ::rltk::RandomNumberGenerator;
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{EntityMoved, MoveMode, Movement, MyTurn, Position, Viewshed};
|
||||
use crate::components::{ApplyMove, MoveMode, Movement, MyTurn, Position};
|
||||
use crate::{spatial, tile_walkable, Map};
|
||||
|
||||
pub struct DefaultMoveAI {}
|
||||
@ -11,35 +11,19 @@ impl<'a> System<'a> for DefaultMoveAI {
|
||||
type SystemData = (
|
||||
WriteStorage<'a, MyTurn>,
|
||||
WriteStorage<'a, MoveMode>,
|
||||
WriteStorage<'a, Position>,
|
||||
ReadStorage<'a, Position>,
|
||||
ReadExpect<'a, Map>,
|
||||
WriteStorage<'a, Viewshed>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
WriteExpect<'a, RandomNumberGenerator>,
|
||||
WriteStorage<'a, ApplyMove>,
|
||||
Entities<'a>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut turns,
|
||||
mut move_mode,
|
||||
mut positions,
|
||||
map,
|
||||
mut viewsheds,
|
||||
mut entity_moved,
|
||||
mut rng,
|
||||
entities,
|
||||
) = data;
|
||||
let (mut turns, mut move_mode, positions, map, mut rng, mut apply_move, entities) = data;
|
||||
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, mut pos, mut mode, mut viewshed, _myturn) in (
|
||||
&entities,
|
||||
&mut positions,
|
||||
&mut move_mode,
|
||||
&mut viewsheds,
|
||||
&turns,
|
||||
)
|
||||
.join()
|
||||
for (entity, pos, mut mode, _myturn) in
|
||||
(&entities, &positions, &mut move_mode, &turns).join()
|
||||
{
|
||||
turn_done.push(entity);
|
||||
|
||||
@ -60,33 +44,23 @@ impl<'a> System<'a> for DefaultMoveAI {
|
||||
if x > 0 && x < map.width - 1 && y > 0 && y < map.height - 1 {
|
||||
let dest_idx = map.xy_idx(x, y);
|
||||
if !spatial::is_blocked(dest_idx) {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to insert movement marker");
|
||||
crate::spatial::move_entity(entity, idx, dest_idx);
|
||||
viewshed.dirty = true;
|
||||
apply_move
|
||||
.insert(entity, ApplyMove { dest_idx })
|
||||
.expect("Unable to insert intent to move.");
|
||||
turn_done.push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
Movement::RandomWaypoint { path } => {
|
||||
if let Some(path) = path {
|
||||
// We have a target - go there
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
if path.len() > 1 {
|
||||
if !spatial::is_blocked(path[1]) {
|
||||
pos.x = (path[1] as i32 % map.width) as i32;
|
||||
pos.y = (path[1] as i32 / map.width) as i32;
|
||||
entity_moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to insert movement marker");
|
||||
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
spatial::move_entity(entity, idx, new_idx);
|
||||
viewshed.dirty = true;
|
||||
apply_move
|
||||
.insert(entity, ApplyMove { dest_idx: path[1] })
|
||||
.expect("Unable to insert intent to move.");
|
||||
path.remove(0); // Remove the first step in the path
|
||||
turn_done.push(entity);
|
||||
}
|
||||
} else {
|
||||
// Otherwise we wait a turn to see if the path clears up
|
||||
|
@ -1,7 +1,7 @@
|
||||
use ::rltk::DijkstraMap;
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{EntityMoved, MyTurn, Position, Viewshed, WantsToFlee};
|
||||
use crate::components::{ApplyMove, MyTurn, Position, WantsToFlee};
|
||||
use crate::{spatial, Map};
|
||||
|
||||
pub struct FleeAI {}
|
||||
@ -13,32 +13,15 @@ impl<'a> System<'a> for FleeAI {
|
||||
WriteStorage<'a, WantsToFlee>,
|
||||
WriteStorage<'a, Position>,
|
||||
WriteExpect<'a, Map>,
|
||||
WriteStorage<'a, Viewshed>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, ApplyMove>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut turns,
|
||||
mut want_flee,
|
||||
mut positions,
|
||||
mut map,
|
||||
mut viewsheds,
|
||||
mut entity_moved,
|
||||
entities,
|
||||
) = data;
|
||||
let (mut turns, mut want_flee, positions, mut map, entities, mut apply_move) = data;
|
||||
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, mut pos, flee, mut viewshed, _myturn) in (
|
||||
&entities,
|
||||
&mut positions,
|
||||
&want_flee,
|
||||
&mut viewsheds,
|
||||
&turns,
|
||||
)
|
||||
.join()
|
||||
{
|
||||
for (entity, pos, flee, _myturn) in (&entities, &positions, &want_flee, &turns).join() {
|
||||
turn_done.push(entity);
|
||||
|
||||
let my_idx = map.xy_idx(pos.x, pos.y);
|
||||
@ -47,13 +30,15 @@ impl<'a> System<'a> for FleeAI {
|
||||
let flee_map = DijkstraMap::new(map.width, map.height, &flee.indices, &*map, 100.0);
|
||||
if let Some(flee_target) = DijkstraMap::find_highest_exit(&flee_map, my_idx, &*map) {
|
||||
if !spatial::is_blocked(flee_target) {
|
||||
spatial::move_entity(entity, my_idx, flee_target);
|
||||
viewshed.dirty = true;
|
||||
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 intent to flee");
|
||||
apply_move
|
||||
.insert(
|
||||
entity,
|
||||
ApplyMove {
|
||||
dest_idx: flee_target,
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intention to flee");
|
||||
turn_done.push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +354,26 @@ pub struct Vendor {
|
||||
pub categories: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct TeleportTo {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub depth: i32,
|
||||
pub player_only: bool,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ApplyMove {
|
||||
pub dest_idx: usize,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ApplyTeleport {
|
||||
pub dest_x: i32,
|
||||
pub dest_y: i32,
|
||||
pub dest_depth: i32,
|
||||
}
|
||||
|
||||
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
|
||||
// Entity.
|
||||
|
||||
|
@ -39,3 +39,6 @@ pub struct MyTurn {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct EquipmentChanged {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct TownPortal {}
|
||||
|
@ -84,6 +84,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
||||
ReadStorage<'a, MagicMapper>,
|
||||
WriteExpect<'a, RunState>,
|
||||
WriteStorage<'a, EquipmentChanged>,
|
||||
ReadStorage<'a, TownPortal>,
|
||||
);
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
@ -112,6 +113,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
||||
magic_mapper,
|
||||
mut runstate,
|
||||
mut dirty,
|
||||
town_portal,
|
||||
) = data;
|
||||
|
||||
for (entity, useitem) in (&entities, &wants_use).join() {
|
||||
@ -236,6 +238,18 @@ impl<'a> System<'a> for ItemUseSystem {
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a town portal...
|
||||
if town_portal.get(useitem.item).is_some() {
|
||||
if map.depth == 1 {
|
||||
gamelog.append("You are already in town, so the scroll does nothing");
|
||||
} else {
|
||||
used_item = true;
|
||||
gamelog.append("You are teleported back to town!");
|
||||
|
||||
*runstate = RunState::TownPortal;
|
||||
}
|
||||
}
|
||||
|
||||
// If the item heals, apply the healing
|
||||
match healing.get(useitem.item) {
|
||||
None => {}
|
||||
|
23
src/main.rs
23
src/main.rs
@ -13,6 +13,7 @@ mod map;
|
||||
pub mod map_builders;
|
||||
mod map_indexing_system;
|
||||
mod melee_combat_system;
|
||||
mod movement_system;
|
||||
mod particle_system;
|
||||
mod player;
|
||||
pub mod random_table;
|
||||
@ -41,6 +42,7 @@ use lighting_system::LightingSystem;
|
||||
pub use map::*;
|
||||
use map_indexing_system::MapIndexingSystem;
|
||||
use melee_combat_system::MeleeCombatSystem;
|
||||
use movement_system::MovementSystem;
|
||||
use particle_system::ParticleSpawnSystem;
|
||||
use player::*;
|
||||
use raws::*;
|
||||
@ -84,6 +86,7 @@ pub enum RunState {
|
||||
SaveGame,
|
||||
NextLevel,
|
||||
PreviousLevel,
|
||||
TownPortal,
|
||||
ShowRemoveItem,
|
||||
GameOver,
|
||||
MagicMapReveal {
|
||||
@ -155,6 +158,9 @@ impl State {
|
||||
let mut defaultmove = ai::DefaultMoveAI {};
|
||||
defaultmove.run_now(&self.ecs);
|
||||
|
||||
let mut moving = MovementSystem {};
|
||||
moving.run_now(&self.ecs);
|
||||
|
||||
let mut triggers = TriggerSystem {};
|
||||
triggers.run_now(&self.ecs);
|
||||
|
||||
@ -244,6 +250,7 @@ impl GameState for State {
|
||||
newrunstate = match *self.ecs.fetch::<RunState>() {
|
||||
RunState::AwaitingInput => RunState::AwaitingInput,
|
||||
RunState::MagicMapReveal { .. } => RunState::MagicMapReveal { row: 0 },
|
||||
RunState::TownPortal => RunState::TownPortal,
|
||||
_ => RunState::Ticking,
|
||||
};
|
||||
}
|
||||
@ -483,6 +490,18 @@ impl GameState for State {
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::TownPortal => {
|
||||
// Spawn the portal
|
||||
spawner::spawn_town_portal(&mut self.ecs);
|
||||
|
||||
// Transition
|
||||
let map_depth = self.ecs.fetch::<Map>().depth;
|
||||
let destination_offset = 0 - (map_depth - 1);
|
||||
self.goto_level(destination_offset);
|
||||
self.mapgen_next_state = Some(RunState::PreRun);
|
||||
|
||||
newrunstate = RunState::MapGeneration;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -556,6 +575,8 @@ fn main() -> ::rltk::BError {
|
||||
|
||||
register!(
|
||||
gs <-
|
||||
ApplyMove,
|
||||
ApplyTeleport,
|
||||
AreaOfEffect,
|
||||
Attributes,
|
||||
BlocksTile,
|
||||
@ -600,6 +621,8 @@ fn main() -> ::rltk::BError {
|
||||
SingleActivation,
|
||||
Skills,
|
||||
SufferDamage,
|
||||
TeleportTo,
|
||||
TownPortal,
|
||||
Vendor,
|
||||
Viewshed,
|
||||
WantsToApproach,
|
||||
|
@ -1,10 +1,11 @@
|
||||
use ::rltk::RandomNumberGenerator;
|
||||
|
||||
use super::prefab_builder::prefab_sections;
|
||||
use super::{
|
||||
prefab_builder::prefab_sections, AreaEndingPosition, AreaStartingPosition, BspDungeonBuilder,
|
||||
BuilderChain, BuilderMap, CellularAutomataBuilder, CullUnreachable, DLABuilder, DistantExit,
|
||||
DrunkardsWalkBuilder, MetaMapBuilder, NearestCorridors, PrefabBuilder, RoomBasedSpawner,
|
||||
RoomDrawer, RoomExploder, RoomSort, RoomSorter, VoronoiSpawning, XEnd, XStart, YEnd, YStart,
|
||||
AreaEndingPosition, AreaStartingPosition, BspDungeonBuilder, BuilderChain, BuilderMap,
|
||||
CellularAutomataBuilder, CullUnreachable, DLABuilder, DistantExit, DrunkardsWalkBuilder,
|
||||
MetaMapBuilder, NearestCorridors, PrefabBuilder, RoomBasedSpawner, RoomDrawer, RoomExploder,
|
||||
RoomSort, RoomSorter, VoronoiSpawning, XEnd, XStart, YEnd, YStart,
|
||||
};
|
||||
use crate::map::TileType;
|
||||
|
||||
|
89
src/movement_system.rs
Normal file
89
src/movement_system.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{
|
||||
ApplyMove, ApplyTeleport, BlocksTile, EntityMoved, OtherLevelPosition, Position, Viewshed,
|
||||
};
|
||||
use crate::{spatial, Map};
|
||||
|
||||
pub struct MovementSystem {}
|
||||
|
||||
impl<'a> System<'a> for MovementSystem {
|
||||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
WriteExpect<'a, Map>,
|
||||
WriteStorage<'a, Position>,
|
||||
ReadStorage<'a, BlocksTile>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, ApplyMove>,
|
||||
WriteStorage<'a, ApplyTeleport>,
|
||||
WriteStorage<'a, OtherLevelPosition>,
|
||||
WriteStorage<'a, EntityMoved>,
|
||||
WriteStorage<'a, Viewshed>,
|
||||
ReadExpect<'a, Entity>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut map,
|
||||
mut position,
|
||||
blockers,
|
||||
entities,
|
||||
mut apply_move,
|
||||
mut apply_teleport,
|
||||
mut other_level,
|
||||
mut moved,
|
||||
mut viewsheds,
|
||||
player_entity,
|
||||
) = data;
|
||||
|
||||
// Apply teleports
|
||||
for (entity, teleport) in (&entities, &apply_teleport).join() {
|
||||
if teleport.dest_depth == map.depth {
|
||||
apply_move
|
||||
.insert(
|
||||
entity,
|
||||
ApplyMove {
|
||||
dest_idx: map.xy_idx(teleport.dest_x, teleport.dest_y),
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intent to teleport");
|
||||
} else if entity == *player_entity {
|
||||
// it's the player - we have a mess
|
||||
::rltk::console::log(format!("Not implemented yet."))
|
||||
} else if let Some(pos) = position.get(entity) {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
let dest_idx = map.xy_idx(teleport.dest_x, teleport.dest_y);
|
||||
spatial::move_entity(entity, idx, dest_idx);
|
||||
other_level
|
||||
.insert(
|
||||
entity,
|
||||
OtherLevelPosition {
|
||||
x: teleport.dest_x,
|
||||
y: teleport.dest_y,
|
||||
depth: teleport.dest_depth,
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intent to teleport.");
|
||||
|
||||
position.remove(entity);
|
||||
}
|
||||
}
|
||||
apply_teleport.clear();
|
||||
|
||||
// Apply broad movement
|
||||
for (entity, movement, mut pos) in (&entities, &apply_move, &mut position).join() {
|
||||
let start_idx = map.xy_idx(pos.x, pos.y);
|
||||
let dest_idx = movement.dest_idx as usize;
|
||||
spatial::move_entity(entity, start_idx, dest_idx);
|
||||
pos.x = movement.dest_idx as i32 % map.width;
|
||||
pos.y = movement.dest_idx as i32 / map.width;
|
||||
if let Some(vs) = viewsheds.get_mut(entity) {
|
||||
vs.dirty = true;
|
||||
}
|
||||
moved
|
||||
.insert(entity, EntityMoved {})
|
||||
.expect("Unable to insert moved marker");
|
||||
}
|
||||
apply_move.clear();
|
||||
}
|
||||
}
|
@ -285,6 +285,7 @@ pub fn spawn_named_item(
|
||||
})
|
||||
}
|
||||
"magic_mapping" => eb = eb.with(MagicMapper {}),
|
||||
"town_portal" => eb = eb.with(TownPortal {}),
|
||||
"food" => eb = eb.with(ProvidesFood {}),
|
||||
_ => {
|
||||
rltk::console::log(format!(
|
||||
|
@ -61,6 +61,8 @@ pub fn save_game(ecs: &mut World) {
|
||||
ecs,
|
||||
serializer,
|
||||
data,
|
||||
ApplyMove,
|
||||
ApplyTeleport,
|
||||
AreaOfEffect,
|
||||
Attributes,
|
||||
BlocksTile,
|
||||
@ -104,6 +106,8 @@ pub fn save_game(ecs: &mut World) {
|
||||
SingleActivation,
|
||||
Skills,
|
||||
SufferDamage,
|
||||
TeleportTo,
|
||||
TownPortal,
|
||||
Vendor,
|
||||
Viewshed,
|
||||
WantsToApproach,
|
||||
@ -170,6 +174,8 @@ pub fn load_game(ecs: &mut World) {
|
||||
ecs,
|
||||
de,
|
||||
d,
|
||||
ApplyMove,
|
||||
ApplyTeleport,
|
||||
AreaOfEffect,
|
||||
Attributes,
|
||||
BlocksTile,
|
||||
@ -213,6 +219,8 @@ pub fn load_game(ecs: &mut World) {
|
||||
SingleActivation,
|
||||
Skills,
|
||||
SufferDamage,
|
||||
TeleportTo,
|
||||
TownPortal,
|
||||
Vendor,
|
||||
Viewshed,
|
||||
WantsToApproach,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ::rltk::RandomNumberGenerator;
|
||||
use ::rltk::{Point, RandomNumberGenerator};
|
||||
use ::specs::prelude::*;
|
||||
use ::specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::components::*;
|
||||
use crate::gamesystem::{mana_at_level, player_hp_at_level};
|
||||
use crate::random_table::RandomTable;
|
||||
use crate::raws::{get_spawn_table_for_depth, spawn_named_entity, SpawnType, RAWS};
|
||||
use crate::{colors, Map, Rect, TileType};
|
||||
use crate::{colors, Map, MasterDungeonMap, Rect, TileType};
|
||||
|
||||
/// Spawns the player and returns their entity object
|
||||
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||
@ -95,6 +95,12 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||
"Old Boots",
|
||||
SpawnType::Equipped { by: player },
|
||||
);
|
||||
spawn_named_entity(
|
||||
&RAWS.lock().unwrap(),
|
||||
ecs,
|
||||
"Town Portal Scroll",
|
||||
SpawnType::Carried { by: player },
|
||||
);
|
||||
|
||||
player
|
||||
}
|
||||
@ -195,3 +201,52 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
||||
spawn.1
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_town_portal(ecs: &mut World) {
|
||||
// Get current position & depth
|
||||
let map = ecs.fetch::<Map>();
|
||||
let player_depth = map.depth;
|
||||
let player_pos = ecs.fetch::<Point>();
|
||||
let player_x = player_pos.x;
|
||||
let player_y = player_pos.y;
|
||||
std::mem::drop(player_pos);
|
||||
std::mem::drop(map);
|
||||
|
||||
// Find part of the town for the portal
|
||||
let dm = ecs.fetch::<MasterDungeonMap>();
|
||||
let town_map = dm.get_map(1).unwrap();
|
||||
let mut stairs_idx = 0;
|
||||
for (idx, tt) in town_map.tiles.iter().enumerate() {
|
||||
if *tt == TileType::DownStairs {
|
||||
stairs_idx = idx;
|
||||
}
|
||||
}
|
||||
let portal_x = (stairs_idx as i32 % town_map.width) - 2;
|
||||
let portal_y = stairs_idx as i32 / town_map.width;
|
||||
|
||||
std::mem::drop(dm);
|
||||
|
||||
// Spawn the portal itself
|
||||
ecs.create_entity()
|
||||
.with(OtherLevelPosition {
|
||||
x: portal_x,
|
||||
y: portal_y,
|
||||
depth: 1,
|
||||
})
|
||||
.with(Renderable {
|
||||
glyph: ::rltk::to_cp437('♥'),
|
||||
fg: colors::CYAN,
|
||||
bg: colors::BLACK,
|
||||
render_order: 0,
|
||||
})
|
||||
.with(EntryTrigger {})
|
||||
.with(TeleportTo {
|
||||
x: player_x,
|
||||
y: player_y,
|
||||
depth: player_depth,
|
||||
player_only: true,
|
||||
})
|
||||
.with(Name::from("Town Portal"))
|
||||
.with(SingleActivation {})
|
||||
.build();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user