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