mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Energy and health change server events now reference EcsEntity instead of Uid. Added TargetGroup to use to determine targets of effects/damage. Added Entity(TargetGroup, Effect) to RadiusEffect enum.
This commit is contained in:
parent
87bff41a66
commit
d38f1d319c
@ -21,8 +21,11 @@ pub struct Damages {
|
|||||||
impl Damages {
|
impl Damages {
|
||||||
pub fn new(enemy: Option<Damage>, group: Option<Damage>) -> Self { Damages { enemy, group } }
|
pub fn new(enemy: Option<Damage>, group: Option<Damage>) -> Self { Damages { enemy, group } }
|
||||||
|
|
||||||
pub fn get_damage(self, same_group: bool) -> Option<Damage> {
|
pub fn get_damage(self, group_target: GroupTarget) -> Option<Damage> {
|
||||||
if same_group { self.group } else { self.enemy }
|
match group_target {
|
||||||
|
GroupTarget::InGroup => self.group,
|
||||||
|
GroupTarget::OutOfGroup => self.enemy,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_damage(self, source: DamageSource) -> bool {
|
pub fn contains_damage(self, source: DamageSource) -> bool {
|
||||||
@ -31,6 +34,12 @@ impl Damages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum GroupTarget {
|
||||||
|
InGroup,
|
||||||
|
OutOfGroup,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum DamageSource {
|
pub enum DamageSource {
|
||||||
Melee,
|
Melee,
|
||||||
|
@ -34,7 +34,7 @@ pub enum ServerEvent {
|
|||||||
reagent: Option<Reagent>,
|
reagent: Option<Reagent>,
|
||||||
},
|
},
|
||||||
Damage {
|
Damage {
|
||||||
uid: Uid,
|
entity: EcsEntity,
|
||||||
change: comp::HealthChange,
|
change: comp::HealthChange,
|
||||||
},
|
},
|
||||||
Destroy {
|
Destroy {
|
||||||
@ -111,7 +111,7 @@ pub enum ServerEvent {
|
|||||||
buff_change: comp::BuffChange,
|
buff_change: comp::BuffChange,
|
||||||
},
|
},
|
||||||
EnergyChange {
|
EnergyChange {
|
||||||
uid: Uid,
|
entity: EcsEntity,
|
||||||
change: comp::EnergyChange,
|
change: comp::EnergyChange,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::{combat::Damages, effect::Effect};
|
use crate::{
|
||||||
|
combat::{Damages, GroupTarget},
|
||||||
|
effect::Effect,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -12,5 +15,5 @@ pub struct Explosion {
|
|||||||
pub enum RadiusEffect {
|
pub enum RadiusEffect {
|
||||||
Damages(Damages),
|
Damages(Damages),
|
||||||
TerrainDestruction(f32),
|
TerrainDestruction(f32),
|
||||||
EntityEffect(Effect),
|
Entity(Option<GroupTarget>, Effect),
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,6 @@ pub mod util;
|
|||||||
pub mod vol;
|
pub mod vol;
|
||||||
pub mod volumes;
|
pub mod volumes;
|
||||||
|
|
||||||
pub use combat::{Damage, DamageSource, Damages, Knockback};
|
pub use combat::{Damage, DamageSource, Damages, GroupTarget, Knockback};
|
||||||
pub use explosion::{Explosion, RadiusEffect};
|
pub use explosion::{Explosion, RadiusEffect};
|
||||||
pub use loadout_builder::LoadoutBuilder;
|
pub use loadout_builder::LoadoutBuilder;
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
state::{DeltaTime, Time},
|
state::{DeltaTime, Time},
|
||||||
sync::{Uid, UidAllocator},
|
sync::{Uid, UidAllocator},
|
||||||
DamageSource,
|
DamageSource, GroupTarget,
|
||||||
};
|
};
|
||||||
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -68,8 +68,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
let dt = dt.0;
|
let dt = dt.0;
|
||||||
|
|
||||||
// Beams
|
// Beams
|
||||||
for (entity, uid, pos, ori, beam_segment) in
|
for (entity, pos, ori, beam_segment) in
|
||||||
(&entities, &uids, &positions, &orientations, &beam_segments).join()
|
(&entities, &positions, &orientations, &beam_segments).join()
|
||||||
{
|
{
|
||||||
let creation_time = match beam_segment.creation {
|
let creation_time = match beam_segment.creation {
|
||||||
Some(time) => time,
|
Some(time) => time,
|
||||||
@ -163,12 +163,19 @@ impl<'a> System<'a> for Sys {
|
|||||||
.map(|group_a| Some(group_a) == groups.get(b))
|
.map(|group_a| Some(group_a) == groups.get(b))
|
||||||
.unwrap_or(Some(*uid_b) == beam_segment.owner);
|
.unwrap_or(Some(*uid_b) == beam_segment.owner);
|
||||||
|
|
||||||
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
// If owner, shouldn't heal or damage
|
// If owner, shouldn't heal or damage
|
||||||
if Some(*uid_b) == beam_segment.owner {
|
if Some(*uid_b) == beam_segment.owner {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let damage = if let Some(damage) = beam_segment.damages.get_damage(same_group) {
|
let damage = if let Some(damage) = beam_segment.damages.get_damage(target_group)
|
||||||
|
{
|
||||||
damage
|
damage
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@ -181,25 +188,22 @@ impl<'a> System<'a> for Sys {
|
|||||||
let change = damage.modify_damage(block, loadouts.get(b), beam_segment.owner);
|
let change = damage.modify_damage(block, loadouts.get(b), beam_segment.owner);
|
||||||
|
|
||||||
if !matches!(damage.source, DamageSource::Healing) {
|
if !matches!(damage.source, DamageSource::Healing) {
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage { entity: b, change });
|
||||||
uid: *uid_b,
|
if let Some(entity) = beam_owner {
|
||||||
change,
|
if beam_segment.lifesteal_eff > 0.0 {
|
||||||
});
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
if beam_segment.lifesteal_eff > 0.0 {
|
entity,
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
change: HealthChange {
|
||||||
uid: beam_segment.owner.unwrap_or(*uid),
|
amount: (-change.amount as f32 * beam_segment.lifesteal_eff)
|
||||||
change: HealthChange {
|
as i32,
|
||||||
amount: (-change.amount as f32 * beam_segment.lifesteal_eff)
|
cause: HealthSource::Healing {
|
||||||
as i32,
|
by: beam_segment.owner,
|
||||||
cause: HealthSource::Healing {
|
},
|
||||||
by: beam_segment.owner,
|
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
if let Some(uid) = beam_segment.owner {
|
|
||||||
server_emitter.emit(ServerEvent::EnergyChange {
|
server_emitter.emit(ServerEvent::EnergyChange {
|
||||||
uid,
|
entity,
|
||||||
change: EnergyChange {
|
change: EnergyChange {
|
||||||
amount: beam_segment.energy_regen as i32,
|
amount: beam_segment.energy_regen as i32,
|
||||||
source: EnergySource::HitEnemy,
|
source: EnergySource::HitEnemy,
|
||||||
@ -208,19 +212,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
} else if let Some(energy) = beam_owner.and_then(|o| energies.get(o)) {
|
} else if let Some(energy) = beam_owner.and_then(|o| energies.get(o)) {
|
||||||
if energy.current() > beam_segment.energy_cost {
|
if energy.current() > beam_segment.energy_cost {
|
||||||
if let Some(uid) = beam_segment.owner {
|
server_emitter.emit(ServerEvent::EnergyChange {
|
||||||
server_emitter.emit(ServerEvent::EnergyChange {
|
entity: beam_owner.unwrap(), /* If it's able to get an energy
|
||||||
uid,
|
* component, the entity exists */
|
||||||
change: EnergyChange {
|
change: EnergyChange {
|
||||||
amount: -(beam_segment.energy_cost as i32), // Stamina use
|
amount: -(beam_segment.energy_cost as i32), // Stamina use
|
||||||
source: EnergySource::Ability,
|
source: EnergySource::Ability,
|
||||||
},
|
},
|
||||||
})
|
|
||||||
}
|
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
|
||||||
uid: *uid_b,
|
|
||||||
change,
|
|
||||||
});
|
});
|
||||||
|
server_emitter.emit(ServerEvent::Damage { entity: b, change });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Adds entities that were hit to the hit_entities list on the beam, sees if it
|
// Adds entities that were hit to the hit_entities list on the beam, sees if it
|
||||||
|
@ -5,7 +5,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
state::DeltaTime,
|
state::DeltaTime,
|
||||||
sync::Uid,
|
|
||||||
};
|
};
|
||||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -17,7 +16,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
ReadStorage<'a, Uid>,
|
|
||||||
ReadStorage<'a, Loadout>,
|
ReadStorage<'a, Loadout>,
|
||||||
WriteStorage<'a, Health>,
|
WriteStorage<'a, Health>,
|
||||||
WriteStorage<'a, Buffs>,
|
WriteStorage<'a, Buffs>,
|
||||||
@ -25,14 +23,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
(entities, dt, server_bus, uids, loadouts, mut healths, mut buffs): Self::SystemData,
|
(entities, dt, server_bus, loadouts, mut healths, mut buffs): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
// Set to false to avoid spamming server
|
// Set to false to avoid spamming server
|
||||||
buffs.set_event_emission(false);
|
buffs.set_event_emission(false);
|
||||||
healths.set_event_emission(false);
|
healths.set_event_emission(false);
|
||||||
for (entity, buff_comp, uid, health) in (&entities, &mut buffs, &uids, &mut healths).join()
|
for (entity, buff_comp, health) in (&entities, &mut buffs, &mut healths).join() {
|
||||||
{
|
|
||||||
let mut expired_buffs = Vec::<BuffId>::new();
|
let mut expired_buffs = Vec::<BuffId>::new();
|
||||||
for (id, buff) in buff_comp.buffs.iter_mut() {
|
for (id, buff) in buff_comp.buffs.iter_mut() {
|
||||||
// Tick the buff and subtract delta from it
|
// Tick the buff and subtract delta from it
|
||||||
@ -94,7 +91,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
HealthSource::Buff { owner: buff_owner }
|
HealthSource::Buff { owner: buff_owner }
|
||||||
};
|
};
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
uid: *uid,
|
entity,
|
||||||
change: HealthChange {
|
change: HealthChange {
|
||||||
amount: *accumulated as i32,
|
amount: *accumulated as i32,
|
||||||
cause,
|
cause,
|
||||||
|
@ -5,6 +5,7 @@ use crate::{
|
|||||||
span,
|
span,
|
||||||
sync::Uid,
|
sync::Uid,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
|
GroupTarget,
|
||||||
};
|
};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
||||||
@ -75,9 +76,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
attack.applied = true;
|
attack.applied = true;
|
||||||
|
|
||||||
// Go through all other entities
|
// Go through all other entities
|
||||||
for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, health_b, body_b) in (
|
for (b, pos_b, ori_b, scale_b_maybe, character_b, health_b, body_b) in (
|
||||||
&entities,
|
&entities,
|
||||||
&uids,
|
|
||||||
&positions,
|
&positions,
|
||||||
&orientations,
|
&orientations,
|
||||||
scales.maybe(),
|
scales.maybe(),
|
||||||
@ -110,7 +110,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
.map(|group_a| Some(group_a) == groups.get(b))
|
.map(|group_a| Some(group_a) == groups.get(b))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
let damage = if let Some(damage) = attack.damages.get_damage(same_group) {
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
|
let damage = if let Some(damage) = attack.damages.get_damage(target_group) {
|
||||||
damage
|
damage
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@ -122,10 +128,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let change = damage.modify_damage(block, loadouts.get(b), Some(*uid));
|
let change = damage.modify_damage(block, loadouts.get(b), Some(*uid));
|
||||||
|
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage { entity: b, change });
|
||||||
uid: *uid_b,
|
|
||||||
change,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Apply bleeding buff on melee hits with 10% chance
|
// Apply bleeding buff on melee hits with 10% chance
|
||||||
// TODO: Don't have buff uniformly applied on all melee attacks
|
// TODO: Don't have buff uniformly applied on all melee attacks
|
||||||
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
span,
|
span,
|
||||||
state::DeltaTime,
|
state::DeltaTime,
|
||||||
sync::UidAllocator,
|
sync::UidAllocator,
|
||||||
|
GroupTarget,
|
||||||
};
|
};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use specs::{
|
use specs::{
|
||||||
@ -83,6 +84,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
.retrieve_entity_internal(other.into())
|
.retrieve_entity_internal(other.into())
|
||||||
.and_then(|e| groups.get(e))
|
.and_then(|e| groups.get(e))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
if projectile.ignore_group
|
if projectile.ignore_group
|
||||||
// Skip if in the same group
|
// Skip if in the same group
|
||||||
&& same_group
|
&& same_group
|
||||||
@ -100,36 +108,49 @@ impl<'a> System<'a> for Sys {
|
|||||||
if Some(other) == projectile.owner {
|
if Some(other) == projectile.owner {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let damage = if let Some(damage) = damages.get_damage(same_group) {
|
let damage = if let Some(damage) = damages.get_damage(target_group) {
|
||||||
damage
|
damage
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let other_entity_loadout = uid_allocator
|
if let Some(other_entity) =
|
||||||
.retrieve_entity_internal(other.into())
|
uid_allocator.retrieve_entity_internal(other.into())
|
||||||
.and_then(|e| loadouts.get(e));
|
{
|
||||||
let change =
|
let other_entity_loadout = loadouts.get(other_entity);
|
||||||
damage.modify_damage(false, other_entity_loadout, projectile.owner);
|
let change = damage.modify_damage(
|
||||||
|
false,
|
||||||
|
other_entity_loadout,
|
||||||
|
projectile.owner,
|
||||||
|
);
|
||||||
|
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
server_emitter.emit(ServerEvent::Damage { uid: other, change });
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
|
entity: other_entity,
|
||||||
|
change,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projectile::Effect::Knockback(knockback) => {
|
projectile::Effect::Knockback(knockback) => {
|
||||||
if let Some(entity) =
|
if let Some(other_entity) =
|
||||||
uid_allocator.retrieve_entity_internal(other.into())
|
uid_allocator.retrieve_entity_internal(other.into())
|
||||||
{
|
{
|
||||||
let impulse = knockback.calculate_impulse(ori.0);
|
let impulse = knockback.calculate_impulse(ori.0);
|
||||||
if !impulse.is_approx_zero() {
|
if !impulse.is_approx_zero() {
|
||||||
local_emitter
|
local_emitter.emit(LocalEvent::ApplyImpulse {
|
||||||
.emit(LocalEvent::ApplyImpulse { entity, impulse });
|
entity: other_entity,
|
||||||
|
impulse,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projectile::Effect::RewardEnergy(energy) => {
|
projectile::Effect::RewardEnergy(energy) => {
|
||||||
if let Some(uid) = projectile.owner {
|
if let Some(entity_owner) = projectile
|
||||||
|
.owner
|
||||||
|
.and_then(|u| uid_allocator.retrieve_entity_internal(u.into()))
|
||||||
|
{
|
||||||
server_emitter.emit(ServerEvent::EnergyChange {
|
server_emitter.emit(ServerEvent::EnergyChange {
|
||||||
uid,
|
entity: entity_owner,
|
||||||
change: EnergyChange {
|
change: EnergyChange {
|
||||||
amount: energy as i32,
|
amount: energy as i32,
|
||||||
source: EnergySource::HitEnemy,
|
source: EnergySource::HitEnemy,
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
state::{DeltaTime, Time},
|
state::{DeltaTime, Time},
|
||||||
sync::{Uid, UidAllocator},
|
sync::{Uid, UidAllocator},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
|
GroupTarget,
|
||||||
};
|
};
|
||||||
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -177,6 +178,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
.map(|group_a| Some(group_a) == groups.get(b))
|
.map(|group_a| Some(group_a) == groups.get(b))
|
||||||
.unwrap_or(Some(*uid_b) == shockwave.owner);
|
.unwrap_or(Some(*uid_b) == shockwave.owner);
|
||||||
|
|
||||||
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
// Check if it is a hit
|
// Check if it is a hit
|
||||||
let hit = entity != b
|
let hit = entity != b
|
||||||
&& !health_b.is_dead
|
&& !health_b.is_dead
|
||||||
@ -192,7 +199,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&& (!shockwave.requires_ground || physics_state_b.on_ground);
|
&& (!shockwave.requires_ground || physics_state_b.on_ground);
|
||||||
|
|
||||||
if hit {
|
if hit {
|
||||||
let damage = if let Some(damage) = shockwave.damages.get_damage(same_group) {
|
let damage = if let Some(damage) = shockwave.damages.get_damage(target_group) {
|
||||||
damage
|
damage
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@ -205,10 +212,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let change = damage.modify_damage(block, loadouts.get(b), Some(owner_uid));
|
let change = damage.modify_damage(block, loadouts.get(b), Some(owner_uid));
|
||||||
|
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage { entity: b, change });
|
||||||
uid: *uid_b,
|
|
||||||
change,
|
|
||||||
});
|
|
||||||
shockwave_hit_list.hit_entities.push(*uid_b);
|
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 kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));
|
||||||
let impulse = shockwave.knockback.calculate_impulse(kb_dir);
|
let impulse = shockwave.knockback.calculate_impulse(kb_dir);
|
||||||
|
@ -1158,10 +1158,13 @@ fn handle_explosion(
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::EntityEffect(Effect::Health(comp::HealthChange {
|
RadiusEffect::Entity(
|
||||||
amount: (-100.0 * power) as i32,
|
None,
|
||||||
cause: comp::HealthSource::Explosion { owner: None },
|
Effect::Health(comp::HealthChange {
|
||||||
})),
|
amount: (-100.0 * power) as i32,
|
||||||
|
cause: comp::HealthSource::Explosion { owner: None },
|
||||||
|
}),
|
||||||
|
),
|
||||||
RadiusEffect::TerrainDestruction(power),
|
RadiusEffect::TerrainDestruction(power),
|
||||||
],
|
],
|
||||||
radius: 3.0 * power,
|
radius: 3.0 * power,
|
||||||
|
@ -19,7 +19,7 @@ use common::{
|
|||||||
sys::melee::BLOCK_ANGLE,
|
sys::melee::BLOCK_ANGLE,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
Damage, DamageSource, Explosion, RadiusEffect,
|
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
||||||
};
|
};
|
||||||
use comp::item::Reagent;
|
use comp::item::Reagent;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
@ -27,12 +27,10 @@ use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt
|
|||||||
use tracing::error;
|
use tracing::error;
|
||||||
use vek::Vec3;
|
use vek::Vec3;
|
||||||
|
|
||||||
pub fn handle_damage(server: &Server, uid: Uid, change: HealthChange) {
|
pub fn handle_damage(server: &Server, entity: EcsEntity, change: HealthChange) {
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
if let Some(entity) = ecs.entity_from_uid(uid.into()) {
|
if let Some(health) = ecs.write_storage::<Health>().get_mut(entity) {
|
||||||
if let Some(health) = ecs.write_storage::<Health>().get_mut(entity) {
|
health.change_by(change);
|
||||||
health.change_by(change);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +568,13 @@ pub fn handle_explosion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut damage = if let Some(damage) = damages.get_damage(same_group) {
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut damage = if let Some(damage) = damages.get_damage(target_group) {
|
||||||
damage
|
damage
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@ -667,13 +671,29 @@ pub fn handle_explosion(
|
|||||||
.cast();
|
.cast();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RadiusEffect::EntityEffect(effect) => {
|
RadiusEffect::Entity(target_group, effect) => {
|
||||||
for (entity, pos_entity) in
|
for (entity_b, pos_b) in (&ecs.entities(), &ecs.read_storage::<comp::Pos>()).join()
|
||||||
(&ecs.entities(), &ecs.read_storage::<comp::Pos>()).join()
|
|
||||||
{
|
{
|
||||||
let distance_squared = pos.distance_squared(pos_entity.0);
|
let distance_squared = pos.distance_squared(pos_b.0);
|
||||||
if distance_squared < explosion.radius.powi(2) {
|
// See if entities are in the same group
|
||||||
server.state().apply_effect(entity, effect);
|
let mut same_group = owner_entity
|
||||||
|
.and_then(|e| groups.get(e))
|
||||||
|
.map_or(false, |group_a| Some(group_a) == groups.get(entity_b));
|
||||||
|
if let Some(entity) = owner_entity {
|
||||||
|
if entity == entity_b {
|
||||||
|
same_group = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hit_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
|
if distance_squared < explosion.radius.powi(2)
|
||||||
|
&& target_group.map_or(true, |g| g == hit_group)
|
||||||
|
{
|
||||||
|
server.state().apply_effect(entity_b, effect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -754,11 +774,9 @@ pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::Bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_energy_change(server: &Server, uid: Uid, change: EnergyChange) {
|
pub fn handle_energy_change(server: &Server, entity: EcsEntity, change: EnergyChange) {
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
if let Some(entity) = ecs.entity_from_uid(uid.into()) {
|
if let Some(energy) = ecs.write_storage::<Energy>().get_mut(entity) {
|
||||||
if let Some(energy) = ecs.write_storage::<Energy>().get_mut(entity) {
|
energy.change_by(change);
|
||||||
energy.change_by(change);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ impl Server {
|
|||||||
ServerEvent::Knockback { entity, impulse } => {
|
ServerEvent::Knockback { entity, impulse } => {
|
||||||
handle_knockback(&self, entity, impulse)
|
handle_knockback(&self, entity, impulse)
|
||||||
},
|
},
|
||||||
ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change),
|
ServerEvent::Damage { entity, change } => handle_damage(&self, entity, change),
|
||||||
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
||||||
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
||||||
ServerEvent::GroupManip(entity, manip) => handle_group(self, entity, manip),
|
ServerEvent::GroupManip(entity, manip) => handle_group(self, entity, manip),
|
||||||
@ -137,8 +137,8 @@ impl Server {
|
|||||||
entity,
|
entity,
|
||||||
buff_change,
|
buff_change,
|
||||||
} => handle_buff(self, entity, buff_change),
|
} => handle_buff(self, entity, buff_change),
|
||||||
ServerEvent::EnergyChange { uid, change } => {
|
ServerEvent::EnergyChange { entity, change } => {
|
||||||
handle_energy_change(&self, uid, change)
|
handle_energy_change(&self, entity, change)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,10 @@ impl StateExt for State {
|
|||||||
z_max: body.height(),
|
z_max: body.height(),
|
||||||
});
|
});
|
||||||
self.write_component(entity, body);
|
self.write_component(entity, body);
|
||||||
|
self.write_component(
|
||||||
|
entity,
|
||||||
|
comp::Health::new(stats.body_type, stats.level.level()),
|
||||||
|
);
|
||||||
self.write_component(entity, stats);
|
self.write_component(entity, stats);
|
||||||
self.write_component(entity, inventory);
|
self.write_component(entity, inventory);
|
||||||
self.write_component(entity, loadout);
|
self.write_component(entity, loadout);
|
||||||
|
@ -50,10 +50,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::EntityEffect(Effect::Health(HealthChange {
|
RadiusEffect::Entity(
|
||||||
amount: -500,
|
None,
|
||||||
cause: HealthSource::Explosion { owner: *owner },
|
Effect::Health(HealthChange {
|
||||||
})),
|
amount: -500,
|
||||||
|
cause: HealthSource::Explosion { owner: *owner },
|
||||||
|
}),
|
||||||
|
),
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
@ -74,10 +77,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::EntityEffect(Effect::Health(HealthChange {
|
RadiusEffect::Entity(
|
||||||
amount: -50,
|
None,
|
||||||
cause: HealthSource::Explosion { owner: *owner },
|
Effect::Health(HealthChange {
|
||||||
})),
|
amount: -50,
|
||||||
|
cause: HealthSource::Explosion { owner: *owner },
|
||||||
|
}),
|
||||||
|
),
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
|
Loading…
Reference in New Issue
Block a user