summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/faction.rs45
-rw-r--r--src/components/mod.rs2
-rw-r--r--src/componentwrapper.rs1
-rw-r--r--src/defaultencyclopedia.rs3
-rw-r--r--src/playerstate.rs6
-rw-r--r--src/room.rs2
-rw-r--r--src/systems/controlai.rs9
-rw-r--r--src/systems/fight.rs10
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;
}