Very basic functioning stun

This commit is contained in:
jiminycrick 2020-12-05 18:29:46 -08:00
parent c83296a4ec
commit e3965ae0ab
28 changed files with 413 additions and 223 deletions

View File

@ -40,7 +40,6 @@ pub enum DamageSource {
pub struct Damage {
pub source: DamageSource,
pub value: f32,
pub poise_damage: f32,
}
impl Damage {
@ -84,16 +83,13 @@ impl Damage {
damage += critdamage;
}
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
-poise_damage as i32,
)
}
},
DamageSource::Projectile => {
// Critical hit
@ -103,82 +99,63 @@ impl Damage {
// Armor
damage *= 1.0 - damage_reduction;
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
-poise_damage as i32,
)
}
},
DamageSource::Explosion => {
// Armor
damage *= 1.0 - damage_reduction;
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
-poise_damage as i32,
)
}
},
DamageSource::Shockwave => {
// Armor
damage *= 1.0 - damage_reduction;
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
-poise_damage as i32,
)
}
},
DamageSource::Energy => {
// Armor
damage *= 1.0 - damage_reduction;
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
},
-poise_damage as i32,
)
},
DamageSource::Healing => (
HealthChange {
amount: damage as i32,
cause: HealthSource::Heal { by: uid },
},
0,
),
amount: -damage as i32,
cause: HealthSource::Damage {
kind: self.source,
by: uid,
},
}
},
DamageSource::Healing => HealthChange {
amount: damage as i32,
cause: HealthSource::Heal { by: uid },
},
DamageSource::Falling => {
// Armor
if (damage_reduction - 1.0).abs() < f32::EPSILON {
damage = 0.0;
poise_damage = 0.0;
}
(
HealthChange {
amount: -damage as i32,
cause: HealthSource::World,
},
-poise_damage as i32,
)
HealthChange {
amount: -damage as i32,
cause: HealthSource::World,
},
},
DamageSource::Buff(_) => HealthChange {
amount: -damage as i32,
@ -193,8 +170,7 @@ impl Damage {
kind: self.source,
by: uid,
},
-poise_damage as i32,
),
},
}
}

View File

