faction table, applying factions to mobs, and querying reactions
This commit is contained in:
parent
0375c31acf
commit
76d835021b
11 changed files with 108 additions and 13 deletions
26
raws/factions.json
Normal file
26
raws/factions.json
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "player",
|
||||||
|
"responses": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mindless",
|
||||||
|
"responses": { "default": "attack" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "neutral",
|
||||||
|
"responses": { "default": "ignore" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hostile",
|
||||||
|
"responses": { "default": "attack", "hostile": "ignore" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "herbivore",
|
||||||
|
"responses": { "default": "flee", "herbivores": "ignore" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "carnivore",
|
||||||
|
"responses": { "default": "attack", "carnivores": "ignore" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Bystander, EntityMoved, Map, Position, TakingTurn, Viewshed};
|
use crate::{Bystander, EntityMoved, Map, Position, TakingTurn, Viewshed};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct BystanderAI {}
|
pub struct BystanderAI {}
|
||||||
|
|
@ -8,3 +8,7 @@ mod regen_system;
|
||||||
pub use regen_system::RegenSystem;
|
pub use regen_system::RegenSystem;
|
||||||
mod encumbrance_system;
|
mod encumbrance_system;
|
||||||
pub use encumbrance_system::{EncumbranceSystem, CARRY_CAPACITY_PER_STRENGTH};
|
pub use encumbrance_system::{EncumbranceSystem, CARRY_CAPACITY_PER_STRENGTH};
|
||||||
|
mod bystander_ai_system;
|
||||||
|
pub use bystander_ai_system::BystanderAI;
|
||||||
|
mod monster_ai_system;
|
||||||
|
pub use monster_ai_system::MonsterAI;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{bystander_ai_system, EntityMoved, Map, Monster, Position, TakingTurn, Viewshed, WantsToMelee};
|
use super::bystander_ai_system::try_move_randomly;
|
||||||
|
use crate::{EntityMoved, Map, Monster, Position, TakingTurn, Viewshed, WantsToMelee};
|
||||||
use rltk::Point;
|
use rltk::Point;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
|
@ -60,7 +61,7 @@ impl<'a> System<'a> for MonsterAI {
|
||||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
|
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if bystander_ai_system::try_move_randomly(&mut pos, &mut rng, &mut map, &mut viewshed) {
|
if try_move_randomly(&mut pos, &mut rng, &mut map, &mut viewshed) {
|
||||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
|
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,6 +46,11 @@ pub struct Renderable {
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Player {}
|
pub struct Player {}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct Faction {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Prop {}
|
pub struct Prop {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,6 @@ mod saveload_system;
|
||||||
mod spawner;
|
mod spawner;
|
||||||
mod visibility_system;
|
mod visibility_system;
|
||||||
use visibility_system::VisibilitySystem;
|
use visibility_system::VisibilitySystem;
|
||||||
mod monster_ai_system;
|
|
||||||
use monster_ai_system::MonsterAI;
|
|
||||||
pub mod bystander_ai_system;
|
|
||||||
mod map_indexing_system;
|
mod map_indexing_system;
|
||||||
use map_indexing_system::MapIndexingSystem;
|
use map_indexing_system::MapIndexingSystem;
|
||||||
mod damage_system;
|
mod damage_system;
|
||||||
|
|
@ -99,8 +96,8 @@ impl State {
|
||||||
let mut encumbrance_system = ai::EncumbranceSystem {};
|
let mut encumbrance_system = ai::EncumbranceSystem {};
|
||||||
let mut turn_status_system = ai::TurnStatusSystem {};
|
let mut turn_status_system = ai::TurnStatusSystem {};
|
||||||
let mut quip_system = ai::QuipSystem {};
|
let mut quip_system = ai::QuipSystem {};
|
||||||
let mut mob = MonsterAI {};
|
let mut mob = ai::MonsterAI {};
|
||||||
let mut bystanders = bystander_ai_system::BystanderAI {};
|
let mut bystanders = ai::BystanderAI {};
|
||||||
let mut trigger_system = trigger_system::TriggerSystem {};
|
let mut trigger_system = trigger_system::TriggerSystem {};
|
||||||
let mut melee_system = MeleeCombatSystem {};
|
let mut melee_system = MeleeCombatSystem {};
|
||||||
let mut damage_system = DamageSystem {};
|
let mut damage_system = DamageSystem {};
|
||||||
|
|
@ -520,6 +517,7 @@ 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::<Faction>();
|
||||||
gs.ecs.register::<Clock>();
|
gs.ecs.register::<Clock>();
|
||||||
gs.ecs.register::<Monster>();
|
gs.ecs.register::<Monster>();
|
||||||
gs.ecs.register::<Bystander>();
|
gs.ecs.register::<Bystander>();
|
||||||
|
|
|
||||||
15
src/raws/faction_structs.rs
Normal file
15
src/raws/faction_structs.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct FactionData {
|
||||||
|
pub id: String,
|
||||||
|
pub responses: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
|
pub enum Reaction {
|
||||||
|
Ignore,
|
||||||
|
Attack,
|
||||||
|
Flee,
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,8 @@ 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;
|
||||||
|
use faction_structs::{FactionData, Reaction};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
@ -24,6 +26,7 @@ pub struct Raws {
|
||||||
pub props: Vec<Prop>,
|
pub props: Vec<Prop>,
|
||||||
pub spawn_tables: Vec<SpawnTable>,
|
pub spawn_tables: Vec<SpawnTable>,
|
||||||
pub loot_tables: Vec<LootTable>,
|
pub loot_tables: Vec<LootTable>,
|
||||||
|
pub factions: Vec<FactionData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
rltk::embedded_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
|
|
@ -31,6 +34,7 @@ rltk::embedded_resource!(RAW_MOBS, "../../raws/mobs.json");
|
||||||
rltk::embedded_resource!(RAW_PROPS, "../../raws/props.json");
|
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");
|
||||||
|
|
||||||
pub fn load_raws() {
|
pub fn load_raws() {
|
||||||
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
|
rltk::link_resource!(RAW_ITEMS, "../../raws/items.json");
|
||||||
|
|
@ -38,6 +42,7 @@ pub fn load_raws() {
|
||||||
rltk::link_resource!(RAW_PROPS, "../../raws/props.json");
|
rltk::link_resource!(RAW_PROPS, "../../raws/props.json");
|
||||||
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");
|
||||||
|
|
||||||
let decoded_raws = get_decoded_raws();
|
let decoded_raws = get_decoded_raws();
|
||||||
RAWS.lock().unwrap().load(decoded_raws);
|
RAWS.lock().unwrap().load(decoded_raws);
|
||||||
|
|
@ -49,8 +54,9 @@ pub fn get_decoded_raws() -> Raws {
|
||||||
let props: Vec<Prop> = ParseJson::parse_raws_into_vector("../../raws/props.json".to_string());
|
let props: Vec<Prop> = ParseJson::parse_raws_into_vector("../../raws/props.json".to_string());
|
||||||
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());
|
||||||
|
|
||||||
return Raws { items, mobs, props, spawn_tables, loot_tables };
|
return Raws { items, mobs, props, spawn_tables, loot_tables, factions };
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ParseJson {
|
trait ParseJson {
|
||||||
|
|
@ -67,4 +73,4 @@ macro_rules! impl_ParseJson {
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl_ParseJson!(for Vec<Item>, Vec<Mob>, Vec<Prop>, Vec<SpawnTable>, Vec<LootTable>);
|
impl_ParseJson!(for Vec<Item>, Vec<Mob>, Vec<Prop>, Vec<SpawnTable>, Vec<LootTable>, Vec<FactionData>);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::Raws;
|
use super::{Raws, Reaction};
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::gamesystem::*;
|
use crate::gamesystem::*;
|
||||||
use crate::random_table::RandomTable;
|
use crate::random_table::RandomTable;
|
||||||
|
|
@ -22,6 +22,7 @@ pub struct RawMaster {
|
||||||
prop_index: HashMap<String, usize>,
|
prop_index: HashMap<String, usize>,
|
||||||
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>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawMaster {
|
impl RawMaster {
|
||||||
|
|
@ -33,12 +34,14 @@ impl RawMaster {
|
||||||
props: Vec::new(),
|
props: Vec::new(),
|
||||||
spawn_tables: Vec::new(),
|
spawn_tables: Vec::new(),
|
||||||
loot_tables: Vec::new(),
|
loot_tables: Vec::new(),
|
||||||
|
factions: Vec::new(),
|
||||||
},
|
},
|
||||||
item_index: HashMap::new(),
|
item_index: HashMap::new(),
|
||||||
mob_index: HashMap::new(),
|
mob_index: HashMap::new(),
|
||||||
prop_index: HashMap::new(),
|
prop_index: HashMap::new(),
|
||||||
table_index: HashMap::new(),
|
table_index: HashMap::new(),
|
||||||
loot_index: HashMap::new(),
|
loot_index: HashMap::new(),
|
||||||
|
faction_index: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,6 +78,20 @@ impl RawMaster {
|
||||||
check_for_unspecified_entity(&used_names, &entry.id)
|
check_for_unspecified_entity(&used_names, &entry.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for faction in self.raws.factions.iter() {
|
||||||
|
let mut reactions: HashMap<String, Reaction> = HashMap::new();
|
||||||
|
for other in faction.responses.iter() {
|
||||||
|
reactions.insert(
|
||||||
|
other.0.clone(),
|
||||||
|
match other.1.as_str() {
|
||||||
|
"flee" => Reaction::Flee,
|
||||||
|
"attack" => Reaction::Attack,
|
||||||
|
_ => Reaction::Ignore,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.faction_index.insert(faction.id.clone(), reactions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,7 +296,14 @@ pub fn spawn_named_mob(
|
||||||
"BLOCKS_TILE" => eb = eb.with(BlocksTile {}),
|
"BLOCKS_TILE" => eb = eb.with(BlocksTile {}),
|
||||||
"BYSTANDER" => eb = eb.with(Bystander {}),
|
"BYSTANDER" => eb = eb.with(Bystander {}),
|
||||||
"MONSTER" => eb = eb.with(Monster {}),
|
"MONSTER" => eb = eb.with(Monster {}),
|
||||||
"MINDLESS" => has_mind = false,
|
"MINDLESS" => {
|
||||||
|
eb = eb.with(Faction { name: "mindless".to_string() });
|
||||||
|
has_mind = false;
|
||||||
|
}
|
||||||
|
"NEUTRAL" => eb = eb.with(Faction { name: "neutral".to_string() }),
|
||||||
|
"HOSTILE" => eb = eb.with(Faction { name: "hostile".to_string() }),
|
||||||
|
"HERBIVORE" => eb = eb.with(Faction { name: "herbivore".to_string() }),
|
||||||
|
"CARNIVORE" => eb = eb.with(Faction { name: "carnivore".to_string() }),
|
||||||
"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" => {
|
||||||
|
|
@ -738,3 +762,16 @@ pub fn is_tag_magic(tag: &str) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Queries the faction index to obtain one faction's reaction to another faction.
|
||||||
|
pub fn faction_reaction(this_faction: &str, other_faction: &str, raws: &RawMaster) -> Reaction {
|
||||||
|
if raws.faction_index.contains_key(this_faction) {
|
||||||
|
let mine = &raws.faction_index[this_faction];
|
||||||
|
if mine.contains_key(other_faction) {
|
||||||
|
return mine[other_faction];
|
||||||
|
} else if mine.contains_key("default") {
|
||||||
|
return mine["default"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Reaction::Ignore;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ pub fn save_game(ecs: &mut World) {
|
||||||
EquipmentChanged,
|
EquipmentChanged,
|
||||||
Equippable,
|
Equippable,
|
||||||
Equipped,
|
Equipped,
|
||||||
|
Faction,
|
||||||
GrantsXP,
|
GrantsXP,
|
||||||
Hidden,
|
Hidden,
|
||||||
HungerClock,
|
HungerClock,
|
||||||
|
|
@ -185,6 +186,7 @@ pub fn load_game(ecs: &mut World) {
|
||||||
EquipmentChanged,
|
EquipmentChanged,
|
||||||
Equippable,
|
Equippable,
|
||||||
Equipped,
|
Equipped,
|
||||||
|
Faction,
|
||||||
GrantsXP,
|
GrantsXP,
|
||||||
Hidden,
|
Hidden,
|
||||||
HungerClock,
|
HungerClock,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{
|
use super::{
|
||||||
ai::NORMAL_SPEED, gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes,
|
ai::NORMAL_SPEED, gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes,
|
||||||
Clock, Energy, EquipmentChanged, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect,
|
Clock, Energy, EquipmentChanged, Faction, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect,
|
||||||
Renderable, SerializeMe, Skill, Skills, TileType, Viewshed,
|
Renderable, SerializeMe, Skill, Skills, TileType, Viewshed,
|
||||||
};
|
};
|
||||||
use rltk::{RandomNumberGenerator, RGB};
|
use rltk::{RandomNumberGenerator, RGB};
|
||||||
|
|
@ -36,6 +36,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
render_order: 0,
|
render_order: 0,
|
||||||
})
|
})
|
||||||
.with(Player {})
|
.with(Player {})
|
||||||
|
.with(Faction { name: "player".to_string() })
|
||||||
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
||||||
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
||||||
.with(HungerClock { state: HungerState::Satiated, duration: 200 })
|
.with(HungerClock { state: HungerState::Satiated, duration: 200 })
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue