summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-04-10 00:16:39 +0200
committertroido <troido@protonmail.com>2020-04-10 00:16:39 +0200
commitafd1317197d1346626c58736defbbdf8aee7da68 (patch)
tree56781223a2664f292ee6f470d992b47c6b1b8609 /src
parente7b4ed0f044c3ada82155f81d3b61c0c5ce36583 (diff)
send out notifications when fighting
Diffstat (limited to 'src')
-rw-r--r--src/components/ear.rs87
-rw-r--r--src/components/mod.rs2
-rw-r--r--src/systems/attacking.rs40
-rw-r--r--src/systems/interact.rs32
-rw-r--r--src/worldmessages.rs2
5 files changed, 135 insertions, 28 deletions
diff --git a/src/components/ear.rs b/src/components/ear.rs
index 4bfc87b..1432164 100644
--- a/src/components/ear.rs
+++ b/src/components/ear.rs
@@ -2,23 +2,96 @@
use specs::{
HashMapStorage,
Component,
+ Entity,
+ WriteStorage
};
#[derive(Debug, Clone)]
-pub struct Sound {
- pub source: Option<String>,
- pub text: String
+pub enum HealthNotification {
+ Attack,
+ Damage,
+ Heal
}
-impl Sound {
- pub fn as_message(self) -> (Option<String>, String) {
- (None, format!("{}: {}", self.source.unwrap_or("".to_string()), self.text))
+use HealthNotification::*;
+
+#[derive(Debug, Clone)]
+pub enum Notification {
+ Sound{
+ source: Option<String>,
+ text: String
+ },
+ Health {
+ actor: String,
+ target: String,
+ amount: i64,
+ typ: HealthNotification
+ },
+ Kill {
+ actor: String,
+ target: String
+ },
+ Die {
+ actor: String,
+ target: String
+ }
+}
+
+use Notification::*;
+
+
+impl Notification {
+
+
+ pub fn type_name(&self) -> String {
+ (match self {
+ Sound{source: _, text: _} => "sound",
+ Health{actor: _, target: _, amount: _, typ} => match typ {
+ Attack => "attack",
+ Damage => "damage",
+ Heal => "heal"
+ },
+ Kill{actor: _, target: _} => "kill",
+ Die{actor: _, target: _} => "die"
+ }).to_string()
+ }
+
+ pub fn as_message(&self) -> (String, String) {
+ let body = match self {
+ Sound{source, text} => {
+ if let Some(name) = &source {
+ format!("{}: {}", name, &text)
+ } else {
+ text.clone()
+ }
+ }
+ Health{actor, target, amount, typ} => {
+ match typ {
+ Attack | Damage => format!("{} attacks {} for {} damage", actor, target, amount),
+ Heal => format!("{} heals {} for {} health", actor, target, amount)
+ }
+ },
+ Kill{actor, target} => {
+ format!("{} kills {}", actor, target)
+ },
+ Die{actor, target} => {
+ format!("{} was killed by {}", target, actor)
+ }
+ };
+ (self.type_name(), body)
}
}
#[derive(Component, Debug, Clone, Default)]
#[storage(HashMapStorage)]
pub struct Ear{
- pub sounds: Vec<Sound>
+ pub sounds: Vec<Notification>
+}
+
+pub fn say(ears: &mut WriteStorage<Ear>, ent: Entity, msg: Notification){
+ if let Some(ear) = ears.get_mut(ent) {
+ ear.sounds.push(msg);
+ }
}
+
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 4065cc2..cb28c4b 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -23,7 +23,7 @@ pub use flags::{
Flags
};
pub use ear::{
- Sound,
+ Notification,
Ear
};
diff --git a/src/systems/attacking.rs b/src/systems/attacking.rs
index e4001c9..804fac1 100644
--- a/src/systems/attacking.rs
+++ b/src/systems/attacking.rs
@@ -11,7 +11,17 @@ use specs::{
};
use crate::{
- components::{Health, AttackInbox, AttackType, Dead, Position, Autofight},
+ components::{
+ Health,
+ AttackInbox,
+ AttackType,
+ Dead,
+ Position,
+ Autofight,
+ Ear,
+ ear::{Notification, HealthNotification::{Attack, Damage, Heal}, say},
+ Visible
+ },
resources::NewEntities,
Template,
util
@@ -27,9 +37,11 @@ impl <'a> System<'a> for Attacking {
WriteStorage<'a, Dead>,
ReadStorage<'a, Position>,
Write<'a, NewEntities>,
- WriteStorage<'a, Autofight>
+ WriteStorage<'a, Autofight>,
+ WriteStorage<'a, Ear>,
+ ReadStorage<'a, Visible>
);
- fn run(&mut self, (entities, mut attackeds, mut healths, mut deads, positions, mut new, mut autofighters): Self::SystemData) {
+ fn run(&mut self, (entities, mut attackeds, mut healths, mut deads, positions, mut new, mut autofighters, mut ears, visibles): Self::SystemData) {
for (entity, attacked, autofighter) in (&entities, &attackeds, &mut autofighters).join() {
for attack in &attacked.messages {
@@ -42,27 +54,43 @@ impl <'a> System<'a> for Attacking {
}
}
}
- for (ent, health, attacked) in (&entities, &mut healths, &mut attackeds).join() {
+ for (target, health, attacked) in (&entities, &mut healths, &mut attackeds).join() {
+ let target_name = visibles.get(target).map(|v| v.name.as_str()).unwrap_or("?").to_string();
let mut wounded = false;
+ let mut attackers = Vec::new();
+ let mut attacker_names = Vec::new();
for attack in attacked.messages.drain(..) {
+ let actor_name = attack.attacker.map(|ae| visibles.get(ae)).flatten().map(|v| v.name.as_str()).unwrap_or("?").to_string();
match attack.typ {
AttackType::Attack(strength) => {
let damage = rand::thread_rng().gen_range(0, strength+1);
health.health -= damage;
if damage > 0 {
wounded = true;
+ if let Some(actor) = attack.attacker {
+ say(&mut ears, actor, Notification::Health{actor: actor_name.clone(), target: target_name.clone(), amount: damage, typ: Attack});
+ attackers.push(actor);
+ attacker_names.push(actor_name.clone());
+ }
+ say(&mut ears, target, Notification::Health{actor: actor_name.clone(), target: target_name.clone(), amount: damage, typ: Damage});
}
}
AttackType::Heal(healthdiff) => {
+ say(&mut ears, target, Notification::Health{actor: actor_name.clone(), target: target_name.clone(), amount: healthdiff, typ: Heal});
health.health += healthdiff;
}
}
}
health.health = util::clamp(health.health, 0, health.maxhealth);
if health.health == 0 {
- deads.insert(ent, Dead).unwrap();
+ deads.insert(target, Dead).unwrap();
+ let killers = attacker_names.join(" and ");
+ say(&mut ears, target, Notification::Die{actor: killers.clone(), target: target_name.clone()});
+ for actor in attackers {
+ say(&mut ears, actor, Notification::Kill{actor: killers.clone(), target: target_name.clone()});
+ }
}
- if let Some(position) = positions.get(ent){
+ if let Some(position) = positions.get(target){
if wounded {
new.create(position.pos, &Template::empty("wound")).unwrap();
}
diff --git a/src/systems/interact.rs b/src/systems/interact.rs
index fb11488..73f9023 100644
--- a/src/systems/interact.rs
+++ b/src/systems/interact.rs
@@ -17,9 +17,10 @@ use crate::{
ControlCooldown,
Interactable,
Dead,
- Sound,
+ Notification,
Ear,
- Inventory
+ Inventory,
+ Visible
},
controls::{Control},
resources::{Ground, NewEntities}
@@ -37,10 +38,11 @@ impl <'a> System<'a> for Interact {
WriteStorage<'a, Dead>,
Write<'a, NewEntities>,
WriteStorage<'a, Ear>,
- WriteStorage<'a, Inventory>
+ WriteStorage<'a, Inventory>,
+ ReadStorage<'a, Visible>
);
- fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut deads, new, mut ears, mut inventories): Self::SystemData) {
+ fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut deads, new, mut ears, mut inventories, visibles): Self::SystemData) {
for (entity, controller, position) in (&entities, &controllers, &positions).join(){
let mut target = None;
let ear = ears.get_mut(entity);
@@ -61,15 +63,16 @@ impl <'a> System<'a> for Interact {
_ => {}
}
if let Some((ent, interactable, arg)) = target {
+ let name = visibles.get(ent).map(|v| v.name.as_str());
match interactable {
Interactable::Harvest => {
deads.insert(ent, Dead).unwrap();
}
Interactable::Say(text) => {
- say(ear, text.clone());
+ say(ear, text.clone(), name);
}
Interactable::Reply(text) => {
- say(ear, text.replace("{}", &arg.unwrap()));
+ say(ear, text.replace("{}", &arg.unwrap()), name);
}
Interactable::Exchange(prefix, exchanges) => {
if let Some(txt) = arg {
@@ -79,19 +82,22 @@ impl <'a> System<'a> for Interact {
if let Some(exchange) = exchanges.get(action) {
if exchange.can_trade(inventory){
exchange.trade(inventory, &new.encyclopedia);
- say(ear, format!("Success! '{}' ({})", txt, exchange.show()));
+ say(ear, format!("Success! '{}' ({})", txt, exchange.show()), name);
} else {
- say(ear, format!("You do not have the required items or inventory space for '{}' ({})", txt, exchange.show()));
+ say(ear, format!("You do not have the required items or inventory space for '{}' ({})", txt, exchange.show()), name);
}
} else {
- say(ear, format!("Invalid option: {}", action));
+ say(ear, format!("Invalid option: {}", action), name);
}
}
}
} else {
- say(ear, format!("options: {:?}", exchanges.iter().map(|(id, exchange)|
+ say(
+ ear,
+ format!("options: {:?}", exchanges.iter().map(|(id, exchange)|
format!("{}{}: {}", prefix, id, exchange.show())
- ).collect::<Vec<String>>())
+ ).collect::<Vec<String>>()),
+ name
);
}
}
@@ -102,8 +108,8 @@ impl <'a> System<'a> for Interact {
}
}
-fn say(maybe_ear: Option<&mut Ear>, text: String){
+fn say(maybe_ear: Option<&mut Ear>, text: String, source: Option<&str>){
if let Some(ear) = maybe_ear {
- ear.sounds.push(Sound{source: None, text});
+ ear.sounds.push(Notification::Sound{text, source: source.map(|s| s.to_string())});
}
}
diff --git a/src/worldmessages.rs b/src/worldmessages.rs
index 676ef00..7dd05ec 100644
--- a/src/worldmessages.rs
+++ b/src/worldmessages.rs
@@ -68,7 +68,7 @@ pub type ChangeMessage = Vec<(Pos, Vec<Sprite>)>;
pub type HealthMessage = (i64, i64);
pub type InventoryMessage = Vec<(String, bool)>;
pub type GroundMessage = Vec<String>;
-pub type SoundMessage = Vec<(Option<String>, String)>;
+pub type SoundMessage = Vec<(String, String)>;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub struct FieldMessage {