diff options
| -rw-r--r-- | src/components/faction.rs | 45 | ||||
| -rw-r--r-- | src/components/mod.rs | 2 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 1 | ||||
| -rw-r--r-- | src/defaultencyclopedia.rs | 3 | ||||
| -rw-r--r-- | src/playerstate.rs | 6 | ||||
| -rw-r--r-- | src/room.rs | 2 | ||||
| -rw-r--r-- | src/systems/controlai.rs | 9 | ||||
| -rw-r--r-- | src/systems/fight.rs | 10 |
8 files changed, 66 insertions, 12 deletions
diff --git a/src/components/faction.rs b/src/components/faction.rs new file mode 100644 index 0000000..5fc02a2 --- /dev/null +++ b/src/components/faction.rs @@ -0,0 +1,45 @@ + +use specs::{ + Component, + HashMapStorage, + ReadStorage, + Entity, +}; + +#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[storage(HashMapStorage)] +pub enum Faction { + Neutral, + Good, + Evil, + None +} + +use Faction::{Neutral, Good, Evil, None}; + +impl Faction { + + pub fn from_str(name: &str) -> Option<Faction> { + match name.to_lowercase().as_str() { + "neutral" => Some(Neutral), + "good" => Some(Good), + "evil" => Some(Evil), + "none" => Some(None), + "" => Some(None), + _ => Option::None + } + } + + pub fn is_enemy(&self, other: Faction) -> bool { + match self { + Neutral => false, + Good => other == Evil || other == None, + Evil => other == Good || other == None, + None => other != Neutral + } + } + + pub fn is_enemy_entity(factions: &ReadStorage<Self>, a: Entity, b: Entity) -> bool{ + factions.get(a).unwrap_or(&None).is_enemy(*factions.get(b).unwrap_or(&None)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 202caf2..d2087b0 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,6 +1,7 @@ pub mod item; pub mod messages; +pub mod faction; pub use item::Item; pub use messages::{ @@ -8,6 +9,7 @@ pub use messages::{ AttackInbox, AttackType }; +pub use faction::Faction; use specs::{ DenseVecStorage, diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index c617d77..3acc8e9 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -134,6 +134,7 @@ components!( }; Clan (name: String) Clan{name}; Home (home: Pos) Home{home}; + Faction (faction: String) {Faction::from_str(faction.as_str()).unwrap()}; ); diff --git a/src/defaultencyclopedia.rs b/src/defaultencyclopedia.rs index 5e9222e..191f0a4 100644 --- a/src/defaultencyclopedia.rs +++ b/src/defaultencyclopedia.rs @@ -160,7 +160,8 @@ pub fn default_encyclopedia() -> Encyclopedia { ["Health", {"health": ["int", 8], "maxhealth": ["int", 8]}], ["Fighter", {"damage": ["int", 2], "cooldown": ["int", 6]}], ["Movable", {"cooldown": ["int", 3]}], - "Mortal" + "Mortal", + ["Faction", {"faction": ["string", "evil"]}] ] }, "spawner": { diff --git a/src/playerstate.rs b/src/playerstate.rs index 4ccd6af..c7b5f8c 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -15,7 +15,8 @@ use crate::{ Healing, Movable, AttackType, - Autofight + Autofight, + Faction }, Result, aerr, @@ -134,7 +135,8 @@ impl PlayerState { ComponentWrapper::Fighter(Fighter{attack: AttackType::Attack(5), cooldown: 8, range: 1}), ComponentWrapper::Healing(Healing{delay: 50, health: 1, next_heal: None}), ComponentWrapper::Movable(Movable{cooldown: 2}), - ComponentWrapper::Autofight(Autofight::default()) + ComponentWrapper::Autofight(Autofight::default()), + ComponentWrapper::Faction(Faction::Good) ] } } diff --git a/src/room.rs b/src/room.rs index f3cdbf8..4202251 100644 --- a/src/room.rs +++ b/src/room.rs @@ -115,7 +115,7 @@ impl <'a, 'b>Room<'a, 'b> { world.insert(NewEntities::new(encyclopedia)); register_insert!( world, - (Position, Visible, Controller, Movable, Blocking, Floor, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, Dead, Trap, Fighter, Healing, Volatile, ControlCooldown, Autofight, MonsterAI, Home, Mortal, AttackInbox, Item, Spawner, Clan), + (Position, Visible, Controller, Movable, Blocking, Floor, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, Dead, Trap, Fighter, Healing, Volatile, ControlCooldown, Autofight, MonsterAI, Home, Mortal, AttackInbox, Item, Spawner, Clan, Faction), (Ground, Input, Output, Size, Spawn, Players, Emigration, TimeStamp) ); diff --git a/src/systems/controlai.rs b/src/systems/controlai.rs index debe716..ab72f77 100644 --- a/src/systems/controlai.rs +++ b/src/systems/controlai.rs @@ -11,7 +11,7 @@ use specs::{ }; use crate::{ - components::{Controller, ControlCooldown, Fighter, MonsterAI, Home, Health, Position}, + components::{Controller, ControlCooldown, Fighter, MonsterAI, Home, Health, Position, Faction}, controls::{Control, Direction::{self, North, South, East, West}}, Pos }; @@ -27,9 +27,10 @@ impl <'a> System<'a> for ControlAI { ReadStorage<'a, Fighter>, ReadStorage<'a, Home>, ReadStorage<'a, Health>, - ReadStorage<'a, Position> + ReadStorage<'a, Position>, + ReadStorage<'a, Faction> ); - fn run(&mut self, (entities, mut controllers, cooldowns, ais, fighters, homes, healths, positions): Self::SystemData) { + fn run(&mut self, (entities, mut controllers, cooldowns, ais, fighters, homes, healths, positions, factions): Self::SystemData) { for (entity, ai, position, ()) in (&entities, &ais, &positions, !&cooldowns).join() { if let Some(fighter) = fighters.get(entity) { @@ -37,7 +38,7 @@ impl <'a> System<'a> for ControlAI { let mut closest = None; let mut closest_position = None; for (target, target_position, _) in (&entities, &positions, &healths).join() { - if target == entity { + if target == entity || !Faction::is_enemy_entity(&factions, entity, target) { continue; } let distance = position.pos.distance_to(target_position.pos); diff --git a/src/systems/fight.rs b/src/systems/fight.rs index 00aeb3e..47b5811 100644 --- a/src/systems/fight.rs +++ b/src/systems/fight.rs @@ -17,7 +17,8 @@ use crate::components::{ Fighter, Health, ControlCooldown, - Autofight + Autofight, + Faction }; use crate::controls::{Control}; @@ -36,17 +37,18 @@ impl <'a> System<'a> for Fight { ReadStorage<'a, Fighter>, ReadStorage<'a, Health>, WriteStorage<'a, ControlCooldown>, - WriteStorage<'a, Autofight> + WriteStorage<'a, Autofight>, + ReadStorage<'a, Faction> ); - fn run(&mut self, (entities, controllers, positions, ground, mut attacked, fighters, healths, mut cooldowns, mut autofighters): Self::SystemData) { + fn run(&mut self, (entities, controllers, positions, ground, mut attacked, fighters, healths, mut cooldowns, mut autofighters, factions): Self::SystemData) { for (entity, controller, position, fighter) in (&entities, &controllers, &positions, &fighters).join(){ let mut target = None; match &controller.control { Control::Attack(directions) => { 'targets: for direction in directions { for ent in ground.cells.get(&(position.pos + direction.to_position())).unwrap_or(&HashSet::new()) { - if healths.contains(*ent) && *ent != entity { + if healths.contains(*ent) && *ent != entity && Faction::is_enemy_entity(&factions, entity, *ent) { target = Some(*ent); break 'targets; } |
