Compare commits
No commits in common. "a1ffc7b95d296ab91f695de01b7993db051c07ff" and "3caf253441c4f65ada888318973b8aed6e2a627e" have entirely different histories.
a1ffc7b95d
...
3caf253441
85
Cargo.lock
generated
85
Cargo.lock
generated
@ -22,9 +22,14 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.3.8"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
|
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
@ -109,7 +114,6 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -118,7 +122,6 @@ version = "0.8.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4db22c32c68bd9330ab982f8ff7ffe7b10541d16ea7d7d51aac074499850402b"
|
checksum = "4db22c32c68bd9330ab982f8ff7ffe7b10541d16ea7d7d51aac074499850402b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
|
||||||
"ultraviolet",
|
"ultraviolet",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -167,7 +170,6 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"rand_xorshift",
|
"rand_xorshift",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -441,13 +443,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.2.3"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
|
checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 1.0.0",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.8.6",
|
||||||
"maybe-uninit",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -752,12 +753,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.7.2"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"autocfg",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -822,12 +822,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni-sys"
|
name = "jni-sys"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -930,12 +924,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maybe-uninit"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.4.1"
|
version = "2.4.1"
|
||||||
@ -1379,7 +1367,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
|
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1476,8 +1463,6 @@ name = "roguelike"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rltk",
|
"rltk",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"specs",
|
"specs",
|
||||||
"specs-derive",
|
"specs-derive",
|
||||||
]
|
]
|
||||||
@ -1492,12 +1477,6 @@ dependencies = [
|
|||||||
"owned_ttf_parser",
|
"owned_ttf_parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "safe_arch"
|
name = "safe_arch"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -1536,34 +1515,9 @@ checksum = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.135"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b"
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.78"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shared_library"
|
name = "shared_library"
|
||||||
@ -1577,9 +1531,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shred"
|
name = "shred"
|
||||||
version = "0.10.2"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5f08237e667ac94ad20f8878b5943d91a93ccb231428446c57c21c57779016d"
|
checksum = "eb0210289d693217926314867c807e0b7b42f7e23c136adb31f8697f5bf242d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -1637,16 +1591,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specs"
|
name = "specs"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fff28a29366aff703d5da8a7e2c8875dc8453ac1118f842cbc0fa70c7db51240"
|
checksum = "5dcc1e4ba7ab1f08ecb3d7e2f693defc3907e2c03bb0924f9978be45b364f83f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"hibitset",
|
"hibitset",
|
||||||
"log",
|
"log",
|
||||||
"rayon",
|
"rayon",
|
||||||
"serde",
|
|
||||||
"shred",
|
"shred",
|
||||||
"shrev",
|
"shrev",
|
||||||
"tuple_utils",
|
"tuple_utils",
|
||||||
|
@ -6,8 +6,6 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rltk = { version = "0.8.0", features = ["serde"] }
|
rltk = {version = "0.8.0"}
|
||||||
specs = { version = "0.16.1", features = ["serde"] }
|
specs = "0.17.0"
|
||||||
specs-derive = { version = "0.4.1" }
|
specs-derive = "0.4.1"
|
||||||
serde = { version = "^1.0.44", features = ["derive"] }
|
|
||||||
serde_json = "1.0.44"
|
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
use rltk::{Point, RGB};
|
use rltk::{Point, RGB};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use specs::error::NoError;
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{ConvertSaveload, Marker};
|
|
||||||
use specs_derive::*;
|
use specs_derive::*;
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component)]
|
||||||
pub struct Renderable {
|
pub struct Renderable {
|
||||||
pub glyph: rltk::FontCharType,
|
pub glyph: rltk::FontCharType,
|
||||||
pub fg: RGB,
|
pub fg: RGB,
|
||||||
@ -19,28 +16,28 @@ pub struct Renderable {
|
|||||||
pub render_order: i32,
|
pub render_order: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Player {}
|
pub struct Player {}
|
||||||
|
|
||||||
#[derive(Component, ConvertSaveload, Clone)]
|
#[derive(Component)]
|
||||||
pub struct Viewshed {
|
pub struct Viewshed {
|
||||||
pub visible_tiles: Vec<rltk::Point>,
|
pub visible_tiles: Vec<rltk::Point>,
|
||||||
pub range: i32,
|
pub range: i32,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
#[derive(Component)]
|
||||||
pub struct Monster {}
|
pub struct Monster {}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct BlocksTile {}
|
pub struct BlocksTile {}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct CombatStats {
|
pub struct CombatStats {
|
||||||
pub max_hp: i32,
|
pub max_hp: i32,
|
||||||
pub hp: i32,
|
pub hp: i32,
|
||||||
@ -48,12 +45,12 @@ pub struct CombatStats {
|
|||||||
pub power: i32,
|
pub power: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct WantsToMelee {
|
pub struct WantsToMelee {
|
||||||
pub target: Entity,
|
pub target: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct SufferDamage {
|
pub struct SufferDamage {
|
||||||
pub amount: Vec<i32>,
|
pub amount: Vec<i32>,
|
||||||
}
|
}
|
||||||
@ -71,67 +68,60 @@ impl SufferDamage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Item {}
|
pub struct Item {}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Potion {
|
pub struct Potion {
|
||||||
pub heal_amount: i32,
|
pub heal_amount: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct InBackpack {
|
pub struct InBackpack {
|
||||||
pub owner: Entity,
|
pub owner: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, ConvertSaveload)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct WantsToPickupItem {
|
pub struct WantsToPickupItem {
|
||||||
pub collected_by: Entity,
|
pub collected_by: Entity,
|
||||||
pub item: Entity,
|
pub item: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct WantsToUseItem {
|
pub struct WantsToUseItem {
|
||||||
pub item: Entity,
|
pub item: Entity,
|
||||||
pub target: Option<Point>,
|
pub target: Option<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, ConvertSaveload)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct WantsToDropItem {
|
pub struct WantsToDropItem {
|
||||||
pub item: Entity,
|
pub item: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Consumable {}
|
pub struct Consumable {}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct ProvidesHealing {
|
pub struct ProvidesHealing {
|
||||||
pub heal_amount: i32,
|
pub heal_amount: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, ConvertSaveload)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Ranged {
|
pub struct Ranged {
|
||||||
pub range: i32,
|
pub range: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, ConvertSaveload)]
|
#[derive(Component, Debug)]
|
||||||
pub struct InflictsDamage {
|
pub struct InflictsDamage {
|
||||||
pub damage: i32,
|
pub damage: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct AreaOfEffect {
|
pub struct AreaOfEffect {
|
||||||
pub radius: i32,
|
pub radius: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Confusion {
|
pub struct Confusion {
|
||||||
pub turns: i32,
|
pub turns: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SerializeMe;
|
|
||||||
|
|
||||||
#[derive(Component, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct SerializationHelper {
|
|
||||||
pub map: super::map::Map,
|
|
||||||
}
|
|
124
src/gui.rs
124
src/gui.rs
@ -1,14 +1,14 @@
|
|||||||
use rltk::{Point, VirtualKeyCode};
|
|
||||||
use rltk::RGB;
|
|
||||||
use rltk::Rltk;
|
use rltk::Rltk;
|
||||||
|
use rltk::RGB;
|
||||||
|
use rltk::{BTerm, Point, VirtualKeyCode};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{CombatStats, InBackpack, RunState, State, Viewshed};
|
|
||||||
use crate::gamelog::GameLog;
|
use crate::gamelog::GameLog;
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
use crate::Name;
|
use crate::Name;
|
||||||
use crate::Player;
|
use crate::Player;
|
||||||
use crate::Position;
|
use crate::Position;
|
||||||
|
use crate::{CombatStats, InBackpack, State, Viewshed};
|
||||||
|
|
||||||
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
ctx.draw_box(
|
ctx.draw_box(
|
||||||
@ -388,121 +388,3 @@ pub fn ranged_target(
|
|||||||
|
|
||||||
(ItemMenuResult::NoResponse, None)
|
(ItemMenuResult::NoResponse, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
|
||||||
pub enum MainMenuSelection {
|
|
||||||
NewGame,
|
|
||||||
LoadGame,
|
|
||||||
Quit,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
|
||||||
pub enum MainMenuResult {
|
|
||||||
NoSelection { selected: MainMenuSelection },
|
|
||||||
Selected { selected: MainMenuSelection },
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|
||||||
let save_exists = super::save_load_system::does_save_exist();
|
|
||||||
let runstate = gs.ecs.fetch::<RunState>();
|
|
||||||
|
|
||||||
ctx.print_color_centered(
|
|
||||||
15,
|
|
||||||
RGB::named(rltk::YELLOW),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Rust Roguelike Tutorial",
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
if let RunState::MainMenu {
|
|
||||||
menu_selection: selection,
|
|
||||||
} = *runstate
|
|
||||||
{
|
|
||||||
if selection == MainMenuSelection::NewGame {
|
|
||||||
ctx.print_color_centered(
|
|
||||||
24,
|
|
||||||
RGB::named(rltk::MAGENTA),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Begin New Game",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ctx.print_color_centered(
|
|
||||||
24,
|
|
||||||
RGB::named(rltk::WHITE),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Begin New Game",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if save_exists {
|
|
||||||
if selection == MainMenuSelection::LoadGame {
|
|
||||||
ctx.print_color_centered(
|
|
||||||
25,
|
|
||||||
RGB::named(rltk::MAGENTA),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Load Game",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ctx.print_color_centered(
|
|
||||||
25,
|
|
||||||
RGB::named(rltk::WHITE),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Load Game",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if selection == MainMenuSelection::Quit {
|
|
||||||
ctx.print_color_centered(
|
|
||||||
26,
|
|
||||||
RGB::named(rltk::MAGENTA),
|
|
||||||
RGB::named(rltk::BLACK),
|
|
||||||
"Quit",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ctx.print_color_centered(26, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Quit");
|
|
||||||
}
|
|
||||||
|
|
||||||
return match ctx.key {
|
|
||||||
None => MainMenuResult::NoSelection {
|
|
||||||
selected: selection,
|
|
||||||
},
|
|
||||||
Some(key) => match key {
|
|
||||||
VirtualKeyCode::Escape => MainMenuResult::NoSelection {
|
|
||||||
selected: MainMenuSelection::Quit,
|
|
||||||
},
|
|
||||||
VirtualKeyCode::Up | VirtualKeyCode::K => {
|
|
||||||
let newselection = match selection {
|
|
||||||
MainMenuSelection::NewGame => MainMenuSelection::Quit,
|
|
||||||
MainMenuSelection::LoadGame => MainMenuSelection::NewGame,
|
|
||||||
MainMenuSelection::Quit => MainMenuSelection::LoadGame,
|
|
||||||
};
|
|
||||||
MainMenuResult::NoSelection {
|
|
||||||
selected: newselection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Down | VirtualKeyCode::J => {
|
|
||||||
let newselection = match selection {
|
|
||||||
MainMenuSelection::NewGame => MainMenuSelection::LoadGame,
|
|
||||||
MainMenuSelection::LoadGame => MainMenuSelection::Quit,
|
|
||||||
MainMenuSelection::Quit => MainMenuSelection::NewGame,
|
|
||||||
};
|
|
||||||
MainMenuResult::NoSelection {
|
|
||||||
selected: newselection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Return | VirtualKeyCode::I => MainMenuResult::Selected {
|
|
||||||
selected: selection,
|
|
||||||
},
|
|
||||||
_ => MainMenuResult::NoSelection {
|
|
||||||
selected: selection,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
MainMenuResult::NoSelection {
|
|
||||||
selected: MainMenuSelection::NewGame,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
|
use rltk::Rltk;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
use crate::{AreaOfEffect, CombatStats, Confusion, Consumable, InBackpack, InflictsDamage, Map, Name, Position, Potion, ProvidesHealing, Ranged, State, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToUseItem};
|
||||||
use crate::gamelog::GameLog;
|
use crate::gamelog::GameLog;
|
||||||
use crate::{
|
use crate::gui::ItemMenuResult;
|
||||||
AreaOfEffect, CombatStats, Confusion, Consumable, InBackpack, InflictsDamage, Map, Name,
|
use crate::spawner::{confusion_scroll, player};
|
||||||
Position, ProvidesHealing, Ranged, SufferDamage, WantsToDropItem, WantsToPickupItem,
|
|
||||||
WantsToUseItem,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ItemCollectionSystem {}
|
pub struct ItemCollectionSystem {}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
map,
|
map,
|
||||||
mut suffer_damage,
|
mut suffer_damage,
|
||||||
aoe,
|
aoe,
|
||||||
mut confused,
|
mut confused
|
||||||
) = data;
|
) = data;
|
||||||
|
|
||||||
for (entity, use_item) in (&entities, &wants_use).join() {
|
for (entity, use_item) in (&entities, &wants_use).join() {
|
||||||
@ -89,7 +88,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
|
|
||||||
let mut targets: Vec<Entity> = Vec::new();
|
let mut targets: Vec<Entity> = Vec::new();
|
||||||
match use_item.target {
|
match use_item.target {
|
||||||
None => targets.push(*player_entity),
|
None => { targets.push(*player_entity) }
|
||||||
Some(target) => {
|
Some(target) => {
|
||||||
let area_effect = aoe.get(use_item.item);
|
let area_effect = aoe.get(use_item.item);
|
||||||
match area_effect {
|
match area_effect {
|
||||||
@ -100,11 +99,8 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(area_effect) => {
|
Some(area_effect) => {
|
||||||
let mut black_tiles =
|
let mut black_tiles = rltk::field_of_view(target, area_effect.radius, &*map);
|
||||||
rltk::field_of_view(target, area_effect.radius, &*map);
|
black_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
||||||
black_tiles.retain(|p| {
|
|
||||||
p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1
|
|
||||||
});
|
|
||||||
for tile_idx in black_tiles.iter() {
|
for tile_idx in black_tiles.iter() {
|
||||||
let idx = map.xy_idx(tile_idx.x, tile_idx.y);
|
let idx = map.xy_idx(tile_idx.x, tile_idx.y);
|
||||||
for mob in map.tile_content[idx].iter() {
|
for mob in map.tile_content[idx].iter() {
|
||||||
@ -123,10 +119,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
if entity == *player_entity {
|
if entity == *player_entity {
|
||||||
let mob_name = names.get(*mob).unwrap();
|
let mob_name = names.get(*mob).unwrap();
|
||||||
let item_name = names.get(use_item.item).unwrap();
|
let item_name = names.get(use_item.item).unwrap();
|
||||||
game_log.entries.push(format!(
|
game_log.entries.push(format!("You use {} on {}, inflicting {} hp.", item_name.name, mob_name.name, item_damages.damage));
|
||||||
"You use {} on {}, inflicting {} hp.",
|
|
||||||
item_name.name, mob_name.name, item_damages.damage
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
used_item = true;
|
used_item = true;
|
||||||
@ -160,20 +153,16 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||||||
if entity == *player_entity {
|
if entity == *player_entity {
|
||||||
let mob_name = names.get(*mob).unwrap();
|
let mob_name = names.get(*mob).unwrap();
|
||||||
let item_name = names.get(use_item.item).unwrap();
|
let item_name = names.get(use_item.item).unwrap();
|
||||||
game_log.entries.push(format!(
|
game_log.entries.push(format!("You use {} on {}, confusing them.", item_name.name, mob_name.name));
|
||||||
"You use {} on {}, confusing them.",
|
|
||||||
item_name.name, mob_name.name
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for mob in add_confusion.iter() {
|
for mob in add_confusion.iter() {
|
||||||
confused
|
confused.insert(mob.0, Confusion { turns: mob.1 }).expect("Unable to insert status");
|
||||||
.insert(mob.0, Confusion { turns: mob.1 })
|
|
||||||
.expect("Unable to insert status");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if used_item {
|
if used_item {
|
||||||
let consumable = consumables.get(use_item.item);
|
let consumable = consumables.get(use_item.item);
|
||||||
match consumable {
|
match consumable {
|
||||||
|
131
src/main.rs
131
src/main.rs
@ -1,8 +1,7 @@
|
|||||||
extern crate serde;
|
use std::thread::spawn;
|
||||||
|
|
||||||
use rltk::{GameState, Point};
|
use rltk::{GameState, Point, RGB};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
|
||||||
|
|
||||||
use components::*;
|
use components::*;
|
||||||
use damage_system::DamageSystem;
|
use damage_system::DamageSystem;
|
||||||
@ -28,7 +27,6 @@ mod player;
|
|||||||
mod rect;
|
mod rect;
|
||||||
mod spawner;
|
mod spawner;
|
||||||
mod visibility_system;
|
mod visibility_system;
|
||||||
mod save_load_system;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum RunState {
|
pub enum RunState {
|
||||||
@ -38,14 +36,7 @@ pub enum RunState {
|
|||||||
MonsterTurn,
|
MonsterTurn,
|
||||||
ShowInventory,
|
ShowInventory,
|
||||||
ShowDropItem,
|
ShowDropItem,
|
||||||
ShowTargeting {
|
ShowTargeting { range: i32, item: Entity },
|
||||||
range: i32,
|
|
||||||
item: Entity,
|
|
||||||
},
|
|
||||||
MainMenu {
|
|
||||||
menu_selection: gui::MainMenuSelection,
|
|
||||||
},
|
|
||||||
SaveGame,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
@ -60,14 +51,14 @@ impl State {
|
|||||||
let mut mob = MonsterAI {};
|
let mut mob = MonsterAI {};
|
||||||
mob.run_now(&self.ecs);
|
mob.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut map_index = MapIndexingSystem {};
|
let mut mapindex = MapIndexingSystem {};
|
||||||
map_index.run_now(&self.ecs);
|
mapindex.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut melee_system = MeleeCombatSystem {};
|
let mut meleesystem = MeleeCombatSystem {};
|
||||||
melee_system.run_now(&self.ecs);
|
meleesystem.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut damage_system = DamageSystem {};
|
let mut damagesystem = DamageSystem {};
|
||||||
damage_system.run_now(&self.ecs);
|
damagesystem.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut inventory = ItemCollectionSystem {};
|
let mut inventory = ItemCollectionSystem {};
|
||||||
inventory.run_now(&self.ecs);
|
inventory.run_now(&self.ecs);
|
||||||
@ -84,17 +75,9 @@ impl State {
|
|||||||
|
|
||||||
impl GameState for State {
|
impl GameState for State {
|
||||||
fn tick(&mut self, ctx: &mut rltk::Rltk) {
|
fn tick(&mut self, ctx: &mut rltk::Rltk) {
|
||||||
let mut new_run_state;
|
|
||||||
{
|
|
||||||
let run_state = self.ecs.fetch::<RunState>();
|
|
||||||
new_run_state = *run_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.cls();
|
ctx.cls();
|
||||||
|
|
||||||
match new_run_state {
|
{
|
||||||
RunState::MainMenu { .. } => {}
|
|
||||||
_ => {
|
|
||||||
draw_map(&self.ecs, ctx);
|
draw_map(&self.ecs, ctx);
|
||||||
|
|
||||||
let positions = self.ecs.read_storage::<Position>();
|
let positions = self.ecs.read_storage::<Position>();
|
||||||
@ -112,33 +95,38 @@ impl GameState for State {
|
|||||||
|
|
||||||
gui::draw_ui(&self.ecs, ctx);
|
gui::draw_ui(&self.ecs, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut newrunstate;
|
||||||
|
{
|
||||||
|
let runstate = self.ecs.fetch::<RunState>();
|
||||||
|
newrunstate = *runstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
match new_run_state {
|
match newrunstate {
|
||||||
RunState::PreRun => {
|
RunState::PreRun => {
|
||||||
self.run_systems();
|
self.run_systems();
|
||||||
new_run_state = RunState::AwaitingInput;
|
newrunstate = RunState::AwaitingInput;
|
||||||
}
|
}
|
||||||
RunState::AwaitingInput => new_run_state = player_input(self, ctx),
|
RunState::AwaitingInput => newrunstate = player_input(self, ctx),
|
||||||
RunState::PlayerTurn => {
|
RunState::PlayerTurn => {
|
||||||
self.run_systems();
|
self.run_systems();
|
||||||
new_run_state = RunState::MonsterTurn;
|
newrunstate = RunState::MonsterTurn;
|
||||||
}
|
}
|
||||||
RunState::MonsterTurn => {
|
RunState::MonsterTurn => {
|
||||||
self.run_systems();
|
self.run_systems();
|
||||||
new_run_state = RunState::AwaitingInput;
|
newrunstate = RunState::AwaitingInput;
|
||||||
}
|
}
|
||||||
RunState::ShowInventory => {
|
RunState::ShowInventory => {
|
||||||
let result = gui::show_inventory(self, ctx);
|
let result = gui::show_inventory(self, ctx);
|
||||||
match result.0 {
|
match result.0 {
|
||||||
gui::ItemMenuResult::Cancel => new_run_state = RunState::AwaitingInput,
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||||
gui::ItemMenuResult::NoResponse => {}
|
gui::ItemMenuResult::NoResponse => {}
|
||||||
gui::ItemMenuResult::Selected => {
|
gui::ItemMenuResult::Selected => {
|
||||||
let item_entity = result.1.unwrap();
|
let item_entity = result.1.unwrap();
|
||||||
let is_ranged = self.ecs.read_storage::<Ranged>();
|
let is_ranged = self.ecs.read_storage::<Ranged>();
|
||||||
let is_item_ranged = is_ranged.get(item_entity);
|
let is_item_ranged = is_ranged.get(item_entity);
|
||||||
if let Some(is_item_ranged) = is_item_ranged {
|
if let Some(is_item_ranged) = is_item_ranged {
|
||||||
new_run_state = RunState::ShowTargeting {
|
newrunstate = RunState::ShowTargeting {
|
||||||
range: is_item_ranged.range,
|
range: is_item_ranged.range,
|
||||||
item: item_entity,
|
item: item_entity,
|
||||||
}
|
}
|
||||||
@ -147,13 +135,10 @@ impl GameState for State {
|
|||||||
intent
|
intent
|
||||||
.insert(
|
.insert(
|
||||||
*self.ecs.fetch::<Entity>(),
|
*self.ecs.fetch::<Entity>(),
|
||||||
WantsToUseItem {
|
WantsToUseItem { item: item_entity, target: None },
|
||||||
item: item_entity,
|
|
||||||
target: None,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.expect("Unable to insert intent");
|
.expect("Unable to insert intent");
|
||||||
new_run_state = RunState::PlayerTurn;
|
newrunstate = RunState::PlayerTurn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +146,7 @@ impl GameState for State {
|
|||||||
RunState::ShowDropItem => {
|
RunState::ShowDropItem => {
|
||||||
let result = gui::drop_item_menu(self, ctx);
|
let result = gui::drop_item_menu(self, ctx);
|
||||||
match result.0 {
|
match result.0 {
|
||||||
gui::ItemMenuResult::Cancel => new_run_state = RunState::AwaitingInput,
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||||
gui::ItemMenuResult::NoResponse => {}
|
gui::ItemMenuResult::NoResponse => {}
|
||||||
gui::ItemMenuResult::Selected => {
|
gui::ItemMenuResult::Selected => {
|
||||||
let item_entity = result.1.unwrap();
|
let item_entity = result.1.unwrap();
|
||||||
@ -172,60 +157,27 @@ impl GameState for State {
|
|||||||
WantsToDropItem { item: item_entity },
|
WantsToDropItem { item: item_entity },
|
||||||
)
|
)
|
||||||
.expect("Unable to insert intent");
|
.expect("Unable to insert intent");
|
||||||
new_run_state = RunState::PlayerTurn;
|
newrunstate = RunState::PlayerTurn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::ShowTargeting { range, item } => {
|
RunState::ShowTargeting { range, item } => {
|
||||||
let result = gui::ranged_target(self, ctx, range);
|
let result = gui::ranged_target(self, ctx, range);
|
||||||
match result.0 {
|
match result.0 {
|
||||||
gui::ItemMenuResult::Cancel => new_run_state = RunState::AwaitingInput,
|
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||||
gui::ItemMenuResult::NoResponse => {}
|
gui::ItemMenuResult::NoResponse => {}
|
||||||
gui::ItemMenuResult::Selected => {
|
gui::ItemMenuResult::Selected => {
|
||||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||||
intent
|
intent.insert(*self.ecs.fetch::<Entity>(), WantsToUseItem { item, target: result.1 }).expect("Unable to insert intent");
|
||||||
.insert(
|
newrunstate = RunState::PlayerTurn;
|
||||||
*self.ecs.fetch::<Entity>(),
|
|
||||||
WantsToUseItem {
|
|
||||||
item,
|
|
||||||
target: result.1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("Unable to insert intent");
|
|
||||||
new_run_state = RunState::PlayerTurn;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunState::MainMenu { .. } => {
|
|
||||||
let result = gui::main_menu(self, ctx);
|
|
||||||
match result {
|
|
||||||
gui::MainMenuResult::NoSelection { selected } => {
|
|
||||||
new_run_state = RunState::MainMenu {
|
|
||||||
menu_selection: selected,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gui::MainMenuResult::Selected { selected } => match selected {
|
|
||||||
gui::MainMenuSelection::NewGame => new_run_state = RunState::PreRun,
|
|
||||||
gui::MainMenuSelection::LoadGame => {
|
|
||||||
save_load_system::load_game(&mut self.ecs);
|
|
||||||
new_run_state = RunState::AwaitingInput;
|
|
||||||
save_load_system::delete_save();
|
|
||||||
}
|
|
||||||
gui::MainMenuSelection::Quit => ::std::process::exit(0),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RunState::SaveGame => {
|
|
||||||
save_load_system::save_game(&mut self.ecs);
|
|
||||||
new_run_state = RunState::MainMenu {
|
|
||||||
menu_selection: gui::MainMenuSelection::Quit,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut run_writer = self.ecs.write_resource::<RunState>();
|
let mut runwriter = self.ecs.write_resource::<RunState>();
|
||||||
*run_writer = new_run_state;
|
*runwriter = newrunstate;
|
||||||
}
|
}
|
||||||
damage_system::delete_the_dead(&mut self.ecs);
|
damage_system::delete_the_dead(&mut self.ecs);
|
||||||
}
|
}
|
||||||
@ -241,7 +193,11 @@ fn main() -> rltk::BError {
|
|||||||
context.with_post_scanlines(true);
|
context.with_post_scanlines(true);
|
||||||
let mut gs = State { ecs: World::new() };
|
let mut gs = State { ecs: World::new() };
|
||||||
|
|
||||||
|
gs.ecs.insert(RunState::PreRun);
|
||||||
gs.ecs.insert(rltk::RandomNumberGenerator::new());
|
gs.ecs.insert(rltk::RandomNumberGenerator::new());
|
||||||
|
gs.ecs.insert(gamelog::GameLog {
|
||||||
|
entries: vec!["Welcome to Rusty Roguelike".to_string()],
|
||||||
|
});
|
||||||
|
|
||||||
gs.ecs.register::<Position>();
|
gs.ecs.register::<Position>();
|
||||||
gs.ecs.register::<Renderable>();
|
gs.ecs.register::<Renderable>();
|
||||||
@ -264,29 +220,18 @@ fn main() -> rltk::BError {
|
|||||||
gs.ecs.register::<InflictsDamage>();
|
gs.ecs.register::<InflictsDamage>();
|
||||||
gs.ecs.register::<AreaOfEffect>();
|
gs.ecs.register::<AreaOfEffect>();
|
||||||
gs.ecs.register::<Confusion>();
|
gs.ecs.register::<Confusion>();
|
||||||
gs.ecs.register::<SimpleMarker<SerializeMe>>();
|
|
||||||
gs.ecs.register::<SerializationHelper>();
|
|
||||||
|
|
||||||
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
|
||||||
|
|
||||||
let map = Map::new_map_rooms_and_corridors();
|
let map = Map::new_map_rooms_and_corridors();
|
||||||
let (player_x, player_y) = map.rooms[0].center();
|
|
||||||
|
|
||||||
|
let (player_x, player_y) = map.rooms[0].center();
|
||||||
|
gs.ecs.insert(Point::new(player_x, player_y));
|
||||||
let player_entity = spawner::player(&mut gs.ecs, player_x, player_y);
|
let player_entity = spawner::player(&mut gs.ecs, player_x, player_y);
|
||||||
|
gs.ecs.insert(player_entity);
|
||||||
|
|
||||||
for room in map.rooms.iter().skip(1) {
|
for room in map.rooms.iter().skip(1) {
|
||||||
spawner::spawn_room(&mut gs.ecs, room);
|
spawner::spawn_room(&mut gs.ecs, room);
|
||||||
}
|
}
|
||||||
|
|
||||||
gs.ecs.insert(map);
|
gs.ecs.insert(map);
|
||||||
gs.ecs.insert(Point::new(player_x, player_y));
|
|
||||||
gs.ecs.insert(player_entity);
|
|
||||||
gs.ecs.insert(RunState::MainMenu {
|
|
||||||
menu_selection: gui::MainMenuSelection::NewGame,
|
|
||||||
});
|
|
||||||
gs.ecs.insert(gamelog::GameLog {
|
|
||||||
entries: vec!["Welcome to Rusty Roguelike".to_string()],
|
|
||||||
});
|
|
||||||
|
|
||||||
rltk::main_loop(context, gs)
|
rltk::main_loop(context, gs)
|
||||||
}
|
}
|
||||||
|
70
src/map.rs
70
src/map.rs
@ -1,12 +1,11 @@
|
|||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
use rltk::{Algorithm2D, BaseMap, Point, RandomNumberGenerator, RGB, Rltk};
|
use rltk::{Algorithm2D, BaseMap, Point, RandomNumberGenerator, Rltk, RGB};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::rect::Rect;
|
use crate::rect::Rect;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum TileType {
|
pub enum TileType {
|
||||||
Wall,
|
Wall,
|
||||||
Floor,
|
Floor,
|
||||||
@ -18,7 +17,6 @@ pub const MAP_COUNT: usize = MAP_HEIGHT * MAP_WIDTH;
|
|||||||
pub const MAX_MONSTER: i32 = 4;
|
pub const MAX_MONSTER: i32 = 4;
|
||||||
pub const MAX_ITEMS: i32 = 2;
|
pub const MAX_ITEMS: i32 = 2;
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
pub tiles: Vec<TileType>,
|
pub tiles: Vec<TileType>,
|
||||||
pub rooms: Vec<Rect>,
|
pub rooms: Vec<Rect>,
|
||||||
@ -27,9 +25,6 @@ pub struct Map {
|
|||||||
pub revealed_tiles: Vec<bool>,
|
pub revealed_tiles: Vec<bool>,
|
||||||
pub visible_tiles: Vec<bool>,
|
pub visible_tiles: Vec<bool>,
|
||||||
pub blocked: Vec<bool>,
|
pub blocked: Vec<bool>,
|
||||||
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
#[serde(skip_deserializing)]
|
|
||||||
pub tile_content: Vec<Vec<Entity>>,
|
pub tile_content: Vec<Vec<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,27 +60,6 @@ impl Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn is_exit_valid(&self, x: i32, y: i32) -> bool {
|
|
||||||
if x < 1 || x > self.width - 1 || y < 1 || y > self.height - 1 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let idx = self.xy_idx(x, y);
|
|
||||||
!self.blocked[idx]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn populate_blocked(&mut self) {
|
|
||||||
for (i, tile) in self.tiles.iter_mut().enumerate() {
|
|
||||||
self.blocked[i] = *tile == TileType::Wall;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_content_index(&mut self) {
|
|
||||||
for content in self.tile_content.iter_mut() {
|
|
||||||
content.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_map_rooms_and_corridors() -> Map {
|
pub fn new_map_rooms_and_corridors() -> Map {
|
||||||
let mut map = Map {
|
let mut map = Map {
|
||||||
tiles: vec![TileType::Wall; MAP_COUNT],
|
tiles: vec![TileType::Wall; MAP_COUNT],
|
||||||
@ -137,11 +111,37 @@ impl Map {
|
|||||||
|
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_exit_valid(&self, x: i32, y: i32) -> bool {
|
||||||
|
if x < 1 || x > self.width - 1 || y < 1 || y > self.height - 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let idx = self.xy_idx(x, y);
|
||||||
|
!self.blocked[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_blocked(&mut self) {
|
||||||
|
for (i, tile) in self.tiles.iter_mut().enumerate() {
|
||||||
|
self.blocked[i] = *tile == TileType::Wall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_content_index(&mut self) {
|
||||||
|
for content in self.tile_content.iter_mut() {
|
||||||
|
content.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Algorithm2D for Map {
|
||||||
|
fn dimensions(&self) -> rltk::Point {
|
||||||
|
Point::new(self.width, self.height)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseMap for Map {
|
impl BaseMap for Map {
|
||||||
fn is_opaque(&self, idx: usize) -> bool {
|
fn is_opaque(&self, idx: usize) -> bool {
|
||||||
self.tiles[idx] == TileType::Wall
|
self.tiles[idx as usize] == TileType::Wall
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pathing_distance(&self, idx1: usize, idx2: usize) -> f32 {
|
fn get_pathing_distance(&self, idx1: usize, idx2: usize) -> f32 {
|
||||||
@ -187,12 +187,6 @@ impl BaseMap for Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Algorithm2D for Map {
|
|
||||||
fn dimensions(&self) -> rltk::Point {
|
|
||||||
Point::new(self.width, self.height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
|
pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
|
|
||||||
@ -204,12 +198,12 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
|
|||||||
let mut fg;
|
let mut fg;
|
||||||
match tile {
|
match tile {
|
||||||
TileType::Floor => {
|
TileType::Floor => {
|
||||||
fg = RGB::from_f32(0.0, 0.5, 0.5);
|
fg = RGB::from_f32(0.5, 0.5, 0.5);
|
||||||
glyph = rltk::to_cp437('.');
|
glyph = rltk::to_cp437('.');
|
||||||
}
|
}
|
||||||
|
|
||||||
TileType::Wall => {
|
TileType::Wall => {
|
||||||
fg = RGB::from_f32(0., 1.0, 0.);
|
fg = RGB::from_f32(0.0, 1.0, 0.0);
|
||||||
glyph = rltk::to_cp437('#');
|
glyph = rltk::to_cp437('#');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,7 +214,7 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
x += 1;
|
x += 1;
|
||||||
if x > MAP_WIDTH as i32 - 1 {
|
if x > 79 {
|
||||||
x = 0;
|
x = 0;
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
use crate::gamelog::GameLog;
|
||||||
|
use rltk::console;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::components::{CombatStats, Name, SufferDamage, WantsToMelee};
|
use crate::components::{CombatStats, Name, SufferDamage, WantsToMelee};
|
||||||
use crate::gamelog::GameLog;
|
|
||||||
|
|
||||||
pub struct MeleeCombatSystem {}
|
pub struct MeleeCombatSystem {}
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
use rltk::Point;
|
use rltk::{console, Point};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{components::{Monster, Position, Viewshed, WantsToMelee}, Confusion, map::Map, RunState};
|
||||||
components::{Monster, Position, Viewshed, WantsToMelee},
|
|
||||||
Confusion,
|
|
||||||
map::Map, RunState,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct MonsterAI {}
|
pub struct MonsterAI {}
|
||||||
|
|
||||||
@ -56,7 +52,7 @@ impl<'a> System<'a> for MonsterAI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !can_act {
|
if !can_act {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let distance =
|
let distance =
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
use rltk::{Point, Rltk, VirtualKeyCode};
|
use rltk::{console, Point, Rltk, VirtualKeyCode};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
use crate::gamelog::GameLog;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{CombatStats, Player, Position, Viewshed, WantsToMelee},
|
components::{CombatStats, Player, Position, Viewshed, WantsToMelee},
|
||||||
Item,
|
map::{Map, TileType},
|
||||||
map::Map, RunState, State, WantsToPickupItem,
|
Item, RunState, State, WantsToPickupItem,
|
||||||
};
|
};
|
||||||
use crate::gamelog::GameLog;
|
|
||||||
|
|
||||||
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
||||||
let mut positions = ecs.write_storage::<Position>();
|
let mut positions = ecs.write_storage::<Position>();
|
||||||
@ -22,7 +22,6 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
|||||||
for (entity, _player, pos, viewshed) in
|
for (entity, _player, pos, viewshed) in
|
||||||
(&entities, &mut players, &mut positions, &mut viewsheds).join()
|
(&entities, &mut players, &mut positions, &mut viewsheds).join()
|
||||||
{
|
{
|
||||||
if pos.x + delta_x < 1 || pos.x + delta_x > map.width - 1 || pos.y + delta_y < 1 || pos.y + delta_y > map.height - 1 { return; }
|
|
||||||
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
|
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
|
||||||
|
|
||||||
for potential_target in map.tile_content[destination_idx].iter() {
|
for potential_target in map.tile_content[destination_idx].iter() {
|
||||||
@ -100,7 +99,6 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
|||||||
VirtualKeyCode::G => get_item(&mut gs.ecs),
|
VirtualKeyCode::G => get_item(&mut gs.ecs),
|
||||||
VirtualKeyCode::I => return RunState::ShowInventory,
|
VirtualKeyCode::I => return RunState::ShowInventory,
|
||||||
VirtualKeyCode::D => return RunState::ShowDropItem,
|
VirtualKeyCode::D => return RunState::ShowDropItem,
|
||||||
VirtualKeyCode::Escape => return RunState::SaveGame,
|
|
||||||
_ => return RunState::AwaitingInput,
|
_ => return RunState::AwaitingInput,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
pub x1: i32,
|
pub x1: i32,
|
||||||
pub x2: i32,
|
pub x2: i32,
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
use std::fs;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use specs::error::NoError;
|
|
||||||
use specs::prelude::*;
|
|
||||||
use specs::saveload::{DeserializeComponents, MarkedBuilder, SerializeComponents, SimpleMarker, SimpleMarkerAllocator};
|
|
||||||
|
|
||||||
use super::components::*;
|
|
||||||
|
|
||||||
macro_rules! serialize_individually {
|
|
||||||
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
|
|
||||||
$(
|
|
||||||
SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
|
|
||||||
&( $ecs.read_storage::<$type>(), ),
|
|
||||||
&$data.0,
|
|
||||||
&$data.1,
|
|
||||||
&mut $ser,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
pub fn save_game(_ecs: &mut World) {}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub fn save_game(ecs: &mut World) {
|
|
||||||
// Create helper
|
|
||||||
let mapcopy = ecs.get_mut::<super::map::Map>().unwrap().clone();
|
|
||||||
let savehelper = ecs
|
|
||||||
.create_entity()
|
|
||||||
.with(SerializationHelper { map: mapcopy })
|
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Actually serialize
|
|
||||||
{
|
|
||||||
let data = (ecs.entities(), ecs.read_storage::<SimpleMarker<SerializeMe>>());
|
|
||||||
|
|
||||||
let writer = File::create("./savegame.json").unwrap();
|
|
||||||
let mut serializer = serde_json::Serializer::new(writer);
|
|
||||||
serialize_individually!(ecs, serializer, data, Position, Renderable, Player, Viewshed, Monster,
|
|
||||||
Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
|
|
||||||
AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
|
|
||||||
WantsToDropItem, SerializationHelper
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
ecs.delete_entity(savehelper).expect("Crash on cleanup");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn does_save_exist() -> bool {
|
|
||||||
Path::new("./savegame.json").exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! deserialize_individually {
|
|
||||||
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => {
|
|
||||||
$(
|
|
||||||
DeserializeComponents::<NoError, _>::deserialize(
|
|
||||||
&mut ( &mut $ecs.write_storage::<$type>(), ),
|
|
||||||
&$data.0, // entities
|
|
||||||
&mut $data.1, // marker
|
|
||||||
&mut $data.2, // allocater
|
|
||||||
&mut $de,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_game(ecs: &mut World) {
|
|
||||||
{
|
|
||||||
// Delete everything
|
|
||||||
let mut to_delete = Vec::new();
|
|
||||||
for e in ecs.entities().join() {
|
|
||||||
to_delete.push(e);
|
|
||||||
}
|
|
||||||
for del in to_delete.iter() {
|
|
||||||
ecs.delete_entity(*del).expect("Deletion failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = fs::read_to_string("./savegame.json").unwrap();
|
|
||||||
let mut de = serde_json::Deserializer::from_str(&data);
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut d = (&mut ecs.entities(), &mut ecs.write_storage::<SimpleMarker<SerializeMe>>(), &mut ecs.write_resource::<SimpleMarkerAllocator<SerializeMe>>());
|
|
||||||
|
|
||||||
deserialize_individually!(ecs, de, d, Position, Renderable, Player, Viewshed, Monster,
|
|
||||||
Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
|
|
||||||
AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
|
|
||||||
WantsToDropItem, SerializationHelper
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut deleteme: Option<Entity> = None;
|
|
||||||
{
|
|
||||||
let entities = ecs.entities();
|
|
||||||
let helper = ecs.read_storage::<SerializationHelper>();
|
|
||||||
let player = ecs.read_storage::<Player>();
|
|
||||||
let position = ecs.read_storage::<Position>();
|
|
||||||
for (e, h) in (&entities, &helper).join() {
|
|
||||||
let mut worldmap = ecs.write_resource::<super::map::Map>();
|
|
||||||
*worldmap = h.map.clone();
|
|
||||||
worldmap.tile_content = vec![Vec::new(); super::map::MAP_COUNT];
|
|
||||||
deleteme = Some(e);
|
|
||||||
}
|
|
||||||
for (e, _p, pos) in (&entities, &player, &position).join() {
|
|
||||||
let mut ppos = ecs.write_resource::<rltk::Point>();
|
|
||||||
*ppos = rltk::Point::new(pos.x, pos.y);
|
|
||||||
let mut player_resource = ecs.write_resource::<Entity>();
|
|
||||||
*player_resource = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ecs.delete_entity(deleteme.unwrap()).expect("Unable to delete helper");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_save() {
|
|
||||||
if Path::new("./savegame.json").exists() { std::fs::remove_file("./savegame.json").expect("Unable to delete file"); }
|
|
||||||
}
|
|
@ -1,8 +1,7 @@
|
|||||||
use rltk::{FontCharType, RandomNumberGenerator, RGB};
|
use rltk::{FontCharType, RandomNumberGenerator, RGB};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
|
||||||
|
|
||||||
use crate::{AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, InflictsDamage, Item, MAP_WIDTH, MAX_ITEMS, MAX_MONSTER, Monster, Name, Player, Position, ProvidesHealing, Ranged, Renderable, SerializeMe, Viewshed};
|
use crate::{AreaOfEffect, BlocksTile, CombatStats, Confusion, Consumable, InflictsDamage, Item, MAP_WIDTH, MAX_ITEMS, MAX_MONSTER, Monster, Name, Player, Position, Potion, ProvidesHealing, Ranged, Renderable, Viewshed};
|
||||||
use crate::rect::Rect;
|
use crate::rect::Rect;
|
||||||
|
|
||||||
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
@ -32,7 +31,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
|||||||
defense: 2,
|
defense: 2,
|
||||||
power: 5,
|
power: 5,
|
||||||
})
|
})
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +79,6 @@ fn monster<S: ToString>(ecs: &mut World, x: i32, y: i32, glyph: FontCharType, na
|
|||||||
defense: 1,
|
defense: 1,
|
||||||
power: 4,
|
power: 4,
|
||||||
})
|
})
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +146,6 @@ pub fn health_potion(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Item {})
|
.with(Item {})
|
||||||
.with(Consumable {})
|
.with(Consumable {})
|
||||||
.with(ProvidesHealing { heal_amount: 8 })
|
.with(ProvidesHealing { heal_amount: 8 })
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +164,7 @@ pub fn magic_missile_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Item {})
|
.with(Item {})
|
||||||
.with(Consumable {})
|
.with(Consumable {})
|
||||||
.with(Ranged { range: 6 })
|
.with(Ranged { range: 6 })
|
||||||
.with(InflictsDamage { damage: 20 })
|
.with(InflictsDamage { damage: 8 })
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +173,7 @@ pub fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Position { x, y })
|
.with(Position { x, y })
|
||||||
.with(Renderable {
|
.with(Renderable {
|
||||||
glyph: rltk::to_cp437(')'),
|
glyph: rltk::to_cp437(')'),
|
||||||
fg: RGB::named(rltk::ORANGE),
|
fg: RGB::named(rltk::CYAN),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(rltk::BLACK),
|
||||||
render_order: 2,
|
render_order: 2,
|
||||||
})
|
})
|
||||||
@ -190,7 +185,6 @@ pub fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Ranged { range: 6 })
|
.with(Ranged { range: 6 })
|
||||||
.with(InflictsDamage { damage: 20 })
|
.with(InflictsDamage { damage: 20 })
|
||||||
.with(AreaOfEffect { radius: 3 })
|
.with(AreaOfEffect { radius: 3 })
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +193,7 @@ pub fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Position { x, y })
|
.with(Position { x, y })
|
||||||
.with(Renderable {
|
.with(Renderable {
|
||||||
glyph: rltk::to_cp437(')'),
|
glyph: rltk::to_cp437(')'),
|
||||||
fg: RGB::named(rltk::PINK),
|
fg: RGB::named(rltk::CYAN),
|
||||||
bg: RGB::named(rltk::BLACK),
|
bg: RGB::named(rltk::BLACK),
|
||||||
render_order: 2,
|
render_order: 2,
|
||||||
})
|
})
|
||||||
@ -210,10 +204,10 @@ pub fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
|
|||||||
.with(Consumable {})
|
.with(Consumable {})
|
||||||
.with(Ranged { range: 6 })
|
.with(Ranged { range: 6 })
|
||||||
.with(Confusion { turns: 4 })
|
.with(Confusion { turns: 4 })
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn random_item(ecs: &mut World, x: i32, y: i32) {
|
pub fn random_item(ecs: &mut World, x: i32, y: i32) {
|
||||||
let roll: i32;
|
let roll: i32;
|
||||||
{
|
{
|
||||||
|
@ -21,10 +21,11 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||||||
let (mut map, entities, mut viewshed, pos, player) = data;
|
let (mut map, entities, mut viewshed, pos, player) = data;
|
||||||
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
|
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
|
||||||
if !viewshed.dirty {
|
if !viewshed.dirty {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewshed.dirty = false;
|
viewshed.dirty = false;
|
||||||
|
viewshed.visible_tiles.clear();
|
||||||
viewshed.visible_tiles = field_of_view(Point::new(pos.x, pos.y), viewshed.range, &*map);
|
viewshed.visible_tiles = field_of_view(Point::new(pos.x, pos.y), viewshed.range, &*map);
|
||||||
viewshed
|
viewshed
|
||||||
.visible_tiles
|
.visible_tiles
|
||||||
|
Loading…
Reference in New Issue
Block a user