mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add knockback to poise
This commit is contained in:
parent
e3965ae0ab
commit
af076aa87f
@ -612,8 +612,8 @@ impl Body {
|
||||
|
||||
pub fn base_poise_dmg(&self) -> u32 {
|
||||
match self {
|
||||
Body::Humanoid(_) => 100,
|
||||
_ => 50,
|
||||
Body::Humanoid(_) => 5,
|
||||
_ => 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,10 +108,6 @@ impl CharacterState {
|
||||
matches!(self, CharacterState::Sneak | CharacterState::Roll(_))
|
||||
}
|
||||
|
||||
pub fn is_stunned(&self) -> bool {
|
||||
matches!(self, CharacterState::Stunned { .. } | CharacterState::Staggered { .. })
|
||||
}
|
||||
|
||||
pub fn is_attack(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
@ -155,6 +151,13 @@ impl CharacterState {
|
||||
matches!(self, CharacterState::Roll(d) if d.static_data.immune_melee)
|
||||
}
|
||||
|
||||
pub fn is_stunned(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
CharacterState::Stunned(_) | CharacterState::Staggered(_)
|
||||
)
|
||||
}
|
||||
|
||||
/// Compares for shallow equality (does not check internal struct equality)
|
||||
pub fn same_variant(&self, other: &Self) -> bool {
|
||||
// Check if state is the same without looking at the inner data
|
||||
|
@ -83,6 +83,7 @@ pub enum PoiseSource {
|
||||
Shockwave,
|
||||
Falling,
|
||||
Revive,
|
||||
Regen,
|
||||
Other,
|
||||
}
|
||||
|
||||
@ -95,6 +96,7 @@ pub struct Poise {
|
||||
pub is_stunned: bool,
|
||||
pub is_dazed: bool,
|
||||
pub is_knockeddown: bool,
|
||||
pub regen_rate: f32,
|
||||
}
|
||||
|
||||
impl Default for Poise {
|
||||
@ -107,6 +109,7 @@ impl Default for Poise {
|
||||
is_stunned: false,
|
||||
is_dazed: false,
|
||||
is_knockeddown: false,
|
||||
regen_rate: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ pub enum ServerEvent {
|
||||
PoiseChange {
|
||||
entity: EcsEntity,
|
||||
change: comp::PoiseChange,
|
||||
kb_dir: Vec3<f32>,
|
||||
},
|
||||
Delete(EcsEntity),
|
||||
Destroy {
|
||||
|
@ -170,7 +170,6 @@ 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 {
|
||||
effects: vec![(
|
||||
Some(GroupTarget::OutOfGroup),
|
||||
|
@ -6,6 +6,7 @@ use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::{DeltaTime, Time},
|
||||
uid::{Uid, UidAllocator},
|
||||
util::Dir,
|
||||
GroupTarget,
|
||||
};
|
||||
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||
@ -170,6 +171,7 @@ impl<'a> System<'a> for Sys {
|
||||
let poise_change = poise_damage
|
||||
.modify_poise_damage(inventories.get(b), beam_segment.owner);
|
||||
|
||||
let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));
|
||||
match target {
|
||||
Some(GroupTarget::OutOfGroup) => {
|
||||
server_emitter.emit(ServerEvent::Damage { entity: b, change });
|
||||
@ -188,6 +190,7 @@ impl<'a> System<'a> for Sys {
|
||||
server_emitter.emit(ServerEvent::PoiseChange {
|
||||
entity,
|
||||
change: poise_change,
|
||||
kb_dir: *kb_dir,
|
||||
});
|
||||
server_emitter.emit(ServerEvent::EnergyChange {
|
||||
entity,
|
||||
|
@ -101,6 +101,9 @@ impl<'a> System<'a> for Sys {
|
||||
// Check if entity is dodging
|
||||
let is_dodge = char_state_b_maybe.map_or(false, |c_s| c_s.is_melee_dodge());
|
||||
|
||||
// Check if entity is stunned
|
||||
let is_stunned = char_state_b_maybe.map_or(false, |c_s| c_s.is_stunned());
|
||||
|
||||
// Check if it is a hit
|
||||
if entity != b
|
||||
&& !health_b.is_dead
|
||||
@ -123,7 +126,8 @@ impl<'a> System<'a> for Sys {
|
||||
for (target, damage, poise_change) in attack.effects.iter() {
|
||||
if let Some(target) = target {
|
||||
if *target != target_group
|
||||
|| (!matches!(target, GroupTarget::InGroup) && is_dodge)
|
||||
|| (!matches!(target, GroupTarget::InGroup)
|
||||
&& (is_dodge || is_stunned))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -132,13 +136,7 @@ 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.amount < 0 && thread_rng().gen::<f32>() < 0.1 {
|
||||
@ -162,6 +160,12 @@ impl<'a> System<'a> for Sys {
|
||||
server_emitter.emit(ServerEvent::Knockback { entity: b, impulse });
|
||||
}
|
||||
|
||||
server_emitter.emit(ServerEvent::PoiseChange {
|
||||
entity: b,
|
||||
change: *poise_change,
|
||||
kb_dir: *kb_dir,
|
||||
});
|
||||
|
||||
attack.hit_count += 1;
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ impl<'a> System<'a> for Sys {
|
||||
server_emitter.emit(ServerEvent::PoiseChange {
|
||||
entity: other_entity,
|
||||
change: poise_change,
|
||||
kb_dir: *ori.0,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -204,10 +204,6 @@ impl<'a> System<'a> for Sys {
|
||||
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));
|
||||
@ -215,6 +211,11 @@ impl<'a> System<'a> for Sys {
|
||||
if !impulse.is_approx_zero() {
|
||||
server_emitter.emit(ServerEvent::Knockback { entity: b, impulse });
|
||||
}
|
||||
server_emitter.emit(ServerEvent::PoiseChange {
|
||||
entity: b,
|
||||
change: poise_change,
|
||||
kb_dir: *kb_dir,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use common::{
|
||||
comp::{
|
||||
skills::{GeneralSkill, Skill},
|
||||
Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats,
|
||||
Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Poise, PoiseChange,
|
||||
PoiseSource, Pos, Stats,
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
metrics::SysMetrics,
|
||||
@ -14,6 +15,7 @@ use hashbrown::HashSet;
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage};
|
||||
|
||||
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||
//const POISE_REGEN_ACCEL: f32 = 5.0;
|
||||
|
||||
/// This system kills players, levels them up, and regenerates energy.
|
||||
pub struct Sys;
|
||||
@ -27,6 +29,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, CharacterState>,
|
||||
WriteStorage<'a, Stats>,
|
||||
WriteStorage<'a, Health>,
|
||||
WriteStorage<'a, Poise>,
|
||||
WriteStorage<'a, Energy>,
|
||||
ReadStorage<'a, Uid>,
|
||||
ReadStorage<'a, Pos>,
|
||||
@ -44,6 +47,7 @@ impl<'a> System<'a> for Sys {
|
||||
character_states,
|
||||
mut stats,
|
||||
mut healths,
|
||||
mut poises,
|
||||
mut energies,
|
||||
uids,
|
||||
positions,
|
||||
@ -147,9 +151,13 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
// Update energies
|
||||
for (character_state, mut energy) in
|
||||
(&character_states, &mut energies.restrict_mut()).join()
|
||||
// Update energies and poises
|
||||
for (character_state, mut energy, mut poise) in (
|
||||
&character_states,
|
||||
&mut energies.restrict_mut(),
|
||||
&mut poises.restrict_mut(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
match character_state {
|
||||
// Accelerate recharging energy.
|
||||
@ -179,6 +187,23 @@ impl<'a> System<'a> for Sys {
|
||||
energy.regen_rate =
|
||||
(energy.regen_rate + ENERGY_REGEN_ACCEL * dt.0).min(100.0);
|
||||
}
|
||||
|
||||
//let res_poise = {
|
||||
// let poise = poise.get_unchecked();
|
||||
// poise.current() < poise.maximum()
|
||||
//};
|
||||
|
||||
//if res_poise {
|
||||
// let mut poise = poise.get_mut_unchecked();
|
||||
// poise.change_by(PoiseChange {
|
||||
// amount: (poise.regen_rate * dt.0
|
||||
// + POISE_REGEN_ACCEL * dt.0.powi(2) / 2.0)
|
||||
// as i32,
|
||||
// source: PoiseSource::Regen,
|
||||
// });
|
||||
// poise.regen_rate = (poise.regen_rate +
|
||||
// POISE_REGEN_ACCEL * dt.0).min(100.0);
|
||||
//}
|
||||
},
|
||||
// Ability and glider use does not regen and sets the rate back to zero.
|
||||
CharacterState::Glide { .. }
|
||||
@ -217,7 +242,10 @@ impl<'a> System<'a> for Sys {
|
||||
CharacterState::Roll { .. }
|
||||
| CharacterState::Climb { .. }
|
||||
| CharacterState::Stunned { .. }
|
||||
| CharacterState::Staggered { .. } => {},
|
||||
| CharacterState::Staggered { .. } => {
|
||||
let poise = poise.get_unchecked();
|
||||
println!("Poise: {:?}", poise.current());
|
||||
},
|
||||
}
|
||||
}
|
||||
sys_metrics.stats_ns.store(
|
||||
|
@ -36,7 +36,12 @@ use std::time::Duration;
|
||||
use tracing::error;
|
||||
use vek::Vec3;
|
||||
|
||||
pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) {
|
||||
pub fn handle_poise(
|
||||
server: &Server,
|
||||
entity: EcsEntity,
|
||||
change: PoiseChange,
|
||||
knockback_dir: Vec3<f32>,
|
||||
) {
|
||||
let ecs = &server.state.ecs();
|
||||
if let Some(poise) = ecs.write_storage::<Poise>().get_mut(entity) {
|
||||
poise.change_by(change);
|
||||
@ -57,7 +62,7 @@ pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) {
|
||||
static_data: common::states::stunned::StaticData {
|
||||
buildup_duration: Duration::from_millis(250),
|
||||
recover_duration: Duration::from_millis(250),
|
||||
knockback: Knockback::Away(0.0),
|
||||
knockback: Knockback::Away(20.0),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
@ -71,47 +76,50 @@ pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) {
|
||||
entity,
|
||||
comp::CharacterState::Stunned(common::states::stunned::Data {
|
||||
static_data: common::states::stunned::StaticData {
|
||||
buildup_duration: Duration::from_millis(250),
|
||||
recover_duration: Duration::from_millis(250),
|
||||
knockback: Knockback::Away(0.0),
|
||||
buildup_duration: Duration::from_millis(500),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
knockback: Knockback::Away(40.0),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
handle_knockback(server, entity, 50.0 * knockback_dir);
|
||||
},
|
||||
PoiseState::Dazed => {
|
||||
poise.reset();
|
||||
let _ = ecs.write_storage::<comp::CharacterState>().insert(
|
||||
entity,
|
||||
comp::CharacterState::Stunned(common::states::stunned::Data {
|
||||
static_data: common::states::stunned::StaticData {
|
||||
buildup_duration: Duration::from_millis(250),
|
||||
recover_duration: Duration::from_millis(250),
|
||||
knockback: Knockback::Away(0.0),
|
||||
comp::CharacterState::Staggered(common::states::staggered::Data {
|
||||
static_data: common::states::staggered::StaticData {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(1000),
|
||||
knockback: Knockback::Away(50.0),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
handle_knockback(server, entity, 50.0 * knockback_dir);
|
||||
},
|
||||
PoiseState::KnockedDown => {
|
||||
poise.reset();
|
||||
let _ = ecs.write_storage::<comp::CharacterState>().insert(
|
||||
entity,
|
||||
comp::CharacterState::Stunned(common::states::stunned::Data {
|
||||
static_data: common::states::stunned::StaticData {
|
||||
buildup_duration: Duration::from_millis(250),
|
||||
comp::CharacterState::Staggered(common::states::staggered::Data {
|
||||
static_data: common::states::staggered::StaticData {
|
||||
buildup_duration: Duration::from_millis(5000),
|
||||
recover_duration: Duration::from_millis(250),
|
||||
knockback: Knockback::Away(0.0),
|
||||
knockback: Knockback::Away(200.0),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
handle_knockback(server, entity, 100.0 * knockback_dir);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,11 @@ 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::PoiseChange {
|
||||
entity,
|
||||
change,
|
||||
kb_dir,
|
||||
} => handle_poise(&self, entity, change, kb_dir),
|
||||
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),
|
||||
|
@ -55,7 +55,7 @@ impl<'a> System<'a> for Sys {
|
||||
value: 500.0,
|
||||
}),
|
||||
Effect::Poise(PoiseChange {
|
||||
amount: -60,
|
||||
amount: -80,
|
||||
source: PoiseSource::Explosion,
|
||||
}),
|
||||
]),
|
||||
|
Loading…
Reference in New Issue
Block a user