@ -1,4 +1,8 @@
use crate::{uid::Uid, Damage, GroupTarget};
use crate::{
comp::{PoiseChange, PoiseSource},
uid::Uid,
Damage, GroupTarget,
};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -8,7 +12,7 @@ use std::time::Duration;
pub struct Properties {
pub angle: f32,
pub speed: f32,
pub damages: Vec<(Option<GroupTarget>, Damage)>,
pub effects: Vec<(Option<GroupTarget>, Damage, PoiseChange)>,
pub lifesteal_eff: f32,
pub energy_regen: u32,
pub energy_cost: u32,

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Energy, Ori, Pos, Vel},
comp::{Energy, Ori, PoiseChange, Pos, Vel},
event::{LocalEvent, ServerEvent},
states::{behavior::JoinData, *},
Damage, GroupTarget, Knockback,
@ -172,7 +172,7 @@ impl Component for CharacterState {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Attacking {
pub damages: Vec<(Option<GroupTarget>, Damage)>,
pub effects: Vec<(Option<GroupTarget>, Damage, PoiseChange)>,
pub range: f32,
pub max_angle: f32,
pub applied: bool,

View File

@ -66,7 +66,7 @@ pub use phys::{
Sticky, Vel,
};
pub use player::Player;
pub use poise::{Poise, PoiseState};
pub use poise::{Poise, PoiseChange, PoiseSource, PoiseState};
pub use projectile::{Projectile, ProjectileConstructor};
pub use shockwave::{Shockwave, ShockwaveHitEntities};
pub use skills::{Skill, SkillGroup, SkillGroupKind, SkillSet};

View File

@ -1,8 +1,91 @@
use crate::{comp::Body, sync::Uid, DamageSource};
use crate::{
comp::{Body, Loadout},
sync::Uid,
DamageSource,
};
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage};
use specs_idvs::IdvStorage;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct PoiseChange {
pub amount: i32,
pub source: PoiseSource,
}
impl PoiseChange {
pub fn modify_poise_damage(self, loadout: Option<&Loadout>, uid: Option<Uid>) -> PoiseChange {
println!("Pre modified: {:?}", self.amount);
let mut poise_damage = -self.amount as f32;
match self.source {
PoiseSource::Melee => {
// Armor
let damage_reduction = loadout.map_or(0.0, |l| l.get_poise_damage_reduction());
poise_damage *= 1.0 - damage_reduction;
PoiseChange {
amount: -poise_damage as i32,
source: PoiseSource::Melee,
}
},
PoiseSource::Projectile => {
// Armor
let damage_reduction = loadout.map_or(0.0, |l| l.get_poise_damage_reduction());
poise_damage *= 1.0 - damage_reduction;
PoiseChange {
amount: -poise_damage as i32,
source: PoiseSource::Projectile,
}
},
PoiseSource::Shockwave => {
// Armor
let damage_reduction = loadout.map_or(0.0, |l| l.get_poise_damage_reduction());
poise_damage *= 1.0 - damage_reduction;
PoiseChange {
amount: -poise_damage as i32,
source: PoiseSource::Shockwave,
}
},
PoiseSource::Explosion => {
// Armor
let damage_reduction = loadout.map_or(0.0, |l| l.get_poise_damage_reduction());
poise_damage *= 1.0 - damage_reduction;
PoiseChange {
amount: -poise_damage as i32,
source: PoiseSource::Explosion,
}
},
PoiseSource::Falling => {
// Armor
let damage_reduction = loadout.map_or(0.0, |l| l.get_poise_damage_reduction());
if (damage_reduction - 1.0).abs() < f32::EPSILON {
poise_damage = 0.0;
}
PoiseChange {
amount: -poise_damage as i32,
source: PoiseSource::Falling,
}
},
_ => PoiseChange {
amount: self.amount,
source: PoiseSource::Other,
},
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum PoiseSource {
LevelUp,
Melee,
Projectile,
Explosion,
Beam,
Shockwave,
Falling,
Revive,
Other,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Poise {
base_max: u32,
@ -69,8 +152,8 @@ impl Poise {
self.current = amount;
}
pub fn change_by(&mut self, change: i32) {
self.current = ((self.current as i32 + change).max(0) as u32).min(self.maximum);
pub fn change_by(&mut self, change: PoiseChange) {
self.current = ((self.current as i32 + change.amount).max(0) as u32).min(self.maximum);
}
pub fn reset(&mut self) { self.current = self.maximum; }

View File

@ -1,5 +1,8 @@
use crate::{
comp::buff::{BuffCategory, BuffData, BuffKind},
comp::{
buff::{BuffCategory, BuffData, BuffKind},
PoiseChange, PoiseSource,
},
effect::{self, BuffEffect},
uid::Uid,
Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect,
@ -11,7 +14,7 @@ use std::time::Duration;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Effect {
Damage(Option<GroupTarget>, Damage),
Damage(Option<GroupTarget>, Damage, PoiseChange),
Knockback(Knockback),
RewardEnergy(u32),
Explode(Explosion),
@ -85,11 +88,17 @@ impl ProjectileConstructor {
Projectile {
hit_solid: vec![Effect::Stick],
hit_entity: vec![
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Projectile,
value: damage,
poise_damage: 0.0,
}),
Effect::Damage(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Projectile,
value: damage,
},
PoiseChange {
amount: 0,
source: PoiseSource::Projectile,
},
),
Effect::Knockback(Knockback::Away(knockback)),
Effect::RewardEnergy(energy_regen),
Effect::Vanish,
@ -111,14 +120,12 @@ impl ProjectileConstructor {
hit_solid: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
RadiusEffect::Entity(Some(GroupTarget::OutOfGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
poise_damage: 10.0,
}),
),
]),
RadiusEffect::TerrainDestruction(2.0),
],
radius,
@ -128,14 +135,12 @@ impl ProjectileConstructor {
],
hit_entity: vec![
Effect::Explode(Explosion {
effects: vec![RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
effects: vec![RadiusEffect::Entity(Some(GroupTarget::OutOfGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
poise_damage: 10.0,
}),
)],
])],
radius,
energy_regen,
}),
@ -170,22 +175,18 @@ impl ProjectileConstructor {
hit_solid: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
RadiusEffect::Entity(Some(GroupTarget::OutOfGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
poise_damage: 0.0,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
]),
RadiusEffect::Entity(Some(GroupTarget::InGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Healing,
value: heal,
poise_damage: 0.0,
}),
),
]),
],
radius,
energy_regen: 0,
@ -195,22 +196,18 @@ impl ProjectileConstructor {
hit_entity: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
RadiusEffect::Entity(Some(GroupTarget::OutOfGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
poise_damage: 0.0,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
]),
RadiusEffect::Entity(Some(GroupTarget::InGroup), vec![
effect::Effect::Damage(Damage {
source: DamageSource::Healing,
value: heal,
poise_damage: 0.0,
}),
),
]),
],
radius,
energy_regen: 0,

