Shockwaves now use attacks.

This commit is contained in:
Sam 2021-01-30 12:11:57 -05:00
parent e5caef8a54
commit 7675e53740
3 changed files with 42 additions and 42 deletions

View File

@ -1,4 +1,4 @@
use crate::{comp::PoiseChange, uid::Uid, Damage, GroupTarget, Knockback};
use crate::{combat::Attack, uid::Uid};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -9,8 +9,7 @@ pub struct Properties {
pub angle: f32,
pub vertical_angle: f32,
pub speed: f32,
pub effects: Vec<(Option<GroupTarget>, Damage, PoiseChange)>,
pub knockback: Knockback,
pub attack: Attack,
pub requires_ground: bool,
pub duration: Duration,
pub owner: Option<Uid>,

View File

@ -1,11 +1,14 @@
use crate::{
comp::{shockwave, CharacterState, PoiseChange, PoiseSource, StateUpdate},
combat::{
Attack, AttackEffect, CombatRequirement, Damage, DamageComponent, DamageSource,
EffectComponent, GroupTarget, Knockback,
},
comp::{shockwave, CharacterState, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
},
Damage, DamageSource, GroupTarget, Knockback,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -80,23 +83,23 @@ impl CharacterBehavior for Data {
});
} else {
// Attack
let damage = Damage {
source: DamageSource::Shockwave,
value: self.static_data.damage as f32,
};
let poise = AttackEffect::Poise(self.static_data.poise_damage as f32);
let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise)
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::Knockback(self.static_data.knockback);
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
.with_effect(knockback);
let attack = Attack::default().with_damage(damage).with_effect(poise);
let properties = shockwave::Properties {
angle: self.static_data.shockwave_angle,
vertical_angle: self.static_data.shockwave_vertical_angle,
speed: self.static_data.shockwave_speed,
duration: self.static_data.shockwave_duration,
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Shockwave,
value: self.static_data.damage as f32,
},
PoiseChange {
amount: -(self.static_data.poise_damage as i32),
source: PoiseSource::Attack,
},
)],
knockback: self.static_data.knockback,
attack,
requires_ground: self.static_data.requires_ground,
owner: Some(*data.uid),
};

View File

@ -1,6 +1,6 @@
use common::{
comp::{
group, Body, Health, HealthSource, Inventory, Last, Ori, PhysicsState, Pos, Scale,
group, Body, Energy, Health, HealthSource, Inventory, Last, Ori, PhysicsState, Pos, Scale,
Shockwave, ShockwaveHitEntities,
},
event::{EventBus, LocalEvent, ServerEvent},
@ -36,6 +36,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, Shockwave>,
WriteStorage<'a, ShockwaveHitEntities>,
ReadStorage<'a, Energy>,
);
fn run(
@ -59,6 +60,7 @@ impl<'a> System<'a> for Sys {
physics_states,
mut shockwaves,
mut shockwave_hit_lists,
energies,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
@ -114,11 +116,13 @@ impl<'a> System<'a> for Sys {
end: frame_end_dist,
};
let shockwave_owner = shockwave
.owner
.and_then(|uid| uid_allocator.retrieve_entity_internal(uid.into()));
// Group to ignore collisions with
// Might make this more nuanced if shockwaves are used for non damage effects
let group = shockwave
.owner
.and_then(|uid| uid_allocator.retrieve_entity_internal(uid.into()))
let group = shockwave_owner
.and_then(|e| groups.get(e));
// Go through all other effectable entities
@ -191,31 +195,25 @@ impl<'a> System<'a> for Sys {
&& (!shockwave.requires_ground || physics_state_b.on_ground);
if hit {
for (target, damage, poise_damage) in shockwave.effects.iter() {
if let Some(target) = target {
if *target != target_group {
continue;
}
}
let dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));
let owner_uid = shockwave.owner.unwrap_or(*uid);
let poise_change = poise_damage.modify_poise_damage(inventories.get(b));
let change =
damage.modify_damage(inventories.get(b), Some(owner_uid), false, 0.0);
let server_events = shockwave.properties.attack.apply_attack(
target_group,
shockwave_owner.unwrap_or(entity),
b,
inventories.get(b),
shockwave.owner.unwrap_or(*uid),
shockwave_owner.and_then(|e| energies.get(e)),
dir,
false,
);
server_emitter.emit(ServerEvent::Damage { entity: b, change });
if !server_events.is_empty() {
shockwave_hit_list.hit_entities.push(*uid_b);
}
let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));
let impulse = shockwave.knockback.calculate_impulse(kb_dir);
if !impulse.is_approx_zero() {
server_emitter.emit(ServerEvent::Knockback { entity: b, impulse });
}
server_emitter.emit(ServerEvent::PoiseChange {
entity: b,
change: poise_change,
kb_dir: *kb_dir,
});
for event in server_events {
server_emitter.emit(event);
}
}
}