ancestries
This commit is contained in:
parent
c8b28a9abd
commit
3050219494
11 changed files with 274 additions and 110 deletions
22
raws/ancestries.json
Normal file
22
raws/ancestries.json
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "human",
|
||||||
|
"allied": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "elf",
|
||||||
|
"allied": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dwarf",
|
||||||
|
"allied": ["gnome"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gnome",
|
||||||
|
"allied": ["dwarf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "catfolk",
|
||||||
|
"allied": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{raws::Reaction, Faction, Map, Position, TakingTurn, WantsToMelee};
|
use crate::{raws::Reaction, Faction, HasAncestry, Map, Position, TakingTurn, WantsToMelee};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct AdjacentAI {}
|
pub struct AdjacentAI {}
|
||||||
|
|
@ -8,6 +8,7 @@ impl<'a> System<'a> for AdjacentAI {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
WriteStorage<'a, TakingTurn>,
|
WriteStorage<'a, TakingTurn>,
|
||||||
ReadStorage<'a, Faction>,
|
ReadStorage<'a, Faction>,
|
||||||
|
ReadStorage<'a, HasAncestry>,
|
||||||
ReadStorage<'a, Position>,
|
ReadStorage<'a, Position>,
|
||||||
ReadExpect<'a, Map>,
|
ReadExpect<'a, Map>,
|
||||||
WriteStorage<'a, WantsToMelee>,
|
WriteStorage<'a, WantsToMelee>,
|
||||||
|
|
@ -16,7 +17,7 @@ impl<'a> System<'a> for AdjacentAI {
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (mut turns, factions, positions, map, mut want_melee, entities, player) = data;
|
let (mut turns, factions, ancestries, positions, map, mut want_melee, entities, player) = data;
|
||||||
|
|
||||||
let mut turn_done: Vec<Entity> = Vec::new();
|
let mut turn_done: Vec<Entity> = Vec::new();
|
||||||
for (entity, _turn, my_faction, pos) in (&entities, &turns, &factions, &positions).join() {
|
for (entity, _turn, my_faction, pos) in (&entities, &turns, &factions, &positions).join() {
|
||||||
|
|
@ -27,28 +28,28 @@ impl<'a> System<'a> for AdjacentAI {
|
||||||
let h = map.height;
|
let h = map.height;
|
||||||
// Add possible reactions to adjacents for each direction
|
// Add possible reactions to adjacents for each direction
|
||||||
if pos.x > 0 {
|
if pos.x > 0 {
|
||||||
evaluate(idx - 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, idx - 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.x < w - 1 {
|
if pos.x < w - 1 {
|
||||||
evaluate(idx + 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, idx + 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y > 0 {
|
if pos.y > 0 {
|
||||||
evaluate(idx - w as usize, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, idx - w as usize, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y < h - 1 {
|
if pos.y < h - 1 {
|
||||||
evaluate(idx + w as usize, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, idx + w as usize, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y > 0 && pos.x > 0 {
|
if pos.y > 0 && pos.x > 0 {
|
||||||
evaluate((idx - w as usize) - 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, (idx - w as usize) - 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y > 0 && pos.x < w - 1 {
|
if pos.y > 0 && pos.x < w - 1 {
|
||||||
evaluate((idx - w as usize) + 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, (idx - w as usize) + 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y < h - 1 && pos.x > 0 {
|
if pos.y < h - 1 && pos.x > 0 {
|
||||||
evaluate((idx + w as usize) - 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, (idx + w as usize) - 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
if pos.y < h - 1 && pos.x < w - 1 {
|
if pos.y < h - 1 && pos.x < w - 1 {
|
||||||
evaluate((idx + w as usize) + 1, &factions, &my_faction.name, &mut reactions);
|
evaluate(entity, (idx + w as usize) + 1, &ancestries, &factions, &my_faction.name, &mut reactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
|
|
@ -73,13 +74,31 @@ impl<'a> System<'a> for AdjacentAI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates all possible reactions between this faction and all entities on a given tile idx.
|
/// Evaluates all possible reactions between this faction and all entities on a given tile idx.
|
||||||
fn evaluate(idx: usize, factions: &ReadStorage<Faction>, this_faction: &str, reactions: &mut Vec<(Entity, Reaction)>) {
|
fn evaluate(
|
||||||
|
entity: Entity,
|
||||||
|
idx: usize,
|
||||||
|
ancestries: &ReadStorage<HasAncestry>,
|
||||||
|
factions: &ReadStorage<Faction>,
|
||||||
|
this_faction: &str,
|
||||||
|
reactions: &mut Vec<(Entity, Reaction)>,
|
||||||
|
) {
|
||||||
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
||||||
if let Some(faction) = factions.get(other_entity) {
|
let mut shared_ancestry = false;
|
||||||
reactions.push((
|
if let Some(this_ancestry) = ancestries.get(entity) {
|
||||||
other_entity,
|
if let Some(other_ancestry) = ancestries.get(other_entity) {
|
||||||
crate::raws::faction_reaction(this_faction, &faction.name, &crate::raws::RAWS.lock().unwrap()),
|
if this_ancestry.name == other_ancestry.name {
|
||||||
));
|
reactions.push((other_entity, Reaction::Ignore));
|
||||||
|
shared_ancestry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !shared_ancestry {
|
||||||
|
if let Some(faction) = factions.get(other_entity) {
|
||||||
|
reactions.push((
|
||||||
|
other_entity,
|
||||||
|
crate::raws::faction_reaction(this_faction, &faction.name, &crate::raws::RAWS.lock().unwrap()),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
raws::Reaction, Chasing, Faction, Map, Mind, Position, TakingTurn, Telepath, Viewshed, WantsToApproach, WantsToFlee,
|
raws::Reaction, Chasing, Faction, HasAncestry, Map, Mind, Position, TakingTurn, Telepath, Viewshed,
|
||||||
|
WantsToApproach, WantsToFlee,
|
||||||
};
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
@ -11,6 +12,7 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
ReadStorage<'a, TakingTurn>,
|
ReadStorage<'a, TakingTurn>,
|
||||||
ReadStorage<'a, Faction>,
|
ReadStorage<'a, Faction>,
|
||||||
|
ReadStorage<'a, HasAncestry>,
|
||||||
ReadStorage<'a, Position>,
|
ReadStorage<'a, Position>,
|
||||||
ReadExpect<'a, Map>,
|
ReadExpect<'a, Map>,
|
||||||
WriteStorage<'a, WantsToApproach>,
|
WriteStorage<'a, WantsToApproach>,
|
||||||
|
|
@ -27,6 +29,7 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
let (
|
let (
|
||||||
turns,
|
turns,
|
||||||
factions,
|
factions,
|
||||||
|
ancestries,
|
||||||
positions,
|
positions,
|
||||||
map,
|
map,
|
||||||
mut wants_to_approach,
|
mut wants_to_approach,
|
||||||
|
|
@ -50,7 +53,7 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
for visible_tile in viewshed.visible_tiles.iter() {
|
for visible_tile in viewshed.visible_tiles.iter() {
|
||||||
let idx = map.xy_idx(visible_tile.x, visible_tile.y);
|
let idx = map.xy_idx(visible_tile.x, visible_tile.y);
|
||||||
if this_idx != idx {
|
if this_idx != idx {
|
||||||
evaluate(idx, &factions, &faction.name, &mut reactions, None);
|
evaluate(entity, idx, &ancestries, &factions, &faction.name, &mut reactions, None);
|
||||||
idxs.insert(idx);
|
idxs.insert(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +64,7 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
// and it's not the idx we're standing on, then evaluate here w/ minds taken into
|
// and it's not the idx we're standing on, then evaluate here w/ minds taken into
|
||||||
// account.
|
// account.
|
||||||
if this_idx != idx && idxs.contains(&idx) {
|
if this_idx != idx && idxs.contains(&idx) {
|
||||||
evaluate(idx, &factions, &faction.name, &mut reactions, Some(&minds));
|
evaluate(entity, idx, &ancestries, &factions, &faction.name, &mut reactions, Some(&minds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,17 +92,42 @@ impl<'a> System<'a> for VisibleAI {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
|
entity: Entity,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
ancestries: &ReadStorage<HasAncestry>,
|
||||||
factions: &ReadStorage<Faction>,
|
factions: &ReadStorage<Faction>,
|
||||||
this_faction: &str,
|
this_faction: &str,
|
||||||
reactions: &mut Vec<(usize, Reaction, Entity)>,
|
reactions: &mut Vec<(usize, Reaction, Entity)>,
|
||||||
minds: Option<&ReadStorage<Mind>>,
|
minds: Option<&ReadStorage<Mind>>,
|
||||||
) {
|
) {
|
||||||
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
||||||
// If minds are passed, we assume we're using telepathy here,
|
let mut shared_ancestry = false;
|
||||||
// so if the other entity is mindless, we skip it.
|
if let Some(this_ancestry) = ancestries.get(entity) {
|
||||||
if minds.is_some() {
|
if let Some(other_ancestry) = ancestries.get(other_entity) {
|
||||||
if minds.unwrap().get(other_entity).is_some() {
|
if this_ancestry.name == other_ancestry.name {
|
||||||
|
reactions.push((idx, Reaction::Ignore, other_entity));
|
||||||
|
shared_ancestry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !shared_ancestry {
|
||||||
|
// If minds are passed, we assume we're using telepathy here,
|
||||||
|
// so if the other entity is mindless, we skip it.
|
||||||
|
if minds.is_some() {
|
||||||
|
if minds.unwrap().get(other_entity).is_some() {
|
||||||
|
if let Some(faction) = factions.get(other_entity) {
|
||||||
|
reactions.push((
|
||||||
|
idx,
|
||||||
|
crate::raws::faction_reaction(
|
||||||
|
this_faction,
|
||||||
|
&faction.name,
|
||||||
|
&crate::raws::RAWS.lock().unwrap(),
|
||||||
|
),
|
||||||
|
other_entity,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if let Some(faction) = factions.get(other_entity) {
|
if let Some(faction) = factions.get(other_entity) {
|
||||||
reactions.push((
|
reactions.push((
|
||||||
idx,
|
idx,
|
||||||
|
|
@ -108,14 +136,6 @@ fn evaluate(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if let Some(faction) = factions.get(other_entity) {
|
|
||||||
reactions.push((
|
|
||||||
idx,
|
|
||||||
crate::raws::faction_reaction(this_faction, &faction.name, &crate::raws::RAWS.lock().unwrap()),
|
|
||||||
other_entity,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::gui::Ancestry;
|
||||||
|
use crate::gui::Class;
|
||||||
use rltk::RGB;
|
use rltk::RGB;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::error::NoError;
|
use specs::error::NoError;
|
||||||
|
|
@ -142,6 +144,16 @@ pub struct HungerClock {
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct ProvidesNutrition {}
|
pub struct ProvidesNutrition {}
|
||||||
|
|
||||||
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct HasAncestry {
|
||||||
|
pub name: Ancestry,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct HasClass {
|
||||||
|
pub name: Class,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Pool {
|
pub struct Pool {
|
||||||
pub max: i32,
|
pub max: i32,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{Skill, Skills};
|
use super::{Skill, Skills};
|
||||||
use crate::gui::Classes;
|
use crate::gui::Class;
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
|
|
@ -77,19 +77,19 @@ pub fn roll_4d6(rng: &mut rltk::RandomNumberGenerator) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles stat distribution for a player character.
|
/// Handles stat distribution for a player character.
|
||||||
pub fn get_attribute_rolls(rng: &mut RandomNumberGenerator, class: Classes) -> (i32, i32, i32, i32, i32, i32) {
|
pub fn get_attribute_rolls(rng: &mut RandomNumberGenerator, class: Class) -> (i32, i32, i32, i32, i32, i32) {
|
||||||
let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class {
|
let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class {
|
||||||
Classes::Fighter => (10, 8, 10, 6, 6, 8),
|
Class::Fighter => (10, 8, 10, 6, 6, 8),
|
||||||
Classes::Rogue => (8, 10, 8, 6, 8, 10),
|
Class::Rogue => (8, 10, 8, 6, 8, 10),
|
||||||
Classes::Wizard => (6, 8, 6, 10, 10, 8),
|
Class::Wizard => (6, 8, 6, 10, 10, 8),
|
||||||
Classes::Villager => (6, 6, 6, 6, 6, 6),
|
Class::Villager => (6, 6, 6, 6, 6, 6),
|
||||||
};
|
};
|
||||||
let remaining_points = 75 - (str + dex + con + int + wis + cha);
|
let remaining_points = 75 - (str + dex + con + int + wis + cha);
|
||||||
let improve_chance: [i32; 6] = match class {
|
let improve_chance: [i32; 6] = match class {
|
||||||
Classes::Fighter => [30, 20, 30, 6, 7, 7],
|
Class::Fighter => [30, 20, 30, 6, 7, 7],
|
||||||
Classes::Rogue => [18, 30, 20, 9, 8, 15],
|
Class::Rogue => [18, 30, 20, 9, 8, 15],
|
||||||
Classes::Wizard => [10, 15, 20, 30, 15, 10],
|
Class::Wizard => [10, 15, 20, 30, 15, 10],
|
||||||
Classes::Villager => [15, 15, 25, 15, 15, 15],
|
Class::Villager => [15, 15, 25, 15, 15, 15],
|
||||||
};
|
};
|
||||||
let improve_table = crate::random_table::RandomTable::new()
|
let improve_table = crate::random_table::RandomTable::new()
|
||||||
.add("Strength", improve_chance[0])
|
.add("Strength", improve_chance[0])
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,36 @@
|
||||||
use super::{gamesystem::attr_bonus, gamesystem::get_attribute_rolls, Attributes, Pools, Renderable, RunState, State};
|
use super::{gamesystem::attr_bonus, gamesystem::get_attribute_rolls, Attributes, Pools, Renderable, RunState, State};
|
||||||
use crate::{ai::NORMAL_SPEED, raws, Attribute, Energy, Pool, Skill, Skills, Telepath};
|
use crate::{ai::NORMAL_SPEED, raws, Attribute, Energy, HasAncestry, HasClass, Pool, Skill, Skills, Telepath};
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
|
||||||
pub enum Races {
|
pub enum Ancestry {
|
||||||
NULL,
|
NULL,
|
||||||
Human,
|
Human,
|
||||||
Dwarf,
|
Dwarf,
|
||||||
|
Gnome,
|
||||||
Elf,
|
Elf,
|
||||||
|
Catfolk,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
|
||||||
|
pub enum Class {
|
||||||
|
Fighter,
|
||||||
|
Rogue,
|
||||||
|
Wizard,
|
||||||
|
Villager,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RACE_CLASS_DATA: HashMap<String, Vec<String>> = {
|
static ref ANCESTRY_CLASS_DATA: HashMap<String, Vec<String>> = {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
// Races
|
// Ancestry
|
||||||
m.insert(
|
m.insert(
|
||||||
"human".to_string(),
|
"human".to_string(),
|
||||||
vec![
|
vec![
|
||||||
"+nothing".to_string()]);
|
"nothing".to_string()]);
|
||||||
m.insert(
|
m.insert(
|
||||||
"dwarf".to_string(),
|
"dwarf".to_string(),
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -29,7 +40,12 @@ lazy_static! {
|
||||||
vec![
|
vec![
|
||||||
"minor telepathy".to_string(),
|
"minor telepathy".to_string(),
|
||||||
"a slightly increased speed".to_string()]);
|
"a slightly increased speed".to_string()]);
|
||||||
// Classes
|
m.insert(
|
||||||
|
"catfolk".to_string(),
|
||||||
|
vec![
|
||||||
|
"increased speed".to_string(),
|
||||||
|
"increased unarmed damage".to_string()]);
|
||||||
|
// Class
|
||||||
m.insert(
|
m.insert(
|
||||||
"fighter".to_string(),
|
"fighter".to_string(),
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -58,18 +74,10 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
|
||||||
pub enum Classes {
|
|
||||||
Fighter,
|
|
||||||
Rogue,
|
|
||||||
Wizard,
|
|
||||||
Villager,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum CharCreateResult {
|
pub enum CharCreateResult {
|
||||||
NoSelection { race: Races, class: Classes },
|
NoSelection { ancestry: Ancestry, class: Class },
|
||||||
Selected { race: Races, class: Classes },
|
Selected { ancestry: Ancestry, class: Class },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the player character creation screen.
|
/// Handles the player character creation screen.
|
||||||
|
|
@ -83,102 +91,110 @@ pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
||||||
ctx.print_color(x, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Who are you? [Aa-Zz]");
|
ctx.print_color(x, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Who are you? [Aa-Zz]");
|
||||||
y += 2;
|
y += 2;
|
||||||
|
|
||||||
if let RunState::CharacterCreation { race, class } = *runstate {
|
if let RunState::CharacterCreation { ancestry, class } = *runstate {
|
||||||
let selected_fg = RGB::named(GREEN);
|
let selected_fg = RGB::named(GREEN);
|
||||||
let unselected_fg = RGB::named(WHITE);
|
let unselected_fg = RGB::named(WHITE);
|
||||||
let mut fg;
|
let mut fg;
|
||||||
let bg = RGB::named(BLACK);
|
let bg = RGB::named(BLACK);
|
||||||
|
|
||||||
// Races
|
// Ancestry
|
||||||
ctx.print_color(x, y, bg, unselected_fg, "Ancestry");
|
ctx.print_color(x, y, bg, unselected_fg, "Ancestry");
|
||||||
ctx.print_color(x + column_width, y, bg, unselected_fg, "Class");
|
ctx.print_color(x + column_width, y, bg, unselected_fg, "Class");
|
||||||
y += 1;
|
y += 1;
|
||||||
let mut race_str = "human";
|
let mut race_str = "human";
|
||||||
if race == Races::Human {
|
if ancestry == Ancestry::Human {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y, fg, bg, "h. Human");
|
ctx.print_color(x, y, fg, bg, "h. Human");
|
||||||
if race == Races::Elf {
|
if ancestry == Ancestry::Elf {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
race_str = "elf";
|
race_str = "elf";
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y + 1, fg, bg, "e. Elf");
|
ctx.print_color(x, y + 1, fg, bg, "e. Elf");
|
||||||
if race == Races::Dwarf {
|
if ancestry == Ancestry::Dwarf {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
race_str = "dwarf";
|
race_str = "dwarf";
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y + 2, fg, bg, "d. Dwarf");
|
ctx.print_color(x, y + 2, fg, bg, "d. Dwarf");
|
||||||
// Classes
|
if ancestry == Ancestry::Catfolk {
|
||||||
|
fg = selected_fg;
|
||||||
|
race_str = "catfolk";
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y + 3, fg, bg, "c. Catfolk");
|
||||||
|
// Class
|
||||||
let mut class_str = "fighter";
|
let mut class_str = "fighter";
|
||||||
x += column_width;
|
x += column_width;
|
||||||
if class == Classes::Fighter {
|
if class == Class::Fighter {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y, fg, bg, "f. Fighter");
|
ctx.print_color(x, y, fg, bg, "f. Fighter");
|
||||||
if class == Classes::Rogue {
|
if class == Class::Rogue {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
class_str = "rogue";
|
class_str = "rogue";
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y + 1, fg, bg, "r. Rogue");
|
ctx.print_color(x, y + 1, fg, bg, "r. Rogue");
|
||||||
if class == Classes::Wizard {
|
if class == Class::Wizard {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
class_str = "wizard";
|
class_str = "wizard";
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y + 2, fg, bg, "w. Wizard");
|
ctx.print_color(x, y + 2, fg, bg, "w. Wizard");
|
||||||
if class == Classes::Villager {
|
if class == Class::Villager {
|
||||||
fg = selected_fg;
|
fg = selected_fg;
|
||||||
class_str = "villager";
|
class_str = "villager";
|
||||||
} else {
|
} else {
|
||||||
fg = unselected_fg;
|
fg = unselected_fg;
|
||||||
}
|
}
|
||||||
ctx.print_color(x, y + 3, fg, bg, "v. Villager");
|
ctx.print_color(x, y + 3, fg, bg, "v. Villager");
|
||||||
// Selected race/class benefits
|
// Selected ancestry/class benefits
|
||||||
x += column_width;
|
x += column_width;
|
||||||
ctx.print_color(x, y, selected_fg, bg, "Your ancestry grants...");
|
ctx.print_color(x, y, selected_fg, bg, "Your ancestry grants...");
|
||||||
for line in RACE_CLASS_DATA.get(race_str).unwrap().iter() {
|
for line in ANCESTRY_CLASS_DATA.get(race_str).unwrap().iter() {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.print_color(x + 1, y, unselected_fg, bg, line);
|
ctx.print_color(x + 1, y, unselected_fg, bg, line);
|
||||||
}
|
}
|
||||||
y += 2;
|
y += 2;
|
||||||
ctx.print_color(x, y, selected_fg, bg, "Your class grants...");
|
ctx.print_color(x, y, selected_fg, bg, "Your class grants...");
|
||||||
for line in RACE_CLASS_DATA.get(class_str).unwrap().iter() {
|
for line in ANCESTRY_CLASS_DATA.get(class_str).unwrap().iter() {
|
||||||
y += 1;
|
y += 1;
|
||||||
ctx.print_color(x + 1, y, unselected_fg, bg, line);
|
ctx.print_color(x + 1, y, unselected_fg, bg, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
match ctx.key {
|
match ctx.key {
|
||||||
None => return CharCreateResult::NoSelection { race, class },
|
None => return CharCreateResult::NoSelection { ancestry, class },
|
||||||
Some(key) => match key {
|
Some(key) => match key {
|
||||||
VirtualKeyCode::Escape => return CharCreateResult::Selected { race: Races::NULL, class },
|
VirtualKeyCode::Escape => return CharCreateResult::Selected { ancestry: Ancestry::NULL, class },
|
||||||
VirtualKeyCode::Return => return CharCreateResult::Selected { race, class },
|
VirtualKeyCode::Return => return CharCreateResult::Selected { ancestry, class },
|
||||||
VirtualKeyCode::H => return CharCreateResult::NoSelection { race: Races::Human, class },
|
VirtualKeyCode::H => return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class },
|
||||||
VirtualKeyCode::E => return CharCreateResult::NoSelection { race: Races::Elf, class },
|
VirtualKeyCode::E => return CharCreateResult::NoSelection { ancestry: Ancestry::Elf, class },
|
||||||
VirtualKeyCode::D => return CharCreateResult::NoSelection { race: Races::Dwarf, class },
|
VirtualKeyCode::D => return CharCreateResult::NoSelection { ancestry: Ancestry::Dwarf, class },
|
||||||
VirtualKeyCode::F => return CharCreateResult::NoSelection { race, class: Classes::Fighter },
|
VirtualKeyCode::C => return CharCreateResult::NoSelection { ancestry: Ancestry::Catfolk, class },
|
||||||
VirtualKeyCode::R => return CharCreateResult::NoSelection { race, class: Classes::Rogue },
|
VirtualKeyCode::F => return CharCreateResult::NoSelection { ancestry, class: Class::Fighter },
|
||||||
VirtualKeyCode::W => return CharCreateResult::NoSelection { race, class: Classes::Wizard },
|
VirtualKeyCode::R => return CharCreateResult::NoSelection { ancestry, class: Class::Rogue },
|
||||||
VirtualKeyCode::V => return CharCreateResult::NoSelection { race, class: Classes::Villager },
|
VirtualKeyCode::W => return CharCreateResult::NoSelection { ancestry, class: Class::Wizard },
|
||||||
_ => return CharCreateResult::NoSelection { race, class },
|
VirtualKeyCode::V => return CharCreateResult::NoSelection { ancestry, class: Class::Villager },
|
||||||
|
_ => return CharCreateResult::NoSelection { ancestry, class },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CharCreateResult::NoSelection { race: Races::Human, class: Classes::Fighter };
|
return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class: Class::Fighter };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles player race setup.
|
/// Handles player ancestry setup.
|
||||||
pub fn setup_player_race(ecs: &mut World, race: Races) {
|
pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
|
||||||
let player = ecs.fetch::<Entity>();
|
let player = ecs.fetch::<Entity>();
|
||||||
let mut renderables = ecs.write_storage::<Renderable>();
|
let mut renderables = ecs.write_storage::<Renderable>();
|
||||||
// SKILLS
|
// SKILLS
|
||||||
|
|
@ -189,9 +205,11 @@ pub fn setup_player_race(ecs: &mut World, race: Races) {
|
||||||
skills.insert(*player, Skills { skills: HashMap::new() }).expect("Unable to insert skills component");
|
skills.insert(*player, Skills { skills: HashMap::new() }).expect("Unable to insert skills component");
|
||||||
skills.get_mut(*player).unwrap()
|
skills.get_mut(*player).unwrap()
|
||||||
};
|
};
|
||||||
match race {
|
let mut ancestries = ecs.write_storage::<HasAncestry>();
|
||||||
Races::Human => {}
|
ancestries.insert(*player, HasAncestry { name: ancestry }).expect("Unable to insert ancestry");
|
||||||
Races::Dwarf => {
|
match ancestry {
|
||||||
|
Ancestry::Human => {}
|
||||||
|
Ancestry::Dwarf => {
|
||||||
renderables
|
renderables
|
||||||
.insert(
|
.insert(
|
||||||
*player,
|
*player,
|
||||||
|
|
@ -205,7 +223,7 @@ pub fn setup_player_race(ecs: &mut World, race: Races) {
|
||||||
.expect("Unable to insert renderable component");
|
.expect("Unable to insert renderable component");
|
||||||
*player_skills.skills.entry(Skill::Defence).or_insert(0) += 1;
|
*player_skills.skills.entry(Skill::Defence).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
Races::Elf => {
|
Ancestry::Elf => {
|
||||||
renderables
|
renderables
|
||||||
.insert(
|
.insert(
|
||||||
*player,
|
*player,
|
||||||
|
|
@ -226,15 +244,23 @@ pub fn setup_player_race(ecs: &mut World, race: Races) {
|
||||||
.insert(*player, Energy { current: 0, speed: NORMAL_SPEED + 1 })
|
.insert(*player, Energy { current: 0, speed: NORMAL_SPEED + 1 })
|
||||||
.expect("Unable to insert energy component");
|
.expect("Unable to insert energy component");
|
||||||
}
|
}
|
||||||
|
Ancestry::Catfolk => {
|
||||||
|
let mut speeds = ecs.write_storage::<Energy>();
|
||||||
|
speeds
|
||||||
|
.insert(*player, Energy { current: 0, speed: NORMAL_SPEED + 2 })
|
||||||
|
.expect("Unable to insert energy component");
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles player class setup
|
/// Handles player class setup
|
||||||
pub fn setup_player_class(ecs: &mut World, class: Classes) {
|
pub fn setup_player_class(ecs: &mut World, class: Class) {
|
||||||
let player = *ecs.fetch::<Entity>();
|
let player = *ecs.fetch::<Entity>();
|
||||||
// ATTRIBUTES
|
// ATTRIBUTES
|
||||||
{
|
{
|
||||||
|
let mut classes = ecs.write_storage::<HasClass>();
|
||||||
|
classes.insert(player, HasClass { name: class }).expect("Unable to insert class component");
|
||||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let mut attributes = ecs.write_storage::<Attributes>();
|
let mut attributes = ecs.write_storage::<Attributes>();
|
||||||
|
|
||||||
|
|
@ -281,12 +307,12 @@ pub fn setup_player_class(ecs: &mut World, class: Classes) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_starting_inventory(class: Classes, rng: &mut RandomNumberGenerator) -> (Vec<String>, Vec<String>) {
|
fn get_starting_inventory(class: Class, rng: &mut RandomNumberGenerator) -> (Vec<String>, Vec<String>) {
|
||||||
let mut equipped: Vec<String> = Vec::new();
|
let mut equipped: Vec<String> = Vec::new();
|
||||||
let mut carried: Vec<String> = Vec::new();
|
let mut carried: Vec<String> = Vec::new();
|
||||||
let starting_food: &str;
|
let starting_food: &str;
|
||||||
match class {
|
match class {
|
||||||
Classes::Fighter => {
|
Class::Fighter => {
|
||||||
starting_food = "1d2+1";
|
starting_food = "1d2+1";
|
||||||
equipped = vec![
|
equipped = vec![
|
||||||
"equip_shortsword".to_string(),
|
"equip_shortsword".to_string(),
|
||||||
|
|
@ -294,18 +320,18 @@ fn get_starting_inventory(class: Classes, rng: &mut RandomNumberGenerator) -> (V
|
||||||
"equip_mediumshield".to_string(),
|
"equip_mediumshield".to_string(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
Classes::Rogue => {
|
Class::Rogue => {
|
||||||
starting_food = "1d2+2";
|
starting_food = "1d2+2";
|
||||||
equipped = vec!["equip_rapier".to_string(), "equip_body_weakleather".to_string()];
|
equipped = vec!["equip_rapier".to_string(), "equip_body_weakleather".to_string()];
|
||||||
carried = vec!["equip_dagger".to_string(), "equip_dagger".to_string()];
|
carried = vec!["equip_dagger".to_string(), "equip_dagger".to_string()];
|
||||||
}
|
}
|
||||||
Classes::Wizard => {
|
Class::Wizard => {
|
||||||
starting_food = "1d2+1";
|
starting_food = "1d2+1";
|
||||||
equipped = vec!["equip_dagger".to_string(), "equip_back_protection".to_string()];
|
equipped = vec!["equip_dagger".to_string(), "equip_back_protection".to_string()];
|
||||||
pick_random_table_item(rng, &mut carried, "scrolls", "1d3", Some(3));
|
pick_random_table_item(rng, &mut carried, "scrolls", "1d3", Some(3));
|
||||||
pick_random_table_item(rng, &mut carried, "potions", "1d3-1", Some(3));
|
pick_random_table_item(rng, &mut carried, "potions", "1d3-1", Some(3));
|
||||||
}
|
}
|
||||||
Classes::Villager => {
|
Class::Villager => {
|
||||||
starting_food = "1d3+2";
|
starting_food = "1d3+2";
|
||||||
pick_random_table_item(rng, &mut equipped, "villager_equipment", "1", None);
|
pick_random_table_item(rng, &mut equipped, "villager_equipment", "1", None);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/main.rs
22
src/main.rs
|
|
@ -55,7 +55,7 @@ pub enum RunState {
|
||||||
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
||||||
ActionWithDirection { function: fn(i: i32, j: i32, ecs: &mut World) -> RunState },
|
ActionWithDirection { function: fn(i: i32, j: i32, ecs: &mut World) -> RunState },
|
||||||
MainMenu { menu_selection: gui::MainMenuSelection },
|
MainMenu { menu_selection: gui::MainMenuSelection },
|
||||||
CharacterCreation { race: gui::Races, class: gui::Classes },
|
CharacterCreation { ancestry: gui::Ancestry, class: gui::Class },
|
||||||
SaveGame,
|
SaveGame,
|
||||||
GameOver,
|
GameOver,
|
||||||
NextLevel,
|
NextLevel,
|
||||||
|
|
@ -383,8 +383,10 @@ impl GameState for State {
|
||||||
}
|
}
|
||||||
gui::MainMenuResult::Selected { selected } => match selected {
|
gui::MainMenuResult::Selected { selected } => match selected {
|
||||||
gui::MainMenuSelection::NewGame => {
|
gui::MainMenuSelection::NewGame => {
|
||||||
new_runstate =
|
new_runstate = RunState::CharacterCreation {
|
||||||
RunState::CharacterCreation { race: gui::Races::Human, class: gui::Classes::Fighter }
|
ancestry: gui::Ancestry::Human,
|
||||||
|
class: gui::Class::Fighter,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gui::MainMenuSelection::LoadGame => {
|
gui::MainMenuSelection::LoadGame => {
|
||||||
saveload_system::load_game(&mut self.ecs);
|
saveload_system::load_game(&mut self.ecs);
|
||||||
|
|
@ -400,14 +402,14 @@ impl GameState for State {
|
||||||
RunState::CharacterCreation { .. } => {
|
RunState::CharacterCreation { .. } => {
|
||||||
let result = gui::character_creation(self, ctx);
|
let result = gui::character_creation(self, ctx);
|
||||||
match result {
|
match result {
|
||||||
gui::CharCreateResult::NoSelection { race, class } => {
|
gui::CharCreateResult::NoSelection { ancestry, class } => {
|
||||||
new_runstate = RunState::CharacterCreation { race, class }
|
new_runstate = RunState::CharacterCreation { ancestry, class }
|
||||||
}
|
}
|
||||||
gui::CharCreateResult::Selected { race, class } => {
|
gui::CharCreateResult::Selected { ancestry, class } => {
|
||||||
if race == gui::Races::NULL {
|
if ancestry == gui::Ancestry::NULL {
|
||||||
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame };
|
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame };
|
||||||
} else {
|
} else {
|
||||||
gui::setup_player_race(&mut self.ecs, race);
|
gui::setup_player_ancestry(&mut self.ecs, ancestry);
|
||||||
gui::setup_player_class(&mut self.ecs, class);
|
gui::setup_player_class(&mut self.ecs, class);
|
||||||
new_runstate = RunState::PreRun;
|
new_runstate = RunState::PreRun;
|
||||||
}
|
}
|
||||||
|
|
@ -550,6 +552,8 @@ fn main() -> rltk::BError {
|
||||||
gs.ecs.register::<Burden>();
|
gs.ecs.register::<Burden>();
|
||||||
gs.ecs.register::<Prop>();
|
gs.ecs.register::<Prop>();
|
||||||
gs.ecs.register::<Player>();
|
gs.ecs.register::<Player>();
|
||||||
|
gs.ecs.register::<HasAncestry>();
|
||||||
|
gs.ecs.register::<HasClass>();
|
||||||
gs.ecs.register::<Chasing>();
|
gs.ecs.register::<Chasing>();
|
||||||
gs.ecs.register::<Faction>();
|
gs.ecs.register::<Faction>();
|
||||||
gs.ecs.register::<Clock>();
|
gs.ecs.register::<Clock>();
|
||||||
|
|
@ -618,7 +622,7 @@ fn main() -> rltk::BError {
|
||||||
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
||||||
gs.ecs.insert(Map::new(1, 64, 64, 0, "New Map")); // Map
|
gs.ecs.insert(Map::new(1, 64, 64, 0, "New Map")); // Map
|
||||||
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
||||||
gs.ecs.insert(gui::Races::Dwarf); // Race
|
gs.ecs.insert(gui::Ancestry::Dwarf); // ancestry
|
||||||
let player_entity = spawner::player(&mut gs.ecs, 0, 0);
|
let player_entity = spawner::player(&mut gs.ecs, 0, 0);
|
||||||
gs.ecs.insert(player_entity); // Player entity
|
gs.ecs.insert(player_entity); // Player entity
|
||||||
gs.ecs.insert(RunState::MapGeneration {}); // RunState
|
gs.ecs.insert(RunState::MapGeneration {}); // RunState
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ mod spawn_table_structs;
|
||||||
use spawn_table_structs::*;
|
use spawn_table_structs::*;
|
||||||
mod loot_table_structs;
|
mod loot_table_structs;
|
||||||
use loot_table_structs::*;
|
use loot_table_structs::*;
|
||||||
mod faction_structs;
|
mod reaction_structs;
|
||||||
use faction_structs::FactionData;
|
pub use reaction_structs::Reaction;
|
||||||
pub use faction_structs::Reaction;
|
use reaction_structs::{AncestryData, FactionData};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
@ -28,6 +28,7 @@ pub struct Raws {
|
||||||
pub spawn_tables: Vec<SpawnTable>,
|
pub spawn_tables: Vec<SpawnTable>,
|
||||||
pub loot_tables: Vec<LootTable>,
|
pub loot_tables: Vec<LootTable>,
|
||||||
pub factions: Vec<FactionData>,
|
pub factions: Vec<FactionData>,
|
||||||
|
pub ancestries: Vec<AncestryData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
|
|
@ -36,6 +37,7 @@ rltk::embedded_resource!(RAW_PROPS, "../../raws/props.json");
|
||||||
rltk::embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
rltk::embedded_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
||||||
rltk::embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
rltk::embedded_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
||||||
rltk::embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
rltk::embedded_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
||||||
|
rltk::embedded_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
||||||
|
|
||||||
pub fn load_raws() {
|
pub fn load_raws() {
|
||||||
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
|
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
|
|
@ -44,6 +46,7 @@ pub fn load_raws() {
|
||||||
rltk::link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
rltk::link_resource!(RAW_SPAWN_TABLES, "../../raws/spawn_tables.json");
|
||||||
rltk::link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
rltk::link_resource!(RAW_LOOT_TABLES, "../../raws/loot_tables.json");
|
||||||
rltk::link_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
rltk::link_resource!(RAW_FACTIONS, "../../raws/factions.json");
|
||||||
|
rltk::link_resource!(RAW_ANCESTRIES, "../../raws/ancestries.json");
|
||||||
|
|
||||||
let decoded_raws = get_decoded_raws();
|
let decoded_raws = get_decoded_raws();
|
||||||
RAWS.lock().unwrap().load(decoded_raws);
|
RAWS.lock().unwrap().load(decoded_raws);
|
||||||
|
|
@ -56,8 +59,9 @@ pub fn get_decoded_raws() -> Raws {
|
||||||
let spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector("../../raws/spawn_tables.json".to_string());
|
let spawn_tables: Vec<SpawnTable> = ParseJson::parse_raws_into_vector("../../raws/spawn_tables.json".to_string());
|
||||||
let loot_tables: Vec<LootTable> = ParseJson::parse_raws_into_vector("../../raws/loot_tables.json".to_string());
|
let loot_tables: Vec<LootTable> = ParseJson::parse_raws_into_vector("../../raws/loot_tables.json".to_string());
|
||||||
let factions: Vec<FactionData> = ParseJson::parse_raws_into_vector("../../raws/factions.json".to_string());
|
let factions: Vec<FactionData> = ParseJson::parse_raws_into_vector("../../raws/factions.json".to_string());
|
||||||
|
let ancestries: Vec<AncestryData> = ParseJson::parse_raws_into_vector("../../raws/ancestries.json".to_string());
|
||||||
|
|
||||||
return Raws { items, mobs, props, spawn_tables, loot_tables, factions };
|
return Raws { items, mobs, props, spawn_tables, loot_tables, factions, ancestries };
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ParseJson {
|
trait ParseJson {
|
||||||
|
|
@ -74,4 +78,4 @@ macro_rules! impl_ParseJson {
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl_ParseJson!(for Vec<Item>, Vec<Mob>, Vec<Prop>, Vec<SpawnTable>, Vec<LootTable>, Vec<FactionData>);
|
impl_ParseJson!(for Vec<Item>, Vec<Mob>, Vec<Prop>, Vec<SpawnTable>, Vec<LootTable>, Vec<FactionData>, Vec<AncestryData>);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use super::{Raws, Reaction};
|
use super::{Raws, Reaction};
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::gamesystem::*;
|
use crate::gamesystem::*;
|
||||||
|
use crate::gui::Ancestry;
|
||||||
use crate::random_table::RandomTable;
|
use crate::random_table::RandomTable;
|
||||||
use crate::LOG_SPAWNING;
|
use crate::LOG_SPAWNING;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
@ -23,6 +24,7 @@ pub struct RawMaster {
|
||||||
table_index: HashMap<String, usize>,
|
table_index: HashMap<String, usize>,
|
||||||
loot_index: HashMap<String, usize>,
|
loot_index: HashMap<String, usize>,
|
||||||
faction_index: HashMap<String, HashMap<String, Reaction>>,
|
faction_index: HashMap<String, HashMap<String, Reaction>>,
|
||||||
|
ancestry_index: HashMap<String, HashSet<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawMaster {
|
impl RawMaster {
|
||||||
|
|
@ -35,6 +37,7 @@ impl RawMaster {
|
||||||
spawn_tables: Vec::new(),
|
spawn_tables: Vec::new(),
|
||||||
loot_tables: Vec::new(),
|
loot_tables: Vec::new(),
|
||||||
factions: Vec::new(),
|
factions: Vec::new(),
|
||||||
|
ancestries: Vec::new(),
|
||||||
},
|
},
|
||||||
item_index: HashMap::new(),
|
item_index: HashMap::new(),
|
||||||
mob_index: HashMap::new(),
|
mob_index: HashMap::new(),
|
||||||
|
|
@ -42,6 +45,7 @@ impl RawMaster {
|
||||||
table_index: HashMap::new(),
|
table_index: HashMap::new(),
|
||||||
loot_index: HashMap::new(),
|
loot_index: HashMap::new(),
|
||||||
faction_index: HashMap::new(),
|
faction_index: HashMap::new(),
|
||||||
|
ancestry_index: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,6 +326,21 @@ pub fn spawn_named_mob(
|
||||||
eb = eb.with(Faction { name: "carnivore".to_string() });
|
eb = eb.with(Faction { name: "carnivore".to_string() });
|
||||||
has_faction = true;
|
has_faction = true;
|
||||||
}
|
}
|
||||||
|
"IS_GNOME" => {
|
||||||
|
eb = eb.with(HasAncestry { name: Ancestry::Gnome });
|
||||||
|
}
|
||||||
|
"IS_DWARF" => {
|
||||||
|
eb = eb.with(HasAncestry { name: Ancestry::Dwarf });
|
||||||
|
}
|
||||||
|
"IS_HUMAN" => {
|
||||||
|
eb = eb.with(HasAncestry { name: Ancestry::Human });
|
||||||
|
}
|
||||||
|
"IS_CATFOLK" => {
|
||||||
|
eb = eb.with(HasAncestry { name: Ancestry::Catfolk });
|
||||||
|
}
|
||||||
|
"IS_Elf" => {
|
||||||
|
eb = eb.with(HasAncestry { name: Ancestry::Elf });
|
||||||
|
}
|
||||||
"SMALL_GROUP" => {} // These flags are for region spawning,
|
"SMALL_GROUP" => {} // These flags are for region spawning,
|
||||||
"LARGE_GROUP" => {} // and don't matter here (yet)?
|
"LARGE_GROUP" => {} // and don't matter here (yet)?
|
||||||
"MULTIATTACK" => {
|
"MULTIATTACK" => {
|
||||||
|
|
@ -825,3 +844,31 @@ pub fn faction_reaction(this_faction: &str, other_faction: &str, raws: &RawMaste
|
||||||
}
|
}
|
||||||
return Reaction::Ignore;
|
return Reaction::Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ancestry_reaction(this_ancestry: Ancestry, other_ancestry: Ancestry, raws: &RawMaster) -> Option<Reaction> {
|
||||||
|
if this_ancestry == other_ancestry {
|
||||||
|
return Some(Reaction::Ignore);
|
||||||
|
} else {
|
||||||
|
let this_ancestry = get_ancestry_string(this_ancestry);
|
||||||
|
let other_ancestry = get_ancestry_string(other_ancestry);
|
||||||
|
if raws.ancestry_index.contains_key(this_ancestry) {
|
||||||
|
let mine = &raws.ancestry_index[this_ancestry];
|
||||||
|
if mine.contains(other_ancestry) {
|
||||||
|
return Some(Reaction::Ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ancestry_string(ancestry: Ancestry) -> &'static str {
|
||||||
|
match ancestry {
|
||||||
|
Ancestry::Human => return "human",
|
||||||
|
Ancestry::Elf => return "elf",
|
||||||
|
Ancestry::Dwarf => return "dwarf",
|
||||||
|
Ancestry::Catfolk => return "catfolk",
|
||||||
|
Ancestry::Gnome => return "gnome",
|
||||||
|
Ancestry::NULL => return "NULL",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct FactionData {
|
pub struct FactionData {
|
||||||
|
|
@ -7,6 +7,12 @@ pub struct FactionData {
|
||||||
pub responses: HashMap<String, String>,
|
pub responses: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct AncestryData {
|
||||||
|
pub id: String,
|
||||||
|
pub allies: HashSet<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
pub enum Reaction {
|
pub enum Reaction {
|
||||||
Ignore,
|
Ignore,
|
||||||
|
|
@ -72,6 +72,8 @@ pub fn save_game(ecs: &mut World) {
|
||||||
Equipped,
|
Equipped,
|
||||||
Faction,
|
Faction,
|
||||||
GrantsXP,
|
GrantsXP,
|
||||||
|
HasAncestry,
|
||||||
|
HasClass,
|
||||||
Hidden,
|
Hidden,
|
||||||
HungerClock,
|
HungerClock,
|
||||||
IdentifiedItem,
|
IdentifiedItem,
|
||||||
|
|
@ -189,6 +191,8 @@ pub fn load_game(ecs: &mut World) {
|
||||||
Equipped,
|
Equipped,
|
||||||
Faction,
|
Faction,
|
||||||
GrantsXP,
|
GrantsXP,
|
||||||
|
HasAncestry,
|
||||||
|
HasClass,
|
||||||
Hidden,
|
Hidden,
|
||||||
HungerClock,
|
HungerClock,
|
||||||
IdentifiedItem,
|
IdentifiedItem,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue