mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Heavy stance required abilities
This commit is contained in:
parent
e73236819a
commit
a3d655970e
@ -1,39 +1,9 @@
|
|||||||
ComboMelee2(
|
SelfBuff(
|
||||||
strikes: [
|
buildup_duration: 0.2,
|
||||||
(
|
cast_duration: 0.2,
|
||||||
melee_constructor: (
|
recover_duration: 0.6,
|
||||||
kind: Slash(
|
buff_kind: Fortitude,
|
||||||
damage: 5,
|
buff_strength: 1.0,
|
||||||
poise: 0,
|
buff_duration: Some(30.0),
|
||||||
knockback: 0,
|
energy_cost: 25,
|
||||||
energy_regen: 5,
|
|
||||||
),
|
|
||||||
range: 3.0,
|
|
||||||
angle: 45.0,
|
|
||||||
),
|
|
||||||
buildup_duration: 0.15,
|
|
||||||
swing_duration: 0.05,
|
|
||||||
hit_timing: 0.5,
|
|
||||||
recover_duration: 0.1,
|
|
||||||
ori_modifier: 0.6,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
melee_constructor: (
|
|
||||||
kind: Slash(
|
|
||||||
damage: 10,
|
|
||||||
poise: 0,
|
|
||||||
knockback: 0,
|
|
||||||
energy_regen: 7.5,
|
|
||||||
),
|
|
||||||
range: 3.0,
|
|
||||||
angle: 45.0,
|
|
||||||
),
|
|
||||||
buildup_duration: 0.1,
|
|
||||||
swing_duration: 0.1,
|
|
||||||
hit_timing: 0.5,
|
|
||||||
recover_duration: 0.2,
|
|
||||||
ori_modifier: 0.6,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
energy_cost_per_strike: 0,
|
|
||||||
)
|
)
|
@ -1,39 +1,26 @@
|
|||||||
ComboMelee2(
|
DiveMelee(
|
||||||
strikes: [
|
energy_cost: 25,
|
||||||
(
|
vertical_speed: 5,
|
||||||
melee_constructor: (
|
buildup_duration: Some(0.2),
|
||||||
kind: Slash(
|
movement_duration: 5,
|
||||||
damage: 5,
|
|
||||||
poise: 0,
|
|
||||||
knockback: 0,
|
|
||||||
energy_regen: 5,
|
|
||||||
),
|
|
||||||
range: 3.0,
|
|
||||||
angle: 45.0,
|
|
||||||
),
|
|
||||||
buildup_duration: 0.15,
|
|
||||||
swing_duration: 0.05,
|
|
||||||
hit_timing: 0.5,
|
|
||||||
recover_duration: 0.1,
|
|
||||||
ori_modifier: 0.6,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
melee_constructor: (
|
|
||||||
kind: Slash(
|
|
||||||
damage: 10,
|
|
||||||
poise: 0,
|
|
||||||
knockback: 0,
|
|
||||||
energy_regen: 7.5,
|
|
||||||
),
|
|
||||||
range: 3.0,
|
|
||||||
angle: 45.0,
|
|
||||||
),
|
|
||||||
buildup_duration: 0.1,
|
|
||||||
swing_duration: 0.1,
|
swing_duration: 0.1,
|
||||||
hit_timing: 0.5,
|
recover_duration: 0.3,
|
||||||
recover_duration: 0.2,
|
melee_constructor: (
|
||||||
ori_modifier: 0.6,
|
kind: Slash(
|
||||||
|
damage: 30,
|
||||||
|
poise: 40,
|
||||||
|
knockback: 0,
|
||||||
|
energy_regen: 0,
|
||||||
),
|
),
|
||||||
],
|
scaled: Some(Slash(
|
||||||
energy_cost_per_strike: 0,
|
damage: 5,
|
||||||
|
poise: 10,
|
||||||
|
knockback: 0,
|
||||||
|
energy_regen: 0,
|
||||||
|
)),
|
||||||
|
range: 2.0,
|
||||||
|
angle: 45.0,
|
||||||
|
multi_target: Some(Normal),
|
||||||
|
),
|
||||||
|
max_scaling: 6,
|
||||||
)
|
)
|
@ -63,7 +63,7 @@ buff-title-ensnared = Ensnared
|
|||||||
buff-desc-ensnared = Vines grasp at your legs, impeding your movement.
|
buff-desc-ensnared = Vines grasp at your legs, impeding your movement.
|
||||||
## Fortitude
|
## Fortitude
|
||||||
buff-title-fortitude = Fortitude
|
buff-title-fortitude = Fortitude
|
||||||
buff-desc-fortitude = You can withstand staggers.
|
buff-desc-fortitude = You can withstand staggers, and as you take more damage you stagger others more easily.
|
||||||
## Parried
|
## Parried
|
||||||
buff-title-parried = Parried
|
buff-title-parried = Parried
|
||||||
buff-desc-parried = You were parried and now are slow to recover.
|
buff-desc-parried = You were parried and now are slow to recover.
|
||||||
|
@ -56,6 +56,7 @@ pub struct AttackerInfo<'a> {
|
|||||||
pub energy: Option<&'a Energy>,
|
pub energy: Option<&'a Energy>,
|
||||||
pub combo: Option<&'a Combo>,
|
pub combo: Option<&'a Combo>,
|
||||||
pub inventory: Option<&'a Inventory>,
|
pub inventory: Option<&'a Inventory>,
|
||||||
|
pub stats: Option<&'a Stats>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@ -294,7 +295,11 @@ impl Attack {
|
|||||||
// that health change amount is greater than 0 would fail.
|
// that health change amount is greater than 0 would fail.
|
||||||
let reduced_damage =
|
let reduced_damage =
|
||||||
applied_damage * damage_reduction / (1.0 - damage_reduction);
|
applied_damage * damage_reduction / (1.0 - damage_reduction);
|
||||||
let poise = reduced_damage * CRUSHING_POISE_FRACTION;
|
let poise = reduced_damage
|
||||||
|
* CRUSHING_POISE_FRACTION
|
||||||
|
* attacker
|
||||||
|
.and_then(|a| a.stats)
|
||||||
|
.map_or(1.0, |s| s.poise_damage_modifier);
|
||||||
let change = -Poise::apply_poise_reduction(
|
let change = -Poise::apply_poise_reduction(
|
||||||
poise,
|
poise,
|
||||||
target.inventory,
|
target.inventory,
|
||||||
@ -369,6 +374,7 @@ impl Attack {
|
|||||||
time,
|
time,
|
||||||
attacker.map(|a| a.uid),
|
attacker.map(|a| a.uid),
|
||||||
target.stats,
|
target.stats,
|
||||||
|
target.health,
|
||||||
applied_damage,
|
applied_damage,
|
||||||
strength_modifier,
|
strength_modifier,
|
||||||
)),
|
)),
|
||||||
@ -401,7 +407,10 @@ impl Attack {
|
|||||||
msm,
|
msm,
|
||||||
target.char_state,
|
target.char_state,
|
||||||
target.stats,
|
target.stats,
|
||||||
) * strength_modifier;
|
) * strength_modifier
|
||||||
|
* attacker
|
||||||
|
.and_then(|a| a.stats)
|
||||||
|
.map_or(1.0, |s| s.poise_damage_modifier);
|
||||||
if change.abs() > Poise::POISE_EPSILON {
|
if change.abs() > Poise::POISE_EPSILON {
|
||||||
let poise_change = PoiseChange {
|
let poise_change = PoiseChange {
|
||||||
amount: change,
|
amount: change,
|
||||||
@ -561,6 +570,7 @@ impl Attack {
|
|||||||
time,
|
time,
|
||||||
attacker.map(|a| a.uid),
|
attacker.map(|a| a.uid),
|
||||||
target.stats,
|
target.stats,
|
||||||
|
target.health,
|
||||||
accumulated_damage,
|
accumulated_damage,
|
||||||
strength_modifier,
|
strength_modifier,
|
||||||
)),
|
)),
|
||||||
@ -593,7 +603,10 @@ impl Attack {
|
|||||||
msm,
|
msm,
|
||||||
target.char_state,
|
target.char_state,
|
||||||
target.stats,
|
target.stats,
|
||||||
) * strength_modifier;
|
) * strength_modifier
|
||||||
|
* attacker
|
||||||
|
.and_then(|a| a.stats)
|
||||||
|
.map_or(1.0, |s| s.poise_damage_modifier);
|
||||||
if change.abs() > Poise::POISE_EPSILON {
|
if change.abs() > Poise::POISE_EPSILON {
|
||||||
let poise_change = PoiseChange {
|
let poise_change = PoiseChange {
|
||||||
amount: change,
|
amount: change,
|
||||||
@ -1082,7 +1095,8 @@ impl CombatBuff {
|
|||||||
self,
|
self,
|
||||||
time: Time,
|
time: Time,
|
||||||
uid: Option<Uid>,
|
uid: Option<Uid>,
|
||||||
stats: Option<&Stats>,
|
tgt_stats: Option<&Stats>,
|
||||||
|
tgt_health: Option<&Health>,
|
||||||
damage: f32,
|
damage: f32,
|
||||||
strength_modifier: f32,
|
strength_modifier: f32,
|
||||||
) -> Buff {
|
) -> Buff {
|
||||||
@ -1102,7 +1116,8 @@ impl CombatBuff {
|
|||||||
Vec::new(),
|
Vec::new(),
|
||||||
source,
|
source,
|
||||||
time,
|
time,
|
||||||
stats,
|
tgt_stats,
|
||||||
|
tgt_health,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -777,6 +777,7 @@ pub enum CharacterAbility {
|
|||||||
DiveMelee {
|
DiveMelee {
|
||||||
energy_cost: f32,
|
energy_cost: f32,
|
||||||
vertical_speed: f32,
|
vertical_speed: f32,
|
||||||
|
buildup_duration: Option<f32>,
|
||||||
movement_duration: f32,
|
movement_duration: f32,
|
||||||
swing_duration: f32,
|
swing_duration: f32,
|
||||||
recover_duration: f32,
|
recover_duration: f32,
|
||||||
@ -893,11 +894,15 @@ impl CharacterAbility {
|
|||||||
&& update.energy.try_change_by(-*energy_cost).is_ok()
|
&& update.energy.try_change_by(-*energy_cost).is_ok()
|
||||||
},
|
},
|
||||||
CharacterAbility::DiveMelee {
|
CharacterAbility::DiveMelee {
|
||||||
|
buildup_duration,
|
||||||
energy_cost,
|
energy_cost,
|
||||||
vertical_speed,
|
vertical_speed,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
data.vel.0.z < -*vertical_speed
|
// If either falling fast enough or is on ground and able to be activated from
|
||||||
|
// ground
|
||||||
|
(data.vel.0.z < -*vertical_speed
|
||||||
|
|| (data.physics.on_ground.is_some() && buildup_duration.is_some()))
|
||||||
&& update.energy.try_change_by(-*energy_cost).is_ok()
|
&& update.energy.try_change_by(-*energy_cost).is_ok()
|
||||||
},
|
},
|
||||||
CharacterAbility::ComboMelee { .. }
|
CharacterAbility::ComboMelee { .. }
|
||||||
@ -1425,12 +1430,14 @@ impl CharacterAbility {
|
|||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
vertical_speed: _,
|
vertical_speed: _,
|
||||||
movement_duration: _,
|
movement_duration: _,
|
||||||
|
ref mut buildup_duration,
|
||||||
ref mut swing_duration,
|
ref mut swing_duration,
|
||||||
ref mut recover_duration,
|
ref mut recover_duration,
|
||||||
ref mut melee_constructor,
|
ref mut melee_constructor,
|
||||||
max_scaling: _,
|
max_scaling: _,
|
||||||
meta: _,
|
meta: _,
|
||||||
} => {
|
} => {
|
||||||
|
*buildup_duration = buildup_duration.map(|b| b / stats.speed);
|
||||||
*swing_duration /= stats.speed;
|
*swing_duration /= stats.speed;
|
||||||
*recover_duration /= stats.speed;
|
*recover_duration /= stats.speed;
|
||||||
*energy_cost /= stats.energy_efficiency;
|
*energy_cost /= stats.energy_efficiency;
|
||||||
@ -2744,6 +2751,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
|||||||
exhausted: false,
|
exhausted: false,
|
||||||
}),
|
}),
|
||||||
CharacterAbility::DiveMelee {
|
CharacterAbility::DiveMelee {
|
||||||
|
buildup_duration,
|
||||||
movement_duration,
|
movement_duration,
|
||||||
swing_duration,
|
swing_duration,
|
||||||
recover_duration,
|
recover_duration,
|
||||||
@ -2754,6 +2762,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
|||||||
meta: _,
|
meta: _,
|
||||||
} => CharacterState::DiveMelee(dive_melee::Data {
|
} => CharacterState::DiveMelee(dive_melee::Data {
|
||||||
static_data: dive_melee::StaticData {
|
static_data: dive_melee::StaticData {
|
||||||
|
buildup_duration: buildup_duration.map(|b| Duration::from_secs_f32(b)),
|
||||||
movement_duration: Duration::from_secs_f32(*movement_duration),
|
movement_duration: Duration::from_secs_f32(*movement_duration),
|
||||||
swing_duration: Duration::from_secs_f32(*swing_duration),
|
swing_duration: Duration::from_secs_f32(*swing_duration),
|
||||||
recover_duration: Duration::from_secs_f32(*recover_duration),
|
recover_duration: Duration::from_secs_f32(*recover_duration),
|
||||||
@ -2763,7 +2772,11 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
|||||||
ability_info,
|
ability_info,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Movement,
|
stage_section: if data.vel.0.z < 0.0 || buildup_duration.is_none() {
|
||||||
|
StageSection::Movement
|
||||||
|
} else {
|
||||||
|
StageSection::Buildup
|
||||||
|
},
|
||||||
exhausted: false,
|
exhausted: false,
|
||||||
max_vertical_speed: 0.0,
|
max_vertical_speed: 0.0,
|
||||||
}),
|
}),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::nonstandard_macro_braces)] //tmp as of false positive !?
|
#![allow(clippy::nonstandard_macro_braces)] //tmp as of false positive !?
|
||||||
use crate::{
|
use crate::{
|
||||||
comp::{aura::AuraKey, Stats},
|
comp::{aura::AuraKey, Health, Stats},
|
||||||
resources::{Secs, Time},
|
resources::{Secs, Time},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
@ -56,10 +56,13 @@ pub enum BuffKind {
|
|||||||
/// Strength scales strength of both effects linearly. 0.5 is a 50%
|
/// Strength scales strength of both effects linearly. 0.5 is a 50%
|
||||||
/// increase, 1.0 is a 100% increase.
|
/// increase, 1.0 is a 100% increase.
|
||||||
Hastened,
|
Hastened,
|
||||||
// TODO: Consider non linear scaling?
|
/// Increases resistance to incoming poise, and poise damage dealt as health
|
||||||
/// Increases resistance to incoming poise over time
|
/// is lost from the time the buff activated
|
||||||
/// Strength scales the resistance linearly, values over 1 will usually do
|
/// Strength scales the resistance non-linearly. 0.5 provides 50%, 1.0
|
||||||
/// nothing. 0.5 is 50%, 1.0 is 100%.
|
/// provides 67%
|
||||||
|
/// Strength scales the poise damage increase linearly, a strength of 1.0
|
||||||
|
/// and n health less from activation will cause poise damage to increase by
|
||||||
|
/// n%
|
||||||
Fortitude,
|
Fortitude,
|
||||||
// Debuffs
|
// Debuffs
|
||||||
/// Does damage to a creature over time
|
/// Does damage to a creature over time
|
||||||
@ -214,6 +217,8 @@ pub enum BuffEffect {
|
|||||||
PoiseReduction(f32),
|
PoiseReduction(f32),
|
||||||
/// Reduces amount healed by consumables
|
/// Reduces amount healed by consumables
|
||||||
HealReduction(f32),
|
HealReduction(f32),
|
||||||
|
/// Increases poise damage dealt when health is lost
|
||||||
|
PoiseDamageFromLostHealth { initial_health: f32, strength: f32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actual de/buff.
|
/// Actual de/buff.
|
||||||
@ -272,6 +277,7 @@ impl Buff {
|
|||||||
source: BuffSource,
|
source: BuffSource,
|
||||||
time: Time,
|
time: Time,
|
||||||
stats: Option<&Stats>,
|
stats: Option<&Stats>,
|
||||||
|
health: Option<&Health>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Normalized nonlinear scaling
|
// Normalized nonlinear scaling
|
||||||
let nn_scaling = |a| a / (a + 0.5);
|
let nn_scaling = |a| a / (a + 0.5);
|
||||||
@ -367,7 +373,13 @@ impl Buff {
|
|||||||
BuffEffect::MovementSpeed(1.0 + data.strength),
|
BuffEffect::MovementSpeed(1.0 + data.strength),
|
||||||
BuffEffect::AttackSpeed(1.0 + data.strength),
|
BuffEffect::AttackSpeed(1.0 + data.strength),
|
||||||
],
|
],
|
||||||
BuffKind::Fortitude => vec![BuffEffect::PoiseReduction(data.strength)],
|
BuffKind::Fortitude => vec![
|
||||||
|
BuffEffect::PoiseReduction(nn_scaling(data.strength)),
|
||||||
|
BuffEffect::PoiseDamageFromLostHealth {
|
||||||
|
initial_health: health.map_or(0.0, |h| h.current()),
|
||||||
|
strength: data.strength,
|
||||||
|
},
|
||||||
|
],
|
||||||
BuffKind::Parried => vec![BuffEffect::AttackSpeed(0.5)],
|
BuffKind::Parried => vec![BuffEffect::AttackSpeed(0.5)],
|
||||||
BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)],
|
BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)],
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,7 @@ pub struct Stats {
|
|||||||
pub attack_speed_modifier: f32,
|
pub attack_speed_modifier: f32,
|
||||||
pub friction_modifier: f32,
|
pub friction_modifier: f32,
|
||||||
pub max_energy_modifiers: StatsModifier,
|
pub max_energy_modifiers: StatsModifier,
|
||||||
|
pub poise_damage_modifier: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stats {
|
impl Stats {
|
||||||
@ -70,6 +71,7 @@ impl Stats {
|
|||||||
attack_speed_modifier: 1.0,
|
attack_speed_modifier: 1.0,
|
||||||
friction_modifier: 1.0,
|
friction_modifier: 1.0,
|
||||||
max_energy_modifiers: StatsModifier::default(),
|
max_energy_modifiers: StatsModifier::default(),
|
||||||
|
poise_damage_modifier: 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,14 +81,8 @@ impl Stats {
|
|||||||
|
|
||||||
/// Resets temporary modifiers to default values
|
/// Resets temporary modifiers to default values
|
||||||
pub fn reset_temp_modifiers(&mut self) {
|
pub fn reset_temp_modifiers(&mut self) {
|
||||||
self.damage_reduction = 0.0;
|
// TODO: Figure out how to avoid clone
|
||||||
self.poise_reduction = 0.0;
|
*self = Self::new(self.name.clone());
|
||||||
self.heal_multiplier = 1.0;
|
|
||||||
self.max_health_modifiers = StatsModifier::default();
|
|
||||||
self.move_speed_modifier = 1.0;
|
|
||||||
self.attack_speed_modifier = 1.0;
|
|
||||||
self.friction_modifier = 1.0;
|
|
||||||
self.max_energy_modifiers = StatsModifier::default();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,6 @@ pub struct JoinData<'a> {
|
|||||||
pub terrain: &'a TerrainGrid,
|
pub terrain: &'a TerrainGrid,
|
||||||
pub mount_data: Option<&'a Is<Rider>>,
|
pub mount_data: Option<&'a Is<Rider>>,
|
||||||
pub stance: Option<&'a Stance>,
|
pub stance: Option<&'a Stance>,
|
||||||
pub time: &'a Time,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct JoinStruct<'a> {
|
pub struct JoinStruct<'a> {
|
||||||
@ -174,7 +173,6 @@ pub struct JoinStruct<'a> {
|
|||||||
pub terrain: &'a TerrainGrid,
|
pub terrain: &'a TerrainGrid,
|
||||||
pub mount_data: Option<&'a Is<Rider>>,
|
pub mount_data: Option<&'a Is<Rider>>,
|
||||||
pub stance: Option<&'a Stance>,
|
pub stance: Option<&'a Stance>,
|
||||||
pub time: &'a Time,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> JoinData<'a> {
|
impl<'a> JoinData<'a> {
|
||||||
@ -216,7 +214,6 @@ impl<'a> JoinData<'a> {
|
|||||||
active_abilities: j.active_abilities,
|
active_abilities: j.active_abilities,
|
||||||
mount_data: j.mount_data,
|
mount_data: j.mount_data,
|
||||||
stance: j.stance,
|
stance: j.stance,
|
||||||
time: j.time,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,9 @@ pub struct StaticData {
|
|||||||
pub energy_drain: f32,
|
pub energy_drain: f32,
|
||||||
/// Energy cost per attack
|
/// Energy cost per attack
|
||||||
pub energy_cost: f32,
|
pub energy_cost: f32,
|
||||||
/// The state can optionally have a buildup strike that applies after buildup before charging
|
/// The state can optionally have a buildup strike that applies after
|
||||||
pub buildup_strike: Option<(
|
/// buildup before charging
|
||||||
Duration,
|
pub buildup_strike: Option<(Duration, MeleeConstructor)>,
|
||||||
MeleeConstructor,
|
|
||||||
)>,
|
|
||||||
/// How long it takes to charge the weapon to max damage and knockback
|
/// How long it takes to charge the weapon to max damage and knockback
|
||||||
pub charge_duration: Duration,
|
pub charge_duration: Duration,
|
||||||
/// How long the weapon is swinging for
|
/// How long the weapon is swinging for
|
||||||
@ -74,10 +72,8 @@ impl CharacterBehavior for Data {
|
|||||||
} else {
|
} else {
|
||||||
let crit_data = get_crit_data(data, self.static_data.ability_info);
|
let crit_data = get_crit_data(data, self.static_data.ability_info);
|
||||||
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
||||||
data.updater.insert(
|
data.updater
|
||||||
data.entity,
|
.insert(data.entity, strike.create_melee(crit_data, buff_strength));
|
||||||
strike.create_melee(crit_data, buff_strength),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let CharacterState::ChargedMelee(c) = &mut update.character {
|
if let CharacterState::ChargedMelee(c) = &mut update.character {
|
||||||
c.stage_section = StageSection::Charge;
|
c.stage_section = StageSection::Charge;
|
||||||
|
@ -76,7 +76,8 @@ pub struct StaticData {
|
|||||||
pub strikes: Vec<Strike<Duration>>,
|
pub strikes: Vec<Strike<Duration>>,
|
||||||
/// The amount of energy consumed with each swing
|
/// The amount of energy consumed with each swing
|
||||||
pub energy_cost_per_strike: f32,
|
pub energy_cost_per_strike: f32,
|
||||||
/// Whether or not the state should progress through all strikes automatically once the state is entered
|
/// Whether or not the state should progress through all strikes
|
||||||
|
/// automatically once the state is entered
|
||||||
pub auto_progress: bool,
|
pub auto_progress: bool,
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
}
|
}
|
||||||
@ -133,7 +134,9 @@ impl CharacterBehavior for Data {
|
|||||||
if let Some(movement) = strike_data.movement.swing {
|
if let Some(movement) = strike_data.movement.swing {
|
||||||
handle_forced_movement(data, &mut update, movement);
|
handle_forced_movement(data, &mut update, movement);
|
||||||
}
|
}
|
||||||
if input_is_pressed(data, self.static_data.ability_info.input) || self.static_data.auto_progress {
|
if input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
|
|| self.static_data.auto_progress
|
||||||
|
{
|
||||||
if let CharacterState::ComboMelee2(c) = &mut update.character {
|
if let CharacterState::ComboMelee2(c) = &mut update.character {
|
||||||
// Only have the next strike skip the recover period of this strike if not
|
// Only have the next strike skip the recover period of this strike if not
|
||||||
// every strike in the combo is complete yet
|
// every strike in the combo is complete yet
|
||||||
|
@ -11,6 +11,8 @@ use std::time::Duration;
|
|||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct StaticData {
|
pub struct StaticData {
|
||||||
|
/// If Some(_), the state can be activated on the ground
|
||||||
|
pub buildup_duration: Option<Duration>,
|
||||||
/// How long the state is moving
|
/// How long the state is moving
|
||||||
pub movement_duration: Duration,
|
pub movement_duration: Duration,
|
||||||
/// How long the weapon swings
|
/// How long the weapon swings
|
||||||
@ -51,6 +53,28 @@ impl CharacterBehavior for Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
|
StageSection::Buildup => {
|
||||||
|
handle_orientation(data, &mut update, 0.5, None);
|
||||||
|
handle_move(data, &mut update, 0.3);
|
||||||
|
|
||||||
|
if let Some(buildup_duration) = self.static_data.buildup_duration {
|
||||||
|
if self.timer < buildup_duration {
|
||||||
|
if let CharacterState::DiveMelee(c) = &mut update.character {
|
||||||
|
c.timer = tick_attack_or_default(data, self.timer, None);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let CharacterState::DiveMelee(c) = &mut update.character {
|
||||||
|
c.timer = Duration::default();
|
||||||
|
c.stage_section = StageSection::Action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let CharacterState::DiveMelee(c) = &mut update.character {
|
||||||
|
c.timer = Duration::default();
|
||||||
|
c.stage_section = StageSection::Action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
StageSection::Movement => {
|
StageSection::Movement => {
|
||||||
handle_move(data, &mut update, 1.0);
|
handle_move(data, &mut update, 1.0);
|
||||||
if data.physics.on_ground.is_some() {
|
if data.physics.on_ground.is_some() {
|
||||||
|
@ -72,6 +72,7 @@ impl CharacterBehavior for Data {
|
|||||||
BuffSource::Character { by: *data.uid },
|
BuffSource::Character { by: *data.uid },
|
||||||
*data.time,
|
*data.time,
|
||||||
Some(data.stats),
|
Some(data.stats),
|
||||||
|
data.health,
|
||||||
);
|
);
|
||||||
output_events.emit_server(ServerEvent::Buff {
|
output_events.emit_server(ServerEvent::Buff {
|
||||||
entity: data.entity,
|
entity: data.entity,
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
astar::Astar,
|
astar::Astar,
|
||||||
combat,
|
combat,
|
||||||
comp::{
|
comp::{
|
||||||
ability::{Ability, AbilityInput, AbilityMeta, Capability, AbilityInitEvent},
|
ability::{Ability, AbilityInitEvent, AbilityInput, AbilityMeta, Capability},
|
||||||
arthropod, biped_large, biped_small, bird_medium,
|
arthropod, biped_large, biped_small, bird_medium,
|
||||||
character_state::OutputEvents,
|
character_state::OutputEvents,
|
||||||
controller::InventoryManip,
|
controller::InventoryManip,
|
||||||
@ -471,7 +471,9 @@ pub fn handle_forced_movement(
|
|||||||
data.inputs.move_dir.reflected(Vec2::from(*data.ori))
|
data.inputs.move_dir.reflected(Vec2::from(*data.ori))
|
||||||
} else {
|
} else {
|
||||||
data.inputs.move_dir
|
data.inputs.move_dir
|
||||||
}.try_normalized().unwrap_or_else(|| -Vec2::from(*data.ori));
|
}
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(|| -Vec2::from(*data.ori));
|
||||||
update.vel.0 += direction * strength * accel * data.dt.0;
|
update.vel.0 += direction * strength * accel * data.dt.0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -485,7 +487,9 @@ pub fn handle_forced_movement(
|
|||||||
data.inputs.move_dir.reflected(Vec2::from(*data.ori))
|
data.inputs.move_dir.reflected(Vec2::from(*data.ori))
|
||||||
} else {
|
} else {
|
||||||
data.inputs.move_dir
|
data.inputs.move_dir
|
||||||
}.try_normalized().unwrap_or_else(|| Vec2::from(*data.ori));
|
}
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(|| Vec2::from(*data.ori));
|
||||||
let direction = direction.reflected(Vec2::from(*data.ori).rotated_z(PI / 2.));
|
let direction = direction.reflected(Vec2::from(*data.ori).rotated_z(PI / 2.));
|
||||||
update.vel.0 += direction * strength * accel * data.dt.0;
|
update.vel.0 += direction * strength * accel * data.dt.0;
|
||||||
}
|
}
|
||||||
@ -1060,7 +1064,12 @@ pub fn handle_jump(
|
|||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, output_events: &mut OutputEvents, input: InputKind) -> bool {
|
fn handle_ability(
|
||||||
|
data: &JoinData<'_>,
|
||||||
|
update: &mut StateUpdate,
|
||||||
|
output_events: &mut OutputEvents,
|
||||||
|
input: InputKind,
|
||||||
|
) -> bool {
|
||||||
let context = AbilityContext::from(data.stance);
|
let context = AbilityContext::from(data.stance);
|
||||||
if let Some(ability_input) = input.into() {
|
if let Some(ability_input) = input.into() {
|
||||||
if let Some((ability, from_offhand)) = data
|
if let Some((ability, from_offhand)) = data
|
||||||
@ -1084,7 +1093,10 @@ fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, output_events:
|
|||||||
if let Some(init_event) = ability.ability_meta().init_event {
|
if let Some(init_event) = ability.ability_meta().init_event {
|
||||||
match init_event {
|
match init_event {
|
||||||
AbilityInitEvent::EnterStance(stance) => {
|
AbilityInitEvent::EnterStance(stance) => {
|
||||||
output_events.emit_server(ServerEvent::ChangeStance { entity: data.entity, stance });
|
output_events.emit_server(ServerEvent::ChangeStance {
|
||||||
|
entity: data.entity,
|
||||||
|
stance,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1428,7 +1440,12 @@ impl AbilityInfo {
|
|||||||
tool,
|
tool,
|
||||||
hand,
|
hand,
|
||||||
input,
|
input,
|
||||||
input_attr: data.controller.queued_inputs.get(&input).map(|x| x.1).or_else(|| data.controller.held_inputs.get(&input).copied()),
|
input_attr: data
|
||||||
|
.controller
|
||||||
|
.queued_inputs
|
||||||
|
.get(&input)
|
||||||
|
.map(|x| x.1)
|
||||||
|
.or_else(|| data.controller.held_inputs.get(&input).copied()),
|
||||||
ability_meta,
|
ability_meta,
|
||||||
ability,
|
ability,
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,7 @@ fn activate_aura(
|
|||||||
source,
|
source,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
stats,
|
stats,
|
||||||
|
Some(health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
energy: read_data.energies.get(entity),
|
energy: read_data.energies.get(entity),
|
||||||
combo: read_data.combos.get(entity),
|
combo: read_data.combos.get(entity),
|
||||||
inventory: read_data.inventories.get(entity),
|
inventory: read_data.inventories.get(entity),
|
||||||
|
stats: read_data.stats.get(entity),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -151,6 +151,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffSource::World,
|
BuffSource::World,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -168,6 +169,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffSource::World,
|
BuffSource::World,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -185,6 +187,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffSource::World,
|
BuffSource::World,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
// When standing on IceSpike also apply Frozen
|
// When standing on IceSpike also apply Frozen
|
||||||
@ -197,6 +200,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffSource::World,
|
BuffSource::World,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -217,6 +221,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffSource::World,
|
BuffSource::World,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
} else if matches!(
|
} else if matches!(
|
||||||
@ -296,6 +301,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
buff.source,
|
buff.source,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
Some(&stat),
|
Some(&stat),
|
||||||
|
Some(&health),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -573,5 +579,12 @@ fn execute_effect(
|
|||||||
BuffEffect::HealReduction(red) => {
|
BuffEffect::HealReduction(red) => {
|
||||||
stat.heal_multiplier *= 1.0 - *red;
|
stat.heal_multiplier *= 1.0 - *red;
|
||||||
},
|
},
|
||||||
|
BuffEffect::PoiseDamageFromLostHealth {
|
||||||
|
initial_health,
|
||||||
|
strength,
|
||||||
|
} => {
|
||||||
|
let lost_health = (*initial_health - health.current()).max(0.0);
|
||||||
|
stat.poise_damage_modifier *= lost_health / 100.0 * *strength;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
terrain: &read_data.terrain,
|
terrain: &read_data.terrain,
|
||||||
mount_data: read_data.is_riders.get(entity),
|
mount_data: read_data.is_riders.get(entity),
|
||||||
stance: read_data.stances.get(entity),
|
stance: read_data.stances.get(entity),
|
||||||
time: &read_data.time,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for action in actions {
|
for action in actions {
|
||||||
@ -274,7 +273,7 @@ impl Sys {
|
|||||||
for (input, attr) in state_update.queued_inputs {
|
for (input, attr) in state_update.queued_inputs {
|
||||||
join.controller
|
join.controller
|
||||||
.queued_inputs
|
.queued_inputs
|
||||||
.insert(input, (*join.time, attr));
|
.insert(input, (Time(0.0), attr));
|
||||||
join.controller.held_inputs.insert(input, attr);
|
join.controller.held_inputs.insert(input, attr);
|
||||||
}
|
}
|
||||||
for input in state_update.used_inputs {
|
for input in state_update.used_inputs {
|
||||||
@ -283,7 +282,7 @@ impl Sys {
|
|||||||
for input in state_update.removed_inputs {
|
for input in state_update.removed_inputs {
|
||||||
join.controller.held_inputs.remove(&input);
|
join.controller.held_inputs.remove(&input);
|
||||||
}
|
}
|
||||||
join.controller.cull_queued_inputs(*join.time);
|
join.controller.cull_queued_inputs(Time(0.0));
|
||||||
if state_update.swap_equipped_weapons {
|
if state_update.swap_equipped_weapons {
|
||||||
output_events.emit_server(ServerEvent::InventoryManip(
|
output_events.emit_server(ServerEvent::InventoryManip(
|
||||||
join.entity,
|
join.entity,
|
||||||
|
@ -191,6 +191,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
energy: read_data.energies.get(attacker),
|
energy: read_data.energies.get(attacker),
|
||||||
combo: read_data.combos.get(attacker),
|
combo: read_data.combos.get(attacker),
|
||||||
inventory: read_data.inventories.get(attacker),
|
inventory: read_data.inventories.get(attacker),
|
||||||
|
stats: read_data.stats.get(attacker),
|
||||||
});
|
});
|
||||||
|
|
||||||
let target_info = TargetInfo {
|
let target_info = TargetInfo {
|
||||||
|
@ -298,6 +298,7 @@ fn dispatch_hit(
|
|||||||
energy: read_data.energies.get(entity),
|
energy: read_data.energies.get(entity),
|
||||||
combo: read_data.combos.get(entity),
|
combo: read_data.combos.get(entity),
|
||||||
inventory: read_data.inventories.get(entity),
|
inventory: read_data.inventories.get(entity),
|
||||||
|
stats: read_data.stats.get(entity),
|
||||||
});
|
});
|
||||||
|
|
||||||
let target_info = TargetInfo {
|
let target_info = TargetInfo {
|
||||||
|
@ -198,6 +198,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
energy: read_data.energies.get(entity),
|
energy: read_data.energies.get(entity),
|
||||||
combo: read_data.combos.get(entity),
|
combo: read_data.combos.get(entity),
|
||||||
inventory: read_data.inventories.get(entity),
|
inventory: read_data.inventories.get(entity),
|
||||||
|
stats: read_data.stats.get(entity),
|
||||||
});
|
});
|
||||||
|
|
||||||
let target_info = TargetInfo {
|
let target_info = TargetInfo {
|
||||||
|
@ -3541,6 +3541,7 @@ fn cast_buff(kind: &str, data: BuffData, server: &mut Server, target: EcsEntity)
|
|||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let stats = ecs.read_storage::<comp::Stats>();
|
||||||
|
let healths = ecs.read_storage::<comp::Health>();
|
||||||
let time = ecs.read_resource::<Time>();
|
let time = ecs.read_resource::<Time>();
|
||||||
if let Some(mut buffs) = buffs_all.get_mut(target) {
|
if let Some(mut buffs) = buffs_all.get_mut(target) {
|
||||||
buffs.insert(
|
buffs.insert(
|
||||||
@ -3551,6 +3552,7 @@ fn cast_buff(kind: &str, data: BuffData, server: &mut Server, target: EcsEntity)
|
|||||||
BuffSource::Command,
|
BuffSource::Command,
|
||||||
*time,
|
*time,
|
||||||
stats.get(target),
|
stats.get(target),
|
||||||
|
healths.get(target),
|
||||||
),
|
),
|
||||||
*time,
|
*time,
|
||||||
);
|
);
|
||||||
|
@ -865,18 +865,18 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
|||||||
let uid_allocator = &ecs.read_resource::<UidAllocator>();
|
let uid_allocator = &ecs.read_resource::<UidAllocator>();
|
||||||
let players = &ecs.read_storage::<Player>();
|
let players = &ecs.read_storage::<Player>();
|
||||||
let buffs = &ecs.read_storage::<comp::Buffs>();
|
let buffs = &ecs.read_storage::<comp::Buffs>();
|
||||||
|
let stats = &ecs.read_storage::<comp::Stats>();
|
||||||
for (
|
for (
|
||||||
entity_b,
|
entity_b,
|
||||||
pos_b,
|
pos_b,
|
||||||
health_b,
|
health_b,
|
||||||
(body_b_maybe, stats_b_maybe, ori_b_maybe, char_state_b_maybe, uid_b),
|
(body_b_maybe, ori_b_maybe, char_state_b_maybe, uid_b),
|
||||||
) in (
|
) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
&ecs.read_storage::<Health>(),
|
&ecs.read_storage::<Health>(),
|
||||||
(
|
(
|
||||||
ecs.read_storage::<Body>().maybe(),
|
ecs.read_storage::<Body>().maybe(),
|
||||||
ecs.read_storage::<Stats>().maybe(),
|
|
||||||
ecs.read_storage::<comp::Ori>().maybe(),
|
ecs.read_storage::<comp::Ori>().maybe(),
|
||||||
ecs.read_storage::<CharacterState>().maybe(),
|
ecs.read_storage::<CharacterState>().maybe(),
|
||||||
&ecs.read_storage::<Uid>(),
|
&ecs.read_storage::<Uid>(),
|
||||||
@ -927,13 +927,14 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
|||||||
energy: energies.get(entity),
|
energy: energies.get(entity),
|
||||||
combo: combos.get(entity),
|
combo: combos.get(entity),
|
||||||
inventory: inventories.get(entity),
|
inventory: inventories.get(entity),
|
||||||
|
stats: stats.get(entity),
|
||||||
});
|
});
|
||||||
|
|
||||||
let target_info = combat::TargetInfo {
|
let target_info = combat::TargetInfo {
|
||||||
entity: entity_b,
|
entity: entity_b,
|
||||||
uid: *uid_b,
|
uid: *uid_b,
|
||||||
inventory: inventories.get(entity_b),
|
inventory: inventories.get(entity_b),
|
||||||
stats: stats_b_maybe,
|
stats: stats.get(entity_b),
|
||||||
health: Some(health_b),
|
health: Some(health_b),
|
||||||
pos: pos_b.0,
|
pos: pos_b.0,
|
||||||
ori: ori_b_maybe,
|
ori: ori_b_maybe,
|
||||||
@ -1159,15 +1160,16 @@ pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::Bu
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
BuffChange::Refresh(kind) => {
|
BuffChange::Refresh(kind) => {
|
||||||
let (buff_comp_kinds, buff_comp_buffs) = buffs.parts();
|
buffs
|
||||||
if let Some(buff_ids) = buff_comp_kinds.get(&kind) {
|
.buffs
|
||||||
for id in buff_ids {
|
.values_mut()
|
||||||
if let Some(buff) = buff_comp_buffs.get_mut(id) {
|
.filter(|b| b.kind == kind)
|
||||||
// Resets buff timer to the original duration
|
.for_each(|buff| {
|
||||||
buff.time = buff.data.duration;
|
// Resets buff so that its remaining duration is equal to its original
|
||||||
}
|
// duration
|
||||||
}
|
buff.start_time = *time;
|
||||||
}
|
buff.end_time = buff.data.duration.map(|dur| Time(time.0 + dur.0));
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1303,6 +1305,7 @@ pub fn handle_parry_hook(server: &Server, defender: EcsEntity, attacker: Option<
|
|||||||
};
|
};
|
||||||
let time = ecs.read_resource::<Time>();
|
let time = ecs.read_resource::<Time>();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let stats = ecs.read_storage::<comp::Stats>();
|
||||||
|
let healths = ecs.read_storage::<comp::Health>();
|
||||||
let buff = buff::Buff::new(
|
let buff = buff::Buff::new(
|
||||||
BuffKind::Parried,
|
BuffKind::Parried,
|
||||||
data,
|
data,
|
||||||
@ -1310,6 +1313,7 @@ pub fn handle_parry_hook(server: &Server, defender: EcsEntity, attacker: Option<
|
|||||||
source,
|
source,
|
||||||
*time,
|
*time,
|
||||||
stats.get(attacker),
|
stats.get(attacker),
|
||||||
|
healths.get(attacker),
|
||||||
);
|
);
|
||||||
server_eventbus.emit_now(ServerEvent::Buff {
|
server_eventbus.emit_now(ServerEvent::Buff {
|
||||||
entity: attacker,
|
entity: attacker,
|
||||||
|
@ -224,6 +224,7 @@ impl StateExt for State {
|
|||||||
Effect::Buff(buff) => {
|
Effect::Buff(buff) => {
|
||||||
let time = self.ecs().read_resource::<Time>();
|
let time = self.ecs().read_resource::<Time>();
|
||||||
let stats = self.ecs().read_storage::<comp::Stats>();
|
let stats = self.ecs().read_storage::<comp::Stats>();
|
||||||
|
let healths = self.ecs().read_storage::<comp::Health>();
|
||||||
self.ecs()
|
self.ecs()
|
||||||
.write_storage::<comp::Buffs>()
|
.write_storage::<comp::Buffs>()
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
@ -236,6 +237,7 @@ impl StateExt for State {
|
|||||||
comp::BuffSource::Item,
|
comp::BuffSource::Item,
|
||||||
*time,
|
*time,
|
||||||
stats.get(entity),
|
stats.get(entity),
|
||||||
|
healths.get(entity),
|
||||||
),
|
),
|
||||||
*time,
|
*time,
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,7 @@ use super::{
|
|||||||
CharacterSkeleton, SkeletonAttr,
|
CharacterSkeleton, SkeletonAttr,
|
||||||
};
|
};
|
||||||
use common::states::utils::{AbilityInfo, StageSection};
|
use common::states::utils::{AbilityInfo, StageSection};
|
||||||
|
use core::f32::consts::PI;
|
||||||
|
|
||||||
pub struct DiveMeleeAnimation;
|
pub struct DiveMeleeAnimation;
|
||||||
impl Animation for DiveMeleeAnimation {
|
impl Animation for DiveMeleeAnimation {
|
||||||
@ -81,6 +82,54 @@ impl Animation for DiveMeleeAnimation {
|
|||||||
next.control.orientation.rotate_x(move3 * -1.2);
|
next.control.orientation.rotate_x(move3 * -1.2);
|
||||||
next.control.position += Vec3::new(0.0, move3 * 4.0, move3 * -8.0);
|
next.control.position += Vec3::new(0.0, move3 * 4.0, move3 * -8.0);
|
||||||
},
|
},
|
||||||
|
Some("common.abilities.sword.heavy_pillar_thrust") => {
|
||||||
|
let (move1, move2, move3) = match stage_section {
|
||||||
|
Some(StageSection::Buildup) => (anim_time.powf(0.5), 0.0, 0.0),
|
||||||
|
Some(StageSection::Movement) => (anim_time.min(1.0).powf(0.5), 0.0, 0.0),
|
||||||
|
Some(StageSection::Action) => (1.0, anim_time.powi(2), 0.0),
|
||||||
|
Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)),
|
||||||
|
_ => (0.0, 0.0, 0.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let move1alt1 = move1.min(0.5) * 2.0;
|
||||||
|
let move1alt2 = (move1.max(0.5) - 0.5) * 2.0;
|
||||||
|
|
||||||
|
let pullback = 1.0 - move3;
|
||||||
|
let move1 = move1 * pullback;
|
||||||
|
let move1alt1 = move1alt1 * pullback;
|
||||||
|
let move1alt2 = move1alt2 * pullback;
|
||||||
|
let move2 = move2 * pullback;
|
||||||
|
|
||||||
|
next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2);
|
||||||
|
next.hand_l.orientation = Quaternion::rotation_x(s_a.shl.3 + move1alt2 * PI)
|
||||||
|
* Quaternion::rotation_y(s_a.shl.4);
|
||||||
|
next.hand_r.position = Vec3::new(
|
||||||
|
-s_a.sc.0 + 6.0 + move1alt1 * -12.0,
|
||||||
|
-4.0 + move1alt1 * 3.0,
|
||||||
|
-2.0,
|
||||||
|
);
|
||||||
|
next.hand_r.orientation =
|
||||||
|
Quaternion::rotation_x(0.9 + move1 * 0.5 + move1alt1 * PI);
|
||||||
|
next.control.position = Vec3::new(s_a.sc.0, s_a.sc.1, s_a.sc.2);
|
||||||
|
next.control.orientation = Quaternion::rotation_x(s_a.sc.3);
|
||||||
|
|
||||||
|
next.control.position += Vec3::new(
|
||||||
|
move1 * 6.0,
|
||||||
|
(1.0 - (move1 - 0.5).abs() * 2.0) * 3.0,
|
||||||
|
move1 * 22.0,
|
||||||
|
);
|
||||||
|
next.control.orientation.rotate_x(move1 * -1.5);
|
||||||
|
|
||||||
|
next.chest.orientation = Quaternion::rotation_x(move2 * -0.4);
|
||||||
|
next.head.orientation = Quaternion::rotation_x(move2 * 0.2);
|
||||||
|
next.belt.orientation = Quaternion::rotation_x(move2 * 0.4);
|
||||||
|
next.shorts.orientation = Quaternion::rotation_x(move2 * 0.8);
|
||||||
|
next.control.orientation.rotate_x(move2 * -0.4);
|
||||||
|
next.control.position += Vec3::new(0.0, 0.0, move2 * -10.0);
|
||||||
|
next.belt.position += Vec3::new(0.0, move2 * 2.0, move2 * 0.0);
|
||||||
|
next.shorts.position += Vec3::new(0.0, move2 * 4.0, move2 * 1.0);
|
||||||
|
next.chest.position += Vec3::new(0.0, move2 * -2.5, 0.0);
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,53 +109,6 @@ impl Animation for FinisherMeleeAnimation {
|
|||||||
next.control.position += Vec3::new(0.0, 0.0, move3 * 4.0);
|
next.control.position += Vec3::new(0.0, 0.0, move3 * 4.0);
|
||||||
next.control.orientation.rotate_x(move3 * 0.6);
|
next.control.orientation.rotate_x(move3 * 0.6);
|
||||||
},
|
},
|
||||||
Some("common.abilities.sword.crippling_finisher") => {
|
|
||||||
let (move1, move2, move3) = match stage_section {
|
|
||||||
Some(StageSection::Buildup) => (anim_time.powf(0.5), 0.0, 0.0),
|
|
||||||
Some(StageSection::Action) => (1.0, anim_time.powi(2), 0.0),
|
|
||||||
Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)),
|
|
||||||
_ => (0.0, 0.0, 0.0),
|
|
||||||
};
|
|
||||||
|
|
||||||
let move1alt1 = move1.min(0.5) * 2.0;
|
|
||||||
let move1alt2 = (move1.max(0.5) - 0.5) * 2.0;
|
|
||||||
|
|
||||||
let pullback = 1.0 - move3;
|
|
||||||
let move1 = move1 * pullback;
|
|
||||||
let move1alt1 = move1alt1 * pullback;
|
|
||||||
let move1alt2 = move1alt2 * pullback;
|
|
||||||
let move2 = move2 * pullback;
|
|
||||||
|
|
||||||
next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2);
|
|
||||||
next.hand_l.orientation = Quaternion::rotation_x(s_a.shl.3 + move1alt2 * PI)
|
|
||||||
* Quaternion::rotation_y(s_a.shl.4);
|
|
||||||
next.hand_r.position = Vec3::new(
|
|
||||||
-s_a.sc.0 + 6.0 + move1alt1 * -12.0,
|
|
||||||
-4.0 + move1alt1 * 3.0,
|
|
||||||
-2.0,
|
|
||||||
);
|
|
||||||
next.hand_r.orientation =
|
|
||||||
Quaternion::rotation_x(0.9 + move1 * 0.5 + move1alt1 * PI);
|
|
||||||
next.control.position = Vec3::new(s_a.sc.0, s_a.sc.1, s_a.sc.2);
|
|
||||||
next.control.orientation = Quaternion::rotation_x(s_a.sc.3);
|
|
||||||
|
|
||||||
next.control.position += Vec3::new(
|
|
||||||
move1 * 6.0,
|
|
||||||
(1.0 - (move1 - 0.5).abs() * 2.0) * 3.0,
|
|
||||||
move1 * 22.0,
|
|
||||||
);
|
|
||||||
next.control.orientation.rotate_x(move1 * -1.5);
|
|
||||||
|
|
||||||
next.chest.orientation = Quaternion::rotation_x(move2 * -0.4);
|
|
||||||
next.head.orientation = Quaternion::rotation_x(move2 * 0.2);
|
|
||||||
next.belt.orientation = Quaternion::rotation_x(move2 * 0.4);
|
|
||||||
next.shorts.orientation = Quaternion::rotation_x(move2 * 0.8);
|
|
||||||
next.control.orientation.rotate_x(move2 * -0.4);
|
|
||||||
next.control.position += Vec3::new(0.0, 0.0, move2 * -10.0);
|
|
||||||
next.belt.position += Vec3::new(0.0, move2 * 2.0, move2 * 0.0);
|
|
||||||
next.shorts.position += Vec3::new(0.0, move2 * 4.0, move2 * 1.0);
|
|
||||||
next.chest.position += Vec3::new(0.0, move2 * -2.5, 0.0);
|
|
||||||
},
|
|
||||||
Some("common.abilities.sword.cleaving_finisher") => {
|
Some("common.abilities.sword.cleaving_finisher") => {
|
||||||
let (move1, move2, move3) = match stage_section {
|
let (move1, move2, move3) = match stage_section {
|
||||||
Some(StageSection::Buildup) => (anim_time.powf(0.5), 0.0, 0.0),
|
Some(StageSection::Buildup) => (anim_time.powf(0.5), 0.0, 0.0),
|
||||||
|
@ -29,6 +29,40 @@ impl Animation for SelfBuffAnimation {
|
|||||||
next.second.orientation = Quaternion::rotation_z(0.0);
|
next.second.orientation = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
match ability_id {
|
match ability_id {
|
||||||
|
Some("common.abilities.sword.heavy_fortitude") => {
|
||||||
|
let (move1, move2, move3) = match stage_section {
|
||||||
|
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
||||||
|
Some(StageSection::Action) => (1.0, anim_time.powi(2), 0.0),
|
||||||
|
Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)),
|
||||||
|
_ => (0.0, 0.0, 0.0),
|
||||||
|
};
|
||||||
|
let pullback = 1.0 - move3;
|
||||||
|
let move1 = move1 * pullback;
|
||||||
|
let move2 = move2 * pullback;
|
||||||
|
|
||||||
|
next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2);
|
||||||
|
next.hand_l.orientation =
|
||||||
|
Quaternion::rotation_x(s_a.shl.3) * Quaternion::rotation_y(s_a.shl.4);
|
||||||
|
next.hand_r.position =
|
||||||
|
Vec3::new(-s_a.sc.0 + 6.0 + move1 * -12.0, -4.0 + move1 * 3.0, -2.0);
|
||||||
|
next.hand_r.orientation = Quaternion::rotation_x(0.9 + move1 * 0.5);
|
||||||
|
next.control.position = Vec3::new(s_a.sc.0, s_a.sc.1, s_a.sc.2);
|
||||||
|
next.control.orientation = Quaternion::rotation_x(s_a.sc.3);
|
||||||
|
|
||||||
|
next.foot_l.position += Vec3::new(move1 * 1.0, move1 * 2.0, 0.0);
|
||||||
|
next.chest.orientation = Quaternion::rotation_z(move1 * -0.4);
|
||||||
|
next.head.orientation = Quaternion::rotation_z(move1 * 0.2);
|
||||||
|
next.shorts.orientation = Quaternion::rotation_z(move1 * 0.3);
|
||||||
|
next.belt.orientation = Quaternion::rotation_z(move1 * 0.1);
|
||||||
|
next.control.orientation.rotate_x(move1 * 0.4 + move2 * 0.6);
|
||||||
|
next.control.orientation.rotate_z(move1 * 0.4);
|
||||||
|
|
||||||
|
next.foot_r.position += Vec3::new(move2 * -1.0, move2 * -2.0, 0.0);
|
||||||
|
next.control.position += Vec3::new(move2 * 5.0, move2 * 7.0, move2 * 5.0);
|
||||||
|
next.chest.position += Vec3::new(0.0, 0.0, move2 * -1.0);
|
||||||
|
next.shorts.orientation.rotate_x(move2 * 0.2);
|
||||||
|
next.shorts.position += Vec3::new(0.0, move2 * 1.0, 0.0);
|
||||||
|
},
|
||||||
Some("common.abilities.sword.defensive_bulwark") => {
|
Some("common.abilities.sword.defensive_bulwark") => {
|
||||||
let (move1, move2, move3) = match stage_section {
|
let (move1, move2, move3) = match stage_section {
|
||||||
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
||||||
@ -67,40 +101,6 @@ impl Animation for SelfBuffAnimation {
|
|||||||
next.shorts.orientation.rotate_x(move2 * 0.2);
|
next.shorts.orientation.rotate_x(move2 * 0.2);
|
||||||
next.control.orientation.rotate_z(move2 * 0.4);
|
next.control.orientation.rotate_z(move2 * 0.4);
|
||||||
},
|
},
|
||||||
Some("common.abilities.sword.heavy_fortitude") => {
|
|
||||||
let (move1, move2, move3) = match stage_section {
|
|
||||||
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
|
||||||
Some(StageSection::Action) => (1.0, anim_time.powi(2), 0.0),
|
|
||||||
Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)),
|
|
||||||
_ => (0.0, 0.0, 0.0),
|
|
||||||
};
|
|
||||||
let pullback = 1.0 - move3;
|
|
||||||
let move1 = move1 * pullback;
|
|
||||||
let move2 = move2 * pullback;
|
|
||||||
|
|
||||||
next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2);
|
|
||||||
next.hand_l.orientation =
|
|
||||||
Quaternion::rotation_x(s_a.shl.3) * Quaternion::rotation_y(s_a.shl.4);
|
|
||||||
next.hand_r.position =
|
|
||||||
Vec3::new(-s_a.sc.0 + 6.0 + move1 * -12.0, -4.0 + move1 * 3.0, -2.0);
|
|
||||||
next.hand_r.orientation = Quaternion::rotation_x(0.9 + move1 * 0.5);
|
|
||||||
next.control.position = Vec3::new(s_a.sc.0, s_a.sc.1, s_a.sc.2);
|
|
||||||
next.control.orientation = Quaternion::rotation_x(s_a.sc.3);
|
|
||||||
|
|
||||||
next.foot_l.position += Vec3::new(move1 * 1.0, move1 * 2.0, 0.0);
|
|
||||||
next.chest.orientation = Quaternion::rotation_z(move1 * -0.4);
|
|
||||||
next.head.orientation = Quaternion::rotation_z(move1 * 0.2);
|
|
||||||
next.shorts.orientation = Quaternion::rotation_z(move1 * 0.3);
|
|
||||||
next.belt.orientation = Quaternion::rotation_z(move1 * 0.1);
|
|
||||||
next.control.orientation.rotate_x(move1 * 0.4 + move2 * 0.6);
|
|
||||||
next.control.orientation.rotate_z(move1 * 0.4);
|
|
||||||
|
|
||||||
next.foot_r.position += Vec3::new(move2 * -1.0, move2 * -2.0, 0.0);
|
|
||||||
next.control.position += Vec3::new(move2 * 5.0, move2 * 7.0, move2 * 5.0);
|
|
||||||
next.chest.position += Vec3::new(0.0, 0.0, move2 * -1.0);
|
|
||||||
next.shorts.orientation.rotate_x(move2 * 0.2);
|
|
||||||
next.shorts.position += Vec3::new(0.0, move2 * 1.0, 0.0);
|
|
||||||
},
|
|
||||||
Some("common.abilities.sword.mobility_agility") => {
|
Some("common.abilities.sword.mobility_agility") => {
|
||||||
let (move1, move2, move3) = match stage_section {
|
let (move1, move2, move3) = match stage_section {
|
||||||
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
Some(StageSection::Movement) => (anim_time.powf(0.25), 0.0, 0.0),
|
||||||
|
@ -250,7 +250,7 @@ pub trait Animation {
|
|||||||
let update_fn: common_dynlib::Symbol<
|
let update_fn: common_dynlib::Symbol<
|
||||||
fn(
|
fn(
|
||||||
&Self::Skeleton,
|
&Self::Skeleton,
|
||||||
Self::Dependency<'a>,
|
Self::Dependency<'_>,
|
||||||
f32,
|
f32,
|
||||||
&mut f32,
|
&mut f32,
|
||||||
&<Self::Skeleton as Skeleton>::Attr,
|
&<Self::Skeleton as Skeleton>::Attr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user