mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Removed mutable pos/vel/ori writes from character state system. Added a movementstate component.
This commit is contained in:
parent
cead27989b
commit
7c5917e9a9
@ -40,6 +40,7 @@ use common::{
|
|||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
recipe::{ComponentRecipeBook, RecipeBook},
|
recipe::{ComponentRecipeBook, RecipeBook},
|
||||||
resources::{GameMode, PlayerEntity, TimeOfDay},
|
resources::{GameMode, PlayerEntity, TimeOfDay},
|
||||||
|
slowjob::SlowJobPool,
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
terrain::{
|
terrain::{
|
||||||
block::Block, map::MapConfig, neighbors, site::DungeonKindMeta, BiomeKind, SiteKindMeta,
|
block::Block, map::MapConfig, neighbors, site::DungeonKindMeta, BiomeKind, SiteKindMeta,
|
||||||
@ -383,6 +384,10 @@ impl Client {
|
|||||||
*state.ecs_mut().write_resource() = PlayerEntity(Some(entity));
|
*state.ecs_mut().write_resource() = PlayerEntity(Some(entity));
|
||||||
state.ecs_mut().insert(material_stats);
|
state.ecs_mut().insert(material_stats);
|
||||||
state.ecs_mut().insert(ability_map);
|
state.ecs_mut().insert(ability_map);
|
||||||
|
state
|
||||||
|
.ecs_mut()
|
||||||
|
.write_resource::<SlowJobPool>()
|
||||||
|
.configure("CHUNK_DROP", |_n| 1);
|
||||||
|
|
||||||
let map_size = map_size_lg.chunks();
|
let map_size = map_size_lg.chunks();
|
||||||
let max_height = world_map.max_height;
|
let max_height = world_map.max_height;
|
||||||
|
@ -53,13 +53,14 @@ macro_rules! synced_components {
|
|||||||
// remove it from that and then see if it's used for anything else and try to move
|
// remove it from that and then see if it's used for anything else and try to move
|
||||||
// to only being synced for the client's entity.
|
// to only being synced for the client's entity.
|
||||||
skill_set: SkillSet,
|
skill_set: SkillSet,
|
||||||
|
loot_owner: LootOwner,
|
||||||
|
|
||||||
// Synced to the client only for its own entity
|
// Synced to the client only for its own entity
|
||||||
|
|
||||||
combo: Combo,
|
combo: Combo,
|
||||||
active_abilities: ActiveAbilities,
|
active_abilities: ActiveAbilities,
|
||||||
can_build: CanBuild,
|
can_build: CanBuild,
|
||||||
loot_owner: LootOwner,
|
movement_state: MovementState,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -215,6 +216,10 @@ impl NetSync for SkillSet {
|
|||||||
const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
|
const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NetSync for LootOwner {
|
||||||
|
const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
|
||||||
|
}
|
||||||
|
|
||||||
// These are synced only from the client's own entity.
|
// These are synced only from the client's own entity.
|
||||||
|
|
||||||
impl NetSync for Combo {
|
impl NetSync for Combo {
|
||||||
@ -229,6 +234,6 @@ impl NetSync for CanBuild {
|
|||||||
const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
|
const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetSync for LootOwner {
|
impl NetSync for MovementState {
|
||||||
const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
|
const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ impl CharacterAbility {
|
|||||||
update.energy.current() >= *energy_cost
|
update.energy.current() >= *energy_cost
|
||||||
},
|
},
|
||||||
CharacterAbility::LeapMelee { energy_cost, .. } => {
|
CharacterAbility::LeapMelee { energy_cost, .. } => {
|
||||||
update.vel.0.z >= 0.0 && update.energy.try_change_by(-*energy_cost).is_ok()
|
data.vel.0.z >= 0.0 && update.energy.try_change_by(-*energy_cost).is_ok()
|
||||||
},
|
},
|
||||||
CharacterAbility::BasicAura {
|
CharacterAbility::BasicAura {
|
||||||
energy_cost,
|
energy_cost,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
inventory::item::armor::Friction, item::ConsumableKind, ControlAction, Density, Energy,
|
inventory::item::armor::Friction, item::ConsumableKind, ControlAction, Density, Energy,
|
||||||
InputAttr, InputKind, Ori, Pos, Vel,
|
InputAttr, InputKind, MovementState,
|
||||||
},
|
},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
states::{
|
states::{
|
||||||
@ -19,9 +19,7 @@ use strum::Display;
|
|||||||
/// Data returned from character behavior fn's to Character Behavior System.
|
/// Data returned from character behavior fn's to Character Behavior System.
|
||||||
pub struct StateUpdate {
|
pub struct StateUpdate {
|
||||||
pub character: CharacterState,
|
pub character: CharacterState,
|
||||||
pub pos: Pos,
|
pub movement: MovementState,
|
||||||
pub vel: Vel,
|
|
||||||
pub ori: Ori,
|
|
||||||
pub density: Density,
|
pub density: Density,
|
||||||
pub energy: Energy,
|
pub energy: Energy,
|
||||||
pub swap_equipped_weapons: bool,
|
pub swap_equipped_weapons: bool,
|
||||||
@ -48,9 +46,7 @@ impl<'a> OutputEvents<'a> {
|
|||||||
impl From<&JoinData<'_>> for StateUpdate {
|
impl From<&JoinData<'_>> for StateUpdate {
|
||||||
fn from(data: &JoinData) -> Self {
|
fn from(data: &JoinData) -> Self {
|
||||||
StateUpdate {
|
StateUpdate {
|
||||||
pos: *data.pos,
|
movement: MovementState::default(),
|
||||||
vel: *data.vel,
|
|
||||||
ori: *data.ori,
|
|
||||||
density: *data.density,
|
density: *data.density,
|
||||||
energy: *data.energy,
|
energy: *data.energy,
|
||||||
swap_equipped_weapons: false,
|
swap_equipped_weapons: false,
|
||||||
|
@ -32,6 +32,7 @@ pub mod invite;
|
|||||||
pub mod loot_owner;
|
pub mod loot_owner;
|
||||||
#[cfg(not(target_arch = "wasm32"))] pub mod melee;
|
#[cfg(not(target_arch = "wasm32"))] pub mod melee;
|
||||||
#[cfg(not(target_arch = "wasm32"))] mod misc;
|
#[cfg(not(target_arch = "wasm32"))] mod misc;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))] mod movement;
|
||||||
#[cfg(not(target_arch = "wasm32"))] pub mod ori;
|
#[cfg(not(target_arch = "wasm32"))] pub mod ori;
|
||||||
#[cfg(not(target_arch = "wasm32"))] pub mod pet;
|
#[cfg(not(target_arch = "wasm32"))] pub mod pet;
|
||||||
#[cfg(not(target_arch = "wasm32"))] mod phys;
|
#[cfg(not(target_arch = "wasm32"))] mod phys;
|
||||||
@ -95,6 +96,7 @@ pub use self::{
|
|||||||
loot_owner::LootOwner,
|
loot_owner::LootOwner,
|
||||||
melee::{Melee, MeleeConstructor},
|
melee::{Melee, MeleeConstructor},
|
||||||
misc::Object,
|
misc::Object,
|
||||||
|
movement::{MovementKind, MovementState, OriUpdate},
|
||||||
ori::Ori,
|
ori::Ori,
|
||||||
pet::Pet,
|
pet::Pet,
|
||||||
phys::{
|
phys::{
|
||||||
|
140
common/src/comp/movement.rs
Normal file
140
common/src/comp/movement.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use crate::{
|
||||||
|
comp::{Ori, Pos, Vel},
|
||||||
|
consts::GRAVITY,
|
||||||
|
resources::DeltaTime,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use std::ops::Mul;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct MovementState {
|
||||||
|
kind: MovementKind,
|
||||||
|
ori: OriUpdate,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum MovementKind {
|
||||||
|
Stationary,
|
||||||
|
SlowFall {
|
||||||
|
lift: f32,
|
||||||
|
},
|
||||||
|
Flight {
|
||||||
|
lift: f32,
|
||||||
|
dir: Vec2<f32>,
|
||||||
|
accel: f32,
|
||||||
|
},
|
||||||
|
Swim {
|
||||||
|
dir: Vec3<f32>,
|
||||||
|
accel: f32,
|
||||||
|
},
|
||||||
|
Leap {
|
||||||
|
dir: Vec2<f32>,
|
||||||
|
vertical: f32,
|
||||||
|
forward: f32,
|
||||||
|
progress: f32,
|
||||||
|
},
|
||||||
|
Ground {
|
||||||
|
dir: Vec2<f32>,
|
||||||
|
accel: f32,
|
||||||
|
},
|
||||||
|
Climb {
|
||||||
|
dir: Vec3<f32>,
|
||||||
|
accel: f32,
|
||||||
|
},
|
||||||
|
Teleport {
|
||||||
|
pos: Vec3<f32>,
|
||||||
|
},
|
||||||
|
Boost {
|
||||||
|
dir: Vec3<f32>,
|
||||||
|
accel: f32,
|
||||||
|
},
|
||||||
|
ChangeSpeed {
|
||||||
|
speed: f32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum OriUpdate {
|
||||||
|
New(Ori),
|
||||||
|
Stationary,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MovementState {
|
||||||
|
pub fn with_movement(mut self, kind: MovementKind) -> Self {
|
||||||
|
self.kind = kind;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_ori_update(mut self, ori: OriUpdate) -> Self {
|
||||||
|
self.ori = ori;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_movement(&self, dt: &DeltaTime, pos: &mut Pos, vel: &mut Vel, ori: &mut Ori) {
|
||||||
|
match self.kind {
|
||||||
|
MovementKind::Stationary => {},
|
||||||
|
MovementKind::SlowFall { lift } => {
|
||||||
|
vel.0.z += dt.0 * lift;
|
||||||
|
},
|
||||||
|
MovementKind::Flight { lift, dir, accel } => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
vel.0.z += dt.0 * lift;
|
||||||
|
vel.0 += dir * accel * dt.0;
|
||||||
|
},
|
||||||
|
MovementKind::Swim { dir, accel } => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
vel.0 += dir * accel * dt.0;
|
||||||
|
},
|
||||||
|
MovementKind::Leap {
|
||||||
|
dir,
|
||||||
|
vertical,
|
||||||
|
forward,
|
||||||
|
progress,
|
||||||
|
} => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
let progress = progress.clamp(0.0, 1.0);
|
||||||
|
// TODO: Make this += instead of =, will require changing magnitude of strengths
|
||||||
|
// probably, and potentially other behavior too Multiplication
|
||||||
|
// by 2 to make `progress` "average" 1.0
|
||||||
|
vel.0 = dir.mul(forward).with_z(vertical * progress * 2.0);
|
||||||
|
},
|
||||||
|
MovementKind::Ground { dir, accel } => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
vel.0 += dir * accel * dt.0;
|
||||||
|
},
|
||||||
|
MovementKind::Climb { dir, accel } => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
vel.0.z += GRAVITY * dt.0;
|
||||||
|
vel.0 += dir * accel * dt.0;
|
||||||
|
},
|
||||||
|
MovementKind::Teleport { pos: new_pos } => pos.0 = new_pos,
|
||||||
|
MovementKind::Boost { dir, accel } => {
|
||||||
|
let dir = dir.try_normalized().unwrap_or_default();
|
||||||
|
vel.0 += dir * accel * dt.0;
|
||||||
|
},
|
||||||
|
MovementKind::ChangeSpeed { speed } => {
|
||||||
|
vel.0 = vel.0.try_normalized().unwrap_or_default() * speed;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.ori {
|
||||||
|
OriUpdate::Stationary => {},
|
||||||
|
OriUpdate::New(new_ori) => *ori = new_ori,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MovementState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
kind: MovementKind::Stationary,
|
||||||
|
ori: OriUpdate::Stationary,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for MovementState {
|
||||||
|
type Storage = DerefFlaggedStorage<Self>;
|
||||||
|
}
|
@ -157,8 +157,8 @@ impl CharacterBehavior for Data {
|
|||||||
let pitch = xy_dir.rotation_between(look_dir);
|
let pitch = xy_dir.rotation_between(look_dir);
|
||||||
|
|
||||||
Ori::from(Vec3::new(
|
Ori::from(Vec3::new(
|
||||||
update.ori.look_vec().x,
|
data.ori.look_vec().x,
|
||||||
update.ori.look_vec().y,
|
data.ori.look_vec().y,
|
||||||
0.0,
|
0.0,
|
||||||
))
|
))
|
||||||
.prerotated(pitch)
|
.prerotated(pitch)
|
||||||
@ -169,7 +169,7 @@ impl CharacterBehavior for Data {
|
|||||||
let body_offsets = beam_offsets(
|
let body_offsets = beam_offsets(
|
||||||
data.body,
|
data.body,
|
||||||
data.inputs.look_dir,
|
data.inputs.look_dir,
|
||||||
update.ori.look_vec(),
|
data.ori.look_vec(),
|
||||||
rel_vel,
|
rel_vel,
|
||||||
data.physics.on_ground,
|
data.physics.on_ground,
|
||||||
);
|
);
|
||||||
|
@ -88,7 +88,7 @@ impl CharacterBehavior for Data {
|
|||||||
// Shoots all projectiles simultaneously
|
// Shoots all projectiles simultaneously
|
||||||
for i in 0..self.static_data.num_projectiles {
|
for i in 0..self.static_data.num_projectiles {
|
||||||
// Gets offsets
|
// Gets offsets
|
||||||
let body_offsets = data.body.projectile_offsets(update.ori.look_vec());
|
let body_offsets = data.body.projectile_offsets(data.ori.look_vec());
|
||||||
let pos = Pos(data.pos.0 + body_offsets);
|
let pos = Pos(data.pos.0 + body_offsets);
|
||||||
// Adds a slight spread to the projectiles. First projectile has no spread,
|
// Adds a slight spread to the projectiles. First projectile has no spread,
|
||||||
// and spread increases linearly with number of projectiles created.
|
// and spread increases linearly with number of projectiles created.
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
self, character_state::OutputEvents, item::MaterialStatManifest, ActiveAbilities, Beam,
|
self, character_state::OutputEvents, item::MaterialStatManifest, ActiveAbilities, Beam,
|
||||||
Body, CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy,
|
Body, CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy,
|
||||||
Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState,
|
Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState,
|
||||||
Pos, SkillSet, StateUpdate, Stats, Vel,
|
Pos, SkillSet, StateUpdate, Stats, Vel, MovementState,
|
||||||
},
|
},
|
||||||
link::Is,
|
link::Is,
|
||||||
mounting::Rider,
|
mounting::Rider,
|
||||||
@ -118,6 +118,7 @@ pub struct JoinData<'a> {
|
|||||||
pub pos: &'a Pos,
|
pub pos: &'a Pos,
|
||||||
pub vel: &'a Vel,
|
pub vel: &'a Vel,
|
||||||
pub ori: &'a Ori,
|
pub ori: &'a Ori,
|
||||||
|
pub movement: &'a MovementState,
|
||||||
pub mass: &'a Mass,
|
pub mass: &'a Mass,
|
||||||
pub density: &'a Density,
|
pub density: &'a Density,
|
||||||
pub dt: &'a DeltaTime,
|
pub dt: &'a DeltaTime,
|
||||||
@ -144,9 +145,10 @@ pub struct JoinStruct<'a> {
|
|||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub uid: &'a Uid,
|
pub uid: &'a Uid,
|
||||||
pub char_state: FlaggedAccessMut<'a, &'a mut CharacterState, CharacterState>,
|
pub char_state: FlaggedAccessMut<'a, &'a mut CharacterState, CharacterState>,
|
||||||
pub pos: &'a mut Pos,
|
pub pos: &'a Pos,
|
||||||
pub vel: &'a mut Vel,
|
pub vel: &'a Vel,
|
||||||
pub ori: &'a mut Ori,
|
pub ori: &'a Ori,
|
||||||
|
pub movement: &'a mut MovementState,
|
||||||
pub mass: &'a Mass,
|
pub mass: &'a Mass,
|
||||||
pub density: FlaggedAccessMut<'a, &'a mut Density, Density>,
|
pub density: FlaggedAccessMut<'a, &'a mut Density, Density>,
|
||||||
pub energy: FlaggedAccessMut<'a, &'a mut Energy, Energy>,
|
pub energy: FlaggedAccessMut<'a, &'a mut Energy, Energy>,
|
||||||
@ -180,6 +182,7 @@ impl<'a> JoinData<'a> {
|
|||||||
pos: j.pos,
|
pos: j.pos,
|
||||||
vel: j.vel,
|
vel: j.vel,
|
||||||
ori: j.ori,
|
ori: j.ori,
|
||||||
|
movement: j.movement,
|
||||||
mass: j.mass,
|
mass: j.mass,
|
||||||
density: &j.density,
|
density: &j.density,
|
||||||
energy: &j.energy,
|
energy: &j.energy,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{character_state::OutputEvents, CharacterState, StateUpdate},
|
comp::{character_state::OutputEvents, CharacterState, StateUpdate, MovementKind},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
@ -59,9 +59,10 @@ impl CharacterBehavior for Data {
|
|||||||
max_range: Some(self.static_data.max_range),
|
max_range: Some(self.static_data.max_range),
|
||||||
});
|
});
|
||||||
} else if let Some(pos) = input_attr.select_pos {
|
} else if let Some(pos) = input_attr.select_pos {
|
||||||
update.pos.0 = pos;
|
update.movement = update.movement.with_movement(MovementKind::Teleport { pos });
|
||||||
} else {
|
} else {
|
||||||
update.pos.0 += *data.inputs.look_dir * 25.0;
|
let pos = data.pos.0 + *data.inputs.look_dir * 25.0;
|
||||||
|
update.movement = update.movement.with_movement(MovementKind::Teleport { pos });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Transitions to recover section of stage
|
// Transitions to recover section of stage
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{character_state::OutputEvents, CharacterState, StateUpdate},
|
comp::{character_state::OutputEvents, CharacterState, StateUpdate, MovementKind},
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
utils::*,
|
utils::*,
|
||||||
@ -8,6 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -36,11 +37,12 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
if self.timer < self.static_data.movement_duration {
|
if self.timer < self.static_data.movement_duration {
|
||||||
// Movement
|
// Movement
|
||||||
if self.static_data.only_up {
|
let dir = if self.static_data.only_up {
|
||||||
update.vel.0.z += self.static_data.speed * data.dt.0;
|
Vec3::unit_z()
|
||||||
} else {
|
} else {
|
||||||
update.vel.0 += *data.inputs.look_dir * self.static_data.speed * data.dt.0;
|
*data.inputs.look_dir
|
||||||
}
|
};
|
||||||
|
update.movement = update.movement.with_movement(MovementKind::Boost { dir, accel: self.static_data.speed });
|
||||||
update.character = CharacterState::Boost(Data {
|
update.character = CharacterState::Boost(Data {
|
||||||
timer: tick_attack_or_default(data, self.timer, None),
|
timer: tick_attack_or_default(data, self.timer, None),
|
||||||
..*self
|
..*self
|
||||||
@ -50,12 +52,8 @@ impl CharacterBehavior for Data {
|
|||||||
if input_is_pressed(data, self.static_data.ability_info.input) {
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
reset_state(self, data, output_events, &mut update);
|
reset_state(self, data, output_events, &mut update);
|
||||||
} else {
|
} else {
|
||||||
update.vel.0 = update.vel.0.try_normalized().unwrap_or_default()
|
let speed = data.vel.0.magnitude().min(self.static_data.max_exit_velocity);
|
||||||
* update
|
update.movement = update.movement.with_movement(MovementKind::ChangeSpeed { speed });
|
||||||
.vel
|
|
||||||
.0
|
|
||||||
.magnitude()
|
|
||||||
.min(self.static_data.max_exit_velocity);
|
|
||||||
update.character = CharacterState::Wielding(wielding::Data { is_sneaking: false });
|
update.character = CharacterState::Wielding(wielding::Data { is_sneaking: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ impl CharacterBehavior for Data {
|
|||||||
get_crit_data(data, self.static_data.ability_info);
|
get_crit_data(data, self.static_data.ability_info);
|
||||||
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
||||||
// Gets offsets
|
// Gets offsets
|
||||||
let body_offsets = data.body.projectile_offsets(update.ori.look_vec());
|
let body_offsets = data.body.projectile_offsets(data.ori.look_vec());
|
||||||
let pos = Pos(data.pos.0 + body_offsets);
|
let pos = Pos(data.pos.0 + body_offsets);
|
||||||
let projectile = arrow.create_projectile(
|
let projectile = arrow.create_projectile(
|
||||||
Some(*data.uid),
|
Some(*data.uid),
|
||||||
|
@ -2,9 +2,8 @@ use crate::{
|
|||||||
comp::{
|
comp::{
|
||||||
character_state::OutputEvents,
|
character_state::OutputEvents,
|
||||||
skills::{ClimbSkill::*, Skill, SKILL_MODIFIERS},
|
skills::{ClimbSkill::*, Skill, SKILL_MODIFIERS},
|
||||||
CharacterState, Climb, InputKind, Ori, StateUpdate,
|
CharacterState, Climb, InputKind, Ori, StateUpdate, MovementKind, OriUpdate,
|
||||||
},
|
},
|
||||||
consts::GRAVITY,
|
|
||||||
event::LocalEvent,
|
event::LocalEvent,
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
@ -82,14 +81,6 @@ impl CharacterBehavior for Data {
|
|||||||
update.character = CharacterState::Idle(idle::Data::default());
|
update.character = CharacterState::Idle(idle::Data::default());
|
||||||
return update;
|
return update;
|
||||||
};
|
};
|
||||||
// Move player
|
|
||||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
|
||||||
* data.inputs.move_dir
|
|
||||||
* if update.vel.0.magnitude_squared() < self.static_data.movement_speed.powi(2) {
|
|
||||||
self.static_data.movement_speed.powi(2)
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Expend energy if climbing
|
// Expend energy if climbing
|
||||||
let energy_use = match climb {
|
let energy_use = match climb {
|
||||||
@ -107,28 +98,33 @@ impl CharacterBehavior for Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set orientation direction based on wall direction
|
// Set orientation direction based on wall direction
|
||||||
if let Some(ori_dir) = Dir::from_unnormalized(Vec2::from(wall_dir).into()) {
|
let new_ori = if let Some(ori_dir) = Dir::from_unnormalized(Vec2::from(wall_dir).into()) {
|
||||||
// Smooth orientation
|
// Smooth orientation
|
||||||
update.ori = update.ori.slerped_towards(
|
data.ori.slerped_towards(
|
||||||
Ori::from(ori_dir),
|
Ori::from(ori_dir),
|
||||||
if data.physics.on_ground.is_some() {
|
if data.physics.on_ground.is_some() {
|
||||||
9.0
|
9.0
|
||||||
} else {
|
} else {
|
||||||
2.0
|
2.0
|
||||||
} * data.dt.0,
|
} * data.dt.0,
|
||||||
);
|
)
|
||||||
|
} else {
|
||||||
|
*data.ori
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply Vertical Climbing Movement
|
// Apply Vertical Climbing Movement
|
||||||
match climb {
|
let dir = data.inputs.move_dir.with_z(match climb {
|
||||||
Climb::Down => {
|
Climb::Down => -1.0,
|
||||||
update.vel.0.z += data.dt.0 * (GRAVITY - self.static_data.movement_speed.powi(2))
|
Climb::Up => 1.0,
|
||||||
},
|
Climb::Hold => 0.0,
|
||||||
Climb::Up => {
|
});
|
||||||
update.vel.0.z += data.dt.0 * (GRAVITY + self.static_data.movement_speed.powi(2))
|
let accel = if data.vel.0.magnitude_squared() < self.static_data.movement_speed.powi(2) {
|
||||||
},
|
self.static_data.movement_speed.powi(2)
|
||||||
Climb::Hold => update.vel.0.z += data.dt.0 * GRAVITY,
|
} else {
|
||||||
}
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
update.movement = update.movement.with_movement(MovementKind::Climb { dir, accel }).with_ori_update(OriUpdate::New(new_ori));
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use super::utils::handle_climb;
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
character_state::OutputEvents, fluid_dynamics::angle_of_attack, inventory::slot::EquipSlot,
|
character_state::OutputEvents, fluid_dynamics::angle_of_attack, inventory::slot::EquipSlot,
|
||||||
CharacterState, Ori, StateUpdate, Vel,
|
CharacterState, Ori, StateUpdate, Vel, OriUpdate,
|
||||||
},
|
},
|
||||||
event::LocalEvent,
|
event::LocalEvent,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -144,7 +144,7 @@ impl CharacterBehavior for Data {
|
|||||||
.unwrap_or_else(|| self.ori.slerped_towards(self.ori.uprighted(), slerp_s))
|
.unwrap_or_else(|| self.ori.slerped_towards(self.ori.uprighted(), slerp_s))
|
||||||
};
|
};
|
||||||
|
|
||||||
update.ori = {
|
update.movement = update.movement.with_ori_update(OriUpdate::New({
|
||||||
let slerp_s = {
|
let slerp_s = {
|
||||||
let angle = data.ori.look_dir().angle_between(*data.inputs.look_dir);
|
let angle = data.ori.look_dir().angle_between(*data.inputs.look_dir);
|
||||||
let rate = 0.2 * data.body.base_ori_rate() * PI / angle;
|
let rate = 0.2 * data.body.base_ori_rate() * PI / angle;
|
||||||
@ -183,12 +183,12 @@ impl CharacterBehavior for Data {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
update.ori.slerped_towards(
|
data.ori.slerped_towards(
|
||||||
ori.to_horizontal()
|
ori.to_horizontal()
|
||||||
.prerotated(rot_from_drag * rot_from_accel),
|
.prerotated(rot_from_drag * rot_from_accel),
|
||||||
slerp_s,
|
slerp_s,
|
||||||
)
|
)
|
||||||
};
|
}));
|
||||||
update.character = CharacterState::Glide(Self {
|
update.character = CharacterState::Glide(Self {
|
||||||
ori,
|
ori,
|
||||||
last_vel: *data.vel,
|
last_vel: *data.vel,
|
||||||
|
@ -93,7 +93,7 @@ impl CharacterBehavior for Data {
|
|||||||
get_crit_data(data, self.static_data.ability_info);
|
get_crit_data(data, self.static_data.ability_info);
|
||||||
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
|
||||||
// Gets offsets
|
// Gets offsets
|
||||||
let body_offsets = data.body.projectile_offsets(update.ori.look_vec());
|
let body_offsets = data.body.projectile_offsets(data.ori.look_vec());
|
||||||
let pos = Pos(data.pos.0 + body_offsets);
|
let pos = Pos(data.pos.0 + body_offsets);
|
||||||
let projectile = self.static_data.projectile.create_projectile(
|
let projectile = self.static_data.projectile.create_projectile(
|
||||||
Some(*data.uid),
|
Some(*data.uid),
|
||||||
|
@ -2,7 +2,7 @@ use super::utils::*;
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
character_state::OutputEvents, item::armor::Friction, CharacterState, InventoryAction,
|
character_state::OutputEvents, item::armor::Friction, CharacterState, InventoryAction,
|
||||||
StateUpdate,
|
StateUpdate, MovementKind, OriUpdate,
|
||||||
},
|
},
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
@ -46,7 +46,7 @@ impl CharacterBehavior for Data {
|
|||||||
} else {
|
} else {
|
||||||
let plane_ori = data.inputs.look_dir.xy();
|
let plane_ori = data.inputs.look_dir.xy();
|
||||||
let orthogonal = vek::Vec2::new(plane_ori.y, -plane_ori.x);
|
let orthogonal = vek::Vec2::new(plane_ori.y, -plane_ori.x);
|
||||||
update.ori = vek::Vec3::new(plane_ori.x, plane_ori.y, 0.0).into();
|
let new_ori = vek::Vec3::new(plane_ori.x, plane_ori.y, 0.0).into();
|
||||||
let current_planar_velocity = data.vel.0.xy().magnitude();
|
let current_planar_velocity = data.vel.0.xy().magnitude();
|
||||||
let long_input = data.inputs.move_dir.dot(plane_ori);
|
let long_input = data.inputs.move_dir.dot(plane_ori);
|
||||||
let lat_input = data.inputs.move_dir.dot(orthogonal);
|
let lat_input = data.inputs.move_dir.dot(orthogonal);
|
||||||
@ -79,8 +79,7 @@ impl CharacterBehavior for Data {
|
|||||||
if let CharacterState::Skate(skate_data) = &mut update.character {
|
if let CharacterState::Skate(skate_data) = &mut update.character {
|
||||||
skate_data.turn = orthogonal.dot(data.vel.0.xy());
|
skate_data.turn = orthogonal.dot(data.vel.0.xy());
|
||||||
}
|
}
|
||||||
let delta_vel = acceleration * data.inputs.move_dir;
|
update.movement = update.movement.with_movement(MovementKind::Ground { dir: data.inputs.move_dir, accel: acceleration }).with_ori_update(OriUpdate::New(new_ori));
|
||||||
update.vel.0 += vek::Vec3::new(delta_vel.x, delta_vel.y, 0.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
|
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate, MovementKind},
|
||||||
consts::GRAVITY,
|
consts::GRAVITY,
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
@ -9,7 +9,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::Vec3;
|
|
||||||
|
|
||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -62,8 +61,13 @@ impl CharacterBehavior for Data {
|
|||||||
match self.static_data.movement_behavior {
|
match self.static_data.movement_behavior {
|
||||||
MovementBehavior::ForwardGround | MovementBehavior::Stationary => {},
|
MovementBehavior::ForwardGround | MovementBehavior::Stationary => {},
|
||||||
MovementBehavior::AxeHover => {
|
MovementBehavior::AxeHover => {
|
||||||
let new_vel_z = update.vel.0.z + GRAVITY * data.dt.0 * 0.5;
|
update.movement = update.movement.with_movement(if data.physics.on_ground.is_some() {
|
||||||
update.vel.0 = Vec3::new(0.0, 0.0, new_vel_z) + data.inputs.move_dir * 5.0;
|
// TODO: Just remove axehover entirely with axe rework, it's really janky
|
||||||
|
// TODO: Should 5 even be used here, or should body accel be used? Maybe just call handle_move?
|
||||||
|
MovementKind::Ground { dir: data.inputs.move_dir, accel: 5.0 }
|
||||||
|
} else {
|
||||||
|
MovementKind::SlowFall { lift: GRAVITY * 0.5 }
|
||||||
|
});
|
||||||
},
|
},
|
||||||
MovementBehavior::Walking => {
|
MovementBehavior::Walking => {
|
||||||
handle_move(data, &mut update, 0.2);
|
handle_move(data, &mut update, 0.2);
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
quadruped_low, quadruped_medium, quadruped_small,
|
quadruped_low, quadruped_medium, quadruped_small,
|
||||||
skills::{Skill, SwimSkill, SKILL_MODIFIERS},
|
skills::{Skill, SwimSkill, SKILL_MODIFIERS},
|
||||||
theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind,
|
theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind,
|
||||||
InventoryAction, StateUpdate,
|
InventoryAction, StateUpdate, MovementKind, OriUpdate,
|
||||||
},
|
},
|
||||||
consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE},
|
consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
@ -370,34 +370,34 @@ fn basic_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
|||||||
} * efficiency;
|
} * efficiency;
|
||||||
|
|
||||||
// Should ability to backpedal be separate from ability to strafe?
|
// Should ability to backpedal be separate from ability to strafe?
|
||||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
let dir = if data.body.can_strafe() {
|
||||||
* accel
|
data.inputs.move_dir
|
||||||
* if data.body.can_strafe() {
|
} else {
|
||||||
data.inputs.move_dir
|
Vec2::from(*data.ori)
|
||||||
* if is_strafing(data, update) {
|
};
|
||||||
Lerp::lerp(
|
let accel_mod = if is_strafing(data, update) {
|
||||||
Vec2::from(update.ori)
|
Lerp::lerp(
|
||||||
.try_normalized()
|
Vec2::from(*data.ori)
|
||||||
.unwrap_or_else(Vec2::zero)
|
.try_normalized()
|
||||||
.dot(
|
.unwrap_or_else(Vec2::zero)
|
||||||
data.inputs
|
.dot(
|
||||||
.move_dir
|
data.inputs
|
||||||
.try_normalized()
|
.move_dir
|
||||||
.unwrap_or_else(Vec2::zero),
|
.try_normalized()
|
||||||
)
|
.unwrap_or_else(Vec2::zero),
|
||||||
.add(1.0)
|
)
|
||||||
.div(2.0)
|
.add(1.0)
|
||||||
.max(0.0),
|
.div(2.0)
|
||||||
1.0,
|
.max(0.0),
|
||||||
data.body.reverse_move_factor(),
|
1.0,
|
||||||
)
|
data.body.reverse_move_factor(),
|
||||||
} else {
|
)
|
||||||
1.0
|
} else {
|
||||||
}
|
data.inputs.move_dir.dot(dir).max(0.0)
|
||||||
} else {
|
};
|
||||||
let fw = Vec2::from(update.ori);
|
let accel = accel * accel_mod;
|
||||||
fw * data.inputs.move_dir.dot(fw).max(0.0)
|
|
||||||
};
|
update.movement = update.movement.with_movement(MovementKind::Ground { dir, accel });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles forced movement
|
/// Handles forced movement
|
||||||
@ -413,10 +413,11 @@ pub fn handle_forced_movement(
|
|||||||
// FRIC_GROUND temporarily used to normalize things around expected values
|
// FRIC_GROUND temporarily used to normalize things around expected values
|
||||||
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
|
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
|
||||||
}) {
|
}) {
|
||||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
// TODO: Remove * 2.0 with changes made in sword branch, added as hack for now to keep same behavior
|
||||||
* accel
|
let accel = accel * strength * 2.0;
|
||||||
* (data.inputs.move_dir * 0.5 + Vec2::from(update.ori) * 1.5)
|
// TODO: Remove move_dir portion with changes made in sword branch, added as hack for now to keep same behavior
|
||||||
* strength;
|
let dir = data.inputs.move_dir * 0.5 + Vec2::from(*data.ori) * 1.5;
|
||||||
|
update.movement = update.movement.with_movement(MovementKind::Ground { dir, accel });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ForcedMovement::Leap {
|
ForcedMovement::Leap {
|
||||||
@ -426,26 +427,12 @@ pub fn handle_forced_movement(
|
|||||||
direction,
|
direction,
|
||||||
} => {
|
} => {
|
||||||
let dir = direction.get_2d_dir(data);
|
let dir = direction.get_2d_dir(data);
|
||||||
// Apply jumping force
|
// Control forward movement based on look direction.
|
||||||
update.vel.0 = Vec3::new(
|
// This allows players to stop moving forward when they
|
||||||
dir.x,
|
// look downward at target
|
||||||
dir.y,
|
let forward = forward * (1.0 - data.inputs.look_dir.z.abs());
|
||||||
vertical,
|
|
||||||
)
|
update.movement = update.movement.with_movement(MovementKind::Leap { dir, vertical, forward, progress });
|
||||||
// Multiply decreasing amount linearly over time (with average of 1)
|
|
||||||
* 2.0 * progress
|
|
||||||
// Apply direction
|
|
||||||
+ Vec3::from(dir)
|
|
||||||
// Multiply by forward leap strength
|
|
||||||
* forward
|
|
||||||
// Control forward movement based on look direction.
|
|
||||||
// This allows players to stop moving forward when they
|
|
||||||
// look downward at target
|
|
||||||
* (1.0 - data.inputs.look_dir.z.abs());
|
|
||||||
},
|
|
||||||
ForcedMovement::Hover { move_input } => {
|
|
||||||
update.vel.0 = Vec3::new(data.vel.0.x, data.vel.0.y, 0.0)
|
|
||||||
+ move_input * data.inputs.move_dir.try_normalized().unwrap_or_default();
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,22 +481,24 @@ pub fn handle_orientation(
|
|||||||
}
|
}
|
||||||
* data.dt.0;
|
* data.dt.0;
|
||||||
// very rough guess
|
// very rough guess
|
||||||
let ticks_from_target_guess = ori_absdiff(&update.ori, &target_ori) / half_turns_per_tick;
|
let ticks_from_target_guess = ori_absdiff(data.ori, &target_ori) / half_turns_per_tick;
|
||||||
let instantaneous = ticks_from_target_guess < 1.0;
|
let instantaneous = ticks_from_target_guess < 1.0;
|
||||||
update.ori = if instantaneous {
|
let new_ori = if instantaneous {
|
||||||
target_ori
|
target_ori
|
||||||
} else {
|
} else {
|
||||||
let target_fraction = {
|
let target_fraction = {
|
||||||
// Angle factor used to keep turning rate approximately constant by
|
// Angle factor used to keep turning rate approximately constant by
|
||||||
// counteracting slerp turning more with a larger angle
|
// counteracting slerp turning more with a larger angle
|
||||||
let angle_factor = 2.0 / (1.0 - update.ori.dot(target_ori)).sqrt();
|
let angle_factor = 2.0 / (1.0 - data.ori.dot(target_ori)).sqrt();
|
||||||
|
|
||||||
half_turns_per_tick * angle_factor
|
half_turns_per_tick * angle_factor
|
||||||
};
|
};
|
||||||
update
|
data
|
||||||
.ori
|
.ori
|
||||||
.slerped_towards(target_ori, target_fraction.min(1.0))
|
.slerped_towards(target_ori, target_fraction.min(1.0))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
update.movement = update.movement.with_ori_update(OriUpdate::New(new_ori));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates components to move player as if theyre swimming
|
/// Updates components to move player as if theyre swimming
|
||||||
@ -532,7 +521,7 @@ fn swim_move(
|
|||||||
let dir = if data.body.can_strafe() {
|
let dir = if data.body.can_strafe() {
|
||||||
data.inputs.move_dir
|
data.inputs.move_dir
|
||||||
} else {
|
} else {
|
||||||
let fw = Vec2::from(update.ori);
|
let fw = Vec2::from(*data.ori);
|
||||||
fw * data.inputs.move_dir.dot(fw).max(0.0)
|
fw * data.inputs.move_dir.dot(fw).max(0.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -543,12 +532,9 @@ fn swim_move(
|
|||||||
data.inputs.move_z
|
data.inputs.move_z
|
||||||
};
|
};
|
||||||
|
|
||||||
update.vel.0 += Vec3::broadcast(data.dt.0)
|
let dir = Vec3::new(dir.x, dir.y, move_z);
|
||||||
* Vec3::new(dir.x, dir.y, move_z)
|
let accel = water_accel * (submersion - 0.2).clamp(0.0, 1.0).powi(2);
|
||||||
.try_normalized()
|
update.movement = update.movement.with_movement(MovementKind::Swim { dir, accel });
|
||||||
.unwrap_or_default()
|
|
||||||
* water_accel
|
|
||||||
* (submersion - 0.2).clamp(0.0, 1.0).powi(2);
|
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -575,11 +561,11 @@ pub fn fly_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32)
|
|||||||
handle_orientation(data, update, efficiency, None);
|
handle_orientation(data, update, efficiency, None);
|
||||||
|
|
||||||
// Elevation control
|
// Elevation control
|
||||||
match data.body {
|
let lift = match data.body {
|
||||||
// flappy flappy
|
// flappy flappy
|
||||||
Body::Dragon(_) | Body::BirdLarge(_) | Body::BirdMedium(_) => {
|
Body::Dragon(_) | Body::BirdLarge(_) | Body::BirdMedium(_) => {
|
||||||
let anti_grav = GRAVITY * (1.0 + data.inputs.move_z.min(0.0));
|
let anti_grav = GRAVITY * (1.0 + data.inputs.move_z.min(0.0));
|
||||||
update.vel.0.z += data.dt.0 * (anti_grav + accel * data.inputs.move_z.max(0.0));
|
anti_grav + accel * data.inputs.move_z.max(0.0)
|
||||||
},
|
},
|
||||||
// floaty floaty
|
// floaty floaty
|
||||||
Body::Ship(ship) if ship.can_fly() => {
|
Body::Ship(ship) if ship.can_fly() => {
|
||||||
@ -601,20 +587,22 @@ pub fn fly_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32)
|
|||||||
update.density.0 =
|
update.density.0 =
|
||||||
regulate_density(def_density * 0.5, def_density * 1.5, def_density, 0.5).0;
|
regulate_density(def_density * 0.5, def_density * 1.5, def_density, 0.5).0;
|
||||||
};
|
};
|
||||||
|
// TODO: Make ships actually specify a lift instead of hacking density
|
||||||
|
0.0
|
||||||
},
|
},
|
||||||
// oopsie woopsie
|
// oopsie woopsie
|
||||||
// TODO: refactor to make this state impossible
|
// TODO: refactor to make this state impossible
|
||||||
_ => {},
|
_ => 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
let dir = if data.body.can_strafe() {
|
||||||
* accel
|
data.inputs.move_dir
|
||||||
* if data.body.can_strafe() {
|
} else {
|
||||||
data.inputs.move_dir
|
let fw = Vec2::from(*data.ori);
|
||||||
} else {
|
fw * data.inputs.move_dir.dot(fw).max(0.0)
|
||||||
let fw = Vec2::from(update.ori);
|
};
|
||||||
fw * data.inputs.move_dir.dot(fw).max(0.0)
|
|
||||||
};
|
update.movement = update.movement.with_movement(MovementKind::Flight { lift, dir, accel });
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -1195,9 +1183,6 @@ pub enum ForcedMovement {
|
|||||||
progress: f32,
|
progress: f32,
|
||||||
direction: MovementDirection,
|
direction: MovementDirection,
|
||||||
},
|
},
|
||||||
Hover {
|
|
||||||
move_input: f32,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::utils::*;
|
use super::utils::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
comp::{character_state::OutputEvents, CharacterState, StateUpdate},
|
comp::{character_state::OutputEvents, CharacterState, StateUpdate, MovementKind},
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
idle,
|
idle,
|
||||||
@ -23,12 +23,11 @@ impl CharacterBehavior for Data {
|
|||||||
handle_climb(data, &mut update);
|
handle_climb(data, &mut update);
|
||||||
|
|
||||||
{
|
{
|
||||||
let lift = WALLRUN_ANTIGRAV;
|
let lift = WALLRUN_ANTIGRAV
|
||||||
update.vel.0.z += data.dt.0
|
* (Vec2::<f32>::from(data.vel.0).magnitude() * 0.075)
|
||||||
* lift
|
.min(1.0)
|
||||||
* (Vec2::<f32>::from(update.vel.0).magnitude() * 0.075)
|
.max(0.2);
|
||||||
.min(1.0)
|
update.movement = update.movement.with_movement(MovementKind::SlowFall { lift });
|
||||||
.max(0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fall off wall, hit ground, or enter water
|
// fall off wall, hit ground, or enter water
|
||||||
|
@ -178,6 +178,7 @@ impl State {
|
|||||||
ecs.register::<comp::BeamSegment>();
|
ecs.register::<comp::BeamSegment>();
|
||||||
ecs.register::<comp::Alignment>();
|
ecs.register::<comp::Alignment>();
|
||||||
ecs.register::<comp::LootOwner>();
|
ecs.register::<comp::LootOwner>();
|
||||||
|
ecs.register::<comp::MovementState>();
|
||||||
|
|
||||||
// Register components send from clients -> server
|
// Register components send from clients -> server
|
||||||
ecs.register::<comp::Controller>();
|
ecs.register::<comp::Controller>();
|
||||||
|
@ -7,8 +7,8 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
self, character_state::OutputEvents, inventory::item::MaterialStatManifest,
|
self, character_state::OutputEvents, inventory::item::MaterialStatManifest,
|
||||||
ActiveAbilities, Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health,
|
ActiveAbilities, Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health,
|
||||||
Inventory, InventoryManip, Mass, Melee, Ori, PhysicsState, Poise, Pos, SkillSet,
|
Inventory, InventoryManip, Mass, Melee, MovementState, Ori, PhysicsState, Poise, Pos,
|
||||||
StateUpdate, Stats, Vel,
|
SkillSet, StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
link::Is,
|
link::Is,
|
||||||
@ -48,6 +48,9 @@ pub struct ReadData<'a> {
|
|||||||
alignments: ReadStorage<'a, comp::Alignment>,
|
alignments: ReadStorage<'a, comp::Alignment>,
|
||||||
terrain: ReadExpect<'a, TerrainGrid>,
|
terrain: ReadExpect<'a, TerrainGrid>,
|
||||||
inventories: ReadStorage<'a, Inventory>,
|
inventories: ReadStorage<'a, Inventory>,
|
||||||
|
positions: ReadStorage<'a, Pos>,
|
||||||
|
velocities: ReadStorage<'a, Vel>,
|
||||||
|
orientations: ReadStorage<'a, Ori>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Character Behavior System
|
/// ## Character Behavior System
|
||||||
@ -60,13 +63,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
type SystemData = (
|
type SystemData = (
|
||||||
ReadData<'a>,
|
ReadData<'a>,
|
||||||
WriteStorage<'a, CharacterState>,
|
WriteStorage<'a, CharacterState>,
|
||||||
WriteStorage<'a, Pos>,
|
|
||||||
WriteStorage<'a, Vel>,
|
|
||||||
WriteStorage<'a, Ori>,
|
|
||||||
WriteStorage<'a, Density>,
|
WriteStorage<'a, Density>,
|
||||||
WriteStorage<'a, Energy>,
|
WriteStorage<'a, Energy>,
|
||||||
WriteStorage<'a, Controller>,
|
WriteStorage<'a, Controller>,
|
||||||
WriteStorage<'a, Poise>,
|
WriteStorage<'a, Poise>,
|
||||||
|
WriteStorage<'a, MovementState>,
|
||||||
Read<'a, EventBus<Outcome>>,
|
Read<'a, EventBus<Outcome>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -79,13 +80,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
(
|
(
|
||||||
read_data,
|
read_data,
|
||||||
mut character_states,
|
mut character_states,
|
||||||
mut positions,
|
|
||||||
mut velocities,
|
|
||||||
mut orientations,
|
|
||||||
mut densities,
|
mut densities,
|
||||||
mut energies,
|
mut energies,
|
||||||
mut controllers,
|
mut controllers,
|
||||||
mut poises,
|
mut poises,
|
||||||
|
mut movements,
|
||||||
outcomes,
|
outcomes,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
@ -101,9 +100,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
entity,
|
entity,
|
||||||
uid,
|
uid,
|
||||||
mut char_state,
|
mut char_state,
|
||||||
pos,
|
(pos, vel, ori, mut movement),
|
||||||
vel,
|
|
||||||
ori,
|
|
||||||
mass,
|
mass,
|
||||||
density,
|
density,
|
||||||
energy,
|
energy,
|
||||||
@ -118,9 +115,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
&read_data.uids,
|
&read_data.uids,
|
||||||
&mut character_states,
|
&mut character_states,
|
||||||
&mut positions,
|
(
|
||||||
&mut velocities,
|
&read_data.positions,
|
||||||
&mut orientations,
|
&read_data.velocities,
|
||||||
|
&read_data.orientations,
|
||||||
|
&mut movements,
|
||||||
|
),
|
||||||
&read_data.masses,
|
&read_data.masses,
|
||||||
&mut densities,
|
&mut densities,
|
||||||
&mut energies,
|
&mut energies,
|
||||||
@ -179,6 +179,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos,
|
pos,
|
||||||
vel,
|
vel,
|
||||||
ori,
|
ori,
|
||||||
|
movement: &mut movement,
|
||||||
mass,
|
mass,
|
||||||
density,
|
density,
|
||||||
energy,
|
energy,
|
||||||
@ -257,9 +258,9 @@ impl Sys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// These components use a different type of change detection.
|
// These components use a different type of change detection.
|
||||||
*join.pos = state_update.pos;
|
// TODO: Would the above comment also apply to movement state? It used to apply
|
||||||
*join.vel = state_update.vel;
|
// to pos/vel/ori
|
||||||
*join.ori = state_update.ori;
|
*join.movement = state_update.movement;
|
||||||
|
|
||||||
join.controller
|
join.controller
|
||||||
.queued_inputs
|
.queued_inputs
|
||||||
|
@ -3,8 +3,8 @@ use common::{
|
|||||||
body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST},
|
body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST},
|
||||||
fluid_dynamics::{Fluid, LiquidKind, Wings},
|
fluid_dynamics::{Fluid, LiquidKind, Wings},
|
||||||
inventory::item::armor::Friction,
|
inventory::item::armor::Friction,
|
||||||
Body, CharacterState, Collider, Density, Immovable, Mass, Ori, PhysicsState, Pos,
|
Body, CharacterState, Collider, Density, Immovable, Mass, MovementState, Ori, PhysicsState,
|
||||||
PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Stats, Sticky, Vel,
|
Pos, PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Stats, Sticky, Vel,
|
||||||
},
|
},
|
||||||
consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY},
|
consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
@ -124,6 +124,7 @@ pub struct PhysicsRead<'a> {
|
|||||||
densities: ReadStorage<'a, Density>,
|
densities: ReadStorage<'a, Density>,
|
||||||
stats: ReadStorage<'a, Stats>,
|
stats: ReadStorage<'a, Stats>,
|
||||||
outcomes: Read<'a, EventBus<Outcome>>,
|
outcomes: Read<'a, EventBus<Outcome>>,
|
||||||
|
movements: ReadStorage<'a, MovementState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SystemData)]
|
#[derive(SystemData)]
|
||||||
@ -1357,6 +1358,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
ref mut write,
|
ref mut write,
|
||||||
} = physics_data;
|
} = physics_data;
|
||||||
|
|
||||||
|
(
|
||||||
|
&read.movements,
|
||||||
|
&mut write.positions,
|
||||||
|
&mut write.velocities,
|
||||||
|
&mut write.orientations,
|
||||||
|
)
|
||||||
|
.par_join()
|
||||||
|
.for_each(|(movement, pos, vel, ori)| {
|
||||||
|
movement.handle_movement(&read.dt, pos, vel, ori);
|
||||||
|
});
|
||||||
|
|
||||||
let (spatial_grid, voxel_collider_spatial_grid) = rayon::join(
|
let (spatial_grid, voxel_collider_spatial_grid) = rayon::join(
|
||||||
|| {
|
|| {
|
||||||
let (spatial_grid, ()) = rayon::join(
|
let (spatial_grid, ()) = rayon::join(
|
||||||
|
@ -272,6 +272,7 @@ impl StateExt for State {
|
|||||||
.with(comp::Buffs::default())
|
.with(comp::Buffs::default())
|
||||||
.with(comp::Combo::default())
|
.with(comp::Combo::default())
|
||||||
.with(comp::Auras::default())
|
.with(comp::Auras::default())
|
||||||
|
.with(comp::MovementState::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 {
|
||||||
@ -330,7 +331,8 @@ impl StateExt for State {
|
|||||||
.with(comp::Stats::new("Airship".to_string()))
|
.with(comp::Stats::new("Airship".to_string()))
|
||||||
.with(comp::SkillSet::default())
|
.with(comp::SkillSet::default())
|
||||||
.with(comp::ActiveAbilities::default())
|
.with(comp::ActiveAbilities::default())
|
||||||
.with(comp::Combo::default());
|
.with(comp::Combo::default())
|
||||||
|
.with(comp::MovementState::default());
|
||||||
|
|
||||||
if mountable {
|
if mountable {
|
||||||
// TODO: Re-add mounting check
|
// TODO: Re-add mounting check
|
||||||
@ -535,6 +537,7 @@ impl StateExt for State {
|
|||||||
self.write_component_ignore_entity_dead(entity, comp::Buffs::default());
|
self.write_component_ignore_entity_dead(entity, comp::Buffs::default());
|
||||||
self.write_component_ignore_entity_dead(entity, comp::Auras::default());
|
self.write_component_ignore_entity_dead(entity, comp::Auras::default());
|
||||||
self.write_component_ignore_entity_dead(entity, comp::Combo::default());
|
self.write_component_ignore_entity_dead(entity, comp::Combo::default());
|
||||||
|
self.write_component_ignore_entity_dead(entity, comp::MovementState::default());
|
||||||
|
|
||||||
// Make sure physics components are updated
|
// Make sure physics components are updated
|
||||||
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate::forced());
|
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate::forced());
|
||||||
|
Loading…
Reference in New Issue
Block a user