mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added necrotic vortex attack to mindflayer
This commit is contained in:
parent
0d3795112c
commit
f1156c9ce5
@ -4,12 +4,14 @@ SpinMelee(
|
||||
recover_duration: 0.2,
|
||||
base_damage: 70,
|
||||
base_poise_damage: 55,
|
||||
knockback: 0.0,
|
||||
knockback: ( strength: 0.0, direction: Away),
|
||||
range: 3.5,
|
||||
damage_effect: None,
|
||||
energy_cost: 100,
|
||||
is_infinite: true,
|
||||
movement_behavior: AxeHover,
|
||||
is_interruptible: false,
|
||||
forward_speed: 0.0,
|
||||
num_spins: 1,
|
||||
specifier: None,
|
||||
)
|
||||
|
@ -4,12 +4,14 @@ SpinMelee(
|
||||
recover_duration: 0.5,
|
||||
base_damage: 160,
|
||||
base_poise_damage: 25,
|
||||
knockback: 10.0,
|
||||
knockback: ( strength: 10.0, direction: Away),
|
||||
range: 3.5,
|
||||
damage_effect: None,
|
||||
energy_cost: 150,
|
||||
is_infinite: false,
|
||||
movement_behavior: ForwardGround,
|
||||
is_interruptible: true,
|
||||
forward_speed: 1.0,
|
||||
num_spins: 3,
|
||||
specifier: None,
|
||||
)
|
||||
|
@ -1 +1,17 @@
|
||||
BasicBlock
|
||||
SpinMelee(
|
||||
buildup_duration: 0.6,
|
||||
swing_duration: 0.2,
|
||||
recover_duration: 0.6,
|
||||
base_damage: 70.0,
|
||||
base_poise_damage: 0.0,
|
||||
knockback: ( strength: 8.0, direction: Towards),
|
||||
range: 15.0,
|
||||
damage_effect: Some(Lifesteal(1.0)),
|
||||
energy_cost: 0.0,
|
||||
is_infinite: true,
|
||||
movement_behavior: Stationary,
|
||||
is_interruptible: false,
|
||||
forward_speed: 0.0,
|
||||
num_spins: 1,
|
||||
specifier: Some(CultistVortex),
|
||||
)
|
||||
|
@ -4,12 +4,14 @@ SpinMelee(
|
||||
recover_duration: 0.1,
|
||||
base_damage: 500,
|
||||
base_poise_damage: 30,
|
||||
knockback: 0.0,
|
||||
knockback: ( strength: 0.0, direction: Away),
|
||||
range: 7.5,
|
||||
damage_effect: None,
|
||||
energy_cost: 0,
|
||||
is_infinite: false,
|
||||
movement_behavior: GolemHover,
|
||||
is_interruptible: false,
|
||||
forward_speed: 0.0,
|
||||
num_spins: 1,
|
||||
specifier: None,
|
||||
)
|
||||
|
@ -395,10 +395,10 @@ void main() {
|
||||
);
|
||||
} else if (inst_mode == CULTIST_FLAME) {
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
float purp_color = 0.8 + 0.5 * rand3;
|
||||
float purp_color = 0.9 + 0.3 * rand3;
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
|
||||
vec3((2.5 * (1 - slow_start(0.2)))),
|
||||
vec3((3.5 * (1 - slow_start(0.2)))),
|
||||
vec4(purp_color, 0.0, purp_color, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
|
@ -156,14 +156,16 @@ pub enum CharacterAbility {
|
||||
recover_duration: f32,
|
||||
base_damage: f32,
|
||||
base_poise_damage: f32,
|
||||
knockback: f32,
|
||||
knockback: Knockback,
|
||||
range: f32,
|
||||
damage_effect: Option<CombatEffect>,
|
||||
energy_cost: f32,
|
||||
is_infinite: bool,
|
||||
movement_behavior: spin_melee::MovementBehavior,
|
||||
is_interruptible: bool,
|
||||
forward_speed: f32,
|
||||
num_spins: u32,
|
||||
specifier: Option<spin_melee::FrontendSpecifier>,
|
||||
},
|
||||
ChargedMelee {
|
||||
energy_cost: f32,
|
||||
@ -1301,12 +1303,14 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
||||
base_poise_damage,
|
||||
knockback,
|
||||
range,
|
||||
damage_effect,
|
||||
energy_cost,
|
||||
is_infinite,
|
||||
movement_behavior,
|
||||
is_interruptible,
|
||||
forward_speed,
|
||||
num_spins,
|
||||
specifier,
|
||||
} => CharacterState::SpinMelee(spin_melee::Data {
|
||||
static_data: spin_melee::StaticData {
|
||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||
@ -1316,6 +1320,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
||||
base_poise_damage: *base_poise_damage,
|
||||
knockback: *knockback,
|
||||
range: *range,
|
||||
damage_effect: *damage_effect,
|
||||
energy_cost: *energy_cost,
|
||||
is_infinite: *is_infinite,
|
||||
movement_behavior: *movement_behavior,
|
||||
@ -1323,6 +1328,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
||||
forward_speed: *forward_speed,
|
||||
num_spins: *num_spins,
|
||||
ability_info,
|
||||
specifier: *specifier,
|
||||
},
|
||||
timer: Duration::default(),
|
||||
spins_remaining: *num_spins - 1,
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::{
|
||||
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
|
||||
combat::{
|
||||
Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage,
|
||||
DamageSource, GroupTarget, Knockback,
|
||||
},
|
||||
comp::{tool::ToolKind, CharacterState, EnergyChange, EnergySource, Melee, StateUpdate},
|
||||
consts::GRAVITY,
|
||||
states::{
|
||||
behavior::{CharacterBehavior, JoinData},
|
||||
utils::*,
|
||||
},
|
||||
Damage, DamageSource, GroupTarget, Knockback, KnockbackDir,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
@ -26,9 +28,11 @@ pub struct StaticData {
|
||||
/// Base poise damage
|
||||
pub base_poise_damage: f32,
|
||||
/// Knockback
|
||||
pub knockback: f32,
|
||||
pub knockback: Knockback,
|
||||
/// Range
|
||||
pub range: f32,
|
||||
/// Adds an effect onto the main damage of the attack
|
||||
pub damage_effect: Option<CombatEffect>,
|
||||
/// Energy cost per attack
|
||||
pub energy_cost: f32,
|
||||
/// Whether spin state is infinite
|
||||
@ -43,6 +47,8 @@ pub struct StaticData {
|
||||
pub num_spins: u32,
|
||||
/// What key is used to press ability
|
||||
pub ability_info: AbilityInfo,
|
||||
/// Used to specify the beam to the frontend
|
||||
pub specifier: Option<FrontendSpecifier>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -65,7 +71,7 @@ impl CharacterBehavior for Data {
|
||||
let mut update = StateUpdate::from(data);
|
||||
|
||||
match self.static_data.movement_behavior {
|
||||
MovementBehavior::ForwardGround => {},
|
||||
MovementBehavior::ForwardGround | MovementBehavior::Stationary => {},
|
||||
MovementBehavior::AxeHover => {
|
||||
let new_vel_z = update.vel.0.z + GRAVITY * data.dt.0 * 0.5;
|
||||
update.vel.0 = Vec3::new(0.0, 0.0, new_vel_z) + data.inputs.move_dir * 5.0;
|
||||
@ -110,21 +116,23 @@ impl CharacterBehavior for Data {
|
||||
.with_requirement(CombatRequirement::AnyDamage);
|
||||
let knockback = AttackEffect::new(
|
||||
Some(GroupTarget::OutOfGroup),
|
||||
CombatEffect::Knockback(Knockback {
|
||||
strength: self.static_data.knockback,
|
||||
direction: KnockbackDir::Away,
|
||||
}),
|
||||
CombatEffect::Knockback(self.static_data.knockback),
|
||||
)
|
||||
.with_requirement(CombatRequirement::AnyDamage);
|
||||
let buff = CombatEffect::Buff(CombatBuff::default_physical());
|
||||
let damage = AttackDamage::new(
|
||||
let mut damage = AttackDamage::new(
|
||||
Damage {
|
||||
source: DamageSource::Melee,
|
||||
value: self.static_data.base_damage as f32,
|
||||
},
|
||||
Some(GroupTarget::OutOfGroup),
|
||||
)
|
||||
.with_effect(buff);
|
||||
);
|
||||
match self.static_data.damage_effect {
|
||||
Some(effect) => damage = damage.with_effect(effect),
|
||||
None => {
|
||||
let buff = CombatEffect::Buff(CombatBuff::default_physical());
|
||||
damage = damage.with_effect(buff);
|
||||
},
|
||||
}
|
||||
let (crit_chance, crit_mult) =
|
||||
get_crit_data(data, self.static_data.ability_info);
|
||||
let attack = Attack::default()
|
||||
@ -204,6 +212,8 @@ impl CharacterBehavior for Data {
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
// Remove melee attack component
|
||||
data.updater.remove::<Melee>(data.entity);
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
@ -242,7 +252,13 @@ impl CharacterBehavior for Data {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum MovementBehavior {
|
||||
Stationary,
|
||||
ForwardGround,
|
||||
AxeHover,
|
||||
GolemHover,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum FrontendSpecifier {
|
||||
CultistVortex,
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use common::{
|
||||
outcome::Outcome,
|
||||
resources::DeltaTime,
|
||||
spiral::Spiral2d,
|
||||
states,
|
||||
terrain::TerrainChunk,
|
||||
vol::{RectRasterableVol, SizedVol},
|
||||
};
|
||||
@ -195,6 +196,7 @@ impl ParticleMgr {
|
||||
self.maintain_shockwave_particles(scene_data);
|
||||
self.maintain_aura_particles(scene_data);
|
||||
self.maintain_buff_particles(scene_data);
|
||||
self.maintain_spin_melee_particles(scene_data);
|
||||
} else {
|
||||
// remove all particle lifespans
|
||||
self.particles.clear();
|
||||
@ -563,6 +565,7 @@ impl ParticleMgr {
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
let time = state.get_time();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for (pos, auras) in (
|
||||
&ecs.read_storage::<Pos>(),
|
||||
@ -577,7 +580,6 @@ impl ParticleMgr {
|
||||
kind: buff::BuffKind::ProtectingWard,
|
||||
..
|
||||
} => {
|
||||
let mut rng = thread_rng();
|
||||
let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5));
|
||||
self.particles.resize_with(
|
||||
self.particles.len()
|
||||
@ -792,14 +794,13 @@ impl ParticleMgr {
|
||||
let ecs = state.ecs();
|
||||
let time = state.get_time();
|
||||
|
||||
for (_i, (_entity, pos, ori, shockwave)) in (
|
||||
for (_entity, pos, ori, shockwave) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<Ori>(),
|
||||
&ecs.read_storage::<Shockwave>(),
|
||||
)
|
||||
.join()
|
||||
.enumerate()
|
||||
{
|
||||
let elapsed = time - shockwave.creation.unwrap_or_default();
|
||||
|
||||
@ -862,6 +863,56 @@ impl ParticleMgr {
|
||||
}
|
||||
}
|
||||
|
||||
fn maintain_spin_melee_particles(&mut self, scene_data: &SceneData) {
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
let time = state.get_time();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for (pos, character_state) in (
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<CharacterState>(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if let CharacterState::SpinMelee(c) = character_state {
|
||||
if let Some(specifier) = c.static_data.specifier {
|
||||
match specifier {
|
||||
states::spin_melee::FrontendSpecifier::CultistVortex => {
|
||||
let heartbeats = self.scheduler.heartbeats(Duration::from_millis(3));
|
||||
self.particles.resize_with(
|
||||
self.particles.len()
|
||||
+ c.static_data.range.powi(2) as usize
|
||||
* usize::from(heartbeats)
|
||||
/ 150,
|
||||
|| {
|
||||
let rand_dist =
|
||||
c.static_data.range * (1.0 - rng.gen::<f32>().powi(10));
|
||||
let init_pos = Vec3::new(
|
||||
2.0 * rng.gen::<f32>() - 1.0,
|
||||
2.0 * rng.gen::<f32>() - 1.0,
|
||||
0.0,
|
||||
)
|
||||
.normalized()
|
||||
* rand_dist
|
||||
+ pos.0
|
||||
+ Vec3::unit_z() * 0.05;
|
||||
Particle::new_directed(
|
||||
Duration::from_millis(900),
|
||||
time,
|
||||
ParticleMode::CultistFlame,
|
||||
init_pos,
|
||||
pos.0,
|
||||
)
|
||||
},
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upload_particles(&mut self, renderer: &mut Renderer) {
|
||||
span!(_guard, "upload_particles", "ParticleMgr::upload_particles");
|
||||
let all_cpu_instances = self
|
||||
|
Loading…
Reference in New Issue
Block a user