mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
fix: sync characterstates, better energy management
This commit is contained in:
parent
31f3aae75c
commit
ac611f4618
@ -53,6 +53,15 @@ pub enum CharacterState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterState {
|
impl CharacterState {
|
||||||
|
pub fn is_wielded(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CharacterState::Wielded(_) => true,
|
||||||
|
CharacterState::BasicAttack(_) => true,
|
||||||
|
CharacterState::BasicBlock(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_attack(&self) -> bool {
|
pub fn is_attack(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CharacterState::BasicAttack(_) => true,
|
CharacterState::BasicAttack(_) => true,
|
||||||
|
@ -16,6 +16,7 @@ pub enum EnergySource {
|
|||||||
Regen,
|
Regen,
|
||||||
Revive,
|
Revive,
|
||||||
Climb,
|
Climb,
|
||||||
|
Roll,
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ sum_type! {
|
|||||||
AbilityAction(comp::AbilityAction),
|
AbilityAction(comp::AbilityAction),
|
||||||
AbilityPool(comp::AbilityPool),
|
AbilityPool(comp::AbilityPool),
|
||||||
Attacking(comp::Attacking),
|
Attacking(comp::Attacking),
|
||||||
|
CharacterState(comp::CharacterState),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Automatically derive From<T> for EcsCompPhantom
|
// Automatically derive From<T> for EcsCompPhantom
|
||||||
@ -47,6 +48,7 @@ sum_type! {
|
|||||||
AbilityAction(PhantomData<comp::AbilityAction>),
|
AbilityAction(PhantomData<comp::AbilityAction>),
|
||||||
AbilityPool(PhantomData<comp::AbilityPool>),
|
AbilityPool(PhantomData<comp::AbilityPool>),
|
||||||
Attacking(PhantomData<comp::Attacking>),
|
Attacking(PhantomData<comp::Attacking>),
|
||||||
|
CharacterState(PhantomData<comp::CharacterState>),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl sync::CompPacket for EcsCompPacket {
|
impl sync::CompPacket for EcsCompPacket {
|
||||||
@ -70,6 +72,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::AbilityAction(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::AbilityAction(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::AbilityPool(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::AbilityPool(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
|
||||||
|
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +94,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::AbilityAction(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::AbilityAction(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::AbilityPool(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::AbilityPool(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
|
||||||
|
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +122,9 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
sync::handle_remove::<comp::AbilityPool>(entity, world)
|
sync::handle_remove::<comp::AbilityPool>(entity, world)
|
||||||
},
|
},
|
||||||
EcsCompPhantom::Attacking(_) => sync::handle_remove::<comp::Attacking>(entity, world),
|
EcsCompPhantom::Attacking(_) => sync::handle_remove::<comp::Attacking>(entity, world),
|
||||||
|
EcsCompPhantom::CharacterState(_) => {
|
||||||
|
sync::handle_remove::<comp::CharacterState>(entity, world)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{Attacking, CharacterState, EcsStateData, ItemKind::Tool, StateUpdate, ToolData},
|
comp::{Attacking, CharacterState, EcsStateData, ItemKind::Tool, StateUpdate, ToolData},
|
||||||
states::{utils, StateHandler},
|
states::StateHandler,
|
||||||
};
|
};
|
||||||
use std::{collections::VecDeque, time::Duration};
|
use std::{collections::VecDeque, time::Duration};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::utils::*;
|
use super::utils::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
comp::{EcsStateData, StateUpdate},
|
comp::{CharacterState, EcsStateData, StateUpdate},
|
||||||
states::StateHandler,
|
states::StateHandler,
|
||||||
};
|
};
|
||||||
use std::{collections::VecDeque, time::Duration};
|
use std::{collections::VecDeque, time::Duration};
|
||||||
@ -26,6 +26,12 @@ impl StateHandler for State {
|
|||||||
server_events: VecDeque::new(),
|
server_events: VecDeque::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handle_move_dir(&ecs_data, &mut update);
|
||||||
|
|
||||||
|
if !ecs_data.physics.on_ground || !ecs_data.inputs.secondary.is_pressed() {
|
||||||
|
update.character = CharacterState::Wielded(None);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,16 @@ impl StateHandler for State {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
* ROLL_SPEED;
|
* ROLL_SPEED;
|
||||||
|
|
||||||
|
// Smooth orientation
|
||||||
|
if update.vel.0.magnitude_squared() > 0.0001
|
||||||
|
&& (update.ori.0.normalized() - Vec3::from(update.vel.0).normalized())
|
||||||
|
.magnitude_squared()
|
||||||
|
> 0.001
|
||||||
|
{
|
||||||
|
update.ori.0 =
|
||||||
|
vek::ops::Slerp::slerp(update.ori.0, update.vel.0.into(), 9.0 * ecs_data.dt.0);
|
||||||
|
}
|
||||||
|
|
||||||
if self.remaining_duration == Duration::default() {
|
if self.remaining_duration == Duration::default() {
|
||||||
// Roll duration has expired
|
// Roll duration has expired
|
||||||
update.character = CharacterState::Idle(None);
|
update.character = CharacterState::Idle(None);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{Attacking, CharacterState, EcsStateData, ItemKind::Tool, StateUpdate},
|
comp::{Attacking, CharacterState, EcsStateData, EnergySource, ItemKind::Tool, StateUpdate},
|
||||||
event::LocalEvent,
|
event::LocalEvent,
|
||||||
};
|
};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -27,7 +27,10 @@ pub fn handle_move_dir(ecs_data: &EcsStateData, update: &mut StateUpdate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set direction based on move direction
|
// Set direction based on move direction
|
||||||
let ori_dir = if update.character.is_attack() || update.character.is_block() {
|
let ori_dir = if update.character.is_wielded()
|
||||||
|
|| update.character.is_attack()
|
||||||
|
|| update.character.is_block()
|
||||||
|
{
|
||||||
Vec2::from(ecs_data.inputs.look_dir).normalized()
|
Vec2::from(ecs_data.inputs.look_dir).normalized()
|
||||||
} else {
|
} else {
|
||||||
Vec2::from(update.vel.0)
|
Vec2::from(update.vel.0)
|
||||||
@ -58,7 +61,7 @@ pub fn handle_sit(ecs_data: &EcsStateData, update: &mut StateUpdate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_climb(ecs_data: &EcsStateData, update: &mut StateUpdate) {
|
pub fn handle_climb(ecs_data: &EcsStateData, update: &mut StateUpdate) {
|
||||||
if (ecs_data.inputs.climb.is_just_pressed() || ecs_data.inputs.climb_down.is_pressed())
|
if (ecs_data.inputs.climb.is_pressed() || ecs_data.inputs.climb_down.is_pressed())
|
||||||
&& ecs_data.physics.on_wall.is_some()
|
&& ecs_data.physics.on_wall.is_some()
|
||||||
&& !ecs_data.physics.on_ground
|
&& !ecs_data.physics.on_ground
|
||||||
//&& update.vel.0.z < 0.0
|
//&& update.vel.0.z < 0.0
|
||||||
@ -121,6 +124,10 @@ pub fn handle_dodge(ecs_data: &EcsStateData, update: &mut StateUpdate) {
|
|||||||
if ecs_data.inputs.roll.is_pressed()
|
if ecs_data.inputs.roll.is_pressed()
|
||||||
&& ecs_data.physics.on_ground
|
&& ecs_data.physics.on_ground
|
||||||
&& ecs_data.body.is_humanoid()
|
&& ecs_data.body.is_humanoid()
|
||||||
|
&& update
|
||||||
|
.energy
|
||||||
|
.try_change_by(-200, EnergySource::Roll)
|
||||||
|
.is_ok()
|
||||||
{
|
{
|
||||||
update.character = state;
|
update.character = state;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
|
|
||||||
const ENERGY_REGEN_ACCEL: f32 = 20.0;
|
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||||
|
|
||||||
/// This system kills players, levels them up, and regenerates energy.
|
/// This system kills players, levels them up, and regenerates energy.
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
@ -87,15 +87,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
as i32,
|
as i32,
|
||||||
EnergySource::Regen,
|
EnergySource::Regen,
|
||||||
);
|
);
|
||||||
energy.regen_rate += ENERGY_REGEN_ACCEL * dt.0;
|
energy.regen_rate =
|
||||||
|
(energy.regen_rate + ENERGY_REGEN_ACCEL * dt.0).min(100.0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// All other states do not regen and set the rate back to zero.
|
// All other states do not regen and set the rate back to zero.
|
||||||
_ => {
|
CharacterState::Wielded(_) => {
|
||||||
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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use super::SysTimer;
|
use super::SysTimer;
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
AbilityPool, Body, CanBuild, Energy, Gravity, Item, LightEmitter, Mass, MountState,
|
AbilityPool, Body, CanBuild, CharacterState, Energy, Gravity, Item, LightEmitter, Mass,
|
||||||
Mounting, Player, Scale, Stats, Sticky,
|
MountState, Mounting, Player, Scale, Stats, Sticky,
|
||||||
},
|
},
|
||||||
msg::EcsCompPacket,
|
msg::EcsCompPacket,
|
||||||
sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt},
|
sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt},
|
||||||
@ -52,6 +52,7 @@ pub struct TrackedComps<'a> {
|
|||||||
pub sticky: ReadStorage<'a, Sticky>,
|
pub sticky: ReadStorage<'a, Sticky>,
|
||||||
pub gravity: ReadStorage<'a, Gravity>,
|
pub gravity: ReadStorage<'a, Gravity>,
|
||||||
pub ability_pool: ReadStorage<'a, AbilityPool>,
|
pub ability_pool: ReadStorage<'a, AbilityPool>,
|
||||||
|
pub character_state: ReadStorage<'a, CharacterState>,
|
||||||
}
|
}
|
||||||
impl<'a> TrackedComps<'a> {
|
impl<'a> TrackedComps<'a> {
|
||||||
pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage<EcsCompPacket> {
|
pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage<EcsCompPacket> {
|
||||||
@ -109,6 +110,10 @@ impl<'a> TrackedComps<'a> {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.copied()
|
.copied()
|
||||||
.map(|c| comps.push(c.into()));
|
.map(|c| comps.push(c.into()));
|
||||||
|
self.character_state
|
||||||
|
.get(entity)
|
||||||
|
.copied()
|
||||||
|
.map(|c| comps.push(c.into()));
|
||||||
|
|
||||||
EntityPackage { uid, comps }
|
EntityPackage { uid, comps }
|
||||||
}
|
}
|
||||||
@ -130,6 +135,7 @@ pub struct ReadTrackers<'a> {
|
|||||||
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
|
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
|
||||||
pub gravity: ReadExpect<'a, UpdateTracker<Gravity>>,
|
pub gravity: ReadExpect<'a, UpdateTracker<Gravity>>,
|
||||||
pub ability_pool: ReadExpect<'a, UpdateTracker<AbilityPool>>,
|
pub ability_pool: ReadExpect<'a, UpdateTracker<AbilityPool>>,
|
||||||
|
pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>,
|
||||||
}
|
}
|
||||||
impl<'a> ReadTrackers<'a> {
|
impl<'a> ReadTrackers<'a> {
|
||||||
pub fn create_sync_package(
|
pub fn create_sync_package(
|
||||||
@ -158,6 +164,12 @@ impl<'a> ReadTrackers<'a> {
|
|||||||
.with_component(&comps.uid, &*self.sticky, &comps.sticky, filter)
|
.with_component(&comps.uid, &*self.sticky, &comps.sticky, filter)
|
||||||
.with_component(&comps.uid, &*self.gravity, &comps.gravity, filter)
|
.with_component(&comps.uid, &*self.gravity, &comps.gravity, filter)
|
||||||
.with_component(&comps.uid, &*self.ability_pool, &comps.ability_pool, filter)
|
.with_component(&comps.uid, &*self.ability_pool, &comps.ability_pool, filter)
|
||||||
|
.with_component(
|
||||||
|
&comps.uid,
|
||||||
|
&*self.character_state,
|
||||||
|
&comps.character_state,
|
||||||
|
filter,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +190,7 @@ pub struct WriteTrackers<'a> {
|
|||||||
sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
|
sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
|
||||||
gravity: WriteExpect<'a, UpdateTracker<Gravity>>,
|
gravity: WriteExpect<'a, UpdateTracker<Gravity>>,
|
||||||
ability_pool: WriteExpect<'a, UpdateTracker<AbilityPool>>,
|
ability_pool: WriteExpect<'a, UpdateTracker<AbilityPool>>,
|
||||||
|
character_state: WriteExpect<'a, UpdateTracker<CharacterState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||||
@ -197,6 +210,9 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
trackers.sticky.record_changes(&comps.sticky);
|
trackers.sticky.record_changes(&comps.sticky);
|
||||||
trackers.gravity.record_changes(&comps.gravity);
|
trackers.gravity.record_changes(&comps.gravity);
|
||||||
trackers.ability_pool.record_changes(&comps.ability_pool);
|
trackers.ability_pool.record_changes(&comps.ability_pool);
|
||||||
|
trackers
|
||||||
|
.character_state
|
||||||
|
.record_changes(&comps.character_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_trackers(world: &mut World) {
|
pub fn register_trackers(world: &mut World) {
|
||||||
@ -215,6 +231,7 @@ pub fn register_trackers(world: &mut World) {
|
|||||||
world.register_tracker::<Sticky>();
|
world.register_tracker::<Sticky>();
|
||||||
world.register_tracker::<Gravity>();
|
world.register_tracker::<Gravity>();
|
||||||
world.register_tracker::<AbilityPool>();
|
world.register_tracker::<AbilityPool>();
|
||||||
|
world.register_tracker::<CharacterState>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deleted entities grouped by region
|
/// Deleted entities grouped by region
|
||||||
|
@ -124,28 +124,23 @@ impl MovementEventMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Voxygen has an existing list of character states via `MoveState::*` and
|
/// Voxygen has an existing list of character states however that list does
|
||||||
/// `ActionState::*` however that list does not provide enough
|
/// not provide enough resolution to target specific entity events, such
|
||||||
/// resolution to target specific entity events, such as opening or
|
/// as opening or closing the glider. These methods translate those
|
||||||
/// closing the glider. These methods translate those entity states with
|
/// entity states with some additional data into more specific
|
||||||
/// some additional data into more specific `SfxEvent`'s which we attach
|
/// `SfxEvent`'s which we attach sounds to
|
||||||
/// sounds to
|
|
||||||
fn map_movement_event(current_event: &CharacterState, previous_event: SfxEvent) -> SfxEvent {
|
fn map_movement_event(current_event: &CharacterState, previous_event: SfxEvent) -> SfxEvent {
|
||||||
match (current_event, previous_event) {
|
match (previous_event, current_event) {
|
||||||
(CharacterState::Roll(_), _) => SfxEvent::Roll,
|
(_, CharacterState::Roll(_)) => SfxEvent::Roll,
|
||||||
(CharacterState::Climb(_), _) => SfxEvent::Climb,
|
(_, CharacterState::Climb(_)) => SfxEvent::Climb,
|
||||||
(CharacterState::Idle(_), _) => SfxEvent::Run,
|
(SfxEvent::Glide, CharacterState::Idle(_)) => SfxEvent::GliderClose,
|
||||||
(CharacterState::Idle(_), SfxEvent::Glide) => SfxEvent::GliderClose,
|
(previous_event, CharacterState::Glide(_)) => {
|
||||||
(CharacterState::Idle(_), SfxEvent::Fall) => SfxEvent::Run,
|
|
||||||
(CharacterState::Idle(_), SfxEvent::Jump) => SfxEvent::Idle,
|
|
||||||
(CharacterState::Glide(_), previous_event) => {
|
|
||||||
if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide {
|
if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide {
|
||||||
SfxEvent::GliderOpen
|
SfxEvent::GliderOpen
|
||||||
} else {
|
} else {
|
||||||
SfxEvent::Glide
|
SfxEvent::Glide
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(CharacterState::Idle(_), SfxEvent::Glide) => SfxEvent::GliderClose,
|
|
||||||
_ => SfxEvent::Idle,
|
_ => SfxEvent::Idle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user