mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Scornful swipe
This commit is contained in:
parent
af755197bb
commit
cc70685f7a
@ -1,6 +1,6 @@
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-fuse-ld=gold",
|
||||
"-C", "link-arg=-fuse-ld=mold",
|
||||
]
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
|
@ -196,7 +196,7 @@
|
||||
primary: Simple(None, "common.abilities.hammer.solid_smash"),
|
||||
secondary: Simple(None, "common.abilities.hammer.wide_wallop"),
|
||||
abilities: [
|
||||
// Simple(Hammer(ScornfulSwipe), "common.abilities.hammer.scornful_swipe"),
|
||||
Simple(Hammer(ScornfulSwipe), "common.abilities.hammer.scornful_swipe"),
|
||||
// Simple(Hammer(Tremor), "common.abilities.hammer.tremor"),
|
||||
// Simple(Hammer(VigorousBash), "common.abilities.hammer.vigorous_bash"),
|
||||
// Simple(Hammer(Retaliate), "common.abilities.hammer.retaliate"),
|
||||
|
21
assets/common/abilities/hammer/scornful_swipe.ron
Normal file
21
assets/common/abilities/hammer/scornful_swipe.ron
Normal file
@ -0,0 +1,21 @@
|
||||
BasicMelee(
|
||||
energy_cost: 0,
|
||||
buildup_duration: 0.7,
|
||||
swing_duration: 0.1,
|
||||
hit_timing: 0.5,
|
||||
recover_duration: 0.2,
|
||||
melee_constructor: (
|
||||
kind: Bash(
|
||||
damage: 20,
|
||||
poise: 10,
|
||||
knockback: 5,
|
||||
energy_regen: 0,
|
||||
),
|
||||
range: 3.0,
|
||||
angle: 15.0,
|
||||
),
|
||||
ori_modifier: 0.6,
|
||||
meta: (
|
||||
init_event: Some(GainBuff(kind: ScornfulTaunt, strength: 0.5, duration: Some(20.0))),
|
||||
),
|
||||
)
|
BIN
assets/voxygen/element/de_buffs/buff_scornfultaunt.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/de_buffs/buff_scornfultaunt.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/skills/hammer/scornful_swipe.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/skills/hammer/scornful_swipe.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/skills/hammer/wide_wallop.png
(Stored with Git LFS)
BIN
assets/voxygen/element/skills/hammer/wide_wallop.png
(Stored with Git LFS)
Binary file not shown.
@ -121,8 +121,9 @@ buff-berserk = Berserk
|
||||
## Heatstroke
|
||||
buff-heatstroke = Heatstroke
|
||||
.desc = You were exposed to heat and now suffer from heatstroke. Your energy reward and movement speed are cut down. Chill.
|
||||
|
||||
|
||||
## Scornful Taunt
|
||||
buff-scornfultaunt = Scornful Taunt
|
||||
.desc = You scornfully taunt your enemies, granting you bolstered fortitude and stamina. However, your death will bolster your killer.
|
||||
## Util
|
||||
buff-text-over_seconds = over { $dur_secs } seconds
|
||||
buff-text-for_seconds = for { $dur_secs } seconds
|
||||
|
@ -383,3 +383,6 @@ common-abilities-hammer-solid_smash = Solid Smash
|
||||
common-abilities-hammer-wide_wallop = Wide Wallop
|
||||
.desc =
|
||||
Pull back and send them flying
|
||||
common-abilities-hammer-scornful_swipe = Scornful Swipe
|
||||
.desc =
|
||||
Bolster your fortitude and stamina by taunting your enemies before striking at them. If you fall to an enemy they become empowered.
|
||||
|
@ -188,7 +188,8 @@ lazy_static! {
|
||||
BuffKind::Defiance => "defiance",
|
||||
BuffKind::Bloodfeast => "bloodfeast",
|
||||
BuffKind::Berserk => "berserk",
|
||||
BuffKind::Heatstroke => "heatstroke"
|
||||
BuffKind::Heatstroke => "heatstroke",
|
||||
BuffKind::ScornfulTaunt => "scornful_taunt",
|
||||
};
|
||||
let mut buff_parser = HashMap::new();
|
||||
for kind in BuffKind::iter() {
|
||||
|
@ -1013,6 +1013,16 @@ pub enum DamagedEffect {
|
||||
Combo(i32),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum DeathEffect {
|
||||
/// Adds buff to the attacker that killed this entity
|
||||
AttackerBuff {
|
||||
kind: BuffKind,
|
||||
strength: f32,
|
||||
duration: Option<Secs>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub enum DamageContributor {
|
||||
Solo(Uid),
|
||||
|
@ -2907,7 +2907,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AbilityMeta {
|
||||
#[serde(default)]
|
||||
@ -2987,9 +2987,14 @@ impl Stance {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum AbilityInitEvent {
|
||||
EnterStance(Stance),
|
||||
GainBuff {
|
||||
kind: buff::BuffKind,
|
||||
strength: f32,
|
||||
duration: Option<Secs>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for Stance {
|
||||
|
@ -2,7 +2,7 @@
|
||||
use crate::{
|
||||
combat::{
|
||||
AttackEffect, CombatBuff, CombatBuffStrength, CombatEffect, CombatRequirement,
|
||||
DamagedEffect,
|
||||
DamagedEffect, DeathEffect,
|
||||
},
|
||||
comp::{aura::AuraKey, Stats},
|
||||
resources::{Secs, Time},
|
||||
@ -127,6 +127,12 @@ pub enum BuffKind {
|
||||
/// non-linearly with strength, 0.5 is a 12.5% increase, 1.0 is a 16.7%
|
||||
/// increase decrease.
|
||||
Berserk,
|
||||
/// Increases poise resistance and energy reward. However if killed, buffs
|
||||
/// killer with Reckless buff. Poise resistance scales non-linearly with
|
||||
/// strength, 0.5 is 50% and 1.0 is 67%. Energy reward scales linearly with
|
||||
/// strength, 0.5 is +50% and 1.0 is +100% strength. Reckless buff reward
|
||||
/// strength is equal to scornful taunt buff strength.
|
||||
ScornfulTaunt,
|
||||
// Debuffs
|
||||
/// Does damage to a creature over time.
|
||||
/// Strength should be the DPS of the debuff.
|
||||
@ -221,7 +227,8 @@ impl BuffKind {
|
||||
| BuffKind::Sunderer
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk => BuffDescriptor::SimplePositive,
|
||||
| BuffKind::Berserk
|
||||
| BuffKind::ScornfulTaunt => BuffDescriptor::SimplePositive,
|
||||
BuffKind::Bleeding
|
||||
| BuffKind::Cursed
|
||||
| BuffKind::Burning
|
||||
@ -463,6 +470,15 @@ impl BuffKind {
|
||||
BuffEffect::MovementSpeed(1.0 - nn_scaling(data.strength) * 0.5),
|
||||
BuffEffect::EnergyReward((1.0 - nn_scaling(data.strength) * 3.0).max(-1.0)),
|
||||
],
|
||||
BuffKind::ScornfulTaunt => vec![
|
||||
BuffEffect::PoiseReduction(nn_scaling(data.strength)),
|
||||
BuffEffect::EnergyReward(1.0 + data.strength),
|
||||
BuffEffect::DeathEffect(DeathEffect::AttackerBuff {
|
||||
kind: BuffKind::Reckless,
|
||||
strength: data.strength,
|
||||
duration: data.duration,
|
||||
}),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,6 +628,8 @@ pub enum BuffEffect {
|
||||
EnergyReward(f32),
|
||||
/// Add an effect to the entity when damaged by an attack
|
||||
DamagedEffect(DamagedEffect),
|
||||
/// Add an effect to the entity when killed
|
||||
DeathEffect(DeathEffect),
|
||||
}
|
||||
|
||||
/// Actual de/buff.
|
||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage};
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
use crate::combat::{AttackEffect, DamagedEffect};
|
||||
use crate::combat::{AttackEffect, DamagedEffect, DeathEffect};
|
||||
|
||||
use super::Body;
|
||||
|
||||
@ -75,6 +75,8 @@ pub struct Stats {
|
||||
pub energy_reward_modifier: f32,
|
||||
/// This creates effects when the entity is damaged
|
||||
pub effects_on_damaged: Vec<DamagedEffect>,
|
||||
/// This creates effects when the entity is killed
|
||||
pub effects_on_death: Vec<DeathEffect>,
|
||||
}
|
||||
|
||||
impl Stats {
|
||||
@ -100,6 +102,7 @@ impl Stats {
|
||||
mitigations_penetration: 0.0,
|
||||
energy_reward_modifier: 1.0,
|
||||
effects_on_damaged: Vec::new(),
|
||||
effects_on_death: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
comp::{
|
||||
ability::{AbilityInitEvent, AbilityMeta, Capability, SpecifiedAbility, Stance},
|
||||
arthropod, biped_large, biped_small, bird_medium,
|
||||
buff::{BuffCategory, BuffChange},
|
||||
buff::{Buff, BuffCategory, BuffChange, BuffData, BuffSource},
|
||||
character_state::OutputEvents,
|
||||
controller::InventoryManip,
|
||||
golem,
|
||||
@ -1321,6 +1321,23 @@ fn handle_ability(
|
||||
stance,
|
||||
});
|
||||
},
|
||||
AbilityInitEvent::GainBuff {
|
||||
kind,
|
||||
strength,
|
||||
duration,
|
||||
} => {
|
||||
output_events.emit_server(BuffEvent {
|
||||
entity: data.entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
kind,
|
||||
BuffData::new(strength, duration),
|
||||
vec![BuffCategory::SelfBuff],
|
||||
BuffSource::Character { by: *data.uid },
|
||||
*data.time,
|
||||
Some(data.stats),
|
||||
)),
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
if let CharacterState::Roll(roll) = &mut update.character {
|
||||
|
@ -792,5 +792,6 @@ fn execute_effect(
|
||||
stat.energy_reward_modifier *= er;
|
||||
},
|
||||
BuffEffect::DamagedEffect(effect) => stat.effects_on_damaged.push(effect.clone()),
|
||||
BuffEffect::DeathEffect(effect) => stat.effects_on_death.push(effect.clone()),
|
||||
};
|
||||
}
|
||||
|
@ -4550,7 +4550,8 @@ fn build_buff(
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Parried
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Heatstroke => {
|
||||
| BuffKind::Heatstroke
|
||||
| BuffKind::ScornfulTaunt => {
|
||||
if buff_kind.is_simple() {
|
||||
unreachable!("is_simple() above")
|
||||
} else {
|
||||
|
@ -18,8 +18,7 @@ use crate::{
|
||||
#[cfg(feature = "worldgen")]
|
||||
use common::rtsim::{Actor, RtSimEntity};
|
||||
use common::{
|
||||
combat,
|
||||
combat::{AttackSource, DamageContributor},
|
||||
combat::{self, AttackSource, DamageContributor, DeathEffect},
|
||||
comp::{
|
||||
self,
|
||||
aura::{self, EnteredAuras},
|
||||
@ -332,6 +331,7 @@ pub struct DestroyEventData<'a> {
|
||||
rtsim_entities: ReadStorage<'a, RtSimEntity>,
|
||||
#[cfg(feature = "worldgen")]
|
||||
presences: ReadStorage<'a, Presence>,
|
||||
buff_events: Read<'a, EventBus<BuffEvent>>,
|
||||
}
|
||||
|
||||
/// Handle an entity dying. If it is a player, it will send a message to all
|
||||
@ -346,6 +346,7 @@ impl ServerEvent for DestroyEvent {
|
||||
let mut create_item_drop = data.create_item_drop.emitter();
|
||||
let mut delete_emitter = data.delete_event.emitter();
|
||||
let mut outcomes_emitter = data.outcomes.emitter();
|
||||
let mut buff_emitter = data.buff_events.emitter();
|
||||
for ev in events {
|
||||
// TODO: Investigate duplicate `Destroy` events (but don't remove this).
|
||||
// If the entity was already deleted, it can't be destroyed again.
|
||||
@ -383,6 +384,40 @@ impl ServerEvent for DestroyEvent {
|
||||
outcomes_emitter.emit(Outcome::Death { pos: pos.0 });
|
||||
}
|
||||
|
||||
// Handle any effects on death
|
||||
if let Some(killed_stats) = data.stats.get(ev.entity) {
|
||||
let attacker_entity = ev.cause.by.and_then(|x| data.id_maps.uid_entity(x.uid()));
|
||||
let killed_uid = data.uids.get(ev.entity);
|
||||
let attacker_stats = attacker_entity.and_then(|e| data.stats.get(e));
|
||||
for effect in killed_stats.effects_on_death.iter() {
|
||||
match effect {
|
||||
DeathEffect::AttackerBuff {
|
||||
kind,
|
||||
strength,
|
||||
duration,
|
||||
} => {
|
||||
if let Some(attacker) = attacker_entity {
|
||||
buff_emitter.emit(BuffEvent {
|
||||
entity: attacker,
|
||||
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
||||
*kind,
|
||||
buff::BuffData::new(*strength, *duration),
|
||||
vec![],
|
||||
if let Some(uid) = killed_uid {
|
||||
BuffSource::Character { by: *uid }
|
||||
} else {
|
||||
BuffSource::World
|
||||
},
|
||||
*data.time,
|
||||
attacker_stats,
|
||||
)),
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chat message
|
||||
// If it was a player that died
|
||||
if let Some((uid, _player)) = (&data.uids, &data.players)
|
||||
|
@ -62,6 +62,33 @@ impl Animation for AlphaAnimation {
|
||||
next.control.orientation.rotate_x(move2 * -1.9);
|
||||
next.control.orientation.rotate_z(move2 * 0.6);
|
||||
},
|
||||
Some("common.abilities.hammer.scornful_swipe") => {
|
||||
hammer_start(&mut next, s_a);
|
||||
let (move1, move2, move3) = match stage_section {
|
||||
Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
|
||||
Some(StageSection::Action) => (1.0, anim_time, 0.0),
|
||||
Some(StageSection::Recover) => (1.0, 1.0, anim_time),
|
||||
_ => (0.0, 0.0, 0.0),
|
||||
};
|
||||
let pullback = 1.0 - move3;
|
||||
let move1 = move1 * pullback;
|
||||
let move2 = move2 * pullback;
|
||||
let move1_pre = move1.min(0.5) * 2.0;
|
||||
let move1_shake = ((move1.max(0.3) - 0.3) * 15.0).sin();
|
||||
let move1_late = move1.powi(4);
|
||||
|
||||
next.control.orientation.rotate_x(move1_pre * 2.3);
|
||||
next.control.position += Vec3::new(0.0, 2.0, 16.0) * move1_pre;
|
||||
next.control.position += Vec3::new(0.0, 0.0, 4.0) * move1_shake;
|
||||
next.control.orientation.rotate_y(move1_late * 1.6);
|
||||
next.control.position += Vec3::new(-8.0, 0.0, -8.0) * move1_late;
|
||||
twist_back(&mut next, move1_late, 1.0, 0.4, 0.2, 0.7);
|
||||
next.control.orientation.rotate_z(move1_late * 1.2);
|
||||
|
||||
twist_forward(&mut next, move2, 1.9, 0.9, 0.6, 1.1);
|
||||
next.control.orientation.rotate_y(move2 * -1.7);
|
||||
next.control.orientation.rotate_z(move2 * -2.7);
|
||||
},
|
||||
_ => {
|
||||
let (move1, move2, _move3, move2h) = match stage_section {
|
||||
Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0, 0.0),
|
||||
|
@ -395,7 +395,8 @@ fn get_buff_ident(buff: BuffKind) -> &'static str {
|
||||
| BuffKind::Sunderer
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk => {
|
||||
| BuffKind::Berserk
|
||||
| BuffKind::ScornfulTaunt => {
|
||||
tracing::error!("Player was killed by a positive buff!");
|
||||
"mysterious"
|
||||
},
|
||||
|
@ -317,6 +317,7 @@ image_ids! {
|
||||
// Hammer
|
||||
hammer_solid_smash: "voxygen.element.skills.hammer.solid_smash",
|
||||
hammer_wide_wallop: "voxygen.element.skills.hammer.wide_wallop",
|
||||
hammer_scornful_swipe: "voxygen.element.skills.hammer.scornful_swipe",
|
||||
// Skilltree Icons
|
||||
health_plus_skill: "voxygen.element.skills.skilltree.health_plus",
|
||||
energy_plus_skill: "voxygen.element.skills.skilltree.energy_plus",
|
||||
@ -791,6 +792,7 @@ image_ids! {
|
||||
buff_lifesteal: "voxygen.element.de_buffs.buff_lifesteal",
|
||||
buff_flame: "voxygen.element.de_buffs.buff_flame",
|
||||
buff_frigid: "voxygen.element.de_buffs.buff_frigid",
|
||||
buff_scornfultaunt: "voxygen.element.de_buffs.buff_scornfultaunt",
|
||||
|
||||
// Debuffs
|
||||
debuff_skull_0: "voxygen.element.de_buffs.debuff_skull_0",
|
||||
|
@ -5261,6 +5261,7 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id {
|
||||
BuffKind::Defiance => imgs.buff_defiance,
|
||||
BuffKind::Bloodfeast => imgs.buff_plus_0,
|
||||
BuffKind::Berserk => imgs.buff_reckless,
|
||||
BuffKind::ScornfulTaunt => imgs.buff_scornfultaunt,
|
||||
// Debuffs
|
||||
BuffKind::Bleeding => imgs.debuff_bleed_0,
|
||||
BuffKind::Cursed => imgs.debuff_skull_0,
|
||||
|
@ -197,6 +197,7 @@ fn buff_key(buff: BuffKind) -> &'static str {
|
||||
BuffKind::Defiance => "buff-defiance",
|
||||
BuffKind::Bloodfeast => "buff-bloodfeast",
|
||||
BuffKind::Berserk => "buff-berserk",
|
||||
BuffKind::ScornfulTaunt => "buff-scornfultaunt",
|
||||
// Debuffs
|
||||
BuffKind::Bleeding => "buff-bleed",
|
||||
BuffKind::Cursed => "buff-cursed",
|
||||
@ -318,7 +319,8 @@ pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk
|
||||
| BuffKind::Heatstroke => Cow::Borrowed(""),
|
||||
| BuffKind::Heatstroke
|
||||
| BuffKind::ScornfulTaunt => Cow::Borrowed(""),
|
||||
};
|
||||
|
||||
write!(&mut description, "{}", buff_desc).unwrap();
|
||||
@ -368,7 +370,8 @@ pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk
|
||||
| BuffKind::Heatstroke => Cow::Borrowed(""),
|
||||
| BuffKind::Heatstroke
|
||||
| BuffKind::ScornfulTaunt => Cow::Borrowed(""),
|
||||
}
|
||||
} else if let BuffKind::Saturation
|
||||
| BuffKind::Regeneration
|
||||
@ -621,6 +624,7 @@ pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id {
|
||||
// Hammer
|
||||
"common.abilities.hammer.solid_smash" => imgs.hammer_solid_smash,
|
||||
"common.abilities.hammer.wide_wallop" => imgs.hammer_wide_wallop,
|
||||
"common.abilities.hammer.scornful_swipe" => imgs.hammer_scornful_swipe,
|
||||
// Bow
|
||||
"common.abilities.bow.charged" => imgs.bow_m1,
|
||||
"common.abilities.bow.repeater" => imgs.bow_m2,
|
||||
|
Loading…
Reference in New Issue
Block a user