View File

@ -1,4 +1,4 @@
use crate::{uid::Uid, Damage, GroupTarget, Knockback};
use crate::{comp::PoiseChange, uid::Uid, Damage, GroupTarget, Knockback};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -9,7 +9,7 @@ pub struct Properties {
pub angle: f32,
pub vertical_angle: f32,
pub speed: f32,
pub damages: Vec<(Option<GroupTarget>, Damage)>,
pub effects: Vec<(Option<GroupTarget>, Damage, PoiseChange)>,
pub knockback: Knockback,
pub requires_ground: bool,
pub duration: Duration,

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Effect {
Health(comp::HealthChange),
Poise(i32),
Poise(comp::PoiseChange),
Damage(combat::Damage),
Buff(BuffEffect),
}
@ -22,7 +22,7 @@ impl Effect {
pub fn info(&self) -> String {
match self {
Effect::Health(c) => format!("{:+} health", c.amount),
Effect::Poise(c) => format!("{:+} poise", c),
Effect::Poise(c) => format!("{:+} poise", c.amount),
Effect::Damage(d) => format!("{:+}", d.value),
Effect::Buff(e) => format!("{:?} buff", e),
}
@ -34,7 +34,7 @@ impl Effect {
change.amount = (change.amount as f32 * modifier) as i32;
},
Effect::Poise(change) => {
*change = (*change as f32 * modifier) as i32;
change.amount = (change.amount as f32 * modifier) as i32;
},
Effect::Damage(damage) => {
damage.interpolate_damage(modifier, 0.0);

View File

@ -34,7 +34,11 @@ pub enum ServerEvent {
},
Damage {
entity: EcsEntity,
change: (comp::HealthChange, i32),
change: comp::HealthChange,
},
PoiseChange {
entity: EcsEntity,
change: comp::PoiseChange,
},
Delete(EcsEntity),
Destroy {

View File

@ -11,5 +11,5 @@ pub struct Explosion {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum RadiusEffect {
TerrainDestruction(f32),
Entity(Option<GroupTarget>, Effect),
Entity(Option<GroupTarget>, Vec<Effect>),
}

View File

@ -1,5 +1,8 @@
use crate::{
comp::{beam, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate},
comp::{
beam, Body, CharacterState, EnergyChange, EnergySource, Ori, PoiseChange, PoiseSource, Pos,
StateUpdate,
},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -122,21 +125,27 @@ impl CharacterBehavior for Data {
let damage = Damage {
source: DamageSource::Energy,
value: self.static_data.base_dps as f32 / self.static_data.tick_rate,
poise_damage: 0.0,
};
let poise_damage = PoiseChange {
amount: 0,
source: PoiseSource::Beam,
};
let heal = Damage {
source: DamageSource::Healing,
value: self.static_data.base_hps as f32 / self.static_data.tick_rate,
poise_damage: 0.0,
};
let reverse_poise = PoiseChange {
amount: 0,
source: PoiseSource::Beam,
};
let speed =
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
let properties = beam::Properties {
angle: self.static_data.max_angle.to_radians(),
speed,
damages: vec![
(Some(GroupTarget::OutOfGroup), damage),
(Some(GroupTarget::InGroup), heal),
effects: vec![
(Some(GroupTarget::OutOfGroup), damage, poise_damage),
(Some(GroupTarget::InGroup), heal, reverse_poise),
],
lifesteal_eff: self.static_data.lifesteal_eff,
energy_regen: self.static_data.energy_regen,

View File

@ -1,5 +1,8 @@
use crate::{
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
comp::{
Attacking, CharacterState, EnergyChange, EnergySource, PoiseChange, PoiseSource,
StateUpdate,
},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -91,11 +94,17 @@ impl CharacterBehavior for Data {
// Hit attempt
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
poise_damage: self.static_data.base_poise_damage as f32,
})],
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
},
PoiseChange {
amount: -(self.static_data.base_poise_damage as i32),
source: PoiseSource::Melee,
},
)],
range: self.static_data.range,
max_angle: 180_f32.to_radians(),
applied: false,

View File

@ -1,5 +1,8 @@
use crate::{
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
comp::{
Attacking, CharacterState, EnergyChange, EnergySource, PoiseChange, PoiseSource,
StateUpdate,
},
states::{
behavior::{CharacterBehavior, JoinData},
utils::{StageSection, *},
@ -154,14 +157,17 @@ impl CharacterBehavior for Data {
source: DamageSource::Melee,
value: self.static_data.initial_damage as f32
+ self.charge_amount * self.static_data.scaled_damage as f32,
poise_damage: self.static_data.initial_poise_damage as f32,
};
let mut poise_damage = PoiseChange {
amount: -(self.static_data.initial_poise_damage as i32),
source: PoiseSource::Melee,
};
let knockback = self.static_data.initial_knockback
+ self.charge_amount * self.static_data.scaled_knockback;
// Hit attempt
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), damage)],
effects: vec![(Some(GroupTarget::OutOfGroup), damage, poise_damage)],
range: self.static_data.range,
max_angle: self.static_data.max_angle.to_radians(),
applied: false,

View File

@ -2,7 +2,7 @@ use crate::{
comp::{
buff::{BuffCategory, BuffData, BuffKind},
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter,
Projectile, StateUpdate,
PoiseChange, PoiseSource, Projectile, StateUpdate,
},
effect::BuffEffect,
event::ServerEvent,
@ -108,7 +108,10 @@ impl CharacterBehavior for Data {
source: DamageSource::Projectile,
value: self.static_data.initial_damage as f32
+ charge_frac * self.static_data.scaled_damage as f32,
poise_damage: self.static_data.initial_poise_damage as f32,
};
let mut poise_damage = PoiseChange {
amount: -(self.static_data.initial_poise_damage as i32),
source: PoiseSource::Projectile,
};
let knockback = self.static_data.initial_knockback
+ charge_frac * self.static_data.scaled_knockback;
@ -116,7 +119,11 @@ impl CharacterBehavior for Data {
let projectile = Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), damage),
projectile::Effect::Damage(
Some(GroupTarget::OutOfGroup),
damage,
poise_damage,
),
projectile::Effect::Knockback(Knockback::Away(knockback)),
projectile::Effect::Vanish,
projectile::Effect::Buff {

View File

@ -1,5 +1,8 @@
use crate::{
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
comp::{
Attacking, CharacterState, EnergyChange, EnergySource, PoiseChange, PoiseSource,
StateUpdate,
},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -167,12 +170,19 @@ impl CharacterBehavior for Data {
.min(self.combo / self.static_data.num_stages)
* self.static_data.stage_data[stage_index].damage_increase;
let poise_damage = self.static_data.stage_data[stage_index].base_poise_damage;
println!("Combo melee poise damage: {:?}", poise_damage);
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Melee,
value: damage as f32,
poise_damage: poise_damage as f32,
})],
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Melee,
value: damage as f32,
},
PoiseChange {
amount: -(poise_damage as i32),
source: PoiseSource::Melee,
},
)],
range: self.static_data.stage_data[stage_index].range,
max_angle: self.static_data.stage_data[stage_index].angle.to_radians(),
applied: false,

View File

@ -1,5 +1,8 @@
use crate::{
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
comp::{
Attacking, CharacterState, EnergyChange, EnergySource, PoiseChange, PoiseSource,
StateUpdate,
},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -131,12 +134,19 @@ impl CharacterBehavior for Data {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32
+ charge_frac * self.static_data.scaled_damage as f32,
poise_damage: self.static_data.base_poise_damage as f32,
};
let mut poise_damage = PoiseChange {
amount: -(self.static_data.base_poise_damage as i32),
source: PoiseSource::Melee,
};
let knockback = self.static_data.base_knockback
+ charge_frac * self.static_data.scaled_knockback;
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), damage)],
effects: vec![(
Some(GroupTarget::OutOfGroup),
damage,
poise_damage,
)],
range: self.static_data.range,
max_angle: self.static_data.angle.to_radians(),
applied: false,

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Attacking, CharacterState, StateUpdate},
comp::{Attacking, CharacterState, PoiseChange, PoiseSource, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::{StageSection, *},
@ -149,11 +149,17 @@ impl CharacterBehavior for Data {
if !self.exhausted {
// Hit attempt, when animation plays
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
poise_damage: self.static_data.base_poise_damage as f32,
})],
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
},
PoiseChange {
amount: -(self.static_data.base_poise_damage as i32),
source: PoiseSource::Melee,
},
)],
range: self.static_data.range,
max_angle: self.static_data.max_angle.to_radians(),
applied: false,

