Spawn monsters from raw data, like items
This commit is contained in:
parent
e154577012
commit
b80c64febb
11
src/raws.rs
11
src/raws.rs
@ -1,10 +1,19 @@
|
|||||||
mod item_structs;
|
mod item_structs;
|
||||||
|
mod mob_structs;
|
||||||
mod rawmaster;
|
mod rawmaster;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use item_structs::Raws;
|
use item_structs::*;
|
||||||
|
use mob_structs::*;
|
||||||
pub use rawmaster::*;
|
pub use rawmaster::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Raws {
|
||||||
|
pub items: Vec<Item>,
|
||||||
|
pub mobs: Vec<Mob>,
|
||||||
|
}
|
||||||
|
|
||||||
rltk::embedded_resource!(RAW_FILE, "../raws/spawns.json");
|
rltk::embedded_resource!(RAW_FILE, "../raws/spawns.json");
|
||||||
|
|
||||||
|
@ -2,11 +2,6 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct Raws {
|
|
||||||
pub items: Vec<Item>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
20
src/raws/mob_structs.rs
Normal file
20
src/raws/mob_structs.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use super::item_structs::Renderable;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Mob {
|
||||||
|
pub name: String,
|
||||||
|
pub renderable: Option<Renderable>,
|
||||||
|
pub blocks_tile: bool,
|
||||||
|
pub stats: MobStats,
|
||||||
|
pub vision_range: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct MobStats {
|
||||||
|
pub max_hp: i32,
|
||||||
|
pub hp: i32,
|
||||||
|
pub power: i32,
|
||||||
|
pub defense: i32,
|
||||||
|
}
|
@ -2,8 +2,8 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use super::Raws;
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
|
use crate::raws::Raws;
|
||||||
|
|
||||||
pub enum SpawnType {
|
pub enum SpawnType {
|
||||||
AtPosition { x: i32, y: i32 },
|
AtPosition { x: i32, y: i32 },
|
||||||
@ -12,13 +12,18 @@ pub enum SpawnType {
|
|||||||
pub struct RawMaster {
|
pub struct RawMaster {
|
||||||
raws: Raws,
|
raws: Raws,
|
||||||
item_index: HashMap<String, usize>,
|
item_index: HashMap<String, usize>,
|
||||||
|
mob_index: HashMap<String, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawMaster {
|
impl RawMaster {
|
||||||
pub fn empty() -> RawMaster {
|
pub fn empty() -> RawMaster {
|
||||||
RawMaster {
|
RawMaster {
|
||||||
raws: Raws { items: Vec::new() },
|
raws: Raws {
|
||||||
|
items: Vec::new(),
|
||||||
|
mobs: Vec::new(),
|
||||||
|
},
|
||||||
item_index: HashMap::new(),
|
item_index: HashMap::new(),
|
||||||
|
mob_index: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +34,33 @@ impl RawMaster {
|
|||||||
for (i, item) in self.raws.items.iter().enumerate() {
|
for (i, item) in self.raws.items.iter().enumerate() {
|
||||||
self.item_index.insert(item.name.clone(), i);
|
self.item_index.insert(item.name.clone(), i);
|
||||||
}
|
}
|
||||||
|
for (i, mob) in self.raws.mobs.iter().enumerate() {
|
||||||
|
self.mob_index.insert(mob.name.clone(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_position(pos: SpawnType, new_entity: EntityBuilder) -> EntityBuilder {
|
||||||
|
let mut eb = new_entity;
|
||||||
|
|
||||||
|
// Spawn in the specified location
|
||||||
|
match pos {
|
||||||
|
SpawnType::AtPosition { x, y } => {
|
||||||
|
eb = eb.with(Position { x, y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eb
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_renderable_component(
|
||||||
|
renderable: &super::item_structs::Renderable,
|
||||||
|
) -> crate::components::Renderable {
|
||||||
|
crate::components::Renderable {
|
||||||
|
glyph: rltk::to_cp437(renderable.glyph.chars().next().unwrap()),
|
||||||
|
fg: rltk::RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
|
||||||
|
bg: rltk::RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
|
||||||
|
render_order: renderable.order,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,20 +76,11 @@ pub fn spawn_named_item(
|
|||||||
let mut eb = new_entity;
|
let mut eb = new_entity;
|
||||||
|
|
||||||
// Spawn in the specified location
|
// Spawn in the specified location
|
||||||
match pos {
|
eb = spawn_position(pos, eb);
|
||||||
SpawnType::AtPosition { x, y } => {
|
|
||||||
eb = eb.with(Position { x, y });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renderable
|
// Renderable
|
||||||
if let Some(renderable) = &item_template.renderable {
|
if let Some(renderable) = &item_template.renderable {
|
||||||
eb = eb.with(Renderable {
|
eb = eb.with(get_renderable_component(renderable));
|
||||||
glyph: rltk::to_cp437(renderable.glyph.chars().next().unwrap()),
|
|
||||||
fg: rltk::RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
|
|
||||||
bg: rltk::RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
|
|
||||||
render_order: renderable.order,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eb = eb.with(Name::from(&item_template.name));
|
eb = eb.with(Name::from(&item_template.name));
|
||||||
@ -129,3 +152,63 @@ pub fn spawn_named_item(
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn spawn_named_mob(
|
||||||
|
raws: &RawMaster,
|
||||||
|
new_entity: EntityBuilder,
|
||||||
|
key: &str,
|
||||||
|
pos: SpawnType,
|
||||||
|
) -> Option<Entity> {
|
||||||
|
if raws.mob_index.contains_key(key) {
|
||||||
|
let mob_template = &raws.raws.mobs[raws.mob_index[key]];
|
||||||
|
|
||||||
|
let mut eb = new_entity;
|
||||||
|
|
||||||
|
// Spawn in the specified location
|
||||||
|
eb = spawn_position(pos, eb);
|
||||||
|
|
||||||
|
// Renderable
|
||||||
|
if let Some(renderable) = &mob_template.renderable {
|
||||||
|
eb = eb.with(get_renderable_component(renderable));
|
||||||
|
}
|
||||||
|
|
||||||
|
eb = eb.with(Name::from(&mob_template.name));
|
||||||
|
|
||||||
|
eb = eb.with(Monster {});
|
||||||
|
if mob_template.blocks_tile {
|
||||||
|
eb = eb.with(BlocksTile {});
|
||||||
|
}
|
||||||
|
|
||||||
|
eb = eb.with(CombatStats {
|
||||||
|
max_hp: mob_template.stats.max_hp,
|
||||||
|
hp: mob_template.stats.hp,
|
||||||
|
power: mob_template.stats.power,
|
||||||
|
defense: mob_template.stats.defense,
|
||||||
|
});
|
||||||
|
|
||||||
|
eb = eb.with(Viewshed {
|
||||||
|
visible_tiles: Vec::new(),
|
||||||
|
range: mob_template.vision_range,
|
||||||
|
dirty: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Some(eb.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_named_entity(
|
||||||
|
raws: &RawMaster,
|
||||||
|
new_entity: EntityBuilder,
|
||||||
|
key: &str,
|
||||||
|
pos: SpawnType,
|
||||||
|
) -> Option<Entity> {
|
||||||
|
if raws.item_index.contains_key(key) {
|
||||||
|
return spawn_named_item(raws, new_entity, key, pos);
|
||||||
|
} else if raws.mob_index.contains_key(key) {
|
||||||
|
return spawn_named_mob(raws, new_entity, key, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ use specs::saveload::{MarkedBuilder, SimpleMarker};
|
|||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::random_table::RandomTable;
|
use crate::random_table::RandomTable;
|
||||||
use crate::raws::{spawn_named_item, SpawnType, RAWS};
|
use crate::raws::{spawn_named_entity, SpawnType, RAWS};
|
||||||
use crate::{Map, Rect, TileType};
|
use crate::{Map, Rect, TileType};
|
||||||
|
|
||||||
/// Spawns the player and returns their entity object
|
/// Spawns the player and returns their entity object
|
||||||
@ -133,7 +133,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
|||||||
// Drop this map reference to make the borrow checker happy
|
// Drop this map reference to make the borrow checker happy
|
||||||
std::mem::drop(map);
|
std::mem::drop(map);
|
||||||
|
|
||||||
let item_result = spawn_named_item(
|
let item_result = spawn_named_entity(
|
||||||
&RAWS.lock().unwrap(),
|
&RAWS.lock().unwrap(),
|
||||||
ecs.create_entity(),
|
ecs.create_entity(),
|
||||||
spawn.1,
|
spawn.1,
|
||||||
@ -144,45 +144,12 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match spawn.1.as_ref() {
|
match spawn.1.as_ref() {
|
||||||
"Goblin" => goblin(ecs, x, y),
|
|
||||||
"Orc" => orc(ecs, x, y),
|
|
||||||
"Bear Trap" => bear_trap(ecs, x, y),
|
"Bear Trap" => bear_trap(ecs, x, y),
|
||||||
"Door" => door(ecs, x, y),
|
"Door" => door(ecs, x, y),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn orc(ecs: &mut World, x: i32, y: i32) {
|
|
||||||
monster(ecs, x, y, rltk::to_cp437('o'), "Orc");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn goblin(ecs: &mut World, x: i32, y: i32) {
|
|
||||||
monster(ecs, x, y, rltk::to_cp437('g'), "Goblin");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn monster<S: ToString>(ecs: &mut World, x: i32, y: i32, glyph: rltk::FontCharType, name: S) {
|
|
||||||
ecs.create_entity()
|
|
||||||
.with(Position { x, y })
|
|
||||||
.with(Renderable {
|
|
||||||
glyph,
|
|
||||||
fg: RGB::named(rltk::RED),
|
|
||||||
bg: RGB::named(rltk::BLACK),
|
|
||||||
render_order: 1,
|
|
||||||
})
|
|
||||||
.with(Viewshed::default())
|
|
||||||
.with(Monster {})
|
|
||||||
.with(Name::from(name))
|
|
||||||
.with(BlocksTile {})
|
|
||||||
.with(CombatStats {
|
|
||||||
max_hp: 16,
|
|
||||||
hp: 16,
|
|
||||||
defense: 1,
|
|
||||||
power: 4,
|
|
||||||
})
|
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bear_trap(ecs: &mut World, x: i32, y: i32) {
|
fn bear_trap(ecs: &mut World, x: i32, y: i32) {
|
||||||
ecs.create_entity()
|
ecs.create_entity()
|
||||||
.with(Position { x, y })
|
.with(Position { x, y })
|
||||||
|
Loading…
Reference in New Issue
Block a user