Projectiles now use attacks.

This commit is contained in:
Sam 2021-01-28 19:04:44 -05:00
parent 46dbb8aef4
commit 59ce8c6843
10 changed files with 140 additions and 149 deletions

View File

@ -469,7 +469,7 @@ impl CombatBuff {
)
}
pub fn default_melee() -> Self {
pub fn default_physical() -> Self {
Self {
kind: BuffKind::Bleeding,
dur_secs: 10.0,

View File

@ -1,30 +1,33 @@
use crate::{
comp::buff::{BuffCategory, BuffData, BuffKind},
effect::{self, BuffEffect},
combat::{
Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource,
EffectComponent, GroupTarget, Knockback, KnockbackDir,
},
effect,
uid::Uid,
Damage, DamageSource, Explosion, GroupTarget, Knockback, KnockbackDir, RadiusEffect,
Explosion, RadiusEffect,
};
use serde::{Deserialize, Serialize};
use specs::Component;
use specs_idvs::IdvStorage;
use std::time::Duration;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub enum Effect {
Damage(Option<GroupTarget>, Damage),
Knockback(Knockback),
RewardEnergy(u32),
Attack(Attack),
//Knockback(Knockback),
//RewardEnergy(u32),
Explode(Explosion),
Vanish,
Stick,
Possess,
Buff {
buff: BuffEffect,
chance: Option<f32>,
},
/*Buff {
* buff: BuffEffect,
* chance: Option<f32>, */
/* */
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Projectile {
// TODO: use SmallVec for these effects
pub hit_solid: Vec<Effect>,
@ -74,32 +77,29 @@ impl ProjectileConstructor {
knockback,
energy_regen,
} => {
let buff = BuffEffect {
kind: BuffKind::Bleeding,
data: BuffData {
strength: damage / 2.0,
duration: Some(Duration::from_secs(5)),
},
cat_ids: vec![BuffCategory::Physical],
let damage = Damage {
source: DamageSource::Projectile,
value: damage,
};
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 {
hit_solid: vec![Effect::Stick],
hit_entity: vec![
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),
},
],
hit_entity: vec![Effect::Attack(attack), Effect::Vanish],
time_left: Duration::from_secs(15),
owner,
ignore_group: true,
@ -148,19 +148,24 @@ impl ProjectileConstructor {
Firebolt {
damage,
energy_regen,
} => Projectile {
hit_solid: vec![Effect::Vanish],
hit_entity: vec![
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Energy,
value: damage,
}),
Effect::RewardEnergy(energy_regen),
Effect::Vanish,
],
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
} => {
let damage = Damage {
source: DamageSource::Energy,
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);
Projectile {
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,

View File

@ -103,7 +103,7 @@ impl CharacterBehavior for Data {
let energy = AttackEffect::EnergyReward(50);
let energy = EffectComponent::new(None, energy)
.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))
.with_effect(knockback)
.with_effect(buff);

View File

@ -173,7 +173,7 @@ impl CharacterBehavior for Data {
strength: knockback,
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))
.with_effect(knockback)
.with_effect(buff);

View File

@ -1,16 +1,17 @@
use crate::{
combat::{
Attack, AttackEffect, CombatBuff, Damage, DamageComponent, DamageSource, GroupTarget,
Knockback, KnockbackDir,
},
comp::{
buff::{BuffCategory, BuffData, BuffKind},
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter,
Projectile, StateUpdate,
},
effect::BuffEffect,
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
},
Damage, DamageSource, GroupTarget, Knockback, KnockbackDir,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -109,27 +110,22 @@ impl CharacterBehavior for Data {
};
let knockback = self.static_data.initial_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
let projectile = Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), damage),
projectile::Effect::Knockback(Knockback {
strength: knockback,
direction: KnockbackDir::Away,
}),
projectile::Effect::Attack(attack),
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),
owner: Some(*data.uid),

View File

@ -200,7 +200,7 @@ impl CharacterBehavior for Data {
let energy = AttackEffect::EnergyReward(energy);
let energy = EffectComponent::new(None, energy)
.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))
.with_effect(knockback)
.with_effect(buff);

View File

@ -150,7 +150,7 @@ impl CharacterBehavior for Data {
strength: knockback,
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))
.with_effect(knockback)

View File

@ -156,7 +156,7 @@ impl CharacterBehavior for Data {
strength: self.static_data.knockback,
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))
.with_effect(knockback)
.with_effect(buff);

View File

@ -124,7 +124,7 @@ impl CharacterBehavior for Data {
strength: self.static_data.knockback,
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))
.with_effect(knockback)
.with_effect(buff);

View File

@ -1,9 +1,5 @@
use common::{
comp::{
buff::{Buff, BuffChange, BuffSource},
projectile, EnergyChange, EnergySource, Group, HealthSource, Inventory, Ori, PhysicsState,
Pos, Projectile, Vel,
},
comp::{projectile, Group, HealthSource, Inventory, Ori, PhysicsState, Pos, Projectile, Vel},
event::{EventBus, ServerEvent},
metrics::SysMetrics,
resources::DeltaTime,
@ -11,7 +7,6 @@ use common::{
uid::UidAllocator,
GroupTarget,
};
use rand::{thread_rng, Rng};
use specs::{
saveload::MarkerAllocator, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage,
};
@ -103,60 +98,55 @@ impl<'a> System<'a> for Sys {
let projectile = &mut *projectile;
for effect in projectile.hit_entity.drain(..) {
match effect {
projectile::Effect::Damage(target, damage) => {
if Some(other) == projectile.owner {
continue;
}
projectile::Effect::Attack(attack) => {
if let Some(owner) = projectile.owner {
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 {
if target != target_group {
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,
});
for event in server_events {
server_emitter.emit(event);
}
}
}
},
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::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) => {
// 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) => {
server_emitter.emit(ServerEvent::Explosion {
pos: pos.0,
@ -180,25 +170,25 @@ impl<'a> System<'a> for Sys {
}
},
// TODO: Change to effect after !1472 merges
projectile::Effect::Buff { buff, chance } => {
if let Some(entity) =
uid_allocator.retrieve_entity_internal(other.into())
{
if chance.map_or(true, |c| thread_rng().gen::<f32>() < c) {
let source = if let Some(owner) = projectile.owner {
BuffSource::Character { by: owner }
} else {
BuffSource::Unknown
};
let buff =
Buff::new(buff.kind, buff.data, buff.cat_ids, source);
server_emitter.emit(ServerEvent::Buff {
entity,
buff_change: BuffChange::Add(buff),
});
}
}
},
// projectile::Effect::Buff { buff, chance } => {
// if let Some(entity) =
// uid_allocator.retrieve_entity_internal(other.into())
// {
// if chance.map_or(true, |c| thread_rng().gen::<f32>() < c) {
// let source = if let Some(owner) = projectile.owner {
// BuffSource::Character { by: owner }
// } else {
// BuffSource::Unknown
// };
// let buff =
// Buff::new(buff.kind, buff.data, buff.cat_ids, source);
// server_emitter.emit(ServerEvent::Buff {
// entity,
// buff_change: BuffChange::Add(buff),
// });
// }
// }
// },
_ => {},
}
}