mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Projectiles now use attacks.
This commit is contained in:
@ -469,7 +469,7 @@ impl CombatBuff {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_melee() -> Self {
|
pub fn default_physical() -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: BuffKind::Bleeding,
|
kind: BuffKind::Bleeding,
|
||||||
dur_secs: 10.0,
|
dur_secs: 10.0,
|
||||||
|
@ -1,30 +1,33 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::buff::{BuffCategory, BuffData, BuffKind},
|
combat::{
|
||||||
effect::{self, BuffEffect},
|
Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource,
|
||||||
|
EffectComponent, GroupTarget, Knockback, KnockbackDir,
|
||||||
|
},
|
||||||
|
effect,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
Damage, DamageSource, Explosion, GroupTarget, Knockback, KnockbackDir, RadiusEffect,
|
Explosion, RadiusEffect,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::Component;
|
use specs::Component;
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum Effect {
|
pub enum Effect {
|
||||||
Damage(Option<GroupTarget>, Damage),
|
Attack(Attack),
|
||||||
Knockback(Knockback),
|
//Knockback(Knockback),
|
||||||
RewardEnergy(u32),
|
//RewardEnergy(u32),
|
||||||
Explode(Explosion),
|
Explode(Explosion),
|
||||||
Vanish,
|
Vanish,
|
||||||
Stick,
|
Stick,
|
||||||
Possess,
|
Possess,
|
||||||
Buff {
|
/*Buff {
|
||||||
buff: BuffEffect,
|
* buff: BuffEffect,
|
||||||
chance: Option<f32>,
|
* chance: Option<f32>, */
|
||||||
},
|
/* */
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Projectile {
|
pub struct Projectile {
|
||||||
// TODO: use SmallVec for these effects
|
// TODO: use SmallVec for these effects
|
||||||
pub hit_solid: Vec<Effect>,
|
pub hit_solid: Vec<Effect>,
|
||||||
@ -74,32 +77,29 @@ impl ProjectileConstructor {
|
|||||||
knockback,
|
knockback,
|
||||||
energy_regen,
|
energy_regen,
|
||||||
} => {
|
} => {
|
||||||
let buff = BuffEffect {
|
let damage = Damage {
|
||||||
kind: BuffKind::Bleeding,
|
source: DamageSource::Projectile,
|
||||||
data: BuffData {
|
value: damage,
|
||||||
strength: damage / 2.0,
|
|
||||||
duration: Some(Duration::from_secs(5)),
|
|
||||||
},
|
|
||||||
cat_ids: vec![BuffCategory::Physical],
|
|
||||||
};
|
};
|
||||||
|
let knockback = AttackEffect::Knockback(Knockback {
|
||||||
|
strength: knockback,
|
||||||
|
direction: KnockbackDir::Away,
|
||||||
|
});
|
||||||
|
let energy = AttackEffect::EnergyReward(energy_regen);
|
||||||
|
let energy = EffectComponent::new(None, energy)
|
||||||
|
.with_requirement(CombatRequirement::AnyDamage);
|
||||||
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
|
.with_effect(knockback)
|
||||||
|
.with_effect(buff);
|
||||||
|
let attack = Attack::default()
|
||||||
|
.with_damage(damage)
|
||||||
|
.with_crit(0.5, 1.2)
|
||||||
|
.with_effect(energy);
|
||||||
|
|
||||||
Projectile {
|
Projectile {
|
||||||
hit_solid: vec![Effect::Stick],
|
hit_solid: vec![Effect::Stick],
|
||||||
hit_entity: vec![
|
hit_entity: vec![Effect::Attack(attack), Effect::Vanish],
|
||||||
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
|
|
||||||
source: DamageSource::Projectile,
|
|
||||||
value: damage,
|
|
||||||
}),
|
|
||||||
Effect::Knockback(Knockback {
|
|
||||||
strength: knockback,
|
|
||||||
direction: KnockbackDir::Away,
|
|
||||||
}),
|
|
||||||
Effect::RewardEnergy(energy_regen),
|
|
||||||
Effect::Vanish,
|
|
||||||
Effect::Buff {
|
|
||||||
buff,
|
|
||||||
chance: Some(0.10),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
time_left: Duration::from_secs(15),
|
time_left: Duration::from_secs(15),
|
||||||
owner,
|
owner,
|
||||||
ignore_group: true,
|
ignore_group: true,
|
||||||
@ -148,19 +148,24 @@ impl ProjectileConstructor {
|
|||||||
Firebolt {
|
Firebolt {
|
||||||
damage,
|
damage,
|
||||||
energy_regen,
|
energy_regen,
|
||||||
} => Projectile {
|
} => {
|
||||||
hit_solid: vec![Effect::Vanish],
|
let damage = Damage {
|
||||||
hit_entity: vec![
|
source: DamageSource::Energy,
|
||||||
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
|
value: damage,
|
||||||
source: DamageSource::Energy,
|
};
|
||||||
value: damage,
|
let energy = AttackEffect::EnergyReward(energy_regen);
|
||||||
}),
|
let energy = EffectComponent::new(None, energy)
|
||||||
Effect::RewardEnergy(energy_regen),
|
.with_requirement(CombatRequirement::AnyDamage);
|
||||||
Effect::Vanish,
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup));
|
||||||
],
|
let attack = Attack::default().with_damage(damage).with_effect(energy);
|
||||||
time_left: Duration::from_secs(10),
|
|
||||||
owner,
|
Projectile {
|
||||||
ignore_group: true,
|
hit_solid: vec![Effect::Vanish],
|
||||||
|
hit_entity: vec![Effect::Attack(attack), Effect::Vanish],
|
||||||
|
time_left: Duration::from_secs(10),
|
||||||
|
owner,
|
||||||
|
ignore_group: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Heal {
|
Heal {
|
||||||
heal,
|
heal,
|
||||||
|
@ -103,7 +103,7 @@ impl CharacterBehavior for Data {
|
|||||||
let energy = AttackEffect::EnergyReward(50);
|
let energy = AttackEffect::EnergyReward(50);
|
||||||
let energy = EffectComponent::new(None, energy)
|
let energy = EffectComponent::new(None, energy)
|
||||||
.with_requirement(CombatRequirement::AnyDamage);
|
.with_requirement(CombatRequirement::AnyDamage);
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
.with_effect(buff);
|
.with_effect(buff);
|
||||||
|
@ -173,7 +173,7 @@ impl CharacterBehavior for Data {
|
|||||||
strength: knockback,
|
strength: knockback,
|
||||||
direction: KnockbackDir::Away,
|
direction: KnockbackDir::Away,
|
||||||
});
|
});
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
.with_effect(buff);
|
.with_effect(buff);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
combat::{
|
||||||
|
Attack, AttackEffect, CombatBuff, Damage, DamageComponent, DamageSource, GroupTarget,
|
||||||
|
Knockback, KnockbackDir,
|
||||||
|
},
|
||||||
comp::{
|
comp::{
|
||||||
buff::{BuffCategory, BuffData, BuffKind},
|
|
||||||
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter,
|
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter,
|
||||||
Projectile, StateUpdate,
|
Projectile, StateUpdate,
|
||||||
},
|
},
|
||||||
effect::BuffEffect,
|
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
utils::*,
|
utils::*,
|
||||||
},
|
},
|
||||||
Damage, DamageSource, GroupTarget, Knockback, KnockbackDir,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -109,27 +110,22 @@ impl CharacterBehavior for Data {
|
|||||||
};
|
};
|
||||||
let knockback = self.static_data.initial_knockback
|
let knockback = self.static_data.initial_knockback
|
||||||
+ charge_frac * self.static_data.scaled_knockback;
|
+ charge_frac * self.static_data.scaled_knockback;
|
||||||
|
let knockback = AttackEffect::Knockback(Knockback {
|
||||||
|
strength: knockback,
|
||||||
|
direction: KnockbackDir::Away,
|
||||||
|
});
|
||||||
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
|
.with_effect(knockback)
|
||||||
|
.with_effect(buff);
|
||||||
|
let attack = Attack::default().with_damage(damage).with_crit(0.5, 1.2);
|
||||||
|
|
||||||
// Fire
|
// Fire
|
||||||
let projectile = Projectile {
|
let projectile = Projectile {
|
||||||
hit_solid: vec![projectile::Effect::Stick],
|
hit_solid: vec![projectile::Effect::Stick],
|
||||||
hit_entity: vec![
|
hit_entity: vec![
|
||||||
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), damage),
|
projectile::Effect::Attack(attack),
|
||||||
projectile::Effect::Knockback(Knockback {
|
|
||||||
strength: knockback,
|
|
||||||
direction: KnockbackDir::Away,
|
|
||||||
}),
|
|
||||||
projectile::Effect::Vanish,
|
projectile::Effect::Vanish,
|
||||||
projectile::Effect::Buff {
|
|
||||||
buff: BuffEffect {
|
|
||||||
kind: BuffKind::Bleeding,
|
|
||||||
data: BuffData {
|
|
||||||
strength: damage.value / 5.0,
|
|
||||||
duration: Some(Duration::from_secs(5)),
|
|
||||||
},
|
|
||||||
cat_ids: vec![BuffCategory::Physical],
|
|
||||||
},
|
|
||||||
chance: Some(0.10),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
time_left: Duration::from_secs(15),
|
time_left: Duration::from_secs(15),
|
||||||
owner: Some(*data.uid),
|
owner: Some(*data.uid),
|
||||||
|
@ -200,7 +200,7 @@ impl CharacterBehavior for Data {
|
|||||||
let energy = AttackEffect::EnergyReward(energy);
|
let energy = AttackEffect::EnergyReward(energy);
|
||||||
let energy = EffectComponent::new(None, energy)
|
let energy = EffectComponent::new(None, energy)
|
||||||
.with_requirement(CombatRequirement::AnyDamage);
|
.with_requirement(CombatRequirement::AnyDamage);
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
.with_effect(buff);
|
.with_effect(buff);
|
||||||
|
@ -150,7 +150,7 @@ impl CharacterBehavior for Data {
|
|||||||
strength: knockback,
|
strength: knockback,
|
||||||
direction: KnockbackDir::Away,
|
direction: KnockbackDir::Away,
|
||||||
});
|
});
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage =
|
let damage =
|
||||||
DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
|
@ -156,7 +156,7 @@ impl CharacterBehavior for Data {
|
|||||||
strength: self.static_data.knockback,
|
strength: self.static_data.knockback,
|
||||||
direction: KnockbackDir::Away,
|
direction: KnockbackDir::Away,
|
||||||
});
|
});
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
.with_effect(buff);
|
.with_effect(buff);
|
||||||
|
@ -124,7 +124,7 @@ impl CharacterBehavior for Data {
|
|||||||
strength: self.static_data.knockback,
|
strength: self.static_data.knockback,
|
||||||
direction: KnockbackDir::Away,
|
direction: KnockbackDir::Away,
|
||||||
});
|
});
|
||||||
let buff = AttackEffect::Buff(CombatBuff::default_melee());
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
||||||
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
||||||
.with_effect(knockback)
|
.with_effect(knockback)
|
||||||
.with_effect(buff);
|
.with_effect(buff);
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{projectile, Group, HealthSource, Inventory, Ori, PhysicsState, Pos, Projectile, Vel},
|
||||||
buff::{Buff, BuffChange, BuffSource},
|
|
||||||
projectile, EnergyChange, EnergySource, Group, HealthSource, Inventory, Ori, PhysicsState,
|
|
||||||
Pos, Projectile, Vel,
|
|
||||||
},
|
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
metrics::SysMetrics,
|
metrics::SysMetrics,
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
@ -11,7 +7,6 @@ use common::{
|
|||||||
uid::UidAllocator,
|
uid::UidAllocator,
|
||||||
GroupTarget,
|
GroupTarget,
|
||||||
};
|
};
|
||||||
use rand::{thread_rng, Rng};
|
|
||||||
use specs::{
|
use specs::{
|
||||||
saveload::MarkerAllocator, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage,
|
saveload::MarkerAllocator, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage,
|
||||||
};
|
};
|
||||||
@ -103,60 +98,55 @@ impl<'a> System<'a> for Sys {
|
|||||||
let projectile = &mut *projectile;
|
let projectile = &mut *projectile;
|
||||||
for effect in projectile.hit_entity.drain(..) {
|
for effect in projectile.hit_entity.drain(..) {
|
||||||
match effect {
|
match effect {
|
||||||
projectile::Effect::Damage(target, damage) => {
|
projectile::Effect::Attack(attack) => {
|
||||||
if Some(other) == projectile.owner {
|
if let Some(owner) = projectile.owner {
|
||||||
continue;
|
if let (Some(owner_entity), Some(target_entity)) = (
|
||||||
}
|
uid_allocator.retrieve_entity_internal(owner.into()),
|
||||||
|
uid_allocator.retrieve_entity_internal(other.into()),
|
||||||
|
) {
|
||||||
|
let server_events = attack.apply_attack(
|
||||||
|
target_group,
|
||||||
|
owner_entity,
|
||||||
|
target_entity,
|
||||||
|
inventories.get(target_entity),
|
||||||
|
owner,
|
||||||
|
ori.0,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(target) = target {
|
for event in server_events {
|
||||||
if target != target_group {
|
server_emitter.emit(event);
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(other_entity) =
|
|
||||||
uid_allocator.retrieve_entity_internal(other.into())
|
|
||||||
{
|
|
||||||
let other_entity_inventory = inventories.get(other_entity);
|
|
||||||
let change = damage.modify_damage(
|
|
||||||
other_entity_inventory,
|
|
||||||
projectile.owner,
|
|
||||||
false,
|
|
||||||
0.0,
|
|
||||||
);
|
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
|
||||||
entity: other_entity,
|
|
||||||
change,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
projectile::Effect::Knockback(knockback) => {
|
|
||||||
if let Some(other_entity) =
|
|
||||||
uid_allocator.retrieve_entity_internal(other.into())
|
|
||||||
{
|
|
||||||
let impulse = knockback.calculate_impulse(ori.0);
|
|
||||||
if !impulse.is_approx_zero() {
|
|
||||||
server_emitter.emit(ServerEvent::Knockback {
|
|
||||||
entity: other_entity,
|
|
||||||
impulse,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projectile::Effect::RewardEnergy(energy) => {
|
// projectile::Effect::Knockback(knockback) => {
|
||||||
if let Some(entity_owner) = projectile
|
// if let Some(other_entity) =
|
||||||
.owner
|
// uid_allocator.retrieve_entity_internal(other.into())
|
||||||
.and_then(|u| uid_allocator.retrieve_entity_internal(u.into()))
|
// {
|
||||||
{
|
// let impulse = knockback.calculate_impulse(ori.0);
|
||||||
server_emitter.emit(ServerEvent::EnergyChange {
|
// if !impulse.is_approx_zero() {
|
||||||
entity: entity_owner,
|
// server_emitter.emit(ServerEvent::Knockback {
|
||||||
change: EnergyChange {
|
// entity: other_entity,
|
||||||
amount: energy as i32,
|
// impulse,
|
||||||
source: EnergySource::HitEnemy,
|
// });
|
||||||
},
|
// }
|
||||||
});
|
// }
|
||||||
}
|
// },
|
||||||
},
|
// projectile::Effect::RewardEnergy(energy) => {
|
||||||
|
// if let Some(entity_owner) = projectile
|
||||||
|
// .owner
|
||||||
|
// .and_then(|u| uid_allocator.retrieve_entity_internal(u.into()))
|
||||||
|
// {
|
||||||
|
// server_emitter.emit(ServerEvent::EnergyChange {
|
||||||
|
// entity: entity_owner,
|
||||||
|
// change: EnergyChange {
|
||||||
|
// amount: energy as i32,
|
||||||
|
// source: EnergySource::HitEnemy,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// },
|
||||||
projectile::Effect::Explode(e) => {
|
projectile::Effect::Explode(e) => {
|
||||||
server_emitter.emit(ServerEvent::Explosion {
|
server_emitter.emit(ServerEvent::Explosion {
|
||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
@ -180,25 +170,25 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: Change to effect after !1472 merges
|
// TODO: Change to effect after !1472 merges
|
||||||
projectile::Effect::Buff { buff, chance } => {
|
// projectile::Effect::Buff { buff, chance } => {
|
||||||
if let Some(entity) =
|
// if let Some(entity) =
|
||||||
uid_allocator.retrieve_entity_internal(other.into())
|
// uid_allocator.retrieve_entity_internal(other.into())
|
||||||
{
|
// {
|
||||||
if chance.map_or(true, |c| thread_rng().gen::<f32>() < c) {
|
// if chance.map_or(true, |c| thread_rng().gen::<f32>() < c) {
|
||||||
let source = if let Some(owner) = projectile.owner {
|
// let source = if let Some(owner) = projectile.owner {
|
||||||
BuffSource::Character { by: owner }
|
// BuffSource::Character { by: owner }
|
||||||
} else {
|
// } else {
|
||||||
BuffSource::Unknown
|
// BuffSource::Unknown
|
||||||
};
|
// };
|
||||||
let buff =
|
// let buff =
|
||||||
Buff::new(buff.kind, buff.data, buff.cat_ids, source);
|
// Buff::new(buff.kind, buff.data, buff.cat_ids, source);
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
// server_emitter.emit(ServerEvent::Buff {
|
||||||
entity,
|
// entity,
|
||||||
buff_change: BuffChange::Add(buff),
|
// buff_change: BuffChange::Add(buff),
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user