View File

@ -1,5 +1,5 @@
use crate::{
comp::{shockwave, CharacterState, StateUpdate},
comp::{shockwave, CharacterState, PoiseChange, PoiseSource, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -85,11 +85,17 @@ impl CharacterBehavior for Data {
vertical_angle: self.static_data.shockwave_vertical_angle,
speed: self.static_data.shockwave_speed,
duration: self.static_data.shockwave_duration,
damages: vec![(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Shockwave,
value: self.static_data.damage as f32,
poise_damage: self.static_data.poise_damage as f32,
})],
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Shockwave,
value: self.static_data.damage as f32,
},
PoiseChange {
amount: -(self.static_data.poise_damage as i32),
source: PoiseSource::Shockwave,
},
)],
knockback: self.static_data.knockback,
requires_ground: self.static_data.requires_ground,
owner: Some(*data.uid),

View File

@ -1,5 +1,8 @@
use crate::{
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
comp::{
Attacking, CharacterState, EnergyChange, EnergySource, PoiseChange, PoiseSource,
StateUpdate,
},
consts::GRAVITY,
states::{
behavior::{CharacterBehavior, JoinData},
@ -113,11 +116,17 @@ impl CharacterBehavior for Data {
});
// Hit attempt
data.updater.insert(data.entity, Attacking {
damages: vec![(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
poise_damage: self.static_data.base_damage as f32,
})],
effects: vec![(
Some(GroupTarget::OutOfGroup),
Damage {
source: DamageSource::Melee,
value: self.static_data.base_damage as f32,
},
PoiseChange {
amount: -(self.static_data.base_poise_damage as i32),
source: PoiseSource::Melee,
},
)],
range: self.static_data.range,
max_angle: 180_f32.to_radians(),
applied: false,

View File

@ -1,7 +1,7 @@
use common::{
comp::{
group, Beam, BeamSegment, Body, Energy, EnergyChange, EnergySource, Health, HealthChange,
HealthSource, Inventory, Last, Ori, Pos, Scale,
HealthSource, Inventory, Last, Ori, PoiseChange, PoiseSource, Pos, Scale,
},
event::{EventBus, ServerEvent},
resources::{DeltaTime, Time},
@ -158,7 +158,7 @@ impl<'a> System<'a> for Sys {
continue;
}
for (target, damage) in beam_segment.damages.iter() {
for (target, damage, poise_damage) in beam_segment.effects.iter() {
if let Some(target) = target {
if *target != target_group {
continue;
@ -167,6 +167,8 @@ impl<'a> System<'a> for Sys {
// Modify damage
let change = damage.modify_damage(inventories.get(b), beam_segment.owner);
let poise_change = poise_damage
.modify_poise_damage(inventories.get(b), beam_segment.owner);
match target {
Some(GroupTarget::OutOfGroup) => {
@ -174,17 +176,18 @@ impl<'a> System<'a> for Sys {
if let Some(entity) = beam_owner {
server_emitter.emit(ServerEvent::Damage {
entity,
change: (
HealthChange {
amount: (-change.0.amount as f32
* beam_segment.lifesteal_eff)
as i32,
cause: HealthSource::Heal {
by: beam_segment.owner,
},
change: HealthChange {
amount: (-change.amount as f32
* beam_segment.lifesteal_eff)
as i32,
cause: HealthSource::Heal {
by: beam_segment.owner,
},
0,
),
},
});
server_emitter.emit(ServerEvent::PoiseChange {
entity,
change: poise_change,
});
server_emitter.emit(ServerEvent::EnergyChange {
entity,

View File

@ -114,7 +114,7 @@ impl<'a> System<'a> for Sys {
};
server_emitter.emit(ServerEvent::Damage {
entity,
change: (HealthChange { amount, cause }, 0),
change: HealthChange { amount, cause },
});
*accumulated = 0.0;
};

View File

@ -1,5 +1,7 @@
use common::{
comp::{buff, group, Attacking, Body, CharacterState, Health, Inventory, Ori, Pos, Scale},
comp::{
buff, group, Attacking, Body, CharacterState, Health, Inventory, Ori, Poise, Pos, Scale,
},
event::{EventBus, LocalEvent, ServerEvent},
metrics::SysMetrics,
span,
@ -118,7 +120,7 @@ impl<'a> System<'a> for Sys {
GroupTarget::OutOfGroup
};
for (target, damage) in attack.damages.iter() {
for (target, damage, poise_change) in attack.effects.iter() {
if let Some(target) = target {
if *target != target_group
|| (!matches!(target, GroupTarget::InGroup) && is_dodge)
@ -128,18 +130,25 @@ impl<'a> System<'a> for Sys {
}
let change = damage.modify_damage(inventories.get(b), Some(*uid));
//let poise_change =
// poise_change.modify_poise_damage(loadouts.get(b), Some(*uid));
println!("poise_change in melee: {:?}", poise_change);
server_emitter.emit(ServerEvent::Damage { entity: b, change });
server_emitter.emit(ServerEvent::PoiseChange {
entity: b,
change: *poise_change,
});
// Apply bleeding buff on melee hits with 10% chance
// TODO: Don't have buff uniformly applied on all melee attacks
if change.0.amount < 0 && thread_rng().gen::<f32>() < 0.1 {
if change.amount < 0 && thread_rng().gen::<f32>() < 0.1 {
use buff::*;
server_emitter.emit(ServerEvent::Buff {
entity: b,
buff_change: BuffChange::Add(Buff::new(
BuffKind::Bleeding,
BuffData {
strength: -change.0.amount as f32 / 10.0,
strength: -change.amount as f32 / 10.0,
duration: Some(Duration::from_secs(10)),
},
vec![BuffCategory::Physical],

View File

@ -102,7 +102,7 @@ impl<'a> System<'a> for Sys {
let projectile = &mut *projectile;
for effect in projectile.hit_entity.drain(..) {
match effect {
projectile::Effect::Damage(target, damage) => {
projectile::Effect::Damage(target, damage, poise_damage) => {
if Some(other) == projectile.owner {
continue;
}
@ -119,10 +119,16 @@ impl<'a> System<'a> for Sys {
let other_entity_inventory = inventories.get(other_entity);
let change =
damage.modify_damage(other_entity_inventory, projectile.owner);
let poise_change = poise_damage
.modify_poise_damage(other_entity_inventory, projectile.owner);
server_emitter.emit(ServerEvent::Damage {
entity: other_entity,
change,
});
server_emitter.emit(ServerEvent::PoiseChange {
entity: other_entity,
change: poise_change,
});
}
},
projectile::Effect::Knockback(knockback) => {

View File

@ -191,7 +191,7 @@ impl<'a> System<'a> for Sys {
&& (!shockwave.requires_ground || physics_state_b.on_ground);
if hit {
for (target, damage) in shockwave.damages.iter() {
for (target, damage, poise_damage) in shockwave.effects.iter() {
if let Some(target) = target {
if *target != target_group {
continue;
@ -200,8 +200,14 @@ impl<'a> System<'a> for Sys {
let owner_uid = shockwave.owner.unwrap_or(*uid);
let change = damage.modify_damage(inventories.get(b), Some(owner_uid));
let poise_change =
poise_damage.modify_poise_damage(inventories.get(b), Some(owner_uid));
server_emitter.emit(ServerEvent::Damage { entity: b, change });
server_emitter.emit(ServerEvent::PoiseChange {
entity: b,
change: poise_change,
});
shockwave_hit_list.hit_entities.push(*uid_b);
let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));

View File

@ -1360,14 +1360,10 @@ fn handle_explosion(
pos: pos.0,
explosion: Explosion {
effects: vec![
RadiusEffect::Entity(
None,
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 100.0 * power,
poise_damage: 100.0,
}),
),
RadiusEffect::Entity(None, vec![Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 100.0 * power,
})]),
RadiusEffect::TerrainDestruction(power),
],
radius: 3.0 * power,

View File

@ -13,8 +13,9 @@ use common::{
comp::{
self, aura, buff,
chat::{KillSource, KillType},
object, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange, HealthSource,
Inventory, Item, Player, Poise, PoiseState, Pos, Stats,
object, poise, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange,
HealthSource, Inventory, Item, Player, Poise, PoiseChange, PoiseSource, PoiseState, Pos,
Stats,
},
effect::Effect,
lottery::Lottery,
@ -35,12 +36,11 @@ use std::time::Duration;
use tracing::error;
use vek::Vec3;
pub fn handle_damage(server: &Server, entity: EcsEntity, change: (HealthChange, i32)) {
pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) {
let ecs = &server.state.ecs();
if let Some(mut health) = ecs.write_storage::<Health>().get_mut(entity) {
health.change_by(change);
if let Some(poise) = ecs.write_storage::<Poise>().get_mut(entity) {
poise.change_by(change.1);
poise.change_by(change);
println!("poise: {:?}", change);
let was_wielded =
if let Some(character_state) = ecs.read_storage::<comp::CharacterState>().get(entity) {
character_state.is_wield()
@ -116,6 +116,12 @@ pub fn handle_damage(server: &Server, entity: EcsEntity, change: (HealthChange,
}
}
}
pub fn handle_damage(server: &Server, entity: EcsEntity, change: HealthChange) {
let ecs = &server.state.ecs();
if let Some(health) = ecs.write_storage::<Health>().get_mut(entity) {
health.change_by(change);
}
}
pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3<f32>) {
let ecs = &server.state.ecs();
@ -559,15 +565,22 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
let state = &server.state;
if vel.z <= -30.0 {
if let Some(mut health) = state.ecs().write_storage::<comp::Health>().get_mut(entity) {
let falldmg = (vel.z.powi(2) / 20.0 - 40.0) * 10.0;
let damage = Damage {
source: DamageSource::Falling,
value: falldmg,
poise_damage: 70.0,
};
let inventories = state.ecs().read_storage::<Inventory>();
let change = damage.modify_damage(inventories.get(entity), None);
health.change_by(change);
if let Some(poise) = state.ecs().write_storage::<comp::Poise>().get_mut(entity) {
let falldmg = (vel.z.powi(2) / 20.0 - 40.0) * 10.0;
let damage = Damage {
source: DamageSource::Falling,
value: falldmg,
};
let poise_damage = PoiseChange {
amount: -(falldmg / 2.0) as i32,
source: PoiseSource::Falling,
};
let inventories = state.ecs().read_storage::<Inventory>();
let change = damage.modify_damage(inventories.get(entity), None);
let poise_change = poise_damage.modify_poise_damage(inventories.get(entity), None);
health.change_by(change);
poise.change_by(poise_change);
}
}
}
}
@ -641,15 +654,29 @@ pub fn handle_explosion(
} 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: true, //explosion
//.effects
//.iter()
////.any(|e| matches!(e, RadiusEffect::Entity(_, Effect::Damage(_)))),
//.any(|e| match e {
// RadiusEffect::Entity(_, effect_vec) => {
// effect_vec.iter().any(|f| {
// matches!(
// f,
// Effect::Damage(Damage {
// source: DamageSource::Healing,
// ..
// })
// )
// })
// },
//}),
reagent,
});
let owner_entity = owner.and_then(|uid| {
@ -733,7 +760,7 @@ pub fn handle_explosion(
.cast();
}
},
RadiusEffect::Entity(target, mut effect) => {
RadiusEffect::Entity(target, mut effects) => {
for (entity_b, pos_b) in (&ecs.entities(), &ecs.read_storage::<comp::Pos>()).join()
{
// See if entities are in the same group
@ -767,17 +794,19 @@ pub fn handle_explosion(
.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,
});
for effect in effects.iter_mut() {
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,
});
}
}
}
}

View File

@ -9,7 +9,7 @@ use entity_creation::{
};
use entity_manipulation::{
handle_aura, handle_buff, handle_damage, handle_delete, handle_destroy, handle_energy_change,
handle_explosion, handle_knockback, handle_land_on_ground, handle_respawn,
handle_explosion, handle_knockback, handle_land_on_ground, handle_poise, handle_respawn,
};
use group_manip::handle_group;
use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
@ -83,6 +83,7 @@ impl Server {
handle_knockback(&self, entity, impulse)
},
ServerEvent::Damage { entity, change } => handle_damage(&self, entity, change),
ServerEvent::PoiseChange { entity, change } => handle_poise(&self, entity, change),
ServerEvent::Delete(entity) => handle_delete(self, entity),
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),

View File

@ -1,5 +1,5 @@
use common::{
comp::{HealthSource, Object, PhysicsState, Pos, Vel},
comp::{HealthSource, Object, PhysicsState, PoiseChange, PoiseSource, Pos, Vel},
effect::Effect,
event::{EventBus, ServerEvent},
resources::DeltaTime,
@ -49,14 +49,16 @@ impl<'a> System<'a> for Sys {
pos: pos.0,
explosion: Explosion {
effects: vec![
RadiusEffect::Entity(
None,
RadiusEffect::Entity(None, vec![
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 500.0,
poise_damage: 60.0,
}),
),
Effect::Poise(PoiseChange {
amount: -60,
source: PoiseSource::Explosion,
}),
]),
RadiusEffect::TerrainDestruction(4.0),
],
radius: 12.0,
@ -77,14 +79,16 @@ impl<'a> System<'a> for Sys {
pos: pos.0,
explosion: Explosion {
effects: vec![
RadiusEffect::Entity(
None,
RadiusEffect::Entity(None, vec![
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 50.0,
poise_damage: 10.0,
}),
),
Effect::Poise(PoiseChange {
amount: -30,
source: PoiseSource::Explosion,
}),
]),
RadiusEffect::TerrainDestruction(4.0),
],
radius: 12.0,