mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Explosions now use attacks.
This commit is contained in:
parent
7675e53740
commit
5c16b0b532
@ -173,7 +173,7 @@ impl Attack {
|
|||||||
.filter(|e| !(matches!(e.target, Some(GroupTarget::OutOfGroup)) && target_dodging))
|
.filter(|e| !(matches!(e.target, Some(GroupTarget::OutOfGroup)) && target_dodging))
|
||||||
{
|
{
|
||||||
if match &effect.requirement {
|
if match &effect.requirement {
|
||||||
Some(CombatRequirement::AnyDamage) => accumulated_damage != 0.0,
|
Some(CombatRequirement::AnyDamage) => accumulated_damage > 0.0,
|
||||||
Some(CombatRequirement::SufficientEnergy(r)) => {
|
Some(CombatRequirement::SufficientEnergy(r)) => {
|
||||||
if attacker_energy.map_or(true, |e| e.current() >= *r) {
|
if attacker_energy.map_or(true, |e| e.current() >= *r) {
|
||||||
server_events.push(ServerEvent::EnergyChange {
|
server_events.push(ServerEvent::EnergyChange {
|
||||||
@ -322,7 +322,6 @@ pub enum CombatRequirement {
|
|||||||
pub enum DamageSource {
|
pub enum DamageSource {
|
||||||
Buff(BuffKind),
|
Buff(BuffKind),
|
||||||
Melee,
|
Melee,
|
||||||
Healing,
|
|
||||||
Projectile,
|
Projectile,
|
||||||
Explosion,
|
Explosion,
|
||||||
Falling,
|
Falling,
|
||||||
@ -444,10 +443,6 @@ impl Damage {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DamageSource::Healing => HealthChange {
|
|
||||||
amount: damage as i32,
|
|
||||||
cause: HealthSource::Heal { by: uid },
|
|
||||||
},
|
|
||||||
DamageSource::Falling => {
|
DamageSource::Falling => {
|
||||||
// Armor
|
// Armor
|
||||||
if (damage_reduction - 1.0).abs() < f32::EPSILON {
|
if (damage_reduction - 1.0).abs() < f32::EPSILON {
|
||||||
|
@ -3,7 +3,6 @@ use crate::{
|
|||||||
Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource,
|
Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource,
|
||||||
EffectComponent, GroupTarget, Knockback, KnockbackDir,
|
EffectComponent, GroupTarget, Knockback, KnockbackDir,
|
||||||
},
|
},
|
||||||
effect,
|
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
Explosion, RadiusEffect,
|
Explosion, RadiusEffect,
|
||||||
};
|
};
|
||||||
@ -109,41 +108,30 @@ impl ProjectileConstructor {
|
|||||||
damage,
|
damage,
|
||||||
radius,
|
radius,
|
||||||
energy_regen,
|
energy_regen,
|
||||||
} => Projectile {
|
} => {
|
||||||
hit_solid: vec![
|
let damage = Damage {
|
||||||
Effect::Explode(Explosion {
|
source: DamageSource::Explosion,
|
||||||
effects: vec![
|
value: damage,
|
||||||
RadiusEffect::Entity(
|
};
|
||||||
Some(GroupTarget::OutOfGroup),
|
let energy = AttackEffect::EnergyReward(energy_regen);
|
||||||
effect::Effect::Damage(Damage {
|
let energy = EffectComponent::new(None, energy)
|
||||||
source: DamageSource::Explosion,
|
.with_requirement(CombatRequirement::AnyDamage);
|
||||||
value: damage,
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup));
|
||||||
}),
|
let attack = Attack::default().with_damage(damage).with_effect(energy);
|
||||||
),
|
let explosion = Explosion {
|
||||||
RadiusEffect::TerrainDestruction(2.0),
|
effects: vec![
|
||||||
],
|
RadiusEffect::Attack(attack),
|
||||||
radius,
|
RadiusEffect::TerrainDestruction(2.0),
|
||||||
energy_regen,
|
],
|
||||||
}),
|
radius,
|
||||||
Effect::Vanish,
|
};
|
||||||
],
|
Projectile {
|
||||||
hit_entity: vec![
|
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
|
||||||
Effect::Explode(Explosion {
|
hit_entity: vec![Effect::Explode(explosion), Effect::Vanish],
|
||||||
effects: vec![RadiusEffect::Entity(
|
time_left: Duration::from_secs(10),
|
||||||
Some(GroupTarget::OutOfGroup),
|
owner,
|
||||||
effect::Effect::Damage(Damage {
|
ignore_group: true,
|
||||||
source: DamageSource::Explosion,
|
}
|
||||||
value: damage,
|
|
||||||
}),
|
|
||||||
)],
|
|
||||||
radius,
|
|
||||||
energy_regen,
|
|
||||||
}),
|
|
||||||
Effect::Vanish,
|
|
||||||
],
|
|
||||||
time_left: Duration::from_secs(10),
|
|
||||||
owner,
|
|
||||||
ignore_group: true,
|
|
||||||
},
|
},
|
||||||
Firebolt {
|
Firebolt {
|
||||||
damage,
|
damage,
|
||||||
@ -171,56 +159,26 @@ impl ProjectileConstructor {
|
|||||||
heal,
|
heal,
|
||||||
damage,
|
damage,
|
||||||
radius,
|
radius,
|
||||||
} => Projectile {
|
} => {
|
||||||
hit_solid: vec![
|
let damage = Damage {
|
||||||
Effect::Explode(Explosion {
|
source: DamageSource::Explosion,
|
||||||
effects: vec![
|
value: damage,
|
||||||
RadiusEffect::Entity(
|
};
|
||||||
Some(GroupTarget::OutOfGroup),
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup));
|
||||||
effect::Effect::Damage(Damage {
|
let heal = AttackEffect::Heal(heal);
|
||||||
source: DamageSource::Explosion,
|
let heal = EffectComponent::new(Some(GroupTarget::InGroup), heal);
|
||||||
value: damage,
|
let attack = Attack::default().with_damage(damage).with_effect(heal);
|
||||||
}),
|
let explosion = Explosion {
|
||||||
),
|
effects: vec![RadiusEffect::Attack(attack)],
|
||||||
RadiusEffect::Entity(
|
radius,
|
||||||
Some(GroupTarget::InGroup),
|
};
|
||||||
effect::Effect::Damage(Damage {
|
Projectile {
|
||||||
source: DamageSource::Healing,
|
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
|
||||||
value: heal,
|
hit_entity: vec![Effect::Explode(explosion), Effect::Vanish],
|
||||||
}),
|
time_left: Duration::from_secs(10),
|
||||||
),
|
owner,
|
||||||
],
|
ignore_group: false,
|
||||||
radius,
|
}
|
||||||
energy_regen: 0,
|
|
||||||
}),
|
|
||||||
Effect::Vanish,
|
|
||||||
],
|
|
||||||
hit_entity: vec![
|
|
||||||
Effect::Explode(Explosion {
|
|
||||||
effects: vec![
|
|
||||||
RadiusEffect::Entity(
|
|
||||||
Some(GroupTarget::OutOfGroup),
|
|
||||||
effect::Effect::Damage(Damage {
|
|
||||||
source: DamageSource::Explosion,
|
|
||||||
value: damage,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
RadiusEffect::Entity(
|
|
||||||
Some(GroupTarget::InGroup),
|
|
||||||
effect::Effect::Damage(Damage {
|
|
||||||
source: DamageSource::Healing,
|
|
||||||
value: heal,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
radius,
|
|
||||||
energy_regen: 0,
|
|
||||||
}),
|
|
||||||
Effect::Vanish,
|
|
||||||
],
|
|
||||||
time_left: Duration::from_secs(10),
|
|
||||||
owner,
|
|
||||||
ignore_group: true,
|
|
||||||
},
|
},
|
||||||
Possess => Projectile {
|
Possess => Projectile {
|
||||||
hit_solid: vec![Effect::Stick],
|
hit_solid: vec![Effect::Stick],
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use crate::{combat::GroupTarget, effect::Effect};
|
use crate::{combat::Attack, effect::Effect};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Explosion {
|
pub struct Explosion {
|
||||||
pub effects: Vec<RadiusEffect>,
|
pub effects: Vec<RadiusEffect>,
|
||||||
pub radius: f32,
|
pub radius: f32,
|
||||||
pub energy_regen: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum RadiusEffect {
|
pub enum RadiusEffect {
|
||||||
TerrainDestruction(f32),
|
TerrainDestruction(f32),
|
||||||
Entity(Option<GroupTarget>, Effect),
|
Entity(Effect),
|
||||||
|
Attack(Attack),
|
||||||
}
|
}
|
||||||
|
@ -122,8 +122,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// Group to ignore collisions with
|
// Group to ignore collisions with
|
||||||
// Might make this more nuanced if shockwaves are used for non damage effects
|
// Might make this more nuanced if shockwaves are used for non damage effects
|
||||||
let group = shockwave_owner
|
let group = shockwave_owner.and_then(|e| groups.get(e));
|
||||||
.and_then(|e| groups.get(e));
|
|
||||||
|
|
||||||
// Go through all other effectable entities
|
// Go through all other effectable entities
|
||||||
for (
|
for (
|
||||||
|
@ -1360,17 +1360,13 @@ fn handle_explosion(
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::Entity(
|
RadiusEffect::Entity(Effect::Damage(Damage {
|
||||||
None,
|
source: DamageSource::Explosion,
|
||||||
Effect::Damage(Damage {
|
value: 100.0 * power,
|
||||||
source: DamageSource::Explosion,
|
})),
|
||||||
value: 100.0 * power,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
RadiusEffect::TerrainDestruction(power),
|
RadiusEffect::TerrainDestruction(power),
|
||||||
],
|
],
|
||||||
radius: 3.0 * power,
|
radius: 3.0 * power,
|
||||||
energy_regen: 0,
|
|
||||||
},
|
},
|
||||||
owner: ecs.read_storage::<Uid>().get(target).copied(),
|
owner: ecs.read_storage::<Uid>().get(target).copied(),
|
||||||
reagent: None,
|
reagent: None,
|
||||||
|
@ -16,12 +16,13 @@ use common::{
|
|||||||
object, Alignment, Body, CharacterState, Energy, EnergyChange, Group, Health, HealthChange,
|
object, Alignment, Body, CharacterState, Energy, EnergyChange, Group, Health, HealthChange,
|
||||||
HealthSource, Inventory, Item, Player, Poise, PoiseChange, PoiseSource, Pos, Stats,
|
HealthSource, Inventory, Item, Player, Poise, PoiseChange, PoiseSource, Pos, Stats,
|
||||||
},
|
},
|
||||||
effect::Effect,
|
event::{EventBus, ServerEvent},
|
||||||
lottery::Lottery,
|
lottery::Lottery,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
uid::{Uid, UidAllocator},
|
uid::{Uid, UidAllocator},
|
||||||
|
util::Dir,
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
||||||
};
|
};
|
||||||
@ -576,32 +577,24 @@ pub fn handle_explosion(
|
|||||||
|
|
||||||
// Add an outcome
|
// Add an outcome
|
||||||
// Uses radius as outcome power, makes negative if explosion has healing effect
|
// Uses radius as outcome power, makes negative if explosion has healing effect
|
||||||
let outcome_power = explosion.radius
|
let outcome_power = explosion.radius;
|
||||||
* if explosion.effects.iter().any(|e| {
|
//
|
||||||
matches!(
|
// * if explosion.effects.iter().any(|e| { matches!( e, RadiusEffect::Entity( _,
|
||||||
e,
|
// Effect::Damage(Damage { source: DamageSource::Healing, .. }) ) )
|
||||||
RadiusEffect::Entity(
|
// }) {
|
||||||
_,
|
// -1.0
|
||||||
Effect::Damage(Damage {
|
// } else {
|
||||||
source: DamageSource::Healing,
|
// 1.0
|
||||||
..
|
// };
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
-1.0
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
ecs.write_resource::<Vec<Outcome>>()
|
ecs.write_resource::<Vec<Outcome>>()
|
||||||
.push(Outcome::Explosion {
|
.push(Outcome::Explosion {
|
||||||
pos,
|
pos,
|
||||||
power: outcome_power,
|
power: outcome_power,
|
||||||
radius: explosion.radius,
|
radius: explosion.radius,
|
||||||
is_attack: explosion
|
is_attack: false, /*explosion
|
||||||
.effects
|
.effects
|
||||||
.iter()
|
.iter()
|
||||||
.any(|e| matches!(e, RadiusEffect::Entity(_, Effect::Damage(_)))),
|
.any(|e| matches!(e, RadiusEffect::Entity(_, Effect::Damage(_))))*/
|
||||||
reagent,
|
reagent,
|
||||||
});
|
});
|
||||||
let owner_entity = owner.and_then(|uid| {
|
let owner_entity = owner.and_then(|uid| {
|
||||||
@ -685,54 +678,74 @@ pub fn handle_explosion(
|
|||||||
.cast();
|
.cast();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RadiusEffect::Entity(target, mut effect) => {
|
RadiusEffect::Attack(attack) => {
|
||||||
for (entity_b, pos_b) in (&ecs.entities(), &ecs.read_storage::<comp::Pos>()).join()
|
// TODO: Before merging handle falloff
|
||||||
|
let energies = &ecs.read_storage::<comp::Energy>();
|
||||||
|
for (entity_b, pos_b, _health_b, inventory_b_maybe) in (
|
||||||
|
&ecs.entities(),
|
||||||
|
&ecs.read_storage::<comp::Pos>(),
|
||||||
|
&ecs.read_storage::<comp::Health>(),
|
||||||
|
ecs.read_storage::<comp::Inventory>().maybe(),
|
||||||
|
)
|
||||||
|
.join()
|
||||||
|
.filter(|(_, _, h, _)| !h.is_dead)
|
||||||
{
|
{
|
||||||
// See if entities are in the same group
|
// Check if it is a hit
|
||||||
let mut same_group = owner_entity
|
let distance_squared = pos.distance_squared(pos_b.0);
|
||||||
.and_then(|e| groups.get(e))
|
let strength = 1.0 - distance_squared / explosion.radius.powi(2);
|
||||||
.map_or(false, |group_a| Some(group_a) == groups.get(entity_b));
|
if strength > 0.0 {
|
||||||
if let Some(entity) = owner_entity {
|
// See if entities are in the same group
|
||||||
if entity == entity_b {
|
let same_group = owner_entity
|
||||||
same_group = true;
|
.and_then(|e| groups.get(e))
|
||||||
|
.map(|group_a| Some(group_a) == groups.get(entity_b))
|
||||||
|
.unwrap_or(Some(entity_b) == owner_entity);
|
||||||
|
|
||||||
|
let target_group = if same_group {
|
||||||
|
GroupTarget::InGroup
|
||||||
|
} else {
|
||||||
|
GroupTarget::OutOfGroup
|
||||||
|
};
|
||||||
|
|
||||||
|
let dir = Dir::new(
|
||||||
|
(pos_b.0 - pos)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec3::unit_z),
|
||||||
|
);
|
||||||
|
|
||||||
|
let server_events = attack.apply_attack(
|
||||||
|
target_group,
|
||||||
|
owner_entity.unwrap(),
|
||||||
|
entity_b,
|
||||||
|
inventory_b_maybe,
|
||||||
|
owner.unwrap(),
|
||||||
|
owner_entity.and_then(|e| energies.get(e)),
|
||||||
|
dir,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
let server_eventbus = ecs.read_resource::<EventBus<ServerEvent>>();
|
||||||
|
|
||||||
|
for event in server_events {
|
||||||
|
server_eventbus.emit_now(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let target_group = if same_group {
|
}
|
||||||
GroupTarget::InGroup
|
},
|
||||||
} else {
|
RadiusEffect::Entity(mut effect) => {
|
||||||
GroupTarget::OutOfGroup
|
for (entity_b, pos_b, _health_b) in (
|
||||||
};
|
&ecs.entities(),
|
||||||
|
&ecs.read_storage::<comp::Pos>(),
|
||||||
if let Some(target) = target {
|
&ecs.read_storage::<comp::Health>(),
|
||||||
if target != target_group {
|
)
|
||||||
continue;
|
.join()
|
||||||
}
|
.filter(|(_, _, h)| !h.is_dead)
|
||||||
}
|
{
|
||||||
|
|
||||||
let distance_squared = pos.distance_squared(pos_b.0);
|
let distance_squared = pos.distance_squared(pos_b.0);
|
||||||
let strength = 1.0 - distance_squared / explosion.radius.powi(2);
|
let strength = 1.0 - distance_squared / explosion.radius.powi(2);
|
||||||
|
|
||||||
if strength > 0.0 {
|
if strength > 0.0 {
|
||||||
let is_alive = ecs
|
effect.modify_strength(strength);
|
||||||
.read_storage::<comp::Health>()
|
server.state().apply_effect(entity_b, effect.clone(), owner);
|
||||||
.get(entity_b)
|
|
||||||
.map_or(false, |h| !h.is_dead);
|
|
||||||
|
|
||||||
if is_alive {
|
|
||||||
effect.modify_strength(strength);
|
|
||||||
server.state().apply_effect(entity_b, effect.clone(), owner);
|
|
||||||
// Apply energy change
|
|
||||||
if let Some(owner) = owner_entity {
|
|
||||||
if let Some(mut energy) =
|
|
||||||
ecs.write_storage::<comp::Energy>().get_mut(owner)
|
|
||||||
{
|
|
||||||
energy.change_by(EnergyChange {
|
|
||||||
amount: explosion.energy_regen as i32,
|
|
||||||
source: comp::EnergySource::HitEnemy,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -49,24 +49,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::Entity(
|
RadiusEffect::Entity(Effect::Damage(Damage {
|
||||||
None,
|
source: DamageSource::Explosion,
|
||||||
Effect::Damage(Damage {
|
value: 500.0,
|
||||||
source: DamageSource::Explosion,
|
})),
|
||||||
value: 500.0,
|
RadiusEffect::Entity(Effect::PoiseChange(PoiseChange {
|
||||||
}),
|
source: PoiseSource::Explosion,
|
||||||
),
|
amount: -100,
|
||||||
RadiusEffect::Entity(
|
})),
|
||||||
None,
|
|
||||||
Effect::PoiseChange(PoiseChange {
|
|
||||||
source: PoiseSource::Explosion,
|
|
||||||
amount: -100,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
energy_regen: 0,
|
|
||||||
},
|
},
|
||||||
owner: *owner,
|
owner: *owner,
|
||||||
reagent: None,
|
reagent: None,
|
||||||
@ -83,24 +76,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
explosion: Explosion {
|
explosion: Explosion {
|
||||||
effects: vec![
|
effects: vec![
|
||||||
RadiusEffect::Entity(
|
RadiusEffect::Entity(Effect::Damage(Damage {
|
||||||
None,
|
source: DamageSource::Explosion,
|
||||||
Effect::Damage(Damage {
|
value: 50.0,
|
||||||
source: DamageSource::Explosion,
|
})),
|
||||||
value: 50.0,
|
RadiusEffect::Entity(Effect::PoiseChange(PoiseChange {
|
||||||
}),
|
source: PoiseSource::Explosion,
|
||||||
),
|
amount: -40,
|
||||||
RadiusEffect::Entity(
|
})),
|
||||||
None,
|
|
||||||
Effect::PoiseChange(PoiseChange {
|
|
||||||
source: PoiseSource::Explosion,
|
|
||||||
amount: -40,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
energy_regen: 0,
|
|
||||||
},
|
},
|
||||||
owner: *owner,
|
owner: *owner,
|
||||||
reagent: Some(*reagent),
|
reagent: Some(*reagent),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user