entity thawing and freezing on level change
This commit is contained in:
parent
dab0683ffd
commit
2a8691efff
4 changed files with 61 additions and 52 deletions
|
|
@ -23,6 +23,13 @@ pub struct Position {
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct OtherLevelPosition {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
pub id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component, ConvertSaveload, Clone)]
|
||||||
pub struct Renderable {
|
pub struct Renderable {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: rltk::FontCharType,
|
||||||
|
|
|
||||||
56
src/main.rs
56
src/main.rs
|
|
@ -85,6 +85,8 @@ impl State {
|
||||||
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);
|
||||||
if let Some(history) = map_building_info {
|
if let Some(history) = map_building_info {
|
||||||
self.mapgen_history = history;
|
self.mapgen_history = history;
|
||||||
|
} else {
|
||||||
|
map::dungeon::thaw_entities(&mut self.ecs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,58 +135,9 @@ impl State {
|
||||||
mapindex.run_now(&self.ecs);
|
mapindex.run_now(&self.ecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entities_to_remove_on_level_change(&mut self) -> Vec<Entity> {
|
|
||||||
let entities = self.ecs.entities();
|
|
||||||
let player = self.ecs.read_storage::<Player>();
|
|
||||||
let clock = self.ecs.read_storage::<Clock>();
|
|
||||||
let backpack = self.ecs.read_storage::<InBackpack>();
|
|
||||||
let player_entity = self.ecs.fetch::<Entity>();
|
|
||||||
let equipped = self.ecs.read_storage::<Equipped>();
|
|
||||||
|
|
||||||
let mut to_delete: Vec<Entity> = Vec::new();
|
|
||||||
for entity in entities.join() {
|
|
||||||
let mut should_delete = true;
|
|
||||||
|
|
||||||
// Don't delete the turn clock
|
|
||||||
let c = clock.get(entity);
|
|
||||||
if let Some(_c) = c {
|
|
||||||
should_delete = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't delete player
|
|
||||||
let p = player.get(entity);
|
|
||||||
if let Some(_p) = p {
|
|
||||||
should_delete = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't delete player's equipment
|
|
||||||
let bp = backpack.get(entity);
|
|
||||||
if let Some(bp) = bp {
|
|
||||||
if bp.owner == *player_entity {
|
|
||||||
should_delete = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let eq = equipped.get(entity);
|
|
||||||
if let Some(eq) = eq {
|
|
||||||
if eq.owner == *player_entity {
|
|
||||||
should_delete = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if should_delete {
|
|
||||||
to_delete.push(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return to_delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn goto_level(&mut self, offset: i32) {
|
fn goto_level(&mut self, offset: i32) {
|
||||||
// Delete entities that aren't player/player's equipment
|
// Freeze the current level
|
||||||
let to_delete = self.entities_to_remove_on_level_change();
|
map::dungeon::freeze_entities(&mut self.ecs);
|
||||||
for target in to_delete {
|
|
||||||
self.ecs.delete_entity(target).expect("Unable to delete entity");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build new map + place player
|
// Build new map + place player
|
||||||
let current_id;
|
let current_id;
|
||||||
|
|
@ -511,6 +464,7 @@ fn main() -> rltk::BError {
|
||||||
};
|
};
|
||||||
|
|
||||||
gs.ecs.register::<Position>();
|
gs.ecs.register::<Position>();
|
||||||
|
gs.ecs.register::<OtherLevelPosition>();
|
||||||
gs.ecs.register::<Renderable>();
|
gs.ecs.register::<Renderable>();
|
||||||
gs.ecs.register::<Prop>();
|
gs.ecs.register::<Prop>();
|
||||||
gs.ecs.register::<Player>();
|
gs.ecs.register::<Player>();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{Map, TileType};
|
use super::{Map, TileType};
|
||||||
use crate::{gamelog, map_builders, Position, Telepath, Viewshed};
|
use crate::{gamelog, map_builders, OtherLevelPosition, Position, Telepath, Viewshed};
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
@ -131,3 +131,49 @@ fn transition_to_new_map(ecs: &mut World, new_id: i32) -> Vec<Map> {
|
||||||
dungeon_master.store_map(&builder.build_data.map);
|
dungeon_master.store_map(&builder.build_data.map);
|
||||||
return mapgen_history;
|
return mapgen_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate through entities on the current level, save the current position and floor
|
||||||
|
/// of each entity-to-be-frozen, and then delete their current position.
|
||||||
|
pub fn freeze_entities(ecs: &mut World) {
|
||||||
|
// Obtain reqs from ECS
|
||||||
|
let entities = ecs.entities();
|
||||||
|
let mut positions = ecs.write_storage::<Position>();
|
||||||
|
let mut other_positions = ecs.write_storage::<OtherLevelPosition>();
|
||||||
|
let player_entity = ecs.fetch::<Entity>();
|
||||||
|
let map_id = ecs.fetch::<Map>().id;
|
||||||
|
// Save Positions and mark for deletion
|
||||||
|
let mut pos_to_delete: Vec<Entity> = Vec::new();
|
||||||
|
for (entity, pos) in (&entities, &positions).join() {
|
||||||
|
if entity != *player_entity {
|
||||||
|
other_positions
|
||||||
|
.insert(entity, OtherLevelPosition { x: pos.x, y: pos.y, id: map_id })
|
||||||
|
.expect("Failed to insert OtherLevelPosition");
|
||||||
|
pos_to_delete.push(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for p in pos_to_delete.iter() {
|
||||||
|
positions.remove(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate through entities, and insert a Position component if the
|
||||||
|
/// entity has an OtherLevelPosition for the new map id.
|
||||||
|
pub fn thaw_entities(ecs: &mut World) {
|
||||||
|
// Obtain reqs from ECS
|
||||||
|
let entities = ecs.entities();
|
||||||
|
let mut positions = ecs.write_storage::<Position>();
|
||||||
|
let mut other_positions = ecs.write_storage::<OtherLevelPosition>();
|
||||||
|
let player_entity = ecs.fetch::<Entity>();
|
||||||
|
let map_id = ecs.fetch::<Map>().id;
|
||||||
|
// Save Positions and mark for deletion
|
||||||
|
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");
|
||||||
|
pos_to_delete.push(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for p in pos_to_delete.iter() {
|
||||||
|
other_positions.remove(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ pub fn save_game(ecs: &mut World) {
|
||||||
MultiAttack,
|
MultiAttack,
|
||||||
NaturalAttacks,
|
NaturalAttacks,
|
||||||
Name,
|
Name,
|
||||||
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
Pools,
|
Pools,
|
||||||
|
|
@ -186,6 +187,7 @@ pub fn load_game(ecs: &mut World) {
|
||||||
MultiAttack,
|
MultiAttack,
|
||||||
NaturalAttacks,
|
NaturalAttacks,
|
||||||
Name,
|
Name,
|
||||||
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
Pools,
|
Pools,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue