Offensive abilities

This commit is contained in:
Sam 2022-03-04 13:35:26 -05:00
parent c37925d1e2
commit 2051d45d2f
13 changed files with 192 additions and 98 deletions

View File

@ -15,7 +15,6 @@ ComboMelee2(
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
recover_duration: 0.5, recover_duration: 0.5,
forward_movement: 0.0,
ori_modifier: 0.6, ori_modifier: 0.6,
), ),
( (
@ -33,11 +32,11 @@ ComboMelee2(
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
recover_duration: 0.3, recover_duration: 0.3,
forward_movement: 0.0,
ori_modifier: 0.6, ori_modifier: 0.6,
), ),
], ],
is_stance: true, is_stance: true,
energy_cost_per_strike: 0,
meta: ( meta: (
kind: Some(Sword(Balanced)), kind: Some(Sword(Balanced)),
), ),

View File

@ -14,4 +14,7 @@ FinisherMelee(
angle: 15.0, angle: 15.0,
), ),
minimum_combo: 10, minimum_combo: 10,
meta: (
kind: Some(Sword(Balanced)),
),
) )

View File

@ -3,7 +3,7 @@ ComboMelee2(
( (
melee_constructor: ( melee_constructor: (
kind: Slash( kind: Slash(
damage: 15, damage: 12,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 5, energy_regen: 5,
@ -15,11 +15,11 @@ ComboMelee2(
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.6, hit_timing: 0.6,
recover_duration: 0.5, recover_duration: 0.5,
forward_movement: 0.0,
ori_modifier: 0.6, ori_modifier: 0.6,
), ),
], ],
is_stance: false, is_stance: false,
energy_cost_per_strike: 5,
meta: ( meta: (
kind: Some(Sword(Balanced)), kind: Some(Sword(Balanced)),
), ),

View File

@ -1,25 +1,27 @@
// TODO: Make actual ability, just for testing right now ComboMelee2(
BasicMelee( strikes: [
energy_cost: 50, (
buildup_duration: 0.3,
swing_duration: 0.1,
recover_duration: 0.2,
melee_constructor: ( melee_constructor: (
kind: Stab( kind: Slash(
damage: 10, damage: 15,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 0, energy_regen: 10,
), ),
range: 5.0, range: 6.0,
angle: 10.0, angle: 5.0,
), ),
ori_modifier: 1.0, buildup_duration: 0.2,
swing_duration: 0.1,
hit_timing: 0.6,
recover_duration: 0.4,
movement: Some(Forward(2.5)),
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 10,
meta: ( meta: (
kind: Some(Sword(Balanced)), kind: Some(Sword(Offensive)),
capabilities: (
// Block
bits: 0b00000010,
),
), ),
) )

View File

@ -1,25 +1,60 @@
// TODO: Make actual ability, just for testing right now ComboMelee2(
BasicMelee( strikes: [
energy_cost: 50, (
buildup_duration: 0.3,
swing_duration: 0.1,
recover_duration: 0.2,
melee_constructor: ( melee_constructor: (
kind: Stab( kind: Slash(
damage: 10, damage: 10,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 0, energy_regen: 5,
), ),
range: 5.0, range: 3.0,
angle: 10.0, angle: 45.0,
), ),
ori_modifier: 1.0, buildup_duration: 0.3,
swing_duration: 0.1,
hit_timing: 0.5,
recover_duration: 0.5,
ori_modifier: 0.6,
),
(
melee_constructor: (
kind: Slash(
damage: 14,
poise: 0,
knockback: 0,
energy_regen: 8,
),
range: 3.0,
angle: 45.0,
),
buildup_duration: 0.3,
swing_duration: 0.1,
hit_timing: 0.5,
recover_duration: 0.3,
ori_modifier: 0.6,
),
(
melee_constructor: (
kind: Slash(
damage: 9,
poise: 0,
knockback: 0,
energy_regen: 10,
),
range: 3.0,
angle: 45.0,
),
buildup_duration: 0.2,
swing_duration: 0.05,
hit_timing: 0.5,
recover_duration: 0.1,
ori_modifier: 0.6,
),
],
is_stance: true,
energy_cost_per_strike: 5,
meta: ( meta: (
kind: Some(Sword(Balanced)), kind: Some(Sword(Offensive)),
capabilities: (
// Block
bits: 0b00000010,
),
), ),
) )

View File

@ -1,25 +1,30 @@
// TODO: Make actual ability, just for testing right now FinisherMelee(
BasicMelee( energy_cost: 40,
energy_cost: 50, buildup_duration: 0.4,
buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.2, recover_duration: 0.4,
melee_constructor: ( melee_constructor: (
kind: Stab( kind: Slash(
damage: 10, damage: 30,
poise: 0,
knockback: 0,
energy_regen: 10,
),
scaled: Some(Slash(
damage: 15,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 0, energy_regen: 0,
)),
range: 3.0,
angle: 15.0,
), ),
range: 5.0, scaling: Some((
angle: 10.0, target: Attack,
), kind: Linear,
ori_modifier: 1.0, )),
minimum_combo: 10,
meta: ( meta: (
kind: Some(Sword(Balanced)), kind: Some(Sword(Offensive)),
capabilities: (
// Block
bits: 0b00000010,
),
), ),
) )

View File

@ -506,6 +506,7 @@ pub enum CharacterAbility {
ComboMelee2 { ComboMelee2 {
strikes: Vec<combo_melee2::Strike<f32>>, strikes: Vec<combo_melee2::Strike<f32>>,
is_stance: bool, is_stance: bool,
energy_cost_per_strike: f32,
#[serde(default)] #[serde(default)]
meta: AbilityMeta, meta: AbilityMeta,
}, },
@ -744,6 +745,22 @@ impl CharacterAbility {
| !*scales_with_combo) | !*scales_with_combo)
&& update.energy.try_change_by(-*energy_cost).is_ok() && update.energy.try_change_by(-*energy_cost).is_ok()
}, },
CharacterAbility::ComboMelee2 {
is_stance,
energy_cost_per_strike,
..
} => {
// If it is a stance, just check that enough energy is present, otherwise
// consume the required energy now
if *is_stance {
update.energy.current() > *energy_cost_per_strike
} else {
update
.energy
.try_change_by(-*energy_cost_per_strike)
.is_ok()
}
},
CharacterAbility::FinisherMelee { CharacterAbility::FinisherMelee {
energy_cost, energy_cost,
minimum_combo, minimum_combo,
@ -753,7 +770,6 @@ impl CharacterAbility {
&& update.energy.try_change_by(-*energy_cost).is_ok() && update.energy.try_change_by(-*energy_cost).is_ok()
}, },
CharacterAbility::ComboMelee { .. } CharacterAbility::ComboMelee { .. }
| CharacterAbility::ComboMelee2 { .. }
| CharacterAbility::Boost { .. } | CharacterAbility::Boost { .. }
| CharacterAbility::BasicBeam { .. } | CharacterAbility::BasicBeam { .. }
| CharacterAbility::Blink { .. } | CharacterAbility::Blink { .. }
@ -920,8 +936,10 @@ impl CharacterAbility {
ComboMelee2 { ComboMelee2 {
ref mut strikes, ref mut strikes,
is_stance: _, is_stance: _,
ref mut energy_cost_per_strike,
meta: _, meta: _,
} => { } => {
*energy_cost_per_strike /= stats.energy_efficiency;
*strikes = strikes *strikes = strikes
.iter_mut() .iter_mut()
.map(|s| s.adjusted_by_stats(stats)) .map(|s| s.adjusted_by_stats(stats))
@ -1208,7 +1226,11 @@ impl CharacterAbility {
| BasicAura { energy_cost, .. } | BasicAura { energy_cost, .. }
| BasicBlock { energy_cost, .. } | BasicBlock { energy_cost, .. }
| SelfBuff { energy_cost, .. } | SelfBuff { energy_cost, .. }
| FinisherMelee { energy_cost, .. } => *energy_cost, | FinisherMelee { energy_cost, .. }
| ComboMelee2 {
energy_cost_per_strike: energy_cost,
..
} => *energy_cost,
BasicBeam { energy_drain, .. } => { BasicBeam { energy_drain, .. } => {
if *energy_drain > f32::EPSILON { if *energy_drain > f32::EPSILON {
1.0 1.0
@ -1218,7 +1240,6 @@ impl CharacterAbility {
}, },
Boost { .. } Boost { .. }
| ComboMelee { .. } | ComboMelee { .. }
| ComboMelee2 { .. }
| Blink { .. } | Blink { .. }
| Music { .. } | Music { .. }
| BasicSummon { .. } | BasicSummon { .. }
@ -1963,12 +1984,14 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
}), }),
CharacterAbility::ComboMelee2 { CharacterAbility::ComboMelee2 {
strikes, strikes,
energy_cost_per_strike,
is_stance, is_stance,
meta: _, meta: _,
} => CharacterState::ComboMelee2(combo_melee2::Data { } => CharacterState::ComboMelee2(combo_melee2::Data {
static_data: combo_melee2::StaticData { static_data: combo_melee2::StaticData {
strikes: strikes.iter().map(|s| s.to_duration()).collect(), strikes: strikes.iter().map(|s| s.to_duration()).collect(),
is_stance: *is_stance, is_stance: *is_stance,
energy_cost_per_strike: *energy_cost_per_strike,
ability_info, ability_info,
}, },
exhausted: false, exhausted: false,

View File

@ -309,9 +309,13 @@ impl CharacterBehavior for Data {
); );
// Forward movement // Forward movement
handle_forced_movement(data, &mut update, ForcedMovement::Forward { handle_forced_movement(
strength: self.static_data.stage_data[stage_index].forward_movement, data,
}); &mut update,
ForcedMovement::Forward(
self.static_data.stage_data[stage_index].forward_movement,
),
);
// Swings // Swings
update.character = CharacterState::ComboMelee(Data { update.character = CharacterState::ComboMelee(Data {

View File

@ -26,7 +26,7 @@ pub struct Strike<T> {
/// Initial recover duration of stage (how long until character exits state) /// Initial recover duration of stage (how long until character exits state)
pub recover_duration: T, pub recover_duration: T,
/// How much forward movement there is in the swing portion of the stage /// How much forward movement there is in the swing portion of the stage
pub forward_movement: f32, pub movement: Option<ForcedMovement>,
/// Adjusts turning rate during the attack /// Adjusts turning rate during the attack
pub ori_modifier: f32, pub ori_modifier: f32,
} }
@ -39,7 +39,7 @@ impl Strike<f32> {
swing_duration: Duration::from_secs_f32(self.swing_duration), swing_duration: Duration::from_secs_f32(self.swing_duration),
hit_timing: self.hit_timing, hit_timing: self.hit_timing,
recover_duration: Duration::from_secs_f32(self.recover_duration), recover_duration: Duration::from_secs_f32(self.recover_duration),
forward_movement: self.forward_movement, movement: self.movement,
ori_modifier: self.ori_modifier, ori_modifier: self.ori_modifier,
} }
} }
@ -52,7 +52,7 @@ impl Strike<f32> {
swing_duration: self.swing_duration / stats.speed, swing_duration: self.swing_duration / stats.speed,
hit_timing: self.hit_timing, hit_timing: self.hit_timing,
recover_duration: self.recover_duration / stats.speed, recover_duration: self.recover_duration / stats.speed,
forward_movement: self.forward_movement, movement: self.movement,
ori_modifier: self.ori_modifier, ori_modifier: self.ori_modifier,
} }
} }
@ -68,6 +68,8 @@ pub struct StaticData {
/// Whether or not combo melee should function as a stance (where it remains /// Whether or not combo melee should function as a stance (where it remains
/// in the character state after a strike has finished) /// in the character state after a strike has finished)
pub is_stance: bool, pub is_stance: bool,
/// The amount of energy consumed with each swing
pub energy_cost_per_strike: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
} }
@ -115,6 +117,9 @@ impl CharacterBehavior for Data {
match self.stage_section { match self.stage_section {
Some(StageSection::Buildup) => { Some(StageSection::Buildup) => {
if let Some(movement) = strike_data.movement {
handle_forced_movement(data, &mut update, movement);
}
if self.timer < strike_data.buildup_duration { if self.timer < strike_data.buildup_duration {
// Build up // Build up
if let CharacterState::ComboMelee2(c) = &mut update.character { if let CharacterState::ComboMelee2(c) = &mut update.character {
@ -129,9 +134,13 @@ impl CharacterBehavior for Data {
} }
}, },
Some(StageSection::Action) => { Some(StageSection::Action) => {
if let Some(movement) = strike_data.movement {
handle_forced_movement(data, &mut update, movement);
}
if input_is_pressed(data, ability_input) { if input_is_pressed(data, ability_input) {
if let CharacterState::ComboMelee2(c) = &mut update.character { if let CharacterState::ComboMelee2(c) = &mut update.character {
c.skip_recover = true; // Only allow recovery to be skipped if attack is a stance
c.skip_recover = c.static_data.is_stance;
} }
} }
if self.timer.as_secs_f32() if self.timer.as_secs_f32()
@ -233,9 +242,15 @@ fn end_strike(update: &mut StateUpdate) {
fn next_strike(update: &mut StateUpdate) { fn next_strike(update: &mut StateUpdate) {
if let CharacterState::ComboMelee2(c) = &mut update.character { if let CharacterState::ComboMelee2(c) = &mut update.character {
if update
.energy
.try_change_by(-c.static_data.energy_cost_per_strike)
.is_ok()
{
c.exhausted = false; c.exhausted = false;
c.skip_recover = false; c.skip_recover = false;
c.timer = Duration::default(); c.timer = Duration::default();
c.stage_section = Some(StageSection::Buildup); c.stage_section = Some(StageSection::Buildup);
} }
}
} }

View File

@ -89,9 +89,13 @@ impl CharacterBehavior for Data {
.min(1.0); .min(1.0);
handle_orientation(data, &mut update, self.static_data.ori_modifier, None); handle_orientation(data, &mut update, self.static_data.ori_modifier, None);
handle_forced_movement(data, &mut update, ForcedMovement::Forward { handle_forced_movement(
strength: self.static_data.forward_speed * charge_frac.sqrt(), data,
}); &mut update,
ForcedMovement::Forward(
self.static_data.forward_speed * charge_frac.sqrt(),
),
);
// This logic basically just decides if a charge should end, // This logic basically just decides if a charge should end,
// and prevents the character state spamming attacks // and prevents the character state spamming attacks

View File

@ -84,14 +84,18 @@ impl CharacterBehavior for Data {
}, },
StageSection::Movement => { StageSection::Movement => {
// Update velocity // Update velocity
handle_forced_movement(data, &mut update, ForcedMovement::Forward { handle_forced_movement(
strength: self.static_data.roll_strength data,
&mut update,
ForcedMovement::Forward(
self.static_data.roll_strength
* ((1.0 * ((1.0
- self.timer.as_secs_f32() - self.timer.as_secs_f32()
/ self.static_data.movement_duration.as_secs_f32()) / self.static_data.movement_duration.as_secs_f32())
/ 2.0 / 2.0
+ 0.25), + 0.25),
}); ),
);
if self.timer < self.static_data.movement_duration { if self.timer < self.static_data.movement_duration {
// Movement // Movement

View File

@ -107,9 +107,11 @@ impl CharacterBehavior for Data {
self.static_data.movement_behavior, self.static_data.movement_behavior,
MovementBehavior::ForwardGround MovementBehavior::ForwardGround
) { ) {
handle_forced_movement(data, &mut update, ForcedMovement::Forward { handle_forced_movement(
strength: self.static_data.forward_speed, data,
}); &mut update,
ForcedMovement::Forward(self.static_data.forward_speed),
);
} }
// Swings // Swings

View File

@ -408,7 +408,7 @@ pub fn handle_forced_movement(
movement: ForcedMovement, movement: ForcedMovement,
) { ) {
match movement { match movement {
ForcedMovement::Forward { strength } => { ForcedMovement::Forward(strength) => {
let strength = strength * data.stats.move_speed_modifier * data.stats.friction_modifier; let strength = strength * data.stats.move_speed_modifier * data.stats.friction_modifier;
if let Some(accel) = data.physics.on_ground.map(|block| { if let Some(accel) = data.physics.on_ground.map(|block| {
// FRIC_GROUND temporarily used to normalize things around expected values // FRIC_GROUND temporarily used to normalize things around expected values
@ -416,7 +416,7 @@ pub fn handle_forced_movement(
}) { }) {
update.vel.0 += Vec2::broadcast(data.dt.0) update.vel.0 += Vec2::broadcast(data.dt.0)
* accel * accel
* (data.inputs.move_dir * 0.5 + Vec2::from(update.ori) * 1.5) * Vec2::from(update.ori)
* strength; * strength;
} }
}, },
@ -1202,9 +1202,7 @@ pub enum StageSection {
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ForcedMovement { pub enum ForcedMovement {
Forward { Forward(f32),
strength: f32,
},
Leap { Leap {
vertical: f32, vertical: f32,
forward: f32, forward: f32,