|
@@ -40,7 +40,8 @@ pub enum RunState { AwaitingInput,
|
|
|
ShowDropItem,
|
|
|
ShowTargeting { range : i32, item : Entity},
|
|
|
MainMenu { menu_selection : gui::MainMenuSelection },
|
|
|
- SaveGame
|
|
|
+ SaveGame,
|
|
|
+ NextLevel
|
|
|
}
|
|
|
|
|
|
pub struct State {
|
|
@@ -164,6 +165,10 @@ impl GameState for State {
|
|
|
saveload_system::save_game(&mut self.ecs);
|
|
|
newrunstate = RunState::MainMenu{ menu_selection : gui::MainMenuSelection::LoadGame };
|
|
|
}
|
|
|
+ RunState::NextLevel => {
|
|
|
+ self.goto_next_level();
|
|
|
+ newrunstate = RunState::PreRun;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
{
|
|
@@ -174,6 +179,90 @@ impl GameState for State {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl State {
|
|
|
+ fn entities_to_remove_on_level_change(&mut self) -> Vec<Entity> {
|
|
|
+ let entities = self.ecs.entities();
|
|
|
+ let player = self.ecs.read_storage::<Player>();
|
|
|
+ let backpack = self.ecs.read_storage::<InBackpack>();
|
|
|
+ let player_entity = self.ecs.fetch::<Entity>();
|
|
|
+
|
|
|
+ let mut to_delete : Vec<Entity> = Vec::new();
|
|
|
+ for entity in entities.join() {
|
|
|
+ let mut should_delete = true;
|
|
|
+
|
|
|
+ // Don't delete the player
|
|
|
+ let p = player.get(entity);
|
|
|
+ if let Some(_p) = p {
|
|
|
+ should_delete = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Don't delete the player's equipment
|
|
|
+ let bp = backpack.get(entity);
|
|
|
+ if let Some(bp) = bp {
|
|
|
+ if bp.owner == *player_entity {
|
|
|
+ should_delete = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if should_delete {
|
|
|
+ to_delete.push(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ to_delete
|
|
|
+ }
|
|
|
+
|
|
|
+ fn goto_next_level(&mut self) {
|
|
|
+ // Delete entities that aren't the player or his/her equipment
|
|
|
+ let to_delete = self.entities_to_remove_on_level_change();
|
|
|
+ for target in to_delete {
|
|
|
+ self.ecs.delete_entity(target).expect("Unable to delete entity");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build a new map and place the player
|
|
|
+ let worldmap;
|
|
|
+ {
|
|
|
+ let mut worldmap_resource = self.ecs.write_resource::<Map>();
|
|
|
+ let current_depth = worldmap_resource.depth;
|
|
|
+ *worldmap_resource = Map::new_map_rooms_and_corridors(current_depth + 1);
|
|
|
+ worldmap = worldmap_resource.clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Spawn bad guys
|
|
|
+ for room in worldmap.rooms.iter().skip(1) {
|
|
|
+ spawner::spawn_room(&mut self.ecs, room);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Place the player and update resources
|
|
|
+ let (player_x, player_y) = worldmap.rooms[0].center();
|
|
|
+ let mut player_position = self.ecs.write_resource::<Point>();
|
|
|
+ *player_position = Point::new(player_x, player_y);
|
|
|
+ let mut position_components = self.ecs.write_storage::<Position>();
|
|
|
+ let player_entity = self.ecs.fetch::<Entity>();
|
|
|
+ let player_pos_comp = position_components.get_mut(*player_entity);
|
|
|
+ if let Some(player_pos_comp) = player_pos_comp {
|
|
|
+ player_pos_comp.x = player_x;
|
|
|
+ player_pos_comp.y = player_y;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Mark the player's visibility as dirty
|
|
|
+ let mut viewshed_components = self.ecs.write_storage::<Viewshed>();
|
|
|
+ let vs = viewshed_components.get_mut(*player_entity);
|
|
|
+ if let Some(vs) = vs {
|
|
|
+ vs.dirty = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Notify the player and give them some health
|
|
|
+ let mut gamelog = self.ecs.fetch_mut::<gamelog::GameLog>();
|
|
|
+ gamelog.entries.insert(0, "You descend to the next level, and take a moment to heal.".to_string());
|
|
|
+ let mut player_health_store = self.ecs.write_storage::<CombatStats>();
|
|
|
+ let player_health = player_health_store.get_mut(*player_entity);
|
|
|
+ if let Some(player_health) = player_health {
|
|
|
+ player_health.hp = i32::max(player_health.hp, player_health.max_hp / 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
fn main() {
|
|
|
let mut context = Rltk::init_simple8x8(80, 50, "Hello Rust World", "../resources");
|
|
|
context.with_post_scanlines(true);
|
|
@@ -216,7 +305,7 @@ fn main() {
|
|
|
|
|
|
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
|
|
|
|
|
- let map : Map = Map::new_map_rooms_and_corridors();
|
|
|
+ let map : Map = Map::new_map_rooms_and_corridors(1);
|
|
|
let (player_x, player_y) = map.rooms[0].center();
|
|
|
|
|
|
let player_entity = spawner::player(&mut gs.ecs, player_x, player_y);
|