diff --git a/assets/common/abilities/sword/cleaving_blade_fever.ron b/assets/common/abilities/sword/cleaving_blade_fever.ron index dba2420527..e6d71fae21 100644 --- a/assets/common/abilities/sword/cleaving_blade_fever.ron +++ b/assets/common/abilities/sword/cleaving_blade_fever.ron @@ -1,39 +1,9 @@ -ComboMelee2( - strikes: [ - ( - melee_constructor: ( - kind: Slash( - 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, - hit_timing: 0.5, - recover_duration: 0.2, - ori_modifier: 0.6, - ), - ], - energy_cost_per_strike: 0, -) \ No newline at end of file +SelfBuff( + buildup_duration: 0.4, + cast_duration: 0.3, + recover_duration: 0.3, + buff_kind: Reckless, + buff_strength: 0.25, + buff_duration: Some(30.0), + energy_cost: 30, +) diff --git a/assets/common/abilities/sword/cleaving_sky_splitter.ron b/assets/common/abilities/sword/cleaving_sky_splitter.ron index dba2420527..37af91dbed 100644 --- a/assets/common/abilities/sword/cleaving_sky_splitter.ron +++ b/assets/common/abilities/sword/cleaving_sky_splitter.ron @@ -1,39 +1,24 @@ +// TODO: When melee system supports it, make this attack hit front, above head, and back ComboMelee2( strikes: [ ( melee_constructor: ( kind: Slash( - damage: 5, - poise: 0, - knockback: 0, - energy_regen: 5, + damage: 40, + poise: 20, + knockback: 10, + energy_regen: 0, ), - range: 3.0, - angle: 45.0, + range: 4.0, + angle: 15.0, + multi_target: Some(Normal), ), - 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, + buildup_duration: 0.2, swing_duration: 0.1, hit_timing: 0.5, - recover_duration: 0.2, + recover_duration: 0.5, ori_modifier: 0.6, ), ], - energy_cost_per_strike: 0, + energy_cost_per_strike: 40, ) \ No newline at end of file diff --git a/assets/voxygen/i18n/en/buff.ftl b/assets/voxygen/i18n/en/buff.ftl index 41c4924bd9..083ca58417 100644 --- a/assets/voxygen/i18n/en/buff.ftl +++ b/assets/voxygen/i18n/en/buff.ftl @@ -73,6 +73,9 @@ buff-desc-potionsickness = Potions heal you less after recently consuming a poti buff-stat-potionsickness = Decreases the amount you heal from subsequent potions by { $strength }%. +## Reckless +buff-title-reckless = Reckless +buff-desc-reckless = Your attacks are more powerful, however you are leaving your defenses open. ## Util buff-text-over_seconds = over { $dur_secs } seconds buff-text-for_seconds = for { $dur_secs } seconds diff --git a/common/src/cmd.rs b/common/src/cmd.rs index eb1b8e852a..974326fc4a 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -156,6 +156,7 @@ lazy_static! { BuffKind::Fortitude => "fortitude", BuffKind::Parried => "parried", BuffKind::PotionSickness => "potion_sickness", + BuffKind::Reckless => "reckless", }; let mut buff_parser = HashMap::new(); for kind in BuffKind::iter() { diff --git a/common/src/combat.rs b/common/src/combat.rs index 946c0caca8..dff60249bc 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -222,6 +222,9 @@ impl Attack { let is_crit = rng.gen::() < self.crit_chance; let mut is_applied = false; let mut accumulated_damage = 0.0; + let damage_modifier = attacker + .and_then(|a| a.stats) + .map_or(1.0, |s| s.attack_damage_modifier); for damage in self .damages .iter() @@ -244,7 +247,7 @@ impl Attack { attacker.map(|x| x.into()), is_crit, self.crit_multiplier, - strength_modifier, + strength_modifier * damage_modifier, time, damage.instance, ); diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index ab4d0a612c..cc307fc2d2 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -64,6 +64,11 @@ pub enum BuffKind { /// and n health less from activation will cause poise damage to increase by /// n% Fortitude, + /// Increases both attack damage and vulnerability to damage + /// Damage increases linearly with strength, 1.0 is a 100% increase + /// Damage reduction decreases linearly with strength, 1.0 is a 100% + /// decrease + Reckless, // Debuffs /// Does damage to a creature over time /// Strength should be the DPS of the debuff @@ -120,7 +125,8 @@ impl BuffKind { | BuffKind::Invulnerability | BuffKind::ProtectingWard | BuffKind::Hastened - | BuffKind::Fortitude => true, + | BuffKind::Fortitude + | BuffKind::Reckless => true, BuffKind::Bleeding | BuffKind::Cursed | BuffKind::Burning @@ -219,6 +225,8 @@ pub enum BuffEffect { HealReduction(f32), /// Increases poise damage dealt when health is lost PoiseDamageFromLostHealth { initial_health: f32, strength: f32 }, + /// Modifier to the amount of damage dealt with attacks + AttackDamage(f32), } /// Actual de/buff. @@ -382,6 +390,10 @@ impl Buff { ], BuffKind::Parried => vec![BuffEffect::AttackSpeed(0.5)], BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)], + BuffKind::Reckless => vec![ + BuffEffect::DamageReduction(-data.strength), + BuffEffect::AttackDamage(data.strength), + ], }; let start_time = Time(time.0 + data.delay.map_or(0.0, |delay| delay.0)); let end_time = if cat_ids diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index e903780eb3..2c17ef8d1b 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -57,6 +57,7 @@ pub struct Stats { pub friction_modifier: f32, pub max_energy_modifiers: StatsModifier, pub poise_damage_modifier: f32, + pub attack_damage_modifier: f32, } impl Stats { @@ -72,6 +73,7 @@ impl Stats { friction_modifier: 1.0, max_energy_modifiers: StatsModifier::default(), poise_damage_modifier: 1.0, + attack_damage_modifier: 1.0, } } diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index 905416d2c9..524c34fcc2 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -586,5 +586,8 @@ fn execute_effect( let lost_health = (*initial_health - health.current()).max(0.0); stat.poise_damage_modifier *= lost_health / 100.0 * *strength; }, + BuffEffect::AttackDamage(dam) => { + stat.attack_damage_modifier *= *dam; + }, }; } diff --git a/voxygen/anim/src/character/combomelee.rs b/voxygen/anim/src/character/combomelee.rs index cb82f4498b..7a8e67cfb9 100644 --- a/voxygen/anim/src/character/combomelee.rs +++ b/voxygen/anim/src/character/combomelee.rs @@ -823,6 +823,34 @@ impl Animation for ComboAnimation { next.control.orientation.rotate_z(move2 * -1.8); next.control.position += Vec3::new(move2 * 14.0, 0.0, 0.0); }, + Some("common.abilities.sword.cleaving_sky_splitter") => { + let (move1, move2) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0), + Some(StageSection::Action) => (1.0, anim_time.powf(0.5)), + Some(StageSection::Recover) => (1.0, 1.0), + _ => (0.0, 0.0), + }; + let move1 = move1 * multi_strike_pullback; + let move2 = move2 * multi_strike_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) * Quaternion::rotation_z(move1 * -0.2); + + next.chest.orientation = Quaternion::rotation_x(move1 * -0.6); + next.control.orientation = Quaternion::rotation_x(move1 * -1.1); + next.control.position += Vec3::new(move1 * 6.0, move1 * 4.0, move1 * 3.0); + + next.chest.orientation.rotate_x(move2 * 1.1); + next.control.orientation.rotate_x(move2 * 2.7); + next.control.position += Vec3::new(0.0, move2 * -9.0, move2 * 17.0); + }, Some("common.abilities.sword.defensive_combo") => { let (move1, move2) = if strike == current_strike { match stage_section { diff --git a/voxygen/anim/src/character/selfbuff.rs b/voxygen/anim/src/character/selfbuff.rs index 7cc85f9a6d..709feb0225 100644 --- a/voxygen/anim/src/character/selfbuff.rs +++ b/voxygen/anim/src/character/selfbuff.rs @@ -130,6 +130,40 @@ impl Animation for SelfBuffAnimation { next.control.position += Vec3::new(0.0, move2 * -2.0, move2 * 12.0); next.control.orientation.rotate_x(move2 * 1.1); }, + Some("common.abilities.sword.cleaving_blade_fever") => { + 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); + }, _ => {}, } diff --git a/voxygen/i18n-helpers/src/lib.rs b/voxygen/i18n-helpers/src/lib.rs index 6323c43971..bae183affa 100644 --- a/voxygen/i18n-helpers/src/lib.rs +++ b/voxygen/i18n-helpers/src/lib.rs @@ -102,7 +102,8 @@ pub fn localize_chat_message( | BuffKind::ProtectingWard | BuffKind::Frenzied | BuffKind::Hastened - | BuffKind::Fortitude => { + | BuffKind::Fortitude + | BuffKind::Reckless => { tracing::error!("Player was killed by a positive buff!"); "hud-outcome-mysterious" }, diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 6c1a1f86df..080f8e41fc 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -4946,6 +4946,8 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id { BuffKind::Frenzied => imgs.buff_frenzy_0, BuffKind::Hastened => imgs.buff_haste_0, BuffKind::Fortitude => imgs.buff_fortitude_0, + // TODO: Get unique icon + BuffKind::Reckless => imgs.buff_plus_0, // Debuffs BuffKind::Bleeding => imgs.debuff_bleed_0, BuffKind::Cursed => imgs.debuff_skull_0, @@ -4979,6 +4981,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> Cow localized_strings.get_msg("buff-title-frenzied"), BuffKind::Hastened => localized_strings.get_msg("buff-title-hastened"), BuffKind::Fortitude => localized_strings.get_msg("buff-title-fortitude"), + BuffKind::Reckless => localized_strings.get_msg("buff-title-reckless"), // Debuffs BuffKind::Bleeding { .. } => localized_strings.get_msg("buff-title-bleed"), BuffKind::Cursed { .. } => localized_strings.get_msg("buff-title-cursed"), @@ -5016,6 +5019,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz BuffKind::Frenzied => localized_strings.get_msg("buff-desc-frenzied"), BuffKind::Hastened => localized_strings.get_msg("buff-desc-hastened"), BuffKind::Fortitude => localized_strings.get_msg("buff-desc-fortitude"), + BuffKind::Reckless => localized_strings.get_msg("buff-desc-reckless"), // Debuffs BuffKind::Bleeding { .. } => localized_strings.get_msg("buff-desc-bleed"), BuffKind::Cursed { .. } => localized_strings.get_msg("buff-desc-cursed"), diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 3fdb476b35..93594abae6 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -190,7 +190,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Poisoned | BuffKind::Hastened | BuffKind::Fortitude - | BuffKind::Parried => Cow::Borrowed(""), + | BuffKind::Parried + | BuffKind::Reckless => Cow::Borrowed(""), }; write!(&mut description, "{}", buff_desc).unwrap(); @@ -223,7 +224,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Poisoned | BuffKind::Hastened | BuffKind::Fortitude - | BuffKind::Parried => Cow::Borrowed(""), + | BuffKind::Parried + | BuffKind::Reckless => Cow::Borrowed(""), } } else if let BuffKind::Saturation | BuffKind::Regeneration | BuffKind::EnergyRegen = buff.kind