mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Initial broken implementation of poise
Character movement no longer broken.
This commit is contained in:
parent
8b97199245
commit
c83296a4ec
286
4
Normal file
286
4
Normal file
@ -0,0 +1,286 @@
|
||||
use crate::{
|
||||
comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate},
|
||||
states::{
|
||||
behavior::{CharacterBehavior, JoinData},
|
||||
utils::*,
|
||||
},
|
||||
Damage, DamageSource, GroupTarget, Knockback,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Stage<T> {
|
||||
/// Specifies which stage the combo attack is in
|
||||
pub stage: u32,
|
||||
/// Initial damage of stage
|
||||
pub base_damage: u32,
|
||||
/// Max damage of stage
|
||||
pub max_damage: u32,
|
||||
/// Damage scaling per combo
|
||||
pub damage_increase: u32,
|
||||
/// Initial poise damage of stage
|
||||
pub base_poise_damage: u32,
|
||||
/// Knockback of stage
|
||||
pub knockback: f32,
|
||||
/// Range of attack
|
||||
pub range: f32,
|
||||
/// Angle of attack
|
||||
pub angle: f32,
|
||||
/// Initial buildup duration of stage (how long until state can deal damage)
|
||||
pub base_buildup_duration: T,
|
||||
/// Duration of stage spent in swing (controls animation stuff, and can also
|
||||
/// be used to handle movement separately to buildup)
|
||||
pub base_swing_duration: T,
|
||||
/// Initial recover duration of stage (how long until character exits state)
|
||||
pub base_recover_duration: T,
|
||||
/// How much forward movement there is in the swing portion of the stage
|
||||
pub forward_movement: f32,
|
||||
}
|
||||
|
||||
impl Stage<u64> {
|
||||
pub fn to_duration(self) -> Stage<Duration> {
|
||||
Stage::<Duration> {
|
||||
stage: self.stage,
|
||||
base_damage: self.base_damage,
|
||||
max_damage: self.max_damage,
|
||||
damage_increase: self.damage_increase,
|
||||
base_poise_damage: self.base_poise_damage,
|
||||
knockback: self.knockback,
|
||||
range: self.range,
|
||||
angle: self.angle,
|
||||
base_buildup_duration: Duration::from_millis(self.base_buildup_duration),
|
||||
base_swing_duration: Duration::from_millis(self.base_swing_duration),
|
||||
base_recover_duration: Duration::from_millis(self.base_recover_duration),
|
||||
forward_movement: self.forward_movement,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn adjusted_by_stats(mut self, power: f32, speed: f32) -> Self {
|
||||
self.base_damage = (self.base_damage as f32 * power) as u32;
|
||||
self.max_damage = (self.max_damage as f32 * power) as u32;
|
||||
self.damage_increase = (self.damage_increase as f32 * power) as u32;
|
||||
self.base_buildup_duration = (self.base_buildup_duration as f32 / speed) as u64;
|
||||
self.base_swing_duration = (self.base_swing_duration as f32 / speed) as u64;
|
||||
self.base_recover_duration = (self.base_recover_duration as f32 / speed) as u64;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
/// Separated out to condense update portions of character state
|
||||
pub struct StaticData {
|
||||
/// Indicates number of stages in combo
|
||||
pub num_stages: u32,
|
||||
/// Data for each stage
|
||||
pub stage_data: Vec<Stage<Duration>>,
|
||||
/// Initial energy gain per strike
|
||||
pub initial_energy_gain: u32,
|
||||
/// Max energy gain per strike
|
||||
pub max_energy_gain: u32,
|
||||
/// Energy gain increase per combo
|
||||
pub energy_increase: u32,
|
||||
/// (100% - speed_increase) is percentage speed increases from current to
|
||||
/// max when combo increases
|
||||
pub speed_increase: f32,
|
||||
/// (100% + max_speed_increase) is the max attack speed
|
||||
pub max_speed_increase: f32,
|
||||
/// Whether the state can be interrupted by other abilities
|
||||
pub is_interruptible: bool,
|
||||
/// What key is used to press ability
|
||||
pub ability_key: AbilityKey,
|
||||
}
|
||||
/// A sequence of attacks that can incrementally become faster and more
|
||||
/// damaging.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Struct containing data that does not change over the course of the
|
||||
/// character state
|
||||
pub static_data: StaticData,
|
||||
/// Indicates what stage the combo is in
|
||||
pub stage: u32,
|
||||
/// Number of consecutive strikes
|
||||
pub combo: u32,
|
||||
/// Timer for each stage
|
||||
pub timer: Duration,
|
||||
/// Checks what section a stage is in
|
||||
pub stage_section: StageSection,
|
||||
/// Whether the state should go onto the next stage
|
||||
pub next_stage: bool,
|
||||
}
|
||||
|
||||
impl CharacterBehavior for Data {
|
||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||
let mut update = StateUpdate::from(data);
|
||||
|
||||
handle_orientation(data, &mut update, 1.0);
|
||||
handle_move(data, &mut update, 0.3);
|
||||
if !ability_key_is_pressed(data, self.static_data.ability_key) {
|
||||
handle_interrupt(data, &mut update, self.static_data.is_interruptible);
|
||||
if let CharacterState::Roll(roll) = &mut update.character {
|
||||
roll.was_combo = Some((self.stage, self.combo));
|
||||
}
|
||||
match update.character {
|
||||
CharacterState::ComboMelee(_) => {},
|
||||
_ => {
|
||||
return update;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let stage_index = (self.stage - 1) as usize;
|
||||
|
||||
let speed_modifer = 1.0
|
||||
+ self.static_data.max_speed_increase
|
||||
* (1.0 - self.static_data.speed_increase.powi(self.combo as i32));
|
||||
|
||||
match self.stage_section {
|
||||
StageSection::Buildup => {
|
||||
if self.timer < self.static_data.stage_data[stage_index].base_buildup_duration {
|
||||
// Build up
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to swing section of stage
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Swing,
|
||||
..*self
|
||||
});
|
||||
|
||||
// Hit attempt
|
||||
let damage = self.static_data.stage_data[stage_index].max_damage.min(
|
||||
self.static_data.stage_data[stage_index].base_damage
|
||||
+ 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;
|
||||
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,
|
||||
})],
|
||||
range: self.static_data.stage_data[stage_index].range,
|
||||
max_angle: self.static_data.stage_data[stage_index].angle.to_radians(),
|
||||
applied: false,
|
||||
hit_count: 0,
|
||||
knockback: Knockback::Away(
|
||||
self.static_data.stage_data[stage_index].knockback,
|
||||
),
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Swing => {
|
||||
if self.timer < self.static_data.stage_data[stage_index].base_swing_duration {
|
||||
// Forward movement
|
||||
handle_forced_movement(
|
||||
data,
|
||||
&mut update,
|
||||
ForcedMovement::Forward {
|
||||
strength: self.static_data.stage_data[stage_index].forward_movement,
|
||||
},
|
||||
0.3,
|
||||
);
|
||||
|
||||
// Swings
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to recover section of stage
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
if self.timer < self.static_data.stage_data[stage_index].base_recover_duration {
|
||||
// Recovers
|
||||
if ability_key_is_pressed(data, self.static_data.ability_key) {
|
||||
// Checks if state will transition to next stage after recover
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
||||
.unwrap_or_default(),
|
||||
next_stage: true,
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
}
|
||||
} else if self.next_stage {
|
||||
// Transitions to buildup section of next stage
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
stage: (self.stage % self.static_data.num_stages) + 1,
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Buildup,
|
||||
next_stage: false,
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Done
|
||||
update.character = CharacterState::Wielding;
|
||||
// Make sure attack component is removed
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If it somehow ends up in an incorrect stage section
|
||||
update.character = CharacterState::Wielding;
|
||||
// Make sure attack component is removed
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
},
|
||||
}
|
||||
|
||||
// Grant energy on successful hit
|
||||
if let Some(attack) = data.attacking {
|
||||
if attack.applied && attack.hit_count > 0 {
|
||||
let energy = self.static_data.max_energy_gain.min(
|
||||
self.static_data.initial_energy_gain
|
||||
+ self.combo * self.static_data.energy_increase,
|
||||
) as i32;
|
||||
update.character = CharacterState::ComboMelee(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
stage: self.stage,
|
||||
combo: self.combo + 1,
|
||||
timer: self.timer,
|
||||
stage_section: self.stage_section,
|
||||
next_stage: self.next_stage,
|
||||
});
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
update.energy.change_by(EnergyChange {
|
||||
amount: energy,
|
||||
source: EnergySource::HitEnemy,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
update
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ ComboMelee(
|
||||
(
|
||||
stage: 1,
|
||||
base_damage: 90,
|
||||
max_damage: 110,
|
||||
base_poise_damage: 40,
|
||||
damage_increase: 10,
|
||||
knockback: 8.0,
|
||||
range: 3.5,
|
||||
@ -15,6 +17,8 @@ ComboMelee(
|
||||
(
|
||||
stage: 2,
|
||||
base_damage: 130,
|
||||
max_damage: 160,
|
||||
base_poise_damage: 40,
|
||||
damage_increase: 15,
|
||||
knockback: 12.0,
|
||||
range: 3.5,
|
||||
@ -32,4 +36,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.6,
|
||||
scales_from_combo: 2,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -5,9 +5,10 @@ LeapMelee(
|
||||
swing_duration: 200,
|
||||
recover_duration: 200,
|
||||
base_damage: 240,
|
||||
base_poise_damage: 70,
|
||||
knockback: 12.0,
|
||||
range: 4.5,
|
||||
max_angle: 30.0,
|
||||
forward_leap_strength: 28.0,
|
||||
vertical_leap_strength: 8.0,
|
||||
)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ SpinMelee(
|
||||
swing_duration: 400,
|
||||
recover_duration: 200,
|
||||
base_damage: 60,
|
||||
base_poise_damage: 20,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
energy_cost: 100,
|
||||
@ -11,4 +12,4 @@ SpinMelee(
|
||||
is_interruptible: false,
|
||||
forward_speed: 0.0,
|
||||
num_spins: 1,
|
||||
)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ ChargedRanged(
|
||||
energy_drain: 300,
|
||||
initial_damage: 10,
|
||||
scaled_damage: 190,
|
||||
initial_poise_damage: 10,
|
||||
initial_knockback: 10.0,
|
||||
scaled_knockback: 10.0,
|
||||
speed: 1.0,
|
||||
|
@ -4,7 +4,8 @@ BasicMelee(
|
||||
swing_duration: 100,
|
||||
recover_duration: 300,
|
||||
base_damage: 50,
|
||||
base_poise_damage: 10,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 20.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,7 +4,8 @@ BasicMelee(
|
||||
swing_duration: 100,
|
||||
recover_duration: 900,
|
||||
base_damage: 20,
|
||||
base_poise_damage: 5,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 15.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,7 +4,8 @@ BasicMelee(
|
||||
swing_duration: 100,
|
||||
recover_duration: 150,
|
||||
base_damage: 50,
|
||||
base_poise_damage: 5,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 20.0,
|
||||
)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ ChargedMelee(
|
||||
energy_drain: 300,
|
||||
initial_damage: 10,
|
||||
scaled_damage: 160,
|
||||
initial_poise_damage: 10,
|
||||
initial_knockback: 10.0,
|
||||
scaled_knockback: 50.0,
|
||||
range: 3.5,
|
||||
|
@ -5,9 +5,10 @@ LeapMelee(
|
||||
swing_duration: 150,
|
||||
recover_duration: 200,
|
||||
base_damage: 240,
|
||||
base_poise_damage: 60,
|
||||
knockback: 25.0,
|
||||
range: 4.5,
|
||||
max_angle: 360.0,
|
||||
forward_leap_strength: 28.0,
|
||||
vertical_leap_strength: 8.0,
|
||||
)
|
||||
)
|
||||
|
@ -3,7 +3,8 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 130,
|
||||
damage_increase: 10,
|
||||
knockback: 10.0,
|
||||
base_poise_damage: 30,
|
||||
knockback: 0.0,
|
||||
range: 4.5,
|
||||
angle: 50.0,
|
||||
base_buildup_duration: 600,
|
||||
@ -18,4 +19,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.4,
|
||||
scales_from_combo: 2,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,7 +4,8 @@ BasicMelee(
|
||||
swing_duration: 100,
|
||||
recover_duration: 300,
|
||||
base_damage: 40,
|
||||
base_poise_damage: 20,
|
||||
knockback: 0.0,
|
||||
range: 3.0,
|
||||
max_angle: 120.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ Shockwave(
|
||||
swing_duration: 100,
|
||||
recover_duration: 300,
|
||||
damage: 200,
|
||||
poise_damage: 10,
|
||||
knockback: Away(25.0),
|
||||
shockwave_angle: 360.0,
|
||||
shockwave_vertical_angle: 90.0,
|
||||
@ -11,4 +12,4 @@ Shockwave(
|
||||
shockwave_duration: 500,
|
||||
requires_ground: false,
|
||||
move_efficiency: 0.1,
|
||||
)
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ DashMelee(
|
||||
energy_cost: 100,
|
||||
base_damage: 80,
|
||||
scaled_damage: 160,
|
||||
base_poise_damage: 20,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 7.0,
|
||||
range: 5.0,
|
||||
|
@ -3,6 +3,7 @@ SpinMelee(
|
||||
swing_duration: 400,
|
||||
recover_duration: 500,
|
||||
base_damage: 160,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
energy_cost: 150,
|
||||
@ -11,4 +12,4 @@ SpinMelee(
|
||||
is_interruptible: true,
|
||||
forward_speed: 1.0,
|
||||
num_spins: 3,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 10,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 15,
|
||||
base_poise_damage: 10,
|
||||
knockback: 12.0,
|
||||
range: 3.5,
|
||||
angle: 180.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 20,
|
||||
base_poise_damage: 10,
|
||||
knockback: 14.0,
|
||||
range: 6.0,
|
||||
angle: 10.0,
|
||||
@ -44,4 +47,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.8,
|
||||
scales_from_combo: 2,
|
||||
is_interruptible: true,
|
||||
)
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ BasicMelee(
|
||||
recover_duration: 250,
|
||||
knockback: 25.0,
|
||||
base_damage: 200,
|
||||
base_poise_damage: 30,
|
||||
range: 5.0,
|
||||
max_angle: 120.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 30,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
@ -20,4 +21,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -44,4 +47,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 150,
|
||||
scaled_damage: 110,
|
||||
base_poise_damage: 60,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 17.0,
|
||||
range: 5.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
|
@ -2,6 +2,7 @@ DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 30,
|
||||
scaled_damage: 10,
|
||||
base_poise_damage: 30,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 7.0,
|
||||
range: 2.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 2.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 2.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 2.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -40,6 +43,7 @@ ComboMelee(
|
||||
stage: 4,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 8.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -56,4 +60,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 60,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 30,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
@ -20,4 +21,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ ChargedMelee(
|
||||
energy_drain: 0,
|
||||
initial_damage: 160,
|
||||
scaled_damage: 40,
|
||||
initial_poise_damage: 50,
|
||||
initial_knockback: 10.0,
|
||||
scaled_knockback: 20.0,
|
||||
range: 6.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -44,4 +47,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 120,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
|
@ -2,6 +2,7 @@ DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 150,
|
||||
scaled_damage: 40,
|
||||
base_poise_damage: 40,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 17.0,
|
||||
range: 4.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
|
@ -4,7 +4,8 @@ BasicMelee(
|
||||
swing_duration: 500,
|
||||
recover_duration: 350,
|
||||
base_damage: 130,
|
||||
base_poise_damage: 70,
|
||||
knockback: 25.0,
|
||||
range: 3.0,
|
||||
max_angle: 120.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 8.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 8.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
|
@ -5,6 +5,7 @@ LeapMelee(
|
||||
swing_duration: 75,
|
||||
recover_duration: 200,
|
||||
base_damage: 240,
|
||||
base_poise_damage: 15,
|
||||
knockback: 12.0,
|
||||
range: 4.5,
|
||||
max_angle: 180.0,
|
||||
|
@ -5,6 +5,7 @@ LeapMelee(
|
||||
swing_duration: 75,
|
||||
recover_duration: 125,
|
||||
base_damage: 120,
|
||||
base_poise_damage: 15,
|
||||
knockback: 7.0,
|
||||
range: 4.5,
|
||||
max_angle: 180.0,
|
||||
|
@ -2,6 +2,7 @@ DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 130,
|
||||
scaled_damage: 20,
|
||||
base_poise_damage: 30,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 7.0,
|
||||
range: 2.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 150,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 150,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 150,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 30,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 60.0,
|
||||
@ -20,4 +21,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ BasicMelee(
|
||||
recover_duration: 250,
|
||||
knockback: 25.0,
|
||||
base_damage: 200,
|
||||
base_poise_damage: 80,
|
||||
range: 5.0,
|
||||
max_angle: 120.0,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ Shockwave(
|
||||
swing_duration: 200,
|
||||
recover_duration: 800,
|
||||
damage: 500,
|
||||
poise_damage: 50,
|
||||
knockback: TowardsUp(40.0),
|
||||
shockwave_angle: 90.0,
|
||||
shockwave_vertical_angle: 90.0,
|
||||
@ -11,4 +12,4 @@ Shockwave(
|
||||
shockwave_duration: 1000,
|
||||
requires_ground: true,
|
||||
move_efficiency: 0.05,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 150,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 15,
|
||||
knockback: 5.0,
|
||||
range: 7.5,
|
||||
angle: 60.0,
|
||||
@ -20,4 +21,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 170,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 7.5,
|
||||
angle: 30.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 190,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 5.5,
|
||||
angle: 30.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 230,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 5.5,
|
||||
angle: 30.0,
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 150,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 5.0,
|
||||
range: 5.5,
|
||||
angle: 5.0,
|
||||
@ -20,4 +21,4 @@ ComboMelee(
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
)
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ ComboMelee(
|
||||
stage: 1,
|
||||
base_damage: 170,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.5,
|
||||
angle: 5.0,
|
||||
@ -16,6 +17,7 @@ ComboMelee(
|
||||
stage: 2,
|
||||
base_damage: 190,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 10.0,
|
||||
@ -28,6 +30,7 @@ ComboMelee(
|
||||
stage: 3,
|
||||
base_damage: 230,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 10.0,
|
||||
|
@ -18,6 +18,7 @@ sum_type! {
|
||||
Auras(comp::Auras),
|
||||
Energy(comp::Energy),
|
||||
Health(comp::Health),
|
||||
Poise(comp::Poise),
|
||||
LightEmitter(comp::LightEmitter),
|
||||
Inventory(comp::Inventory),
|
||||
Item(comp::Item),
|
||||
@ -50,6 +51,7 @@ sum_type! {
|
||||
Auras(PhantomData<comp::Auras>),
|
||||
Energy(PhantomData<comp::Energy>),
|
||||
Health(PhantomData<comp::Health>),
|
||||
Poise(PhantomData<comp::Poise>),
|
||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||
Inventory(PhantomData<comp::Inventory>),
|
||||
Item(PhantomData<comp::Item>),
|
||||
@ -82,6 +84,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Health(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Poise(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Inventory(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
|
||||
@ -112,6 +115,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Health(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Poise(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Inventory(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
|
||||
@ -142,6 +146,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
||||
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
||||
EcsCompPhantom::Health(_) => sync::handle_remove::<comp::Health>(entity, world),
|
||||
EcsCompPhantom::Poise(_) => sync::handle_remove::<comp::Poise>(entity, world),
|
||||
EcsCompPhantom::LightEmitter(_) => {
|
||||
sync::handle_remove::<comp::LightEmitter>(entity, world)
|
||||
},
|
||||
|
@ -40,6 +40,7 @@ pub enum DamageSource {
|
||||
pub struct Damage {
|
||||
pub source: DamageSource,
|
||||
pub value: f32,
|
||||
pub poise_damage: f32,
|
||||
}
|
||||
|
||||
impl Damage {
|
||||
@ -68,7 +69,6 @@ impl Damage {
|
||||
pub fn modify_damage(self, inventory: Option<&Inventory>, uid: Option<Uid>) -> HealthChange {
|
||||
let mut damage = self.value;
|
||||
let damage_reduction = inventory.map_or(0.0, |inv| Damage::compute_damage_reduction(inv));
|
||||
|
||||
match self.source {
|
||||
DamageSource::Melee => {
|
||||
// Critical hit
|
||||
@ -84,13 +84,16 @@ 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
|
||||
@ -100,63 +103,82 @@ 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,
|
||||
(
|
||||
HealthChange {
|
||||
amount: -damage as i32,
|
||||
cause: HealthSource::Damage {
|
||||
kind: self.source,
|
||||
by: uid,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
DamageSource::Healing => HealthChange {
|
||||
amount: damage as i32,
|
||||
cause: HealthSource::Heal { by: uid },
|
||||
-poise_damage as i32,
|
||||
)
|
||||
},
|
||||
DamageSource::Healing => (
|
||||
HealthChange {
|
||||
amount: damage as i32,
|
||||
cause: HealthSource::Heal { by: uid },
|
||||
},
|
||||
0,
|
||||
),
|
||||
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,
|
||||
}
|
||||
(
|
||||
HealthChange {
|
||||
amount: -damage as i32,
|
||||
cause: HealthSource::World,
|
||||
},
|
||||
-poise_damage as i32,
|
||||
)
|
||||
},
|
||||
DamageSource::Buff(_) => HealthChange {
|
||||
amount: -damage as i32,
|
||||
@ -171,7 +193,8 @@ impl Damage {
|
||||
kind: self.source,
|
||||
by: uid,
|
||||
},
|
||||
},
|
||||
-poise_damage as i32,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ pub enum CharacterAbility {
|
||||
swing_duration: u64,
|
||||
recover_duration: u64,
|
||||
base_damage: u32,
|
||||
base_poise_damage: u32,
|
||||
knockback: f32,
|
||||
range: f32,
|
||||
max_angle: f32,
|
||||
@ -98,6 +99,7 @@ pub enum CharacterAbility {
|
||||
energy_cost: u32,
|
||||
base_damage: u32,
|
||||
scaled_damage: u32,
|
||||
base_poise_damage: u32,
|
||||
base_knockback: f32,
|
||||
scaled_knockback: f32,
|
||||
range: f32,
|
||||
@ -137,6 +139,7 @@ pub enum CharacterAbility {
|
||||
swing_duration: u64,
|
||||
recover_duration: u64,
|
||||
base_damage: u32,
|
||||
base_poise_damage: u32,
|
||||
range: f32,
|
||||
max_angle: f32,
|
||||
knockback: f32,
|
||||
@ -148,6 +151,7 @@ pub enum CharacterAbility {
|
||||
swing_duration: u64,
|
||||
recover_duration: u64,
|
||||
base_damage: u32,
|
||||
base_poise_damage: u32,
|
||||
knockback: f32,
|
||||
range: f32,
|
||||
energy_cost: u32,
|
||||
@ -162,6 +166,7 @@ pub enum CharacterAbility {
|
||||
energy_drain: u32,
|
||||
initial_damage: u32,
|
||||
scaled_damage: u32,
|
||||
initial_poise_damage: u32,
|
||||
initial_knockback: f32,
|
||||
scaled_knockback: f32,
|
||||
range: f32,
|
||||
@ -177,6 +182,7 @@ pub enum CharacterAbility {
|
||||
energy_drain: u32,
|
||||
initial_damage: u32,
|
||||
scaled_damage: u32,
|
||||
initial_poise_damage: u32,
|
||||
initial_knockback: f32,
|
||||
scaled_knockback: f32,
|
||||
speed: f32,
|
||||
@ -196,6 +202,7 @@ pub enum CharacterAbility {
|
||||
swing_duration: u64,
|
||||
recover_duration: u64,
|
||||
damage: u32,
|
||||
poise_damage: u32,
|
||||
knockback: Knockback,
|
||||
shockwave_angle: f32,
|
||||
shockwave_vertical_angle: f32,
|
||||
@ -228,6 +235,7 @@ impl Default for CharacterAbility {
|
||||
swing_duration: 250,
|
||||
recover_duration: 500,
|
||||
base_damage: 10,
|
||||
base_poise_damage: 10,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 15.0,
|
||||
@ -1071,6 +1079,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration,
|
||||
recover_duration,
|
||||
base_damage,
|
||||
base_poise_damage,
|
||||
knockback,
|
||||
range,
|
||||
max_angle,
|
||||
@ -1081,6 +1090,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration: Duration::from_millis(*swing_duration),
|
||||
recover_duration: Duration::from_millis(*recover_duration),
|
||||
base_damage: *base_damage,
|
||||
base_poise_damage: *base_poise_damage,
|
||||
knockback: *knockback,
|
||||
range: *range,
|
||||
max_angle: *max_angle,
|
||||
@ -1131,6 +1141,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
energy_cost: _,
|
||||
base_damage,
|
||||
scaled_damage,
|
||||
base_poise_damage,
|
||||
base_knockback,
|
||||
scaled_knockback,
|
||||
range,
|
||||
@ -1147,6 +1158,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
static_data: dash_melee::StaticData {
|
||||
base_damage: *base_damage,
|
||||
scaled_damage: *scaled_damage,
|
||||
base_poise_damage: *base_poise_damage,
|
||||
base_knockback: *base_knockback,
|
||||
scaled_knockback: *scaled_knockback,
|
||||
range: *range,
|
||||
@ -1224,6 +1236,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration,
|
||||
recover_duration,
|
||||
base_damage,
|
||||
base_poise_damage,
|
||||
knockback,
|
||||
range,
|
||||
max_angle,
|
||||
@ -1236,6 +1249,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration: Duration::from_millis(*swing_duration),
|
||||
recover_duration: Duration::from_millis(*recover_duration),
|
||||
base_damage: *base_damage,
|
||||
base_poise_damage: *base_poise_damage,
|
||||
knockback: *knockback,
|
||||
range: *range,
|
||||
max_angle: *max_angle,
|
||||
@ -1252,6 +1266,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration,
|
||||
recover_duration,
|
||||
base_damage,
|
||||
base_poise_damage,
|
||||
knockback,
|
||||
range,
|
||||
energy_cost,
|
||||
@ -1266,6 +1281,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration: Duration::from_millis(*swing_duration),
|
||||
recover_duration: Duration::from_millis(*recover_duration),
|
||||
base_damage: *base_damage,
|
||||
base_poise_damage: *base_damage,
|
||||
knockback: *knockback,
|
||||
range: *range,
|
||||
energy_cost: *energy_cost,
|
||||
@ -1286,6 +1302,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
energy_drain,
|
||||
initial_damage,
|
||||
scaled_damage,
|
||||
initial_poise_damage,
|
||||
initial_knockback,
|
||||
scaled_knockback,
|
||||
speed,
|
||||
@ -1301,6 +1318,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
energy_drain: *energy_drain,
|
||||
initial_damage: *initial_damage,
|
||||
scaled_damage: *scaled_damage,
|
||||
initial_poise_damage: *initial_poise_damage,
|
||||
initial_knockback: *initial_knockback,
|
||||
scaled_knockback: *scaled_knockback,
|
||||
speed: *speed,
|
||||
@ -1322,6 +1340,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
energy_drain,
|
||||
initial_damage,
|
||||
scaled_damage,
|
||||
initial_poise_damage,
|
||||
initial_knockback,
|
||||
scaled_knockback,
|
||||
speed,
|
||||
@ -1342,6 +1361,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
energy_drain: *energy_drain,
|
||||
initial_damage: *initial_damage,
|
||||
scaled_damage: *scaled_damage,
|
||||
initial_poise_damage: *initial_poise_damage,
|
||||
speed: *speed,
|
||||
initial_knockback: *initial_knockback,
|
||||
scaled_knockback: *scaled_knockback,
|
||||
@ -1394,6 +1414,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration,
|
||||
recover_duration,
|
||||
damage,
|
||||
poise_damage,
|
||||
knockback,
|
||||
shockwave_angle,
|
||||
shockwave_vertical_angle,
|
||||
@ -1407,6 +1428,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
swing_duration: Duration::from_millis(*swing_duration),
|
||||
recover_duration: Duration::from_millis(*recover_duration),
|
||||
damage: *damage,
|
||||
poise_damage: *poise_damage,
|
||||
knockback: *knockback,
|
||||
shockwave_angle: *shockwave_angle,
|
||||
shockwave_vertical_angle: *shockwave_vertical_angle,
|
||||
|
@ -444,6 +444,14 @@ impl Body {
|
||||
// TODO: Match on species
|
||||
pub fn combat_multiplier(&self) -> f32 { if let Body::Object(_) = self { 0.0 } else { 1.0 } }
|
||||
|
||||
pub fn base_poise(&self) -> u32 {
|
||||
match self {
|
||||
Body::Humanoid(_) => 100,
|
||||
Body::BipedLarge(_) => 200,
|
||||
_ => 100,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
pub fn base_exp(&self) -> u32 {
|
||||
match self {
|
||||
@ -602,6 +610,13 @@ impl Body {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_poise_dmg(&self) -> u32 {
|
||||
match self {
|
||||
Body::Humanoid(_) => 100,
|
||||
_ => 50,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_range(&self) -> f32 {
|
||||
match self {
|
||||
Body::Humanoid(_) => 5.0,
|
||||
|
@ -44,6 +44,10 @@ pub enum CharacterState {
|
||||
Sneak,
|
||||
Glide,
|
||||
GlideWield,
|
||||
/// A stunned state
|
||||
Stunned(stunned::Data),
|
||||
/// A stagger state similar to a stun but knocked to the ground
|
||||
Staggered(staggered::Data),
|
||||
/// A basic blocking state
|
||||
BasicBlock,
|
||||
/// Player is busy equipping or unequipping weapons
|
||||
@ -104,6 +108,10 @@ 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,
|
||||
|
@ -19,6 +19,7 @@ mod location;
|
||||
mod misc;
|
||||
mod phys;
|
||||
mod player;
|
||||
pub mod poise;
|
||||
pub mod projectile;
|
||||
pub mod shockwave;
|
||||
pub mod skills;
|
||||
@ -65,6 +66,7 @@ pub use phys::{
|
||||
Sticky, Vel,
|
||||
};
|
||||
pub use player::Player;
|
||||
pub use poise::{Poise, PoiseState};
|
||||
pub use projectile::{Projectile, ProjectileConstructor};
|
||||
pub use shockwave::{Shockwave, ShockwaveHitEntities};
|
||||
pub use skills::{Skill, SkillGroup, SkillGroupKind, SkillSet};
|
||||
|
106
common/src/comp/poise.rs
Normal file
106
common/src/comp/poise.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use crate::{comp::Body, sync::Uid, DamageSource};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct Poise {
|
||||
base_max: u32,
|
||||
current: u32,
|
||||
maximum: u32,
|
||||
pub is_interrupted: bool,
|
||||
pub is_stunned: bool,
|
||||
pub is_dazed: bool,
|
||||
pub is_knockeddown: bool,
|
||||
}
|
||||
|
||||
impl Default for Poise {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
current: 0,
|
||||
maximum: 0,
|
||||
base_max: 0,
|
||||
is_interrupted: false,
|
||||
is_stunned: false,
|
||||
is_dazed: false,
|
||||
is_knockeddown: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum PoiseState {
|
||||
Normal,
|
||||
Interrupted,
|
||||
Stunned,
|
||||
Dazed,
|
||||
KnockedDown,
|
||||
}
|
||||
|
||||
impl Poise {
|
||||
pub fn new(body: Body) -> Self {
|
||||
let mut poise = Poise::default();
|
||||
poise.update_max_poise(Some(body));
|
||||
poise.set_to(poise.maximum());
|
||||
|
||||
poise
|
||||
}
|
||||
|
||||
pub fn poise_state(&self) -> PoiseState {
|
||||
if self.current >= 5 * self.maximum / 10 {
|
||||
PoiseState::Normal
|
||||
} else if self.current >= 4 * self.maximum / 10 {
|
||||
PoiseState::Interrupted
|
||||
} else if self.current >= 3 * self.maximum / 10 {
|
||||
PoiseState::Stunned
|
||||
} else if self.current >= 2 * self.maximum / 10 {
|
||||
PoiseState::Dazed
|
||||
} else {
|
||||
PoiseState::KnockedDown
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current(&self) -> u32 { self.current }
|
||||
|
||||
pub fn maximum(&self) -> u32 { self.maximum }
|
||||
|
||||
pub fn set_to(&mut self, amount: u32) {
|
||||
let amount = amount.min(self.maximum);
|
||||
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 reset(&mut self) { self.current = self.maximum; }
|
||||
|
||||
pub fn set_maximum(&mut self, amount: u32) {
|
||||
self.maximum = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
}
|
||||
|
||||
fn set_base_max(&mut self, amount: u32) {
|
||||
self.base_max = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
}
|
||||
|
||||
pub fn reset_max(&mut self) { self.maximum = self.base_max; }
|
||||
|
||||
pub fn update_max_poise(&mut self, body: Option<Body>) {
|
||||
if let Some(body) = body {
|
||||
self.set_base_max(body.base_poise());
|
||||
self.set_maximum(body.base_poise());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_max_poise(mut self, amount: u32) -> Self {
|
||||
self.maximum = amount;
|
||||
self.current = amount;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Poise {
|
||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||
}
|
@ -88,6 +88,7 @@ impl ProjectileConstructor {
|
||||
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
|
||||
source: DamageSource::Projectile,
|
||||
value: damage,
|
||||
poise_damage: 0.0,
|
||||
}),
|
||||
Effect::Knockback(Knockback::Away(knockback)),
|
||||
Effect::RewardEnergy(energy_regen),
|
||||
@ -115,6 +116,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: damage,
|
||||
poise_damage: 10.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::TerrainDestruction(2.0),
|
||||
@ -131,6 +133,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: damage,
|
||||
poise_damage: 10.0,
|
||||
}),
|
||||
)],
|
||||
radius,
|
||||
@ -172,6 +175,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: damage,
|
||||
poise_damage: 0.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::Entity(
|
||||
@ -179,6 +183,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Healing,
|
||||
value: heal,
|
||||
poise_damage: 0.0,
|
||||
}),
|
||||
),
|
||||
],
|
||||
@ -195,6 +200,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: damage,
|
||||
poise_damage: 0.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::Entity(
|
||||
@ -202,6 +208,7 @@ impl ProjectileConstructor {
|
||||
effect::Effect::Damage(Damage {
|
||||
source: DamageSource::Healing,
|
||||
value: heal,
|
||||
poise_damage: 0.0,
|
||||
}),
|
||||
),
|
||||
],
|
||||
|
@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Effect {
|
||||
Health(comp::HealthChange),
|
||||
Poise(i32),
|
||||
Damage(combat::Damage),
|
||||
Buff(BuffEffect),
|
||||
}
|
||||
@ -21,6 +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::Damage(d) => format!("{:+}", d.value),
|
||||
Effect::Buff(e) => format!("{:?} buff", e),
|
||||
}
|
||||
@ -31,6 +33,9 @@ impl Effect {
|
||||
Effect::Health(change) => {
|
||||
change.amount = (change.amount as f32 * modifier) as i32;
|
||||
},
|
||||
Effect::Poise(change) => {
|
||||
*change = (*change as f32 * modifier) as i32;
|
||||
},
|
||||
Effect::Damage(damage) => {
|
||||
damage.interpolate_damage(modifier, 0.0);
|
||||
},
|
||||
|
@ -34,7 +34,7 @@ pub enum ServerEvent {
|
||||
},
|
||||
Damage {
|
||||
entity: EcsEntity,
|
||||
change: comp::HealthChange,
|
||||
change: (comp::HealthChange, i32),
|
||||
},
|
||||
Delete(EcsEntity),
|
||||
Destroy {
|
||||
@ -98,6 +98,7 @@ pub enum ServerEvent {
|
||||
pos: comp::Pos,
|
||||
stats: comp::Stats,
|
||||
health: comp::Health,
|
||||
poise: comp::Poise,
|
||||
loadout: comp::inventory::loadout::Loadout,
|
||||
body: comp::Body,
|
||||
agent: Option<comp::Agent>,
|
||||
|
@ -122,10 +122,12 @@ 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 heal = Damage {
|
||||
source: DamageSource::Healing,
|
||||
value: self.static_data.base_hps as f32 / self.static_data.tick_rate,
|
||||
poise_damage: 0.0,
|
||||
};
|
||||
let speed =
|
||||
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
|
||||
|
@ -20,6 +20,8 @@ pub struct StaticData {
|
||||
pub recover_duration: Duration,
|
||||
/// Base damage
|
||||
pub base_damage: u32,
|
||||
/// Base poise reduction
|
||||
pub base_poise_damage: u32,
|
||||
/// Knockback
|
||||
pub knockback: f32,
|
||||
/// Max range
|
||||
@ -92,6 +94,7 @@ impl CharacterBehavior for Data {
|
||||
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,
|
||||
})],
|
||||
range: self.static_data.range,
|
||||
max_angle: 180_f32.to_radians(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
Attacking, Beam, Body, CharacterState, ControlAction, Controller, ControllerInputs, Energy,
|
||||
Health, Inventory, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
|
||||
Health, Inventory, Ori, PhysicsState, Poise, Pos, StateUpdate, Stats, Vel,
|
||||
},
|
||||
resources::DeltaTime,
|
||||
uid::Uid,
|
||||
@ -51,6 +51,7 @@ pub struct JoinData<'a> {
|
||||
pub controller: &'a Controller,
|
||||
pub inputs: &'a ControllerInputs,
|
||||
pub health: &'a Health,
|
||||
pub poise: Option<&'a Poise>,
|
||||
pub energy: &'a Energy,
|
||||
pub inventory: &'a Inventory,
|
||||
pub body: &'a Body,
|
||||
@ -80,6 +81,7 @@ pub type JoinTuple<'a> = (
|
||||
RestrictedMut<'a, Inventory>,
|
||||
&'a mut Controller,
|
||||
&'a Health,
|
||||
Option<&'a Poise>,
|
||||
&'a Body,
|
||||
&'a PhysicsState,
|
||||
Option<&'a Attacking>,
|
||||
@ -101,10 +103,11 @@ impl<'a> JoinData<'a> {
|
||||
controller: j.8,
|
||||
inputs: &j.8.inputs,
|
||||
health: j.9,
|
||||
body: j.10,
|
||||
physics: j.11,
|
||||
attacking: j.12,
|
||||
stats: j.14,
|
||||
poise: j.10,
|
||||
body: j.11,
|
||||
physics: j.12,
|
||||
attacking: j.13,
|
||||
stats: j.15,
|
||||
updater,
|
||||
dt,
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ pub struct StaticData {
|
||||
pub initial_knockback: f32,
|
||||
/// How much the knockback is scaled by
|
||||
pub scaled_knockback: f32,
|
||||
/// Initial poise damage
|
||||
pub initial_poise_damage: u32,
|
||||
/// Max range
|
||||
pub range: f32,
|
||||
/// Max angle (45.0 will give you a 90.0 angle window)
|
||||
@ -152,6 +154,7 @@ 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 knockback = self.static_data.initial_knockback
|
||||
+ self.charge_amount * self.static_data.scaled_knockback;
|
||||
|
@ -30,6 +30,8 @@ pub struct StaticData {
|
||||
pub initial_damage: u32,
|
||||
/// How much the damage scales as it is charged
|
||||
pub scaled_damage: u32,
|
||||
/// Initial poise damage
|
||||
pub initial_poise_damage: u32,
|
||||
/// How much knockback there is with no charge
|
||||
pub initial_knockback: f32,
|
||||
/// How much the knockback scales as it is charged
|
||||
@ -106,6 +108,7 @@ 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 knockback = self.static_data.initial_knockback
|
||||
+ charge_frac * self.static_data.scaled_knockback;
|
||||
|
@ -17,6 +17,8 @@ pub struct Stage<T> {
|
||||
pub base_damage: u32,
|
||||
/// Damage scaling per combo
|
||||
pub damage_increase: u32,
|
||||
/// Initial poise damage of stage
|
||||
pub base_poise_damage: u32,
|
||||
/// Knockback of stage
|
||||
pub knockback: f32,
|
||||
/// Range of attack
|
||||
@ -40,6 +42,7 @@ impl Stage<u64> {
|
||||
stage: self.stage,
|
||||
base_damage: self.base_damage,
|
||||
damage_increase: self.damage_increase,
|
||||
base_poise_damage: self.base_poise_damage,
|
||||
knockback: self.knockback,
|
||||
range: self.range,
|
||||
angle: self.angle,
|
||||
@ -163,10 +166,12 @@ impl CharacterBehavior for Data {
|
||||
.scales_from_combo
|
||||
.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;
|
||||
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,
|
||||
})],
|
||||
range: self.static_data.stage_data[stage_index].range,
|
||||
max_angle: self.static_data.stage_data[stage_index].angle.to_radians(),
|
||||
|
@ -17,6 +17,8 @@ pub struct StaticData {
|
||||
pub base_damage: u32,
|
||||
/// How much the attack scales in damage
|
||||
pub scaled_damage: u32,
|
||||
/// Initial poise damage
|
||||
pub base_poise_damage: u32,
|
||||
/// How much the attack knocks the target back initially
|
||||
pub base_knockback: f32,
|
||||
/// How much the attack scales in knockback
|
||||
@ -129,6 +131,7 @@ 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 knockback = self.static_data.base_knockback
|
||||
+ charge_frac * self.static_data.scaled_knockback;
|
||||
|
@ -22,6 +22,8 @@ pub struct StaticData {
|
||||
pub recover_duration: Duration,
|
||||
/// Base damage
|
||||
pub base_damage: u32,
|
||||
/// Base poise damage
|
||||
pub base_poise_damage: u32,
|
||||
/// Knockback
|
||||
pub knockback: f32,
|
||||
/// Max range
|
||||
@ -150,6 +152,7 @@ impl CharacterBehavior for Data {
|
||||
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,
|
||||
})],
|
||||
range: self.static_data.range,
|
||||
max_angle: self.static_data.max_angle.to_radians(),
|
||||
|
@ -21,5 +21,7 @@ pub mod shockwave;
|
||||
pub mod sit;
|
||||
pub mod sneak;
|
||||
pub mod spin_melee;
|
||||
pub mod staggered;
|
||||
pub mod stunned;
|
||||
pub mod utils;
|
||||
pub mod wielding;
|
||||
|
@ -21,6 +21,8 @@ pub struct StaticData {
|
||||
pub recover_duration: Duration,
|
||||
/// Base damage
|
||||
pub damage: u32,
|
||||
/// Base poise damage
|
||||
pub poise_damage: u32,
|
||||
/// Knockback
|
||||
pub knockback: Knockback,
|
||||
/// Angle of the shockwave
|
||||
@ -86,6 +88,7 @@ impl CharacterBehavior for Data {
|
||||
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,
|
||||
})],
|
||||
knockback: self.static_data.knockback,
|
||||
requires_ground: self.static_data.requires_ground,
|
||||
|
@ -22,6 +22,8 @@ pub struct StaticData {
|
||||
pub recover_duration: Duration,
|
||||
/// Base damage
|
||||
pub base_damage: u32,
|
||||
/// Base poise damage
|
||||
pub base_poise_damage: u32,
|
||||
/// Knockback
|
||||
pub knockback: f32,
|
||||
/// Range
|
||||
@ -114,6 +116,7 @@ impl CharacterBehavior for Data {
|
||||
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,
|
||||
})],
|
||||
range: self.static_data.range,
|
||||
max_angle: 180_f32.to_radians(),
|
||||
|
89
common/src/states/staggered.rs
Normal file
89
common/src/states/staggered.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use super::utils::*;
|
||||
use crate::{
|
||||
comp::{CharacterState, StateUpdate},
|
||||
states::behavior::{CharacterBehavior, JoinData},
|
||||
Knockback,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Separated out to condense update portions of character state
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct StaticData {
|
||||
/// How long until state begins to exit
|
||||
pub buildup_duration: Duration,
|
||||
/// How long the state has until exiting
|
||||
pub recover_duration: Duration,
|
||||
/// Knockback
|
||||
pub knockback: Knockback,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Struct containing data that does not change over the course of the
|
||||
/// character state
|
||||
pub static_data: StaticData,
|
||||
/// Timer for each stage
|
||||
pub timer: Duration,
|
||||
/// What section the character stage is in
|
||||
pub stage_section: StageSection,
|
||||
/// Whether the character was wielding or not
|
||||
pub was_wielded: bool,
|
||||
}
|
||||
|
||||
impl CharacterBehavior for Data {
|
||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||
println!("staggered");
|
||||
let mut update = StateUpdate::from(data);
|
||||
match self.stage_section {
|
||||
StageSection::Buildup => {
|
||||
if self.timer < self.static_data.buildup_duration {
|
||||
// Build up
|
||||
update.character = CharacterState::Staggered(Data {
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to recovery section of stage
|
||||
update.character = CharacterState::Staggered(Data {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
if self.timer < self.static_data.recover_duration {
|
||||
// Recovery
|
||||
update.character = CharacterState::Staggered(Data {
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Done
|
||||
if self.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If it somehow ends up in an incorrect stage section
|
||||
if self.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
update
|
||||
}
|
||||
}
|
89
common/src/states/stunned.rs
Normal file
89
common/src/states/stunned.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use super::utils::*;
|
||||
use crate::{
|
||||
comp::{CharacterState, StateUpdate},
|
||||
states::behavior::{CharacterBehavior, JoinData},
|
||||
Knockback,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Separated out to condense update portions of character state
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct StaticData {
|
||||
/// How long until state begins to exit
|
||||
pub buildup_duration: Duration,
|
||||
/// How long the state has until exiting
|
||||
pub recover_duration: Duration,
|
||||
/// Knockback
|
||||
pub knockback: Knockback,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Struct containing data that does not change over the course of the
|
||||
/// character state
|
||||
pub static_data: StaticData,
|
||||
/// Timer for each stage
|
||||
pub timer: Duration,
|
||||
/// What section the character stage is in
|
||||
pub stage_section: StageSection,
|
||||
/// Whether the character was wielding or not
|
||||
pub was_wielded: bool,
|
||||
}
|
||||
|
||||
impl CharacterBehavior for Data {
|
||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||
println!("stunned");
|
||||
let mut update = StateUpdate::from(data);
|
||||
match self.stage_section {
|
||||
StageSection::Buildup => {
|
||||
if self.timer < self.static_data.buildup_duration {
|
||||
// Build up
|
||||
update.character = CharacterState::Stunned(Data {
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to recovery section of stage
|
||||
update.character = CharacterState::Stunned(Data {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
if self.timer < self.static_data.recover_duration {
|
||||
// Recovery
|
||||
update.character = CharacterState::Stunned(Data {
|
||||
timer: self
|
||||
.timer
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Done
|
||||
if self.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If it somehow ends up in an incorrect stage section
|
||||
if self.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
update
|
||||
}
|
||||
}
|
@ -174,14 +174,17 @@ impl<'a> System<'a> for Sys {
|
||||
if let Some(entity) = beam_owner {
|
||||
server_emitter.emit(ServerEvent::Damage {
|
||||
entity,
|
||||
change: HealthChange {
|
||||
amount: (-change.amount as f32
|
||||
* beam_segment.lifesteal_eff)
|
||||
as i32,
|
||||
cause: HealthSource::Heal {
|
||||
by: beam_segment.owner,
|
||||
change: (
|
||||
HealthChange {
|
||||
amount: (-change.0.amount as f32
|
||||
* beam_segment.lifesteal_eff)
|
||||
as i32,
|
||||
cause: HealthSource::Heal {
|
||||
by: beam_segment.owner,
|
||||
},
|
||||
},
|
||||
},
|
||||
0,
|
||||
),
|
||||
});
|
||||
server_emitter.emit(ServerEvent::EnergyChange {
|
||||
entity,
|
||||
|
@ -114,7 +114,7 @@ impl<'a> System<'a> for Sys {
|
||||
};
|
||||
server_emitter.emit(ServerEvent::Damage {
|
||||
entity,
|
||||
change: HealthChange { amount, cause },
|
||||
change: (HealthChange { amount, cause }, 0),
|
||||
});
|
||||
*accumulated = 0.0;
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ use common::{
|
||||
comp::{
|
||||
inventory::slot::{EquipSlot, Slot},
|
||||
Attacking, Beam, Body, CharacterState, Controller, Energy, Health, Inventory, Mounting,
|
||||
Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
|
||||
Ori, PhysicsState, Poise, Pos, StateUpdate, Stats, Vel,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
metrics::SysMetrics,
|
||||
@ -65,6 +65,7 @@ impl<'a> System<'a> for Sys {
|
||||
WriteStorage<'a, Inventory>,
|
||||
WriteStorage<'a, Controller>,
|
||||
ReadStorage<'a, Health>,
|
||||
ReadStorage<'a, Poise>,
|
||||
ReadStorage<'a, Body>,
|
||||
ReadStorage<'a, PhysicsState>,
|
||||
ReadStorage<'a, Attacking>,
|
||||
@ -93,6 +94,7 @@ impl<'a> System<'a> for Sys {
|
||||
mut inventories,
|
||||
mut controllers,
|
||||
healths,
|
||||
poises,
|
||||
bodies,
|
||||
physics_states,
|
||||
attacking_storage,
|
||||
@ -118,6 +120,7 @@ impl<'a> System<'a> for Sys {
|
||||
&mut inventories.restrict_mut(),
|
||||
&mut controllers,
|
||||
&healths,
|
||||
poises.maybe(),
|
||||
&bodies,
|
||||
&physics_states,
|
||||
attacking_storage.maybe(),
|
||||
@ -151,6 +154,8 @@ impl<'a> System<'a> for Sys {
|
||||
CharacterState::GlideWield => {
|
||||
states::glide_wield::Data.handle_event(&j, action)
|
||||
},
|
||||
CharacterState::Stunned(data) => data.handle_event(&j, action),
|
||||
CharacterState::Staggered(data) => data.handle_event(&j, action),
|
||||
CharacterState::Sit => {
|
||||
states::sit::Data::handle_event(&states::sit::Data, &j, action)
|
||||
},
|
||||
@ -191,6 +196,8 @@ impl<'a> System<'a> for Sys {
|
||||
CharacterState::Climb => states::climb::Data.behavior(&j),
|
||||
CharacterState::Glide => states::glide::Data.behavior(&j),
|
||||
CharacterState::GlideWield => states::glide_wield::Data.behavior(&j),
|
||||
CharacterState::Stunned(data) => data.behavior(&j),
|
||||
CharacterState::Staggered(data) => data.behavior(&j),
|
||||
CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j),
|
||||
CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j),
|
||||
CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j),
|
||||
|
@ -132,14 +132,14 @@ impl<'a> System<'a> for Sys {
|
||||
server_emitter.emit(ServerEvent::Damage { entity: b, 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 {
|
||||
if change.0.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.amount as f32 / 10.0,
|
||||
strength: -change.0.amount as f32 / 10.0,
|
||||
duration: Some(Duration::from_secs(10)),
|
||||
},
|
||||
vec![BuffCategory::Physical],
|
||||
|
@ -116,6 +116,7 @@ impl State {
|
||||
ecs.register::<comp::Auras>();
|
||||
ecs.register::<comp::Energy>();
|
||||
ecs.register::<comp::Health>();
|
||||
ecs.register::<comp::Poise>();
|
||||
ecs.register::<comp::CanBuild>();
|
||||
ecs.register::<comp::LightEmitter>();
|
||||
ecs.register::<comp::Item>();
|
||||
|
@ -214,7 +214,10 @@ impl<'a> System<'a> for Sys {
|
||||
},
|
||||
// Non-combat abilities that consume energy;
|
||||
// temporarily stall energy gain, but preserve regen_rate.
|
||||
CharacterState::Roll { .. } | CharacterState::Climb { .. } => {},
|
||||
CharacterState::Roll { .. }
|
||||
| CharacterState::Climb { .. }
|
||||
| CharacterState::Stunned { .. }
|
||||
| CharacterState::Staggered { .. } => {},
|
||||
}
|
||||
}
|
||||
sys_metrics.stats_ns.store(
|
||||
|
@ -825,6 +825,7 @@ fn handle_spawn(
|
||||
npc::BodyType::from_body(body),
|
||||
)),
|
||||
comp::Health::new(body, 1),
|
||||
comp::Poise::new(body),
|
||||
inventory,
|
||||
body,
|
||||
)
|
||||
@ -932,10 +933,11 @@ fn handle_spawn_training_dummy(
|
||||
let stats = comp::Stats::new("Training Dummy".to_string());
|
||||
|
||||
let health = comp::Health::new(body, 0);
|
||||
let poise = comp::Poise::new(body);
|
||||
|
||||
server
|
||||
.state
|
||||
.create_npc(pos, stats, health, Inventory::new_empty(), body)
|
||||
.create_npc(pos, stats, health, poise, Inventory::new_empty(), body)
|
||||
.with(comp::Vel(vel))
|
||||
.with(comp::MountState::Unmounted)
|
||||
.build();
|
||||
@ -1363,6 +1365,7 @@ fn handle_explosion(
|
||||
Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: 100.0 * power,
|
||||
poise_damage: 100.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::TerrainDestruction(power),
|
||||
|
@ -9,7 +9,7 @@ use common::{
|
||||
group,
|
||||
inventory::loadout::Loadout,
|
||||
shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop,
|
||||
LightEmitter, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||
LightEmitter, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||
},
|
||||
outcome::Outcome,
|
||||
rtsim::RtSimEntity,
|
||||
@ -49,6 +49,7 @@ pub fn handle_create_npc(
|
||||
pos: Pos,
|
||||
stats: Stats,
|
||||
health: Health,
|
||||
poise: Poise,
|
||||
loadout: Loadout,
|
||||
body: Body,
|
||||
agent: impl Into<Option<Agent>>,
|
||||
@ -71,7 +72,7 @@ pub fn handle_create_npc(
|
||||
|
||||
let entity = server
|
||||
.state
|
||||
.create_npc(pos, stats, health, inventory, body)
|
||||
.create_npc(pos, stats, health, poise, inventory, body)
|
||||
.with(scale)
|
||||
.with(alignment);
|
||||
|
||||
|
@ -14,7 +14,7 @@ use common::{
|
||||
self, aura, buff,
|
||||
chat::{KillSource, KillType},
|
||||
object, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange, HealthSource,
|
||||
Inventory, Item, Player, Pos, Stats,
|
||||
Inventory, Item, Player, Poise, PoiseState, Pos, Stats,
|
||||
},
|
||||
effect::Effect,
|
||||
lottery::Lottery,
|
||||
@ -23,7 +23,7 @@ use common::{
|
||||
terrain::{Block, TerrainGrid},
|
||||
uid::{Uid, UidAllocator},
|
||||
vol::ReadVol,
|
||||
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
||||
Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect,
|
||||
};
|
||||
use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
|
||||
use common_sys::state::BlockChange;
|
||||
@ -31,13 +31,89 @@ use comp::item::Reagent;
|
||||
use hashbrown::HashSet;
|
||||
use rand::prelude::*;
|
||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||
use std::time::Duration;
|
||||
use tracing::error;
|
||||
use vek::Vec3;
|
||||
|
||||
pub fn handle_damage(server: &Server, entity: EcsEntity, change: HealthChange) {
|
||||
pub fn handle_damage(server: &Server, entity: EcsEntity, change: (HealthChange, i32)) {
|
||||
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);
|
||||
let was_wielded =
|
||||
if let Some(character_state) = ecs.read_storage::<comp::CharacterState>().get(entity) {
|
||||
character_state.is_wield()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
match poise.poise_state() {
|
||||
PoiseState::Normal => {},
|
||||
PoiseState::Interrupted => {
|
||||
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),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
},
|
||||
PoiseState::Stunned => {
|
||||
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),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
},
|
||||
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),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
},
|
||||
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),
|
||||
recover_duration: Duration::from_millis(250),
|
||||
knockback: Knockback::Away(0.0),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: common::states::utils::StageSection::Buildup,
|
||||
was_wielded,
|
||||
}),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,6 +563,7 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
|
||||
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);
|
||||
|
@ -110,6 +110,7 @@ impl Server {
|
||||
pos,
|
||||
stats,
|
||||
health,
|
||||
poise,
|
||||
loadout,
|
||||
body,
|
||||
agent,
|
||||
@ -123,6 +124,7 @@ impl Server {
|
||||
pos,
|
||||
stats,
|
||||
health,
|
||||
poise,
|
||||
loadout,
|
||||
body,
|
||||
agent,
|
||||
|
@ -103,6 +103,7 @@ impl<'a> System<'a> for Sys {
|
||||
comp::Body::Humanoid(_) => entity.get_loadout(),
|
||||
_ => LoadoutBuilder::new().build(),
|
||||
},
|
||||
poise: comp::Poise::new(body),
|
||||
body,
|
||||
agent: Some(comp::Agent::new(
|
||||
None,
|
||||
|
@ -36,6 +36,7 @@ pub trait StateExt {
|
||||
stats: comp::Stats,
|
||||
health: comp::Health,
|
||||
inventory: comp::Inventory,
|
||||
poise: comp::Poise,
|
||||
body: comp::Body,
|
||||
) -> EcsEntityBuilder;
|
||||
/// Build a static object entity
|
||||
@ -95,6 +96,12 @@ impl StateExt for State {
|
||||
.get_mut(entity)
|
||||
.map(|mut health| health.change_by(change));
|
||||
},
|
||||
Effect::Poise(change) => {
|
||||
self.ecs()
|
||||
.write_storage::<comp::Poise>()
|
||||
.get_mut(entity)
|
||||
.map(|poise| poise.change_by(change));
|
||||
},
|
||||
Effect::Buff(buff) => {
|
||||
self.ecs()
|
||||
.write_storage::<comp::Buffs>()
|
||||
@ -117,6 +124,7 @@ impl StateExt for State {
|
||||
stats: comp::Stats,
|
||||
health: comp::Health,
|
||||
inventory: comp::Inventory,
|
||||
poise: comp::Poise,
|
||||
body: comp::Body,
|
||||
) -> EcsEntityBuilder {
|
||||
self.ecs_mut()
|
||||
@ -149,6 +157,7 @@ impl StateExt for State {
|
||||
))
|
||||
.with(stats)
|
||||
.with(health)
|
||||
.with(poise)
|
||||
.with(comp::Alignment::Npc)
|
||||
.with(comp::Gravity(1.0))
|
||||
.with(comp::CharacterState::default())
|
||||
@ -292,6 +301,7 @@ impl StateExt for State {
|
||||
);
|
||||
self.write_component(entity, comp::Health::new(body, health_level));
|
||||
self.write_component(entity, comp::Energy::new(body, energy_level));
|
||||
self.write_component(entity, comp::Poise::new(body));
|
||||
self.write_component(entity, stats);
|
||||
self.write_component(entity, inventory);
|
||||
self.write_component(
|
||||
|
@ -54,6 +54,7 @@ impl<'a> System<'a> for Sys {
|
||||
Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: 500.0,
|
||||
poise_damage: 60.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::TerrainDestruction(4.0),
|
||||
@ -81,6 +82,7 @@ impl<'a> System<'a> for Sys {
|
||||
Effect::Damage(Damage {
|
||||
source: DamageSource::Explosion,
|
||||
value: 50.0,
|
||||
poise_damage: 10.0,
|
||||
}),
|
||||
),
|
||||
RadiusEffect::TerrainDestruction(4.0),
|
||||
|
@ -2,8 +2,8 @@ use super::SysTimer;
|
||||
use common::{
|
||||
comp::{
|
||||
Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Energy, Gravity,
|
||||
Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, Player, Pos,
|
||||
Scale, Shockwave, Stats, Sticky, Vel,
|
||||
Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, Player,
|
||||
Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel,
|
||||
},
|
||||
span,
|
||||
uid::Uid,
|
||||
@ -51,6 +51,7 @@ pub struct TrackedComps<'a> {
|
||||
pub auras: ReadStorage<'a, Auras>,
|
||||
pub energy: ReadStorage<'a, Energy>,
|
||||
pub health: ReadStorage<'a, Health>,
|
||||
pub poise: ReadStorage<'a, Poise>,
|
||||
pub can_build: ReadStorage<'a, CanBuild>,
|
||||
pub light_emitter: ReadStorage<'a, LightEmitter>,
|
||||
pub item: ReadStorage<'a, Item>,
|
||||
@ -179,6 +180,7 @@ pub struct ReadTrackers<'a> {
|
||||
pub auras: ReadExpect<'a, UpdateTracker<Auras>>,
|
||||
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
||||
pub health: ReadExpect<'a, UpdateTracker<Health>>,
|
||||
pub poise: ReadExpect<'a, UpdateTracker<Poise>>,
|
||||
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
||||
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
|
||||
pub inventory: ReadExpect<'a, UpdateTracker<Inventory>>,
|
||||
@ -252,6 +254,7 @@ pub struct WriteTrackers<'a> {
|
||||
auras: WriteExpect<'a, UpdateTracker<Auras>>,
|
||||
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
||||
health: WriteExpect<'a, UpdateTracker<Health>>,
|
||||
poise: WriteExpect<'a, UpdateTracker<Poise>>,
|
||||
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
||||
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
|
||||
item: WriteExpect<'a, UpdateTracker<Item>>,
|
||||
@ -319,6 +322,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||
log_counts!(stats, "Stats");
|
||||
log_counts!(energy, "Energies");
|
||||
log_vounts!(health, "Healths");
|
||||
log_vounts!(poise, "Poises");
|
||||
log_counts!(light_emitter, "Light emitters");
|
||||
log_counts!(item, "Items");
|
||||
log_counts!(scale, "Scales");
|
||||
@ -344,6 +348,7 @@ pub fn register_trackers(world: &mut World) {
|
||||
world.register_tracker::<Auras>();
|
||||
world.register_tracker::<Energy>();
|
||||
world.register_tracker::<Health>();
|
||||
world.register_tracker::<Poise>();
|
||||
world.register_tracker::<CanBuild>();
|
||||
world.register_tracker::<LightEmitter>();
|
||||
world.register_tracker::<Item>();
|
||||
|
@ -152,6 +152,7 @@ impl<'a> System<'a> for Sys {
|
||||
LoadoutBuilder::build_loadout(body, main_tool, loadout_config).build();
|
||||
|
||||
let health = comp::Health::new(body, entity.level.unwrap_or(0));
|
||||
let poise = comp::Poise::new(stats.body_type);
|
||||
|
||||
let can_speak = match body {
|
||||
comp::Body::Humanoid(_) => alignment == comp::Alignment::Npc,
|
||||
@ -176,6 +177,7 @@ impl<'a> System<'a> for Sys {
|
||||
pos: Pos(entity.pos),
|
||||
stats,
|
||||
health,
|
||||
poise,
|
||||
loadout,
|
||||
agent: if entity.has_agency {
|
||||
Some(comp::Agent::new(
|
||||
|
Loading…
Reference in New Issue
Block a user