From c630df7f9a705d42cae1ae88a763468b2527a4b5 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Fri, 20 Mar 2020 14:26:18 +0100 Subject: [PATCH] Ranged weapons now give xp on kill and also make enemies angry --- common/src/comp/inventory/item.rs | 4 ++-- common/src/comp/projectile.rs | 20 ++++++++++++++++++++ common/src/comp/stats.rs | 1 + common/src/states/basic_ranged.rs | 2 +- common/src/sys/agent.rs | 5 ++++- server/src/events/entity_manipulation.rs | 8 ++++++-- voxygen/src/ecs/sys/floater.rs | 7 +++---- 7 files changed, 37 insertions(+), 10 deletions(-) diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index 6392756d71..1a3898cf61 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -99,7 +99,7 @@ impl ToolData { projectile::Effect::Damage(HealthChange { // TODO: This should not be fixed (?) amount: -3, - cause: HealthSource::Item, + cause: HealthSource::Projectile { owner: None }, }), projectile::Effect::Vanish, ], @@ -128,7 +128,7 @@ impl ToolData { projectile::Effect::Damage(HealthChange { // TODO: This should not be fixed (?) amount: -8, - cause: HealthSource::Item, + cause: HealthSource::Projectile { owner: None }, }), projectile::Effect::Vanish, ], diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 27e997b08e..4c32bf0ee9 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -22,6 +22,26 @@ pub struct Projectile { pub owner: Option, } +impl Projectile { + pub fn set_owner(&mut self, new_owner: Uid) { + self.owner = Some(new_owner); + for e in self + .hit_ground + .iter_mut() + .chain(self.hit_wall.iter_mut()) + .chain(self.hit_entity.iter_mut()) + { + if let Effect::Damage(comp::HealthChange { + cause: comp::HealthSource::Projectile { owner, .. }, + .. + }) = e + { + *owner = Some(new_owner); + } + } + } +} + impl Component for Projectile { type Storage = FlaggedStorage>; } diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index e5e3e7e642..3e6d957fef 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -15,6 +15,7 @@ pub struct HealthChange { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub enum HealthSource { Attack { by: Uid }, // TODO: Implement weapon + Projectile { owner: Option }, Suicide, World, Revive, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index 40412bb558..e8ce491676 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -49,7 +49,7 @@ impl CharacterBehavior for Data { } else if !self.exhausted { // Fire let mut projectile = self.projectile.clone(); - projectile.owner = Some(*data.uid); + projectile.set_owner(*data.uid); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, dir: data.inputs.look_dir, diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index fd7313af78..866bf00e5c 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -252,7 +252,10 @@ impl<'a> System<'a> for Sys { if let Some(stats) = stats.get(entity) { // Only if the attack was recent if stats.health.last_change.0 < 5.0 { - if let comp::HealthSource::Attack { by } = stats.health.last_change.1.cause { + if let comp::HealthSource::Attack { by } + | comp::HealthSource::Projectile { owner: Some(by) } = + stats.health.last_change.1.cause + { if !agent.activity.is_attack() { if let Some(attacker) = uid_allocator.retrieve_entity_internal(by.id()) { diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 1de8f83dd7..8d9de9215c 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -27,7 +27,9 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc // Chat message if let Some(player) = state.ecs().read_storage::().get(entity) { - let msg = if let HealthSource::Attack { by } = cause { + let msg = if let HealthSource::Attack { by } + | HealthSource::Projectile { owner: Some(by) } = cause + { state.ecs().entity_from_uid(by.into()).and_then(|attacker| { state .ecs() @@ -49,7 +51,9 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc // Give EXP to the killer if entity had stats let mut stats = state.ecs().write_storage::(); if let Some(entity_stats) = stats.get(entity).cloned() { - if let HealthSource::Attack { by } = cause { + if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } = + cause + { state.ecs().entity_from_uid(by.into()).map(|attacker| { if let Some(attacker_stats) = stats.get_mut(attacker) { // TODO: Discuss whether we should give EXP by Player diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs index f9f05f5540..2c3e54a3dd 100644 --- a/voxygen/src/ecs/sys/floater.rs +++ b/voxygen/src/ecs/sys/floater.rs @@ -70,7 +70,7 @@ impl<'a> System<'a> for Sys { // (maybe health changes could be sent to the client as a list // of events) if match health.last_change.1.cause { - HealthSource::Attack { by } => { + HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } => { let by_me = my_uid.map_or(false, |&uid| by == uid); // If the attack was by me also reset this timer if by_me { @@ -80,11 +80,10 @@ impl<'a> System<'a> for Sys { }, HealthSource::Suicide => my_entity.0 == entity, HealthSource::World => my_entity.0 == entity, - HealthSource::Revive => false, - HealthSource::Command => true, HealthSource::LevelUp => my_entity.0 == entity, + HealthSource::Command => true, HealthSource::Item => true, - HealthSource::Unknown => false, + _ => false, } { hp_floater_list.floaters.push(HpFloater { timer: 0.0,