mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added combo component
This commit is contained in:
parent
d2fffa1a92
commit
f24433c8cf
@ -17,6 +17,7 @@ sum_type! {
|
|||||||
Buffs(comp::Buffs),
|
Buffs(comp::Buffs),
|
||||||
Auras(comp::Auras),
|
Auras(comp::Auras),
|
||||||
Energy(comp::Energy),
|
Energy(comp::Energy),
|
||||||
|
Combo(comp::Combo),
|
||||||
Health(comp::Health),
|
Health(comp::Health),
|
||||||
Poise(comp::Poise),
|
Poise(comp::Poise),
|
||||||
LightEmitter(comp::LightEmitter),
|
LightEmitter(comp::LightEmitter),
|
||||||
@ -50,6 +51,7 @@ sum_type! {
|
|||||||
Buffs(PhantomData<comp::Buffs>),
|
Buffs(PhantomData<comp::Buffs>),
|
||||||
Auras(PhantomData<comp::Auras>),
|
Auras(PhantomData<comp::Auras>),
|
||||||
Energy(PhantomData<comp::Energy>),
|
Energy(PhantomData<comp::Energy>),
|
||||||
|
Combo(PhantomData<comp::Combo>),
|
||||||
Health(PhantomData<comp::Health>),
|
Health(PhantomData<comp::Health>),
|
||||||
Poise(PhantomData<comp::Poise>),
|
Poise(PhantomData<comp::Poise>),
|
||||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||||
@ -83,6 +85,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
||||||
|
EcsCompPacket::Combo(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Health(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Health(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Poise(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Poise(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
||||||
@ -114,6 +117,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
||||||
|
EcsCompPacket::Combo(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Health(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Health(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Poise(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Poise(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
||||||
@ -145,6 +149,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
||||||
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
||||||
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
||||||
|
EcsCompPhantom::Combo(_) => sync::handle_remove::<comp::Combo>(entity, world),
|
||||||
EcsCompPhantom::Health(_) => sync::handle_remove::<comp::Health>(entity, world),
|
EcsCompPhantom::Health(_) => sync::handle_remove::<comp::Health>(entity, world),
|
||||||
EcsCompPhantom::Poise(_) => sync::handle_remove::<comp::Poise>(entity, world),
|
EcsCompPhantom::Poise(_) => sync::handle_remove::<comp::Poise>(entity, world),
|
||||||
EcsCompPhantom::LightEmitter(_) => {
|
EcsCompPhantom::LightEmitter(_) => {
|
||||||
|
@ -86,6 +86,13 @@ impl Attack {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_combo_increment(self) -> Self {
|
||||||
|
self.with_effect(
|
||||||
|
AttackEffect::new(None, CombatEffect::Combo(1))
|
||||||
|
.with_requirement(CombatRequirement::AnyDamage),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn effects(&self) -> impl Iterator<Item = &AttackEffect> { self.effects.iter() }
|
pub fn effects(&self) -> impl Iterator<Item = &AttackEffect> { self.effects.iter() }
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@ -195,6 +202,14 @@ impl Attack {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
CombatEffect::Combo(c) => {
|
||||||
|
if let Some(attacker_entity) = attacker_info.map(|a| a.entity) {
|
||||||
|
emit(ServerEvent::ComboChange {
|
||||||
|
entity: attacker_entity,
|
||||||
|
change: *c,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,6 +318,14 @@ impl Attack {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
CombatEffect::Combo(c) => {
|
||||||
|
if let Some(attacker_entity) = attacker_info.map(|a| a.entity) {
|
||||||
|
emit(ServerEvent::ComboChange {
|
||||||
|
entity: attacker_entity,
|
||||||
|
change: c,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,6 +391,7 @@ pub enum CombatEffect {
|
|||||||
EnergyReward(f32),
|
EnergyReward(f32),
|
||||||
Lifesteal(f32),
|
Lifesteal(f32),
|
||||||
Poise(f32),
|
Poise(f32),
|
||||||
|
Combo(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
39
common/src/comp/combo.rs
Normal file
39
common/src/comp/combo.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Combo {
|
||||||
|
counter: u32,
|
||||||
|
last_increase: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Combo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
counter: 0,
|
||||||
|
last_increase: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Combo {
|
||||||
|
pub fn counter(&self) -> u32 { self.counter }
|
||||||
|
|
||||||
|
pub fn last_increase(&self) -> f64 { self.last_increase }
|
||||||
|
|
||||||
|
pub fn reset(&mut self) { self.counter = 0; }
|
||||||
|
|
||||||
|
pub fn increase_by(&mut self, amount: u32, time: f64) {
|
||||||
|
self.counter = self.counter.saturating_add(amount);
|
||||||
|
self.last_increase = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrease_by(&mut self, amount: u32) {
|
||||||
|
self.counter = self.counter.saturating_sub(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Combo {
|
||||||
|
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
|
}
|
@ -8,6 +8,7 @@ pub mod buff;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod character_state;
|
mod character_state;
|
||||||
#[cfg(not(target_arch = "wasm32"))] pub mod chat;
|
#[cfg(not(target_arch = "wasm32"))] pub mod chat;
|
||||||
|
pub mod combo;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod controller;
|
mod controller;
|
||||||
#[cfg(not(target_arch = "wasm32"))] mod energy;
|
#[cfg(not(target_arch = "wasm32"))] mod energy;
|
||||||
@ -58,6 +59,7 @@ pub use self::{
|
|||||||
chat::{
|
chat::{
|
||||||
ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,
|
ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,
|
||||||
},
|
},
|
||||||
|
combo::Combo,
|
||||||
controller::{
|
controller::{
|
||||||
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip, Input,
|
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip, Input,
|
||||||
InventoryManip, LoadoutManip, MountState, Mounting, SlotManip,
|
InventoryManip, LoadoutManip, MountState, Mounting, SlotManip,
|
||||||
|
@ -143,6 +143,10 @@ pub enum ServerEvent {
|
|||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
change: comp::EnergyChange,
|
change: comp::EnergyChange,
|
||||||
},
|
},
|
||||||
|
ComboChange {
|
||||||
|
entity: EcsEntity,
|
||||||
|
change: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventBus<E> {
|
pub struct EventBus<E> {
|
||||||
|
@ -214,7 +214,8 @@ impl CharacterBehavior for Data {
|
|||||||
.with_crit(0.5, 1.3)
|
.with_crit(0.5, 1.3)
|
||||||
.with_effect(energy)
|
.with_effect(energy)
|
||||||
.with_effect(poise)
|
.with_effect(poise)
|
||||||
.with_effect(knockback);
|
.with_effect(knockback)
|
||||||
|
.with_combo_increment();
|
||||||
|
|
||||||
data.updater.insert(data.entity, Melee {
|
data.updater.insert(data.entity, Melee {
|
||||||
attack,
|
attack,
|
||||||
|
@ -127,6 +127,7 @@ impl State {
|
|||||||
ecs.register::<comp::Buffs>();
|
ecs.register::<comp::Buffs>();
|
||||||
ecs.register::<comp::Auras>();
|
ecs.register::<comp::Auras>();
|
||||||
ecs.register::<comp::Energy>();
|
ecs.register::<comp::Energy>();
|
||||||
|
ecs.register::<comp::Combo>();
|
||||||
ecs.register::<comp::Health>();
|
ecs.register::<comp::Health>();
|
||||||
ecs.register::<comp::Poise>();
|
ecs.register::<comp::Poise>();
|
||||||
ecs.register::<comp::CanBuild>();
|
ecs.register::<comp::CanBuild>();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
skills::{GeneralSkill, Skill},
|
skills::{GeneralSkill, Skill},
|
||||||
Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Poise, PoiseChange,
|
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise,
|
||||||
PoiseSource, Pos, Stats,
|
PoiseChange, PoiseSource, Pos, Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
metrics::SysMetrics,
|
metrics::SysMetrics,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
resources::DeltaTime,
|
resources::{DeltaTime, Time},
|
||||||
span,
|
span,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
@ -20,11 +20,13 @@ use vek::Vec3;
|
|||||||
|
|
||||||
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||||
const POISE_REGEN_ACCEL: f32 = 2.0;
|
const POISE_REGEN_ACCEL: f32 = 2.0;
|
||||||
|
const COMBO_DECAY_START: f64 = 10.0; // seconds
|
||||||
|
|
||||||
#[derive(SystemData)]
|
#[derive(SystemData)]
|
||||||
pub struct ReadData<'a> {
|
pub struct ReadData<'a> {
|
||||||
entities: Entities<'a>,
|
entities: Entities<'a>,
|
||||||
dt: Read<'a, DeltaTime>,
|
dt: Read<'a, DeltaTime>,
|
||||||
|
time: Read<'a, Time>,
|
||||||
server_bus: Read<'a, EventBus<ServerEvent>>,
|
server_bus: Read<'a, EventBus<ServerEvent>>,
|
||||||
metrics: ReadExpect<'a, SysMetrics>,
|
metrics: ReadExpect<'a, SysMetrics>,
|
||||||
positions: ReadStorage<'a, Pos>,
|
positions: ReadStorage<'a, Pos>,
|
||||||
@ -43,6 +45,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Health>,
|
WriteStorage<'a, Health>,
|
||||||
WriteStorage<'a, Poise>,
|
WriteStorage<'a, Poise>,
|
||||||
WriteStorage<'a, Energy>,
|
WriteStorage<'a, Energy>,
|
||||||
|
WriteStorage<'a, Combo>,
|
||||||
Write<'a, Vec<Outcome>>,
|
Write<'a, Vec<Outcome>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -54,6 +57,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut healths,
|
mut healths,
|
||||||
mut poises,
|
mut poises,
|
||||||
mut energies,
|
mut energies,
|
||||||
|
mut combos,
|
||||||
mut outcomes,
|
mut outcomes,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
@ -256,6 +260,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decay combo
|
||||||
|
for (_, mut combo) in (&read_data.entities, &mut combos).join() {
|
||||||
|
if combo.counter() > 0 && read_data.time.0 - combo.last_increase() > COMBO_DECAY_START {
|
||||||
|
combo.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
read_data.metrics.stats_ns.store(
|
read_data.metrics.stats_ns.store(
|
||||||
start_time.elapsed().as_nanos() as u64,
|
start_time.elapsed().as_nanos() as u64,
|
||||||
std::sync::atomic::Ordering::Relaxed,
|
std::sync::atomic::Ordering::Relaxed,
|
||||||
|
@ -20,6 +20,7 @@ use common::{
|
|||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
lottery::Lottery,
|
lottery::Lottery,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
|
resources::Time,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
uid::{Uid, UidAllocator},
|
uid::{Uid, UidAllocator},
|
||||||
@ -880,3 +881,15 @@ fn handle_exp_gain(
|
|||||||
exp: exp_reward as i32,
|
exp: exp_reward as i32,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_combo_change(server: &Server, entity: EcsEntity, change: i32) {
|
||||||
|
let ecs = &server.state.ecs();
|
||||||
|
if let Some(mut combo) = ecs.write_storage::<comp::Combo>().get_mut(entity) {
|
||||||
|
if change > 0 {
|
||||||
|
let time = ecs.read_resource::<Time>();
|
||||||
|
combo.increase_by(change as u32, time.0);
|
||||||
|
} else {
|
||||||
|
combo.decrease_by(change.abs() as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,8 +8,9 @@ use entity_creation::{
|
|||||||
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
||||||
};
|
};
|
||||||
use entity_manipulation::{
|
use entity_manipulation::{
|
||||||
handle_aura, handle_buff, handle_damage, handle_delete, handle_destroy, handle_energy_change,
|
handle_aura, handle_buff, handle_combo_change, handle_damage, handle_delete, handle_destroy,
|
||||||
handle_explosion, handle_knockback, handle_land_on_ground, handle_poise, handle_respawn,
|
handle_energy_change, handle_explosion, handle_knockback, handle_land_on_ground, handle_poise,
|
||||||
|
handle_respawn,
|
||||||
};
|
};
|
||||||
use group_manip::handle_group;
|
use group_manip::handle_group;
|
||||||
use interaction::{
|
use interaction::{
|
||||||
@ -182,6 +183,9 @@ impl Server {
|
|||||||
ServerEvent::EnergyChange { entity, change } => {
|
ServerEvent::EnergyChange { entity, change } => {
|
||||||
handle_energy_change(&self, entity, change)
|
handle_energy_change(&self, entity, change)
|
||||||
},
|
},
|
||||||
|
ServerEvent::ComboChange { entity, change } => {
|
||||||
|
handle_combo_change(&self, entity, change)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +178,7 @@ impl StateExt for State {
|
|||||||
.with(comp::CharacterState::default())
|
.with(comp::CharacterState::default())
|
||||||
.with(inventory)
|
.with(inventory)
|
||||||
.with(comp::Buffs::default())
|
.with(comp::Buffs::default())
|
||||||
|
.with(comp::Combo::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder {
|
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder {
|
||||||
@ -269,6 +270,7 @@ impl StateExt for State {
|
|||||||
comp::Alignment::Owned(self.read_component_copied(entity).unwrap()),
|
comp::Alignment::Owned(self.read_component_copied(entity).unwrap()),
|
||||||
);
|
);
|
||||||
self.write_component(entity, comp::Buffs::default());
|
self.write_component(entity, comp::Buffs::default());
|
||||||
|
self.write_component(entity, comp::Combo::default());
|
||||||
|
|
||||||
// Make sure physics components are updated
|
// Make sure physics components are updated
|
||||||
self.write_component(entity, comp::ForceUpdate);
|
self.write_component(entity, comp::ForceUpdate);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user