mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Started to implement shockwave system.
This commit is contained in:
parent
68ecfba291
commit
717142d5ea
@ -24,6 +24,7 @@ pub enum CharacterAbilityType {
|
|||||||
TripleStrike(Stage),
|
TripleStrike(Stage),
|
||||||
LeapMelee,
|
LeapMelee,
|
||||||
SpinMelee,
|
SpinMelee,
|
||||||
|
GroundShockwave,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&CharacterState> for CharacterAbilityType {
|
impl From<&CharacterState> for CharacterAbilityType {
|
||||||
@ -38,6 +39,7 @@ impl From<&CharacterState> for CharacterAbilityType {
|
|||||||
CharacterState::TripleStrike(data) => Self::TripleStrike(data.stage),
|
CharacterState::TripleStrike(data) => Self::TripleStrike(data.stage),
|
||||||
CharacterState::SpinMelee(_) => Self::SpinMelee,
|
CharacterState::SpinMelee(_) => Self::SpinMelee,
|
||||||
CharacterState::ChargedRanged(_) => Self::ChargedRanged,
|
CharacterState::ChargedRanged(_) => Self::ChargedRanged,
|
||||||
|
CharacterState::GroundShockwave(_) => Self::ChargedRanged,
|
||||||
_ => Self::BasicMelee,
|
_ => Self::BasicMelee,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,6 +112,16 @@ pub enum CharacterAbility {
|
|||||||
initial_projectile_speed: f32,
|
initial_projectile_speed: f32,
|
||||||
max_projectile_speed: f32,
|
max_projectile_speed: f32,
|
||||||
},
|
},
|
||||||
|
GroundShockwave {
|
||||||
|
energy_cost: u32,
|
||||||
|
buildup_duration: Duration,
|
||||||
|
recover_duration: Duration,
|
||||||
|
damage: u32,
|
||||||
|
knockback: f32,
|
||||||
|
shockwave_angle: f32,
|
||||||
|
shockwave_speed: f32,
|
||||||
|
shockwave_duration: Duration,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterAbility {
|
impl CharacterAbility {
|
||||||
@ -155,6 +167,10 @@ impl CharacterAbility {
|
|||||||
.energy
|
.energy
|
||||||
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||||
.is_ok(),
|
.is_ok(),
|
||||||
|
CharacterAbility::GroundShockwave { energy_cost, .. } => update
|
||||||
|
.energy
|
||||||
|
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||||
|
.is_ok(),
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,6 +408,25 @@ impl From<&CharacterAbility> for CharacterState {
|
|||||||
initial_projectile_speed: *initial_projectile_speed,
|
initial_projectile_speed: *initial_projectile_speed,
|
||||||
max_projectile_speed: *max_projectile_speed,
|
max_projectile_speed: *max_projectile_speed,
|
||||||
}),
|
}),
|
||||||
|
CharacterAbility::GroundShockwave {
|
||||||
|
energy_cost: _,
|
||||||
|
buildup_duration,
|
||||||
|
recover_duration,
|
||||||
|
damage,
|
||||||
|
knockback,
|
||||||
|
shockwave_angle,
|
||||||
|
shockwave_speed,
|
||||||
|
shockwave_duration,
|
||||||
|
} => CharacterState::GroundShockwave(ground_shockwave::Data {
|
||||||
|
exhausted: false,
|
||||||
|
buildup_duration: *buildup_duration,
|
||||||
|
recover_duration: *recover_duration,
|
||||||
|
damage: *damage,
|
||||||
|
knockback: *knockback,
|
||||||
|
shockwave_angle: *shockwave_angle,
|
||||||
|
shockwave_speed: *shockwave_speed,
|
||||||
|
shockwave_duration: *shockwave_duration,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ pub enum CharacterState {
|
|||||||
SpinMelee(spin_melee::Data),
|
SpinMelee(spin_melee::Data),
|
||||||
/// A charged ranged attack (e.g. bow)
|
/// A charged ranged attack (e.g. bow)
|
||||||
ChargedRanged(charged_ranged::Data),
|
ChargedRanged(charged_ranged::Data),
|
||||||
|
/// A ground shockwave attack
|
||||||
|
GroundShockwave(ground_shockwave::Data),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterState {
|
impl CharacterState {
|
||||||
@ -83,6 +85,7 @@ impl CharacterState {
|
|||||||
| CharacterState::LeapMelee(_)
|
| CharacterState::LeapMelee(_)
|
||||||
| CharacterState::SpinMelee(_)
|
| CharacterState::SpinMelee(_)
|
||||||
| CharacterState::ChargedRanged(_)
|
| CharacterState::ChargedRanged(_)
|
||||||
|
| CharacterState::GroundShockwave(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +98,7 @@ impl CharacterState {
|
|||||||
| CharacterState::LeapMelee(_)
|
| CharacterState::LeapMelee(_)
|
||||||
| CharacterState::SpinMelee(_)
|
| CharacterState::SpinMelee(_)
|
||||||
| CharacterState::ChargedRanged(_)
|
| CharacterState::ChargedRanged(_)
|
||||||
|
| CharacterState::GroundShockwave(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +111,7 @@ impl CharacterState {
|
|||||||
| CharacterState::BasicBlock
|
| CharacterState::BasicBlock
|
||||||
| CharacterState::LeapMelee(_)
|
| CharacterState::LeapMelee(_)
|
||||||
| CharacterState::ChargedRanged(_)
|
| CharacterState::ChargedRanged(_)
|
||||||
|
| CharacterState::GroundShockwave(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,15 +350,27 @@ impl Tool {
|
|||||||
],
|
],
|
||||||
NpcWeapon(kind) => {
|
NpcWeapon(kind) => {
|
||||||
if kind == "CyclopsHammer" {
|
if kind == "CyclopsHammer" {
|
||||||
vec![BasicMelee {
|
vec![
|
||||||
energy_cost: 0,
|
BasicMelee {
|
||||||
buildup_duration: Duration::from_millis(0),
|
energy_cost: 0,
|
||||||
recover_duration: Duration::from_millis(300),
|
buildup_duration: Duration::from_millis(0),
|
||||||
knockback: 20.0,
|
recover_duration: Duration::from_millis(300),
|
||||||
base_healthchange: -200,
|
knockback: 20.0,
|
||||||
range: 10.0,
|
base_healthchange: -200,
|
||||||
max_angle: 120.0,
|
range: 10.0,
|
||||||
}]
|
max_angle: 120.0,
|
||||||
|
},
|
||||||
|
GroundShockwave {
|
||||||
|
energy_cost: 0,
|
||||||
|
buildup_duration: Duration::from_millis(1000),
|
||||||
|
recover_duration: Duration::from_millis(2000),
|
||||||
|
damage: 300,
|
||||||
|
knockback: -30.0,
|
||||||
|
shockwave_angle: 15.0,
|
||||||
|
shockwave_speed: 10.0,
|
||||||
|
shockwave_duration: Duration::from_millis(3000),
|
||||||
|
},
|
||||||
|
]
|
||||||
} else {
|
} else {
|
||||||
vec![BasicMelee {
|
vec![BasicMelee {
|
||||||
energy_cost: 0,
|
energy_cost: 0,
|
||||||
|
@ -16,6 +16,7 @@ mod misc;
|
|||||||
mod phys;
|
mod phys;
|
||||||
mod player;
|
mod player;
|
||||||
pub mod projectile;
|
pub mod projectile;
|
||||||
|
pub mod shockwave;
|
||||||
pub mod skills;
|
pub mod skills;
|
||||||
mod stats;
|
mod stats;
|
||||||
pub mod visual;
|
pub mod visual;
|
||||||
@ -51,6 +52,7 @@ pub use misc::Object;
|
|||||||
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
|
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
|
||||||
pub use player::{Player, MAX_MOUNT_RANGE_SQR};
|
pub use player::{Player, MAX_MOUNT_RANGE_SQR};
|
||||||
pub use projectile::Projectile;
|
pub use projectile::Projectile;
|
||||||
|
pub use shockwave::Shockwave;
|
||||||
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
|
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
|
||||||
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
||||||
pub use visual::{LightAnimation, LightEmitter};
|
pub use visual::{LightAnimation, LightEmitter};
|
||||||
|
25
common/src/comp/shockwave.rs
Normal file
25
common/src/comp/shockwave.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::{
|
||||||
|
comp::phys::{Ori, Pos},
|
||||||
|
sync::Uid,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specs::{Component, FlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Shockwave {
|
||||||
|
pub shockwave_origin: Pos,
|
||||||
|
pub shockwave_direction: Ori,
|
||||||
|
pub shockwave_angle: f32,
|
||||||
|
pub shockwave_speed: f32,
|
||||||
|
pub shockwave_duration: Duration,
|
||||||
|
pub damage: u32,
|
||||||
|
pub knockback: f32,
|
||||||
|
pub requires_ground: bool,
|
||||||
|
pub owner: Option<Uid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Shockwave {
|
||||||
|
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
|
}
|
@ -48,6 +48,7 @@ pub enum ServerEvent {
|
|||||||
gravity: Option<comp::Gravity>,
|
gravity: Option<comp::Gravity>,
|
||||||
speed: f32,
|
speed: f32,
|
||||||
},
|
},
|
||||||
|
Shockwave {shockwave: comp::Shockwave},
|
||||||
LandOnGround {
|
LandOnGround {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
vel: Vec3<f32>,
|
vel: Vec3<f32>,
|
||||||
|
103
common/src/states/ground_shockwave.rs
Normal file
103
common/src/states/ground_shockwave.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
use crate::{
|
||||||
|
comp::{Attacking, CharacterState, Shockwave, StateUpdate},
|
||||||
|
event::ServerEvent,
|
||||||
|
states::utils::*,
|
||||||
|
sys::character_behavior::*,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Data {
|
||||||
|
/// Whether the attack can deal more damage
|
||||||
|
pub exhausted: bool,
|
||||||
|
/// How long until state should deal damage
|
||||||
|
pub buildup_duration: Duration,
|
||||||
|
/// How long the state has until exiting
|
||||||
|
pub recover_duration: Duration,
|
||||||
|
/// Base damage
|
||||||
|
pub damage: u32,
|
||||||
|
/// Knockback
|
||||||
|
pub knockback: f32,
|
||||||
|
/// Angle of the shockwave
|
||||||
|
pub shockwave_angle: f32,
|
||||||
|
/// Speed of the shockwave
|
||||||
|
pub shockwave_speed: f32,
|
||||||
|
/// How long the shockwave travels for
|
||||||
|
pub shockwave_duration: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CharacterBehavior for Data {
|
||||||
|
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||||
|
let mut update = StateUpdate::from(data);
|
||||||
|
|
||||||
|
handle_move(data, &mut update, 0.7);
|
||||||
|
handle_jump(data, &mut update);
|
||||||
|
|
||||||
|
if self.buildup_duration != Duration::default() {
|
||||||
|
// Build up
|
||||||
|
update.character = CharacterState::GroundShockwave(Data {
|
||||||
|
exhausted: false,
|
||||||
|
buildup_duration: self
|
||||||
|
.buildup_duration
|
||||||
|
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
recover_duration: self.recover_duration,
|
||||||
|
damage: self.damage,
|
||||||
|
knockback: self.knockback,
|
||||||
|
shockwave_angle: self.shockwave_angle,
|
||||||
|
shockwave_speed: self.shockwave_speed,
|
||||||
|
shockwave_duration: self.shockwave_duration,
|
||||||
|
});
|
||||||
|
} else if !self.exhausted {
|
||||||
|
// Attack
|
||||||
|
let shockwave = Shockwave {
|
||||||
|
shockwave_origin: *data.pos,
|
||||||
|
shockwave_direction: *data.ori,
|
||||||
|
shockwave_angle: self.shockwave_angle,
|
||||||
|
shockwave_speed: self.shockwave_speed,
|
||||||
|
shockwave_duration: self.shockwave_duration,
|
||||||
|
damage: self.damage,
|
||||||
|
knockback: self.knockback,
|
||||||
|
requires_ground: true,
|
||||||
|
owner: Some(*data.uid),
|
||||||
|
};
|
||||||
|
update.server_events.push_front(ServerEvent::Shockwave {
|
||||||
|
shockwave,
|
||||||
|
});
|
||||||
|
|
||||||
|
update.character = CharacterState::GroundShockwave(Data {
|
||||||
|
exhausted: true,
|
||||||
|
buildup_duration: self.buildup_duration,
|
||||||
|
recover_duration: self.recover_duration,
|
||||||
|
damage: self.damage,
|
||||||
|
knockback: self.knockback,
|
||||||
|
shockwave_angle: self.shockwave_angle,
|
||||||
|
shockwave_speed: self.shockwave_speed,
|
||||||
|
shockwave_duration: self.shockwave_duration,
|
||||||
|
});
|
||||||
|
} else if self.recover_duration != Duration::default() {
|
||||||
|
// Recovery
|
||||||
|
update.character = CharacterState::GroundShockwave(Data {
|
||||||
|
exhausted: false,
|
||||||
|
buildup_duration: self.buildup_duration,
|
||||||
|
recover_duration: self
|
||||||
|
.recover_duration
|
||||||
|
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
damage: self.damage,
|
||||||
|
knockback: self.knockback,
|
||||||
|
shockwave_angle: self.shockwave_angle,
|
||||||
|
shockwave_speed: self.shockwave_speed,
|
||||||
|
shockwave_duration: self.shockwave_duration,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Done
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
// Make sure attack component is removed
|
||||||
|
data.updater.remove::<Attacking>(data.entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
update
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ pub mod dash_melee;
|
|||||||
pub mod equipping;
|
pub mod equipping;
|
||||||
pub mod glide;
|
pub mod glide;
|
||||||
pub mod glide_wield;
|
pub mod glide_wield;
|
||||||
|
pub mod ground_shockwave;
|
||||||
pub mod idle;
|
pub mod idle;
|
||||||
pub mod leap_melee;
|
pub mod leap_melee;
|
||||||
pub mod roll;
|
pub mod roll;
|
||||||
|
@ -258,6 +258,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::LeapMelee(data) => data.handle_event(&j, action),
|
CharacterState::LeapMelee(data) => data.handle_event(&j, action),
|
||||||
CharacterState::SpinMelee(data) => data.handle_event(&j, action),
|
CharacterState::SpinMelee(data) => data.handle_event(&j, action),
|
||||||
CharacterState::ChargedRanged(data) => data.handle_event(&j, action),
|
CharacterState::ChargedRanged(data) => data.handle_event(&j, action),
|
||||||
|
CharacterState::GroundShockwave(data) => data.handle_event(&j, action),
|
||||||
};
|
};
|
||||||
local_emitter.append(&mut state_update.local_events);
|
local_emitter.append(&mut state_update.local_events);
|
||||||
server_emitter.append(&mut state_update.server_events);
|
server_emitter.append(&mut state_update.server_events);
|
||||||
@ -286,6 +287,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::LeapMelee(data) => data.behavior(&j),
|
CharacterState::LeapMelee(data) => data.behavior(&j),
|
||||||
CharacterState::SpinMelee(data) => data.behavior(&j),
|
CharacterState::SpinMelee(data) => data.behavior(&j),
|
||||||
CharacterState::ChargedRanged(data) => data.behavior(&j),
|
CharacterState::ChargedRanged(data) => data.behavior(&j),
|
||||||
|
CharacterState::GroundShockwave(data) => data.behavior(&j),
|
||||||
};
|
};
|
||||||
|
|
||||||
local_emitter.append(&mut state_update.local_events);
|
local_emitter.append(&mut state_update.local_events);
|
||||||
|
@ -112,7 +112,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
| CharacterState::SpinMelee { .. }
|
| CharacterState::SpinMelee { .. }
|
||||||
| CharacterState::TripleStrike { .. }
|
| CharacterState::TripleStrike { .. }
|
||||||
| CharacterState::BasicRanged { .. }
|
| CharacterState::BasicRanged { .. }
|
||||||
| CharacterState::ChargedRanged { .. } => {
|
| CharacterState::ChargedRanged { .. }
|
||||||
|
| CharacterState::GroundShockwave { .. } => {
|
||||||
if energy.get_unchecked().regen_rate != 0.0 {
|
if energy.get_unchecked().regen_rate != 0.0 {
|
||||||
energy.get_mut_unchecked().regen_rate = 0.0
|
energy.get_mut_unchecked().regen_rate = 0.0
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use common::{
|
|||||||
character::CharacterId,
|
character::CharacterId,
|
||||||
comp::{
|
comp::{
|
||||||
self, humanoid::DEFAULT_HUMANOID_EYE_HEIGHT, Agent, Alignment, Body, Gravity, Item,
|
self, humanoid::DEFAULT_HUMANOID_EYE_HEIGHT, Agent, Alignment, Body, Gravity, Item,
|
||||||
ItemDrop, LightEmitter, Loadout, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
ItemDrop, LightEmitter, Loadout, Pos, Projectile, Scale, Shockwave, Stats, Vel, WaypointArea,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
@ -124,6 +124,12 @@ pub fn handle_shoot(
|
|||||||
builder.build();
|
builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_shockwave(server: &mut Server, shockwave: Shockwave) {
|
||||||
|
let state = server.state_mut();
|
||||||
|
let builder = state.create_shockwave(shockwave);
|
||||||
|
builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||||
server
|
server
|
||||||
.state
|
.state
|
||||||
|
@ -70,6 +70,7 @@ impl Server {
|
|||||||
gravity,
|
gravity,
|
||||||
speed,
|
speed,
|
||||||
} => handle_shoot(self, entity, dir, body, light, projectile, gravity, speed),
|
} => handle_shoot(self, entity, dir, body, light, projectile, gravity, speed),
|
||||||
|
ServerEvent::Shockwave {shockwave} => handle_shockwave(self, shockwave),
|
||||||
ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change),
|
ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change),
|
||||||
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
||||||
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
||||||
|
@ -79,6 +79,7 @@ fn maps_basic_melee() {
|
|||||||
&CharacterState::BasicMelee(states::basic_melee::Data {
|
&CharacterState::BasicMelee(states::basic_melee::Data {
|
||||||
buildup_duration: Duration::default(),
|
buildup_duration: Duration::default(),
|
||||||
recover_duration: Duration::default(),
|
recover_duration: Duration::default(),
|
||||||
|
knockback: 0.0,
|
||||||
base_healthchange: 10,
|
base_healthchange: 10,
|
||||||
range: 1.0,
|
range: 1.0,
|
||||||
max_angle: 1.0,
|
max_angle: 1.0,
|
||||||
|
Loading…
Reference in New Issue
Block a user