2022-01-21 15:55:13 -05:00
|
|
|
//!
|
2022-01-18 11:40:31 -05:00
|
|
|
use ::rltk::{GameState, Point, Rltk};
|
|
|
|
use ::specs::prelude::*;
|
|
|
|
|
|
|
|
use crate::components::*;
|
|
|
|
use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection};
|
|
|
|
use crate::hunger_system::HungerSystem;
|
|
|
|
use crate::inventory_system::{
|
2022-01-20 14:04:47 -05:00
|
|
|
ItemCollectionSystem, ItemDropSystem, ItemEquipOnUse, ItemIdentificationSystem,
|
2022-01-25 11:15:32 -05:00
|
|
|
ItemRemoveSystem, ItemUseSystem, SpellUseSystem,
|
2022-01-18 11:40:31 -05:00
|
|
|
};
|
|
|
|
use crate::lighting_system::LightingSystem;
|
|
|
|
use crate::map::{self, *};
|
|
|
|
use crate::map_indexing_system::MapIndexingSystem;
|
|
|
|
use crate::melee_combat_system::MeleeCombatSystem;
|
|
|
|
use crate::movement_system::MovementSystem;
|
|
|
|
use crate::particle_system::{self, ParticleSpawnSystem};
|
|
|
|
use crate::player::*;
|
2022-01-31 11:25:36 -05:00
|
|
|
use crate::ranged_combat_system::RangedCombatSystem;
|
2022-01-18 11:40:31 -05:00
|
|
|
use crate::raws::*;
|
|
|
|
use crate::trigger_system::TriggerSystem;
|
|
|
|
use crate::visibility_system::VisibilitySystem;
|
2022-02-01 10:39:46 -05:00
|
|
|
use crate::{
|
|
|
|
ai, camera, colors, damage_system, effects, gamelog, player, saveload_system, spawner,
|
|
|
|
};
|
2022-01-18 11:40:31 -05:00
|
|
|
|
2022-01-21 15:55:13 -05:00
|
|
|
/// Whether to show a visual representation of map generation
|
2022-01-28 10:54:19 -05:00
|
|
|
pub const SHOW_MAPGEN_VISUALIZER: bool = false;
|
2022-01-18 11:40:31 -05:00
|
|
|
|
2022-01-21 15:55:13 -05:00
|
|
|
/// The main actions possible with a vendor
|
2022-01-18 11:40:31 -05:00
|
|
|
#[derive(PartialEq, Copy, Clone)]
|
|
|
|
pub enum VendorMode {
|
|
|
|
Buy,
|
|
|
|
Sell,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(PartialEq, Copy, Clone)]
|
2022-01-21 15:55:13 -05:00
|
|
|
/// The states for the game engine's state machine
|
2022-01-18 11:40:31 -05:00
|
|
|
pub enum RunState {
|
|
|
|
AwaitingInput,
|
|
|
|
PreRun,
|
|
|
|
Ticking,
|
|
|
|
ShowInventory,
|
|
|
|
ShowDropItem,
|
|
|
|
ShowTargeting { range: i32, item: Entity },
|
|
|
|
MainMenu { menu_selection: MainMenuSelection },
|
|
|
|
SaveGame,
|
|
|
|
NextLevel,
|
|
|
|
PreviousLevel,
|
|
|
|
TownPortal,
|
|
|
|
ShowRemoveItem,
|
|
|
|
GameOver,
|
|
|
|
MagicMapReveal { row: i32 },
|
|
|
|
MapGeneration,
|
|
|
|
ShowCheatMenu,
|
|
|
|
ShowVendor { vendor: Entity, mode: VendorMode },
|
|
|
|
TeleportingToOtherLevel { x: i32, y: i32, depth: i32 },
|
2022-01-21 11:57:36 -05:00
|
|
|
ShowRemoveCurse,
|
2022-01-21 16:16:48 -05:00
|
|
|
ShowIdentify,
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct State {
|
|
|
|
pub ecs: World,
|
|
|
|
mapgen_next_state: Option<RunState>,
|
|
|
|
mapgen_history: Vec<Map>,
|
|
|
|
mapgen_index: usize,
|
|
|
|
mapgen_timer: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
2022-01-19 13:31:06 -05:00
|
|
|
pub(super) fn new() -> Self {
|
2022-01-18 11:40:31 -05:00
|
|
|
State {
|
|
|
|
ecs: World::new(),
|
|
|
|
mapgen_next_state: Some(RunState::MainMenu {
|
|
|
|
menu_selection: MainMenuSelection::NewGame,
|
|
|
|
}),
|
|
|
|
mapgen_index: 0,
|
|
|
|
mapgen_history: Vec::new(),
|
|
|
|
mapgen_timer: 0.0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_systems(&mut self) {
|
2022-01-31 11:25:36 -05:00
|
|
|
MapIndexingSystem {}.run_now(&self.ecs);
|
|
|
|
VisibilitySystem {}.run_now(&self.ecs);
|
|
|
|
|
|
|
|
ai::EncumbranceSystem {}.run_now(&self.ecs);
|
|
|
|
ai::InitiativeSystem {}.run_now(&self.ecs);
|
|
|
|
ai::TurnStatusSystem {}.run_now(&self.ecs);
|
|
|
|
ai::QuipSystem {}.run_now(&self.ecs);
|
|
|
|
ai::AdjacentAI {}.run_now(&self.ecs);
|
|
|
|
ai::VisibleAI {}.run_now(&self.ecs);
|
|
|
|
ai::ApproachAI {}.run_now(&self.ecs);
|
|
|
|
ai::FleeAI {}.run_now(&self.ecs);
|
|
|
|
ai::ChaseAI {}.run_now(&self.ecs);
|
|
|
|
ai::DefaultMoveAI {}.run_now(&self.ecs);
|
|
|
|
|
|
|
|
MovementSystem {}.run_now(&self.ecs);
|
|
|
|
TriggerSystem {}.run_now(&self.ecs);
|
|
|
|
MeleeCombatSystem {}.run_now(&self.ecs);
|
|
|
|
RangedCombatSystem {}.run_now(&self.ecs);
|
|
|
|
ItemCollectionSystem {}.run_now(&self.ecs);
|
|
|
|
ItemEquipOnUse {}.run_now(&self.ecs);
|
|
|
|
ItemUseSystem {}.run_now(&self.ecs);
|
|
|
|
SpellUseSystem {}.run_now(&self.ecs);
|
|
|
|
ItemIdentificationSystem {}.run_now(&self.ecs);
|
|
|
|
ItemDropSystem {}.run_now(&self.ecs);
|
|
|
|
ItemRemoveSystem {}.run_now(&self.ecs);
|
|
|
|
HungerSystem {}.run_now(&self.ecs);
|
2022-01-18 11:40:31 -05:00
|
|
|
|
2022-01-20 11:48:58 -05:00
|
|
|
effects::run_effects_queue(&mut self.ecs);
|
|
|
|
|
2022-01-31 11:25:36 -05:00
|
|
|
ParticleSpawnSystem {}.run_now(&self.ecs);
|
|
|
|
LightingSystem {}.run_now(&self.ecs);
|
2022-01-18 11:40:31 -05:00
|
|
|
|
|
|
|
self.ecs.maintain();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn goto_level(&mut self, offset: i32) {
|
|
|
|
freeze_level_entities(&mut self.ecs);
|
|
|
|
|
|
|
|
// Build a new map and place the player
|
|
|
|
let current_depth = self.ecs.fetch::<Map>().depth;
|
|
|
|
self.generate_world_map(current_depth + offset, offset);
|
|
|
|
|
|
|
|
// Notify the player
|
2022-02-01 10:39:46 -05:00
|
|
|
gamelog::log_line("You change level.");
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn game_over_cleanup(&mut self) {
|
|
|
|
// Delete everything
|
|
|
|
let mut to_delete = Vec::new();
|
|
|
|
for e in self.ecs.entities().join() {
|
|
|
|
to_delete.push(e);
|
|
|
|
}
|
|
|
|
for del in to_delete.iter() {
|
|
|
|
self.ecs
|
|
|
|
.delete_entity(*del)
|
|
|
|
.expect("Failed to delete entity");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Spawn a new player
|
|
|
|
{
|
|
|
|
let player_entity = spawner::player(&mut self.ecs, 0, 0);
|
|
|
|
let mut player_entity_writer = self.ecs.write_resource::<Entity>();
|
|
|
|
*player_entity_writer = player_entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the world maps
|
|
|
|
self.ecs.insert(map::MasterDungeonMap::new());
|
|
|
|
|
|
|
|
// Build a new map and place the player
|
|
|
|
self.generate_world_map(1, 0);
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:31:06 -05:00
|
|
|
pub(super) fn generate_world_map(&mut self, new_depth: i32, offset: i32) {
|
2022-01-18 11:40:31 -05:00
|
|
|
self.mapgen_index = 0;
|
|
|
|
self.mapgen_timer = 0.0;
|
|
|
|
self.mapgen_history.clear();
|
|
|
|
|
|
|
|
if let Some(history) = map::level_transition(&mut self.ecs, new_depth, offset) {
|
|
|
|
self.mapgen_history = history;
|
|
|
|
} else {
|
|
|
|
map::thaw_level_entities(&mut self.ecs);
|
|
|
|
}
|
2022-02-01 09:22:23 -05:00
|
|
|
|
|
|
|
// Set up the game log
|
2022-02-01 10:39:46 -05:00
|
|
|
gamelog::clear_log();
|
|
|
|
gamelog::line("Welcome to")
|
2022-02-01 09:22:23 -05:00
|
|
|
.append_color(colors::CYAN, "Rusty Roguelike")
|
|
|
|
.log();
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GameState for State {
|
2022-01-21 15:55:13 -05:00
|
|
|
/// The big, nasty, state machine handler
|
2022-01-18 11:40:31 -05:00
|
|
|
fn tick(&mut self, ctx: &mut Rltk) {
|
|
|
|
let mut newrunstate;
|
|
|
|
{
|
|
|
|
let runstate = self.ecs.fetch::<RunState>();
|
|
|
|
newrunstate = *runstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.cls();
|
2022-01-31 11:53:38 -05:00
|
|
|
particle_system::update_particles(&mut self.ecs, ctx);
|
2022-01-18 11:40:31 -05:00
|
|
|
|
|
|
|
match newrunstate {
|
|
|
|
RunState::MainMenu { .. } => {}
|
|
|
|
RunState::GameOver { .. } => {}
|
|
|
|
_ => {
|
|
|
|
camera::render_camera(&self.ecs, ctx);
|
|
|
|
gui::draw_ui(&self.ecs, ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match newrunstate {
|
|
|
|
RunState::MapGeneration => {
|
|
|
|
if !SHOW_MAPGEN_VISUALIZER {
|
|
|
|
newrunstate = self.mapgen_next_state.unwrap();
|
|
|
|
}
|
|
|
|
ctx.cls();
|
|
|
|
if self.mapgen_index < self.mapgen_history.len() {
|
|
|
|
camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.mapgen_timer += ctx.frame_time_ms;
|
|
|
|
if self.mapgen_timer > 300.0 {
|
|
|
|
self.mapgen_timer = 0.0;
|
|
|
|
self.mapgen_index += 1;
|
|
|
|
if self.mapgen_index >= self.mapgen_history.len() {
|
|
|
|
newrunstate = self.mapgen_next_state.unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::PreRun => {
|
|
|
|
self.run_systems();
|
|
|
|
self.ecs.maintain();
|
|
|
|
newrunstate = RunState::AwaitingInput;
|
|
|
|
}
|
|
|
|
RunState::AwaitingInput => {
|
|
|
|
newrunstate = player_input(self, ctx);
|
|
|
|
}
|
|
|
|
RunState::Ticking => {
|
2022-01-31 11:25:36 -05:00
|
|
|
let mut should_change_target = false;
|
2022-01-18 11:40:31 -05:00
|
|
|
while newrunstate == RunState::Ticking {
|
|
|
|
self.run_systems();
|
|
|
|
self.ecs.maintain();
|
|
|
|
|
|
|
|
newrunstate = match *self.ecs.fetch::<RunState>() {
|
2022-01-31 11:25:36 -05:00
|
|
|
RunState::AwaitingInput => {
|
|
|
|
should_change_target = true;
|
|
|
|
|
|
|
|
RunState::AwaitingInput
|
|
|
|
}
|
2022-01-18 11:40:31 -05:00
|
|
|
RunState::MagicMapReveal { .. } => RunState::MagicMapReveal { row: 0 },
|
|
|
|
RunState::TownPortal => RunState::TownPortal,
|
|
|
|
RunState::TeleportingToOtherLevel { x, y, depth } => {
|
|
|
|
RunState::TeleportingToOtherLevel { x, y, depth }
|
|
|
|
}
|
2022-01-21 11:57:36 -05:00
|
|
|
RunState::ShowRemoveCurse => RunState::ShowRemoveCurse,
|
2022-01-21 16:16:48 -05:00
|
|
|
RunState::ShowIdentify => RunState::ShowIdentify,
|
2022-01-18 11:40:31 -05:00
|
|
|
_ => RunState::Ticking,
|
|
|
|
};
|
|
|
|
}
|
2022-01-31 11:25:36 -05:00
|
|
|
|
|
|
|
if should_change_target {
|
|
|
|
player::end_turn_targeting(&mut self.ecs);
|
|
|
|
}
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
RunState::ShowInventory => {
|
|
|
|
let result = gui::show_inventory(self, ctx);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
|
|
|
let item_entity = result.1.unwrap();
|
|
|
|
let is_ranged = self.ecs.read_storage::<Ranged>();
|
|
|
|
|
|
|
|
if let Some(is_item_ranged) = is_ranged.get(item_entity) {
|
|
|
|
newrunstate = RunState::ShowTargeting {
|
|
|
|
range: is_item_ranged.range,
|
|
|
|
item: item_entity,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
|
|
|
intent
|
|
|
|
.insert(
|
|
|
|
*self.ecs.fetch::<Entity>(),
|
|
|
|
WantsToUseItem {
|
|
|
|
item: item_entity,
|
|
|
|
target: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("failed to add intent to use item");
|
|
|
|
|
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::ShowDropItem => {
|
|
|
|
let result = gui::drop_item_menu(self, ctx);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
|
|
|
let item_entity = result.1.unwrap();
|
|
|
|
let mut intent = self.ecs.write_storage::<WantsToDropItem>();
|
|
|
|
intent
|
|
|
|
.insert(
|
|
|
|
*self.ecs.fetch::<Entity>(),
|
|
|
|
WantsToDropItem { item: item_entity },
|
|
|
|
)
|
|
|
|
.expect("failed to add intent to drop item");
|
|
|
|
|
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::ShowRemoveItem => {
|
|
|
|
let result = gui::remove_item_menu(self, ctx);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
|
|
|
let item_entity = result.1.unwrap();
|
|
|
|
let mut intent = self.ecs.write_storage::<WantsToRemoveItem>();
|
|
|
|
intent
|
|
|
|
.insert(
|
|
|
|
*self.ecs.fetch::<Entity>(),
|
|
|
|
WantsToRemoveItem { item: item_entity },
|
|
|
|
)
|
|
|
|
.expect("Unable to insert intent to remove item");
|
|
|
|
|
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::ShowTargeting { range, item } => {
|
|
|
|
let result = gui::ranged_target(self, ctx, range);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
2022-01-25 11:15:32 -05:00
|
|
|
if self.ecs.read_storage::<SpellTemplate>().get(item).is_some() {
|
|
|
|
let mut intent = self.ecs.write_storage::<WantsToCastSpell>();
|
|
|
|
intent
|
|
|
|
.insert(
|
|
|
|
*self.ecs.fetch::<Entity>(),
|
|
|
|
WantsToCastSpell {
|
|
|
|
spell: item,
|
|
|
|
target: result.1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("failed to add intent to cast spell");
|
2022-01-18 11:40:31 -05:00
|
|
|
|
2022-01-25 11:15:32 -05:00
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
} else {
|
|
|
|
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
2022-01-18 11:40:31 -05:00
|
|
|
|
2022-01-25 11:15:32 -05:00
|
|
|
intent
|
|
|
|
.insert(
|
|
|
|
*self.ecs.fetch::<Entity>(),
|
|
|
|
WantsToUseItem {
|
|
|
|
item,
|
|
|
|
target: result.1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("failed to add intent to use item");
|
|
|
|
|
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::MainMenu { .. } => match gui::main_menu(self, ctx) {
|
|
|
|
gui::MainMenuResult::NoSelection { selected } => {
|
|
|
|
newrunstate = RunState::MainMenu {
|
|
|
|
menu_selection: selected,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gui::MainMenuResult::Selected { selected } => match selected {
|
|
|
|
gui::MainMenuSelection::NewGame => newrunstate = RunState::PreRun,
|
|
|
|
gui::MainMenuSelection::LoadGame => {
|
|
|
|
saveload_system::load_game(&mut self.ecs);
|
|
|
|
newrunstate = RunState::AwaitingInput;
|
|
|
|
saveload_system::delete_save();
|
|
|
|
}
|
|
|
|
gui::MainMenuSelection::Quit => {
|
|
|
|
::std::process::exit(0);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
RunState::GameOver => match gui::game_over(ctx) {
|
|
|
|
gui::GameOverResult::NoSelection => {}
|
|
|
|
gui::GameOverResult::QuitToMenu => {
|
|
|
|
self.game_over_cleanup();
|
|
|
|
newrunstate = RunState::MainMenu {
|
|
|
|
menu_selection: gui::MainMenuSelection::NewGame,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
RunState::SaveGame => {
|
|
|
|
saveload_system::save_game(&mut self.ecs);
|
|
|
|
|
|
|
|
newrunstate = RunState::MainMenu {
|
|
|
|
menu_selection: gui::MainMenuSelection::LoadGame,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::NextLevel => {
|
|
|
|
self.goto_level(1);
|
|
|
|
newrunstate = RunState::PreRun;
|
|
|
|
}
|
|
|
|
RunState::PreviousLevel => {
|
|
|
|
self.goto_level(-1);
|
|
|
|
self.mapgen_next_state = Some(RunState::PreRun);
|
|
|
|
newrunstate = RunState::MapGeneration;
|
|
|
|
}
|
|
|
|
RunState::MagicMapReveal { row } => {
|
|
|
|
let mut map = self.ecs.fetch_mut::<Map>();
|
|
|
|
for x in 0..map.width {
|
|
|
|
let idx = map.xy_idx(x as i32, row);
|
|
|
|
map.revealed_tiles[idx] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if row == map.height - 1 {
|
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
} else {
|
|
|
|
newrunstate = RunState::MagicMapReveal { row: row + 1 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::ShowCheatMenu => match show_cheat_mode(self, ctx) {
|
|
|
|
CheatMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
CheatMenuResult::NoResponse => {}
|
|
|
|
CheatMenuResult::TeleportToExit => {
|
|
|
|
self.goto_level(1);
|
|
|
|
self.mapgen_next_state = Some(RunState::PreRun);
|
|
|
|
|
|
|
|
newrunstate = RunState::MapGeneration
|
|
|
|
}
|
|
|
|
CheatMenuResult::Heal => {
|
|
|
|
let player = self.ecs.fetch::<Entity>();
|
|
|
|
let mut pools = self.ecs.write_storage::<Pools>();
|
|
|
|
let mut player_pools = pools.get_mut(*player).unwrap();
|
|
|
|
player_pools.hit_points.current = player_pools.hit_points.max;
|
|
|
|
|
|
|
|
newrunstate = RunState::AwaitingInput;
|
|
|
|
}
|
|
|
|
CheatMenuResult::Reveal => {
|
|
|
|
let mut map = self.ecs.fetch_mut::<Map>();
|
|
|
|
for v in map.revealed_tiles.iter_mut() {
|
|
|
|
*v = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
newrunstate = RunState::AwaitingInput;
|
|
|
|
}
|
|
|
|
CheatMenuResult::GodMode => {
|
|
|
|
let player = self.ecs.fetch::<Entity>();
|
|
|
|
let mut pools = self.ecs.write_storage::<Pools>();
|
|
|
|
let mut player_pools = pools.get_mut(*player).unwrap();
|
|
|
|
player_pools.god_mode = true;
|
|
|
|
|
|
|
|
newrunstate = RunState::AwaitingInput;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
RunState::ShowVendor { vendor, mode } => {
|
|
|
|
let result = gui::show_vendor_menu(self, ctx, vendor, mode);
|
|
|
|
match result.0 {
|
|
|
|
gui::VendorResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::VendorResult::NoResponse => {}
|
|
|
|
gui::VendorResult::Sell => {
|
|
|
|
let price = self
|
|
|
|
.ecs
|
|
|
|
.read_storage::<Item>()
|
|
|
|
.get(result.1.unwrap())
|
|
|
|
.unwrap()
|
|
|
|
.base_value
|
|
|
|
* 0.8;
|
|
|
|
self.ecs
|
|
|
|
.write_storage::<Pools>()
|
|
|
|
.get_mut(*self.ecs.fetch::<Entity>())
|
|
|
|
.unwrap()
|
|
|
|
.gold += price;
|
|
|
|
self.ecs
|
|
|
|
.delete_entity(result.1.unwrap())
|
|
|
|
.expect("Unable to delete sold item");
|
|
|
|
}
|
|
|
|
gui::VendorResult::Buy => {
|
|
|
|
let tag = result.2.unwrap();
|
|
|
|
let price = result.3.unwrap();
|
|
|
|
let mut pools = self.ecs.write_storage::<Pools>();
|
2022-01-19 11:04:10 -05:00
|
|
|
let player_entity = self.ecs.fetch::<Entity>();
|
|
|
|
|
|
|
|
let mut identified = self.ecs.write_storage::<IdentifiedItem>();
|
|
|
|
identified
|
|
|
|
.insert(*player_entity, IdentifiedItem { name: tag.clone() })
|
|
|
|
.expect("Unable to identify item");
|
|
|
|
std::mem::drop(identified);
|
|
|
|
|
|
|
|
let player_pools = pools.get_mut(*player_entity).unwrap();
|
|
|
|
std::mem::drop(player_entity);
|
2022-01-18 11:40:31 -05:00
|
|
|
if player_pools.gold >= price {
|
|
|
|
player_pools.gold -= price;
|
|
|
|
std::mem::drop(pools);
|
|
|
|
|
|
|
|
let player_entity = *self.ecs.fetch::<Entity>();
|
|
|
|
spawn_named_item(
|
|
|
|
&RAWS.lock().unwrap(),
|
|
|
|
&mut self.ecs,
|
|
|
|
&tag,
|
|
|
|
SpawnType::Carried { by: player_entity },
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gui::VendorResult::BuyMode => {
|
|
|
|
newrunstate = RunState::ShowVendor {
|
|
|
|
vendor,
|
|
|
|
mode: VendorMode::Buy,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gui::VendorResult::SellMode => {
|
|
|
|
newrunstate = RunState::ShowVendor {
|
|
|
|
vendor,
|
|
|
|
mode: VendorMode::Sell,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
RunState::TeleportingToOtherLevel { x, y, depth } => {
|
|
|
|
self.goto_level(depth - 1);
|
|
|
|
let player_entity = self.ecs.fetch::<Entity>();
|
|
|
|
if let Some(pos) = self.ecs.write_storage::<Position>().get_mut(*player_entity) {
|
|
|
|
pos.x = x;
|
|
|
|
pos.y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut ppos = self.ecs.fetch_mut::<Point>();
|
|
|
|
ppos.x = x;
|
|
|
|
ppos.y = y;
|
|
|
|
self.mapgen_next_state = Some(RunState::PreRun);
|
|
|
|
|
|
|
|
newrunstate = RunState::MapGeneration;
|
|
|
|
}
|
2022-01-21 11:57:36 -05:00
|
|
|
RunState::ShowRemoveCurse => {
|
|
|
|
let result = gui::remove_curse_menu(self, ctx);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
|
|
|
let item_entity = result.1.unwrap();
|
|
|
|
self.ecs.write_storage::<CursedItem>().remove(item_entity);
|
|
|
|
|
2022-01-21 16:16:48 -05:00
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunState::ShowIdentify => {
|
|
|
|
let result = gui::identify_menu(self, ctx);
|
|
|
|
match result.0 {
|
|
|
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
|
|
|
gui::ItemMenuResult::NoResponse => {}
|
|
|
|
gui::ItemMenuResult::Selected => {
|
|
|
|
let item_entity = result.1.unwrap();
|
|
|
|
if let Some(name) = self.ecs.read_storage::<Name>().get(item_entity) {
|
|
|
|
let mut dm = self.ecs.fetch_mut::<MasterDungeonMap>();
|
|
|
|
dm.identified_items.insert(name.name.clone());
|
|
|
|
}
|
|
|
|
|
2022-01-21 11:57:36 -05:00
|
|
|
newrunstate = RunState::Ticking;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-18 11:40:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut runwriter = self.ecs.write_resource::<RunState>();
|
|
|
|
*runwriter = newrunstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
damage_system::delete_the_dead(&mut self.ecs);
|
|
|
|
}
|
|
|
|
}
|