Ranged weapons now give xp on kill and also make enemies angry

This commit is contained in:
timokoesters
2020-03-20 14:26:18 +01:00
parent 6836a043af
commit c630df7f9a
7 changed files with 37 additions and 10 deletions

View File

@ -99,7 +99,7 @@ impl ToolData {
projectile::Effect::Damage(HealthChange { projectile::Effect::Damage(HealthChange {
// TODO: This should not be fixed (?) // TODO: This should not be fixed (?)
amount: -3, amount: -3,
cause: HealthSource::Item, cause: HealthSource::Projectile { owner: None },
}), }),
projectile::Effect::Vanish, projectile::Effect::Vanish,
], ],
@ -128,7 +128,7 @@ impl ToolData {
projectile::Effect::Damage(HealthChange { projectile::Effect::Damage(HealthChange {
// TODO: This should not be fixed (?) // TODO: This should not be fixed (?)
amount: -8, amount: -8,
cause: HealthSource::Item, cause: HealthSource::Projectile { owner: None },
}), }),
projectile::Effect::Vanish, projectile::Effect::Vanish,
], ],

View File

@ -22,6 +22,26 @@ pub struct Projectile {
pub owner: Option<Uid>, pub owner: Option<Uid>,
} }
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 { impl Component for Projectile {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>; type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
} }

View File

@ -15,6 +15,7 @@ pub struct HealthChange {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub enum HealthSource { pub enum HealthSource {
Attack { by: Uid }, // TODO: Implement weapon Attack { by: Uid }, // TODO: Implement weapon
Projectile { owner: Option<Uid> },
Suicide, Suicide,
World, World,
Revive, Revive,

View File

@ -49,7 +49,7 @@ impl CharacterBehavior for Data {
} else if !self.exhausted { } else if !self.exhausted {
// Fire // Fire
let mut projectile = self.projectile.clone(); let mut projectile = self.projectile.clone();
projectile.owner = Some(*data.uid); projectile.set_owner(*data.uid);
update.server_events.push_front(ServerEvent::Shoot { update.server_events.push_front(ServerEvent::Shoot {
entity: data.entity, entity: data.entity,
dir: data.inputs.look_dir, dir: data.inputs.look_dir,

View File

@ -252,7 +252,10 @@ impl<'a> System<'a> for Sys {
if let Some(stats) = stats.get(entity) { if let Some(stats) = stats.get(entity) {
// Only if the attack was recent // Only if the attack was recent
if stats.health.last_change.0 < 5.0 { 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 !agent.activity.is_attack() {
if let Some(attacker) = uid_allocator.retrieve_entity_internal(by.id()) if let Some(attacker) = uid_allocator.retrieve_entity_internal(by.id())
{ {

View File

@ -27,7 +27,9 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
// Chat message // Chat message
if let Some(player) = state.ecs().read_storage::<Player>().get(entity) { if let Some(player) = state.ecs().read_storage::<Player>().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().entity_from_uid(by.into()).and_then(|attacker| {
state state
.ecs() .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 // Give EXP to the killer if entity had stats
let mut stats = state.ecs().write_storage::<Stats>(); let mut stats = state.ecs().write_storage::<Stats>();
if let Some(entity_stats) = stats.get(entity).cloned() { 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| { state.ecs().entity_from_uid(by.into()).map(|attacker| {
if let Some(attacker_stats) = stats.get_mut(attacker) { if let Some(attacker_stats) = stats.get_mut(attacker) {
// TODO: Discuss whether we should give EXP by Player // TODO: Discuss whether we should give EXP by Player

View File

@ -70,7 +70,7 @@ impl<'a> System<'a> for Sys {
// (maybe health changes could be sent to the client as a list // (maybe health changes could be sent to the client as a list
// of events) // of events)
if match health.last_change.1.cause { 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); let by_me = my_uid.map_or(false, |&uid| by == uid);
// If the attack was by me also reset this timer // If the attack was by me also reset this timer
if by_me { if by_me {
@ -80,11 +80,10 @@ impl<'a> System<'a> for Sys {
}, },
HealthSource::Suicide => my_entity.0 == entity, HealthSource::Suicide => my_entity.0 == entity,
HealthSource::World => my_entity.0 == entity, HealthSource::World => my_entity.0 == entity,
HealthSource::Revive => false,
HealthSource::Command => true,
HealthSource::LevelUp => my_entity.0 == entity, HealthSource::LevelUp => my_entity.0 == entity,
HealthSource::Command => true,
HealthSource::Item => true, HealthSource::Item => true,
HealthSource::Unknown => false, _ => false,
} { } {
hp_floater_list.floaters.push(HpFloater { hp_floater_list.floaters.push(HpFloater {
timer: 0.0, timer: 0.0,