mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Remove write to Body from Buff.
Also fix tests and add an inner PhysicsState type that is Copy, to make it easier to facilitate reading Last<PhysicsState> and read deltas.
This commit is contained in:
parent
8383a72818
commit
338b377ef4
@ -655,7 +655,7 @@ impl CharacterAbility {
|
||||
pub fn requirements_paid(&self, data: &JoinData, update: &mut StateUpdate) -> bool {
|
||||
match self {
|
||||
CharacterAbility::Roll { energy_cost, .. } => {
|
||||
data.physics.on_ground.is_some()
|
||||
data.physics.state.on_ground.is_some()
|
||||
&& data.inputs.move_dir.magnitude_squared() > 0.25
|
||||
&& update.energy.try_change_by(-*energy_cost).is_ok()
|
||||
},
|
||||
|
@ -100,8 +100,8 @@ pub use self::{
|
||||
ori::Ori,
|
||||
pet::Pet,
|
||||
phys::{
|
||||
Collider, Density, ForceUpdate, Immovable, Mass, PhysicsState, Pos, PosVelOriDefer,
|
||||
PreviousPhysCache, Scale, Sticky, Vel,
|
||||
Collider, Density, ForceUpdate, Immovable, Mass, PhysicsState, PhysicsStateFast, Pos,
|
||||
PosVelOriDefer, PreviousPhysCache, Scale, Sticky, Vel,
|
||||
},
|
||||
player::DisconnectReason,
|
||||
player::{AliasError, Player, MAX_ALIAS_LEN},
|
||||
|
@ -170,13 +170,13 @@ impl Component for Immovable {
|
||||
type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
|
||||
}
|
||||
|
||||
// PhysicsState
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PhysicsState {
|
||||
/// Cheaply copyable components of PhysicsState used for most delta
|
||||
/// computations.
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PhysicsStateFast {
|
||||
pub on_ground: Option<Block>,
|
||||
pub on_ceiling: bool,
|
||||
pub on_wall: Option<Vec3<f32>>,
|
||||
pub touch_entities: HashSet<Uid>,
|
||||
pub in_fluid: Option<Fluid>,
|
||||
pub ground_vel: Vec3<f32>,
|
||||
pub footwear: Friction,
|
||||
@ -184,6 +184,13 @@ pub struct PhysicsState {
|
||||
pub skating_active: bool,
|
||||
}
|
||||
|
||||
// PhysicsState
|
||||
#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PhysicsState {
|
||||
pub state: PhysicsStateFast,
|
||||
pub touch_entities: HashSet<Uid>,
|
||||
}
|
||||
|
||||
impl PhysicsState {
|
||||
pub fn reset(&mut self) {
|
||||
// Avoid allocation overhead!
|
||||
@ -191,12 +198,17 @@ impl PhysicsState {
|
||||
touch_entities.clear();
|
||||
*self = Self {
|
||||
touch_entities,
|
||||
ground_vel: self.ground_vel, /* Preserved, since it's the velocity of the last
|
||||
* contact point */
|
||||
..Self::default()
|
||||
state: PhysicsStateFast {
|
||||
ground_vel: self.state.ground_vel, /* Preserved, since it's the velocity of the
|
||||
* last
|
||||
* contact point */
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PhysicsStateFast {
|
||||
pub fn on_surface(&self) -> Option<Vec3<f32>> {
|
||||
self.on_ground
|
||||
.map(|_| -Vec3::unit_z())
|
||||
|
@ -226,6 +226,11 @@ pub enum ServerEvent {
|
||||
entity: EcsEntity,
|
||||
update: comp::MapMarkerChange,
|
||||
},
|
||||
/// FIXME: Remove this hack! It is only used for dousing flames.
|
||||
UpdateBody {
|
||||
entity: EcsEntity,
|
||||
new_body: comp::Body,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct EventBus<E> {
|
||||
|
@ -164,14 +164,14 @@ impl CharacterBehavior for Data {
|
||||
.prerotated(pitch)
|
||||
};
|
||||
// Velocity relative to the current ground
|
||||
let rel_vel = data.vel.0 - data.physics.ground_vel;
|
||||
let rel_vel = data.vel.0 - data.physics.state.ground_vel;
|
||||
// Gets offsets
|
||||
let body_offsets = beam_offsets(
|
||||
data.body,
|
||||
data.inputs.look_dir,
|
||||
data.ori.look_vec(),
|
||||
rel_vel,
|
||||
data.physics.on_ground,
|
||||
data.physics.state.on_ground,
|
||||
);
|
||||
let pos = Pos(data.pos.0 + body_offsets);
|
||||
|
||||
|
@ -60,9 +60,9 @@ impl CharacterBehavior for Data {
|
||||
|
||||
// If no wall is in front of character or we stopped climbing;
|
||||
let (wall_dir, climb) = if let (Some(wall_dir), Some(climb), None) = (
|
||||
data.physics.on_wall,
|
||||
data.physics.state.on_wall,
|
||||
data.inputs.climb,
|
||||
data.physics.on_ground,
|
||||
data.physics.state.on_ground,
|
||||
) {
|
||||
(wall_dir, climb)
|
||||
} else {
|
||||
@ -102,7 +102,7 @@ impl CharacterBehavior for Data {
|
||||
// Smooth orientation
|
||||
data.ori.slerped_towards(
|
||||
Ori::from(ori_dir),
|
||||
if data.physics.on_ground.is_some() {
|
||||
if data.physics.state.on_ground.is_some() {
|
||||
9.0
|
||||
} else {
|
||||
2.0
|
||||
|
@ -19,7 +19,7 @@ impl CharacterBehavior for Data {
|
||||
handle_jump(data, output_events, &mut update, 1.0);
|
||||
|
||||
// Try to Fall/Stand up/Move
|
||||
if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
if data.physics.state.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
update.character = CharacterState::Idle(idle::Data::default());
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,11 @@ impl CharacterBehavior for Data {
|
||||
let mut update = StateUpdate::from(data);
|
||||
|
||||
// If player is on ground, end glide
|
||||
if data.physics.on_ground.is_some()
|
||||
&& (data.vel.0 - data.physics.ground_vel).magnitude_squared() < 2_f32.powi(2)
|
||||
if data.physics.state.on_ground.is_some()
|
||||
&& (data.vel.0 - data.physics.state.ground_vel).magnitude_squared() < 2_f32.powi(2)
|
||||
{
|
||||
update.character = CharacterState::GlideWield(glide_wield::Data::from(data));
|
||||
} else if data.physics.in_liquid().is_some()
|
||||
} else if data.physics.state.in_liquid().is_some()
|
||||
|| data
|
||||
.inventory
|
||||
.and_then(|inv| inv.equipped(EquipSlot::Glider))
|
||||
@ -93,6 +93,7 @@ impl CharacterBehavior for Data {
|
||||
} else if !handle_climb(data, &mut update) {
|
||||
let air_flow = data
|
||||
.physics
|
||||
.state
|
||||
.in_fluid
|
||||
.map(|fluid| fluid.relative_flow(data.vel))
|
||||
.unwrap_or_default();
|
||||
@ -171,7 +172,7 @@ impl CharacterBehavior for Data {
|
||||
Quaternion::rotation_3d(
|
||||
PI / 2.0
|
||||
* accel_factor
|
||||
* if data.physics.on_ground.is_some() {
|
||||
* if data.physics.state.on_ground.is_some() {
|
||||
-1.0
|
||||
} else {
|
||||
1.0
|
||||
|
@ -49,7 +49,7 @@ impl CharacterBehavior for Data {
|
||||
// If still in this state, do the things
|
||||
if matches!(update.character, CharacterState::GlideWield(_)) {
|
||||
// If not on the ground while wielding glider enter gliding state
|
||||
update.character = if data.physics.on_ground.is_none() {
|
||||
update.character = if data.physics.state.on_ground.is_none() {
|
||||
CharacterState::Glide(glide::Data::new(
|
||||
self.span_length,
|
||||
self.chord_length,
|
||||
@ -60,7 +60,7 @@ impl CharacterBehavior for Data {
|
||||
.inventory
|
||||
.and_then(|inv| inv.equipped(EquipSlot::Glider))
|
||||
.is_some()
|
||||
&& data.physics.in_liquid().map_or(true, |depth| depth < 0.5)
|
||||
&& data.physics.state.in_liquid().map_or(true, |depth| depth < 0.5)
|
||||
{
|
||||
CharacterState::GlideWield(Self {
|
||||
// Glider tilt follows look dir
|
||||
|
@ -30,7 +30,7 @@ impl CharacterBehavior for Data {
|
||||
|
||||
// Try to Fall/Stand up/Move
|
||||
if self.is_sneaking
|
||||
&& (data.physics.on_ground.is_none() || data.physics.in_liquid().is_some())
|
||||
&& (data.physics.state.on_ground.is_none() || data.physics.state.in_liquid().is_some())
|
||||
{
|
||||
update.character = CharacterState::Idle(Data {
|
||||
is_sneaking: false,
|
||||
|
@ -90,7 +90,7 @@ impl CharacterBehavior for Data {
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else if data.physics.on_ground.is_some() | data.physics.in_liquid().is_some() {
|
||||
} else if data.physics.state.on_ground.is_some() | data.physics.state.in_liquid().is_some() {
|
||||
// Transitions to swing portion of state upon hitting ground
|
||||
update.character = CharacterState::LeapMelee(Data {
|
||||
timer: Duration::default(),
|
||||
|
@ -19,7 +19,7 @@ impl CharacterBehavior for Data {
|
||||
handle_jump(data, output_events, &mut update, 1.0);
|
||||
|
||||
// Try to Fall/Stand up/Move
|
||||
if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
if data.physics.state.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
update.character = CharacterState::Idle(idle::Data::default());
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ impl CharacterBehavior for Data {
|
||||
handle_wield(data, &mut update);
|
||||
handle_jump(data, output_events, &mut update, 1.0);
|
||||
|
||||
if !data.physics.skating_active {
|
||||
if !data.physics.state.skating_active {
|
||||
update.character = CharacterState::Idle(idle::Data {
|
||||
is_sneaking: false,
|
||||
footwear: Some(self.footwear),
|
||||
|
@ -62,7 +62,7 @@ impl CharacterBehavior for Data {
|
||||
match self.static_data.movement_behavior {
|
||||
MovementBehavior::ForwardGround | MovementBehavior::Stationary => {},
|
||||
MovementBehavior::AxeHover => {
|
||||
update.movement = update.movement.with_movement(if data.physics.on_ground.is_some() {
|
||||
update.movement = update.movement.with_movement(if data.physics.state.on_ground.is_some() {
|
||||
// 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?
|
||||
let dir = Dir::from_unnormalized(data.inputs.move_dir.with_z(0.0));
|
||||
|
@ -327,7 +327,7 @@ pub fn handle_skating(data: &JoinData, update: &mut StateUpdate) {
|
||||
footwear,
|
||||
});
|
||||
}
|
||||
if data.physics.skating_active {
|
||||
if data.physics.state.skating_active {
|
||||
update.character =
|
||||
CharacterState::Skate(skate::Data::new(data, footwear.unwrap_or(Friction::Normal)));
|
||||
}
|
||||
@ -338,16 +338,17 @@ pub fn handle_skating(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
||||
let submersion = data
|
||||
.physics
|
||||
.state
|
||||
.in_liquid()
|
||||
.map(|depth| depth / data.body.height());
|
||||
|
||||
if input_is_pressed(data, InputKind::Fly)
|
||||
&& submersion.map_or(true, |sub| sub < 1.0)
|
||||
&& (data.physics.on_ground.is_none() || data.body.jump_impulse().is_none())
|
||||
&& (data.physics.state.on_ground.is_none() || data.body.jump_impulse().is_none())
|
||||
&& data.body.fly_thrust().is_some()
|
||||
{
|
||||
fly_move(data, update, efficiency);
|
||||
} else if let Some(submersion) = (data.physics.on_ground.is_none()
|
||||
} else if let Some(submersion) = (data.physics.state.on_ground.is_none()
|
||||
&& data.body.swim_thrust().is_some())
|
||||
.then_some(submersion)
|
||||
.flatten()
|
||||
@ -362,7 +363,7 @@ pub fn handle_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f3
|
||||
fn basic_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
||||
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
|
||||
let accel = if let Some(block) = data.physics.on_ground {
|
||||
let accel = if let Some(block) = data.physics.state.on_ground {
|
||||
// FRIC_GROUND temporarily used to normalize things around expected values
|
||||
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
|
||||
} else {
|
||||
@ -409,7 +410,7 @@ pub fn handle_forced_movement(
|
||||
match movement {
|
||||
ForcedMovement::Forward { strength } => {
|
||||
let strength = strength * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
if let Some(accel) = data.physics.on_ground.map(|block| {
|
||||
if let Some(accel) = data.physics.state.on_ground.map(|block| {
|
||||
// FRIC_GROUND temporarily used to normalize things around expected values
|
||||
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
|
||||
}) {
|
||||
@ -474,7 +475,7 @@ pub fn handle_orientation(
|
||||
// unit is multiples of 180°
|
||||
let half_turns_per_tick = data.body.base_ori_rate()
|
||||
* efficiency
|
||||
* if data.physics.on_ground.is_some() {
|
||||
* if data.physics.state.on_ground.is_some() {
|
||||
1.0
|
||||
} else {
|
||||
0.2
|
||||
@ -579,7 +580,7 @@ pub fn fly_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32)
|
||||
Density((update.density.0 + data.dt.0 * rate * change).clamp(min, max))
|
||||
};
|
||||
let def_density = ship.density().0;
|
||||
if data.physics.in_liquid().is_some() {
|
||||
if data.physics.state.in_liquid().is_some() {
|
||||
let hull_density = ship.hull_density().0;
|
||||
update.density.0 =
|
||||
regulate_density(def_density * 0.6, hull_density, hull_density, 25.0).0;
|
||||
@ -660,25 +661,25 @@ pub fn attempt_wield(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
|
||||
/// Checks that player can `Sit` and updates `CharacterState` if so
|
||||
pub fn attempt_sit(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() {
|
||||
if data.physics.state.on_ground.is_some() {
|
||||
update.character = CharacterState::Sit;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_dance(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() && data.body.is_humanoid() {
|
||||
if data.physics.state.on_ground.is_some() && data.body.is_humanoid() {
|
||||
update.character = CharacterState::Dance;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_talk(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() {
|
||||
if data.physics.state.on_ground.is_some() {
|
||||
update.character = CharacterState::Talk;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_sneak(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() && data.body.is_humanoid() {
|
||||
if data.physics.state.on_ground.is_some() && data.body.is_humanoid() {
|
||||
update.character = Idle(idle::Data {
|
||||
is_sneaking: true,
|
||||
footwear: data.character.footwear(),
|
||||
@ -689,10 +690,11 @@ pub fn attempt_sneak(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
/// Checks that player can `Climb` and updates `CharacterState` if so
|
||||
pub fn handle_climb(data: &JoinData<'_>, update: &mut StateUpdate) -> bool {
|
||||
if data.inputs.climb.is_some()
|
||||
&& data.physics.on_wall.is_some()
|
||||
&& data.physics.on_ground.is_none()
|
||||
&& data.physics.state.on_wall.is_some()
|
||||
&& data.physics.state.on_ground.is_none()
|
||||
&& !data
|
||||
.physics
|
||||
.state
|
||||
.in_liquid()
|
||||
.map(|depth| depth > 1.0)
|
||||
.unwrap_or(false)
|
||||
@ -708,9 +710,9 @@ pub fn handle_climb(data: &JoinData<'_>, update: &mut StateUpdate) -> bool {
|
||||
}
|
||||
|
||||
pub fn handle_wallrun(data: &JoinData<'_>, update: &mut StateUpdate) -> bool {
|
||||
if data.physics.on_wall.is_some()
|
||||
&& data.physics.on_ground.is_none()
|
||||
&& data.physics.in_liquid().is_none()
|
||||
if data.physics.state.on_wall.is_some()
|
||||
&& data.physics.state.on_ground.is_none()
|
||||
&& data.physics.state.in_liquid().is_none()
|
||||
&& data.body.can_climb()
|
||||
{
|
||||
update.character = CharacterState::Wallrun(wallrun::Data);
|
||||
@ -895,6 +897,7 @@ pub fn attempt_glide_wield(
|
||||
.is_some()
|
||||
&& !data
|
||||
.physics
|
||||
.state
|
||||
.in_liquid()
|
||||
.map(|depth| depth > 1.0)
|
||||
.unwrap_or(false)
|
||||
@ -916,7 +919,7 @@ pub fn handle_jump(
|
||||
_update: &mut StateUpdate,
|
||||
strength: f32,
|
||||
) -> bool {
|
||||
(input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some())
|
||||
(input_is_pressed(data, InputKind::Jump) && data.physics.state.on_ground.is_some())
|
||||
.then(|| data.body.jump_impulse())
|
||||
.flatten()
|
||||
.map(|impulse| {
|
||||
|
@ -33,9 +33,9 @@ impl CharacterBehavior for Data {
|
||||
// fall off wall, hit ground, or enter water
|
||||
// TODO: Rugged way to determine when state change occurs and we need to leave
|
||||
// this state
|
||||
if data.physics.on_wall.is_none()
|
||||
|| data.physics.on_ground.is_some()
|
||||
|| data.physics.in_liquid().is_some()
|
||||
if data.physics.state.on_wall.is_none()
|
||||
|| data.physics.state.on_ground.is_some()
|
||||
|| data.physics.state.in_liquid().is_some()
|
||||
{
|
||||
update.character = CharacterState::Idle(idle::Data::default());
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl CharacterBehavior for Data {
|
||||
handle_jump(data, output_events, &mut update, 1.0);
|
||||
|
||||
if self.is_sneaking
|
||||
&& (data.physics.on_ground.is_none() || data.physics.in_liquid().is_some())
|
||||
&& (data.physics.state.on_ground.is_none() || data.physics.state.in_liquid().is_some())
|
||||
{
|
||||
update.character = CharacterState::Wielding(Data { is_sneaking: false });
|
||||
}
|
||||
@ -96,7 +96,7 @@ impl CharacterBehavior for Data {
|
||||
|
||||
fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
|
||||
let mut update = StateUpdate::from(data);
|
||||
if data.physics.on_ground.is_some() && data.body.is_humanoid() {
|
||||
if data.physics.state.on_ground.is_some() && data.body.is_humanoid() {
|
||||
update.character = CharacterState::Wielding(Data { is_sneaking: true });
|
||||
}
|
||||
update
|
||||
|
@ -575,7 +575,8 @@ impl State {
|
||||
match event {
|
||||
LocalEvent::Jump(entity, impulse) => {
|
||||
if let Some(vel) = velocities.get_mut(entity) {
|
||||
vel.0.z = impulse + physics.get(entity).map_or(0.0, |ps| ps.ground_vel.z);
|
||||
vel.0.z =
|
||||
impulse + physics.get(entity).map_or(0.0, |ps| ps.state.ground_vel.z);
|
||||
}
|
||||
},
|
||||
LocalEvent::ApplyImpulse { entity, impulse } => {
|
||||
|
@ -31,6 +31,7 @@ pub struct ReadData<'a> {
|
||||
entities: Entities<'a>,
|
||||
dt: Read<'a, DeltaTime>,
|
||||
server_bus: Read<'a, EventBus<ServerEvent>>,
|
||||
bodies: ReadStorage<'a, Body>,
|
||||
inventories: ReadStorage<'a, Inventory>,
|
||||
healths: ReadStorage<'a, Health>,
|
||||
energies: ReadStorage<'a, Energy>,
|
||||
@ -48,7 +49,6 @@ impl<'a> System<'a> for Sys {
|
||||
ReadData<'a>,
|
||||
WriteStorage<'a, Buffs>,
|
||||
WriteStorage<'a, Stats>,
|
||||
WriteStorage<'a, Body>,
|
||||
WriteStorage<'a, LightEmitter>,
|
||||
);
|
||||
|
||||
@ -58,7 +58,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
fn run(
|
||||
job: &mut Job<Self>,
|
||||
(read_data, mut buffs, mut stats, mut bodies, mut light_emitters): Self::SystemData,
|
||||
(read_data, mut buffs, mut stats, mut light_emitters): Self::SystemData,
|
||||
) {
|
||||
let mut server_emitter = read_data.server_bus.emitter();
|
||||
let dt = read_data.dt.0;
|
||||
@ -74,7 +74,7 @@ impl<'a> System<'a> for Sys {
|
||||
prof_span!(guard_, "buff campfire deactivate");
|
||||
(
|
||||
&read_data.entities,
|
||||
&mut bodies,
|
||||
&read_data.bodies,
|
||||
&read_data.physics_states,
|
||||
light_emitters_mask, //to improve iteration speed
|
||||
)
|
||||
@ -82,16 +82,19 @@ impl<'a> System<'a> for Sys {
|
||||
.filter(|(_, body, physics_state, _)| {
|
||||
matches!(&**body, Body::Object(object::Body::CampfireLit))
|
||||
&& matches!(
|
||||
physics_state.in_fluid,
|
||||
physics_state.state.in_fluid,
|
||||
Some(Fluid::Liquid {
|
||||
kind: LiquidKind::Water,
|
||||
..
|
||||
})
|
||||
)
|
||||
})
|
||||
.for_each(|(e, mut body, _, _)| {
|
||||
*body = Body::Object(object::Body::Campfire);
|
||||
light_emitters.remove(e);
|
||||
.for_each(|(entity, _, _, _)| {
|
||||
server_emitter.emit(ServerEvent::UpdateBody {
|
||||
entity,
|
||||
new_body: Body::Object(object::Body::Campfire),
|
||||
});
|
||||
light_emitters.remove(entity);
|
||||
});
|
||||
drop(guard_);
|
||||
|
||||
@ -108,7 +111,7 @@ impl<'a> System<'a> for Sys {
|
||||
// Apply buffs to entity based off of their current physics_state
|
||||
if let Some(physics_state) = physics_state {
|
||||
if matches!(
|
||||
physics_state.on_ground.and_then(|b| b.get_sprite()),
|
||||
physics_state.state.on_ground.and_then(|b| b.get_sprite()),
|
||||
Some(SpriteKind::EnsnaringVines) | Some(SpriteKind::EnsnaringWeb)
|
||||
) {
|
||||
// If on ensnaring vines, apply ensnared debuff
|
||||
@ -123,7 +126,7 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
if matches!(
|
||||
physics_state.on_ground.and_then(|b| b.get_sprite()),
|
||||
physics_state.state.on_ground.and_then(|b| b.get_sprite()),
|
||||
Some(SpriteKind::SeaUrchin)
|
||||
) {
|
||||
// If touching Sea Urchin apply Bleeding buff
|
||||
@ -138,7 +141,7 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
if matches!(
|
||||
physics_state.in_fluid,
|
||||
physics_state.state.in_fluid,
|
||||
Some(Fluid::Liquid {
|
||||
kind: LiquidKind::Lava,
|
||||
..
|
||||
@ -155,7 +158,7 @@ impl<'a> System<'a> for Sys {
|
||||
)),
|
||||
});
|
||||
} else if matches!(
|
||||
physics_state.in_fluid,
|
||||
physics_state.state.in_fluid,
|
||||
Some(Fluid::Liquid {
|
||||
kind: LiquidKind::Water,
|
||||
..
|
||||
|
@ -4,7 +4,8 @@ use common::{
|
||||
fluid_dynamics::{Fluid, LiquidKind, Wings},
|
||||
inventory::item::armor::Friction,
|
||||
Body, CharacterState, Collider, Density, Immovable, Mass, MovementState, Ori, PhysicsState,
|
||||
Pos, PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Stats, Sticky, Vel,
|
||||
PhysicsStateFast, Pos, PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Stats, Sticky,
|
||||
Vel,
|
||||
},
|
||||
consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY},
|
||||
event::{EventBus, ServerEvent},
|
||||
@ -388,7 +389,7 @@ impl<'a> PhysicsRead<'a> {
|
||||
)| {
|
||||
let is_sticky = sticky.is_some();
|
||||
let is_immovable = immovable.is_some();
|
||||
let is_mid_air = physics.on_surface().is_none();
|
||||
let is_mid_air = physics.state.on_surface().is_none();
|
||||
let mut entity_entity_collision_checks = 0;
|
||||
let mut entity_entity_collisions = 0;
|
||||
|
||||
@ -667,7 +668,7 @@ impl<'a> PhysicsData<'a> {
|
||||
// Apply physics only if in a loaded chunk
|
||||
if in_loaded_chunk
|
||||
// And not already stuck on a block (e.g., for arrows)
|
||||
&& !(physics_state.on_surface().is_some() && sticky.is_some())
|
||||
&& !(physics_state.state.on_surface().is_some() && sticky.is_some())
|
||||
{
|
||||
// Clamp dt to an effective 10 TPS, to prevent gravity
|
||||
// from slamming the players into the floor when
|
||||
@ -675,7 +676,7 @@ impl<'a> PhysicsData<'a> {
|
||||
// to lag (as observed in the 0.9 release party).
|
||||
let dt = DeltaTime(read.dt.0.min(0.1));
|
||||
|
||||
match physics_state.in_fluid {
|
||||
match physics_state.state.in_fluid {
|
||||
None => {
|
||||
vel.0.z -= dt.0 * GRAVITY;
|
||||
},
|
||||
@ -814,8 +815,8 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
if let Some(state) = character_state {
|
||||
let footwear = state.footwear().unwrap_or(Friction::Normal);
|
||||
if footwear != physics_state.footwear {
|
||||
physics_state.footwear = footwear;
|
||||
if footwear != physics_state.state.footwear {
|
||||
physics_state.state.footwear = footwear;
|
||||
}
|
||||
}
|
||||
|
||||
@ -849,7 +850,7 @@ impl<'a> PhysicsData<'a> {
|
||||
// velocities or entirely broken position snapping.
|
||||
let mut tgt_pos = pos.0 + pos_delta;
|
||||
|
||||
let was_on_ground = physics_state.on_ground.is_some();
|
||||
let was_on_ground = physics_state.state.on_ground.is_some();
|
||||
let block_snap =
|
||||
body.map_or(false, |b| !matches!(b, Body::Object(_) | Body::Ship(_)));
|
||||
let climbing =
|
||||
@ -876,7 +877,7 @@ impl<'a> PhysicsData<'a> {
|
||||
&mut cpos,
|
||||
tgt_pos,
|
||||
&mut vel,
|
||||
physics_state,
|
||||
&mut physics_state.state,
|
||||
Vec3::zero(),
|
||||
&read.dt,
|
||||
was_on_ground,
|
||||
@ -909,7 +910,7 @@ impl<'a> PhysicsData<'a> {
|
||||
&mut cpos,
|
||||
tgt_pos,
|
||||
&mut vel,
|
||||
physics_state,
|
||||
&mut physics_state.state,
|
||||
Vec3::zero(),
|
||||
&read.dt,
|
||||
was_on_ground,
|
||||
@ -921,8 +922,8 @@ impl<'a> PhysicsData<'a> {
|
||||
);
|
||||
|
||||
// Sticky things shouldn't move when on a surface
|
||||
if physics_state.on_surface().is_some() && sticky.is_some() {
|
||||
vel.0 = physics_state.ground_vel;
|
||||
if physics_state.state.on_surface().is_some() && sticky.is_some() {
|
||||
vel.0 = physics_state.state.ground_vel;
|
||||
}
|
||||
|
||||
tgt_pos = cpos.0;
|
||||
@ -982,13 +983,13 @@ impl<'a> PhysicsData<'a> {
|
||||
> block_rpos.xy().map(|e| e.abs()).reduce_partial_max()
|
||||
{
|
||||
if block_rpos.z > 0.0 {
|
||||
physics_state.on_ground = block.copied();
|
||||
physics_state.state.on_ground = block.copied();
|
||||
} else {
|
||||
physics_state.on_ceiling = true;
|
||||
physics_state.state.on_ceiling = true;
|
||||
}
|
||||
vel.0.z = 0.0;
|
||||
} else {
|
||||
physics_state.on_wall =
|
||||
physics_state.state.on_wall =
|
||||
Some(if block_rpos.x.abs() > block_rpos.y.abs() {
|
||||
vel.0.x = 0.0;
|
||||
Vec3::unit_x() * -block_rpos.x.signum()
|
||||
@ -1000,11 +1001,11 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
// Sticky things shouldn't move
|
||||
if sticky.is_some() {
|
||||
vel.0 = physics_state.ground_vel;
|
||||
vel.0 = physics_state.state.ground_vel;
|
||||
}
|
||||
}
|
||||
|
||||
physics_state.in_fluid = read
|
||||
physics_state.state.in_fluid = read
|
||||
.terrain
|
||||
.get(pos.0.map(|e| e.floor() as i32))
|
||||
.ok()
|
||||
@ -1015,7 +1016,7 @@ impl<'a> PhysicsData<'a> {
|
||||
vel: Vel::zero(),
|
||||
})
|
||||
})
|
||||
.or_else(|| match physics_state.in_fluid {
|
||||
.or_else(|| match physics_state.state.in_fluid {
|
||||
Some(Fluid::Liquid { .. }) | None => Some(Fluid::Air {
|
||||
elevation: pos.0.z,
|
||||
vel: Vel::default(),
|
||||
@ -1113,7 +1114,7 @@ impl<'a> PhysicsData<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut physics_state_delta = physics_state.clone();
|
||||
let mut physics_state_delta = physics_state.state;
|
||||
// deliberately don't use scale yet here, because the
|
||||
// 11.0/0.8 thing is
|
||||
// in the comp::Scale for visual reasons
|
||||
@ -1191,7 +1192,7 @@ impl<'a> PhysicsData<'a> {
|
||||
// based on the most
|
||||
// recent terrain that collision was attempted with
|
||||
if physics_state_delta.on_ground.is_some() {
|
||||
physics_state.ground_vel = vel_other;
|
||||
physics_state.state.ground_vel = vel_other;
|
||||
|
||||
// Rotate if on ground
|
||||
ori = ori.rotated(
|
||||
@ -1199,16 +1200,16 @@ impl<'a> PhysicsData<'a> {
|
||||
* previous_cache_other.ori.inverse(),
|
||||
);
|
||||
}
|
||||
physics_state.on_ground =
|
||||
physics_state.on_ground.or(physics_state_delta.on_ground);
|
||||
physics_state.on_ceiling |= physics_state_delta.on_ceiling;
|
||||
physics_state.on_wall = physics_state.on_wall.or_else(|| {
|
||||
physics_state.state.on_ground =
|
||||
physics_state.state.on_ground.or(physics_state_delta.on_ground);
|
||||
physics_state.state.on_ceiling |= physics_state_delta.on_ceiling;
|
||||
physics_state.state.on_wall = physics_state.state.on_wall.or_else(|| {
|
||||
physics_state_delta
|
||||
.on_wall
|
||||
.map(|dir| ori_from.mul_direction(dir))
|
||||
});
|
||||
physics_state.in_fluid = match (
|
||||
physics_state.in_fluid,
|
||||
physics_state.state.in_fluid = match (
|
||||
physics_state.state.in_fluid,
|
||||
physics_state_delta.in_fluid,
|
||||
) {
|
||||
(Some(x), Some(y)) => x
|
||||
@ -1467,7 +1468,7 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
||||
pos: &mut Pos,
|
||||
tgt_pos: Vec3<f32>,
|
||||
vel: &mut Vel,
|
||||
physics_state: &mut PhysicsState,
|
||||
physics_state: &mut PhysicsStateFast,
|
||||
ground_vel: Vec3<f32>,
|
||||
dt: &DeltaTime,
|
||||
was_on_ground: bool,
|
||||
|
@ -86,7 +86,7 @@ impl<'a> System<'a> for Sys {
|
||||
.and_then(|uid| read_data.uid_allocator.retrieve_entity_internal(uid.into()));
|
||||
|
||||
let mut rng = thread_rng();
|
||||
if physics.on_surface().is_none() && rng.gen_bool(0.05) {
|
||||
if physics.state.on_surface().is_none() && rng.gen_bool(0.05) {
|
||||
server_emitter.emit(ServerEvent::Sound {
|
||||
sound: Sound::new(SoundKind::Projectile, pos.0, 4.0, read_data.time.0),
|
||||
});
|
||||
@ -162,7 +162,7 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
if physics.on_surface().is_some() {
|
||||
if physics.state.on_surface().is_some() {
|
||||
let projectile_write = &mut *projectile_write;
|
||||
for effect in projectile_write.hit_solid.drain(..) {
|
||||
match effect {
|
||||
|
@ -182,7 +182,7 @@ impl<'a> System<'a> for Sys {
|
||||
arc_strip.collides_with_circle(Disk::new(pos_b2, rad_b))
|
||||
}
|
||||
&& (pos_b_ground - pos.0).angle_between(pos_b.0 - pos.0) < max_angle
|
||||
&& (!shockwave.requires_ground || physics_state_b.on_ground.is_some());
|
||||
&& (!shockwave.requires_ground || physics_state_b.state.on_ground.is_some());
|
||||
|
||||
if hit {
|
||||
let dir = Dir::from_unnormalized(pos_b.0 - pos.0).unwrap_or(look_dir);
|
||||
|
@ -23,6 +23,7 @@ const POISE_REGEN_ACCEL: f32 = 2.0;
|
||||
#[derive(SystemData)]
|
||||
pub struct ReadData<'a> {
|
||||
entities: Entities<'a>,
|
||||
stats: ReadStorage<'a, Stats>,
|
||||
dt: Read<'a, DeltaTime>,
|
||||
time: Read<'a, Time>,
|
||||
server_bus: Read<'a, EventBus<ServerEvent>>,
|
||||
@ -39,7 +40,6 @@ pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
ReadData<'a>,
|
||||
WriteStorage<'a, Stats>,
|
||||
WriteStorage<'a, SkillSet>,
|
||||
WriteStorage<'a, Health>,
|
||||
WriteStorage<'a, Poise>,
|
||||
@ -56,7 +56,6 @@ impl<'a> System<'a> for Sys {
|
||||
_job: &mut Job<Self>,
|
||||
(
|
||||
read_data,
|
||||
stats,
|
||||
mut skill_sets,
|
||||
mut healths,
|
||||
mut poises,
|
||||
@ -72,7 +71,7 @@ impl<'a> System<'a> for Sys {
|
||||
// Update stats
|
||||
for (entity, stats, mut health, pos, mut energy, inventory) in (
|
||||
&read_data.entities,
|
||||
&stats,
|
||||
&read_data.stats,
|
||||
&mut healths,
|
||||
&read_data.positions,
|
||||
&mut energies,
|
||||
|
@ -3,7 +3,7 @@ mod tests {
|
||||
use common::{
|
||||
comp::{
|
||||
item::MaterialStatManifest, skills::GeneralSkill, CharacterState, Controller, Energy,
|
||||
Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel,
|
||||
MovementState, Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel,
|
||||
},
|
||||
resources::{DeltaTime, GameMode, Time},
|
||||
terrain::{MapSizeLg, TerrainChunk},
|
||||
@ -51,6 +51,7 @@ mod tests {
|
||||
.ecs_mut()
|
||||
.create_entity()
|
||||
.with(CharacterState::Idle(common::states::idle::Data::default()))
|
||||
.with(MovementState::default())
|
||||
.with(Pos(Vec3::zero()))
|
||||
.with(Vel::default())
|
||||
.with(ori)
|
||||
@ -105,11 +106,22 @@ mod tests {
|
||||
Ori::from_unnormalized_vec(testcases[i].0).unwrap_or_default(),
|
||||
));
|
||||
}
|
||||
tick(&mut state, Duration::from_secs_f32(0.033));
|
||||
let results = state.ecs().read_storage::<Ori>();
|
||||
let dt = 0.033;
|
||||
tick(&mut state, Duration::from_secs_f32(dt));
|
||||
let movement = state.ecs().read_storage::<MovementState>();
|
||||
let pos = state.ecs().read_storage::<Pos>();
|
||||
let vel = state.ecs().read_storage::<Vel>();
|
||||
let ori = state.ecs().read_storage::<Ori>();
|
||||
let dt = DeltaTime(dt);
|
||||
for i in 0..TESTCASES {
|
||||
if let Some(e) = entities[i] {
|
||||
let result = Dir::from(*results.get(e).expect("Ori missing"));
|
||||
let mut pos = *pos.get(e).expect("Pos missing");
|
||||
let mut vel = *vel.get(e).expect("Vel missing");
|
||||
let mut ori = *ori.get(e).expect("Ori missing");
|
||||
if let Some(movement) = movement.get(e) {
|
||||
movement.handle_movement(&dt, &mut pos, &mut vel, &mut ori);
|
||||
}
|
||||
let result = Dir::from(ori);
|
||||
assert!(result.abs_diff_eq(&testcases[i].1, 0.0005));
|
||||
// println!("{:?}", result);
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ use common::{
|
||||
comp::{
|
||||
inventory::item::MaterialStatManifest,
|
||||
skills::{GeneralSkill, Skill},
|
||||
Auras, Buffs, CharacterState, Collider, Combo, Controller, Energy, Health, Ori, Pos, Stats,
|
||||
Vel,
|
||||
Auras, Buffs, CharacterState, Collider, Combo, Controller, Energy, Health, MovementState,
|
||||
Ori, Pos, Stats, Vel,
|
||||
},
|
||||
resources::{DeltaTime, GameMode, Time},
|
||||
skillset_builder::SkillSetBuilder,
|
||||
slowjob::SlowJobPool,
|
||||
terrain::{
|
||||
Block, BlockKind, MapSizeLg, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainGrid,
|
||||
},
|
||||
@ -42,6 +43,10 @@ pub fn setup() -> State {
|
||||
Arc::new(TerrainChunk::water(0)),
|
||||
);
|
||||
state.ecs_mut().insert(MaterialStatManifest::with_empty());
|
||||
state
|
||||
.ecs_mut()
|
||||
.write_resource::<SlowJobPool>()
|
||||
.configure("CHUNK_DROP", |_n| 1);
|
||||
state.ecs_mut().read_resource::<Time>();
|
||||
state.ecs_mut().read_resource::<DeltaTime>();
|
||||
for x in 0..2 {
|
||||
@ -117,6 +122,7 @@ pub fn create_player(state: &mut State) -> Entity {
|
||||
.with(body)
|
||||
.with(Controller::default())
|
||||
.with(CharacterState::default())
|
||||
.with(MovementState::default())
|
||||
.with(Buffs::default())
|
||||
.with(Combo::default())
|
||||
.with(Auras::default())
|
||||
|
@ -966,8 +966,8 @@ impl<'a> AgentData<'a> {
|
||||
controller.inputs.look_dir,
|
||||
self.ori.look_vec(),
|
||||
// Try to match animation by getting some context
|
||||
self.vel.0 - self.physics_state.ground_vel,
|
||||
self.physics_state.on_ground,
|
||||
self.vel.0 - self.physics_state.state.ground_vel,
|
||||
self.physics_state.state.on_ground,
|
||||
)
|
||||
});
|
||||
let aim_to = Vec3::new(
|
||||
|
@ -106,7 +106,7 @@ pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3<f32>)
|
||||
if let Some(physics) = ecs.read_storage::<PhysicsState>().get(entity) {
|
||||
//Check if the entity is on a surface. If it is not, reduce knockback.
|
||||
let mut impulse = impulse
|
||||
* if physics.on_surface().is_some() {
|
||||
* if physics.state.on_surface().is_some() {
|
||||
1.0
|
||||
} else {
|
||||
0.4
|
||||
@ -1359,3 +1359,11 @@ pub fn handle_update_map_marker(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// FIXME: Remove this hack! It should only be used for dousing flames from
|
||||
/// campfires.
|
||||
pub fn handle_update_body(server: &mut Server, entity: EcsEntity, new_body: comp::Body) {
|
||||
server
|
||||
.state
|
||||
.write_component_ignore_entity_dead(entity, new_body);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use entity_manipulation::{
|
||||
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
|
||||
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
|
||||
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground, handle_parry,
|
||||
handle_poise, handle_respawn, handle_teleport_to, handle_update_map_marker,
|
||||
handle_poise, handle_respawn, handle_teleport_to, handle_update_body, handle_update_map_marker,
|
||||
};
|
||||
use group_manip::handle_group;
|
||||
use information::handle_site_info;
|
||||
@ -287,6 +287,9 @@ impl Server {
|
||||
ServerEvent::UpdateMapMarker { entity, update } => {
|
||||
handle_update_map_marker(self, entity, update)
|
||||
},
|
||||
ServerEvent::UpdateBody { entity, new_body } => {
|
||||
handle_update_body(self, entity, new_body)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ impl<'a> System<'a> for Sys {
|
||||
let is_gliding = matches!(
|
||||
read_data.char_states.get(entity),
|
||||
Some(CharacterState::GlideWield(_) | CharacterState::Glide(_))
|
||||
) && physics_state.on_ground.is_none();
|
||||
) && physics_state.state.on_ground.is_none();
|
||||
|
||||
if let Some(pid) = agent.position_pid_controller.as_mut() {
|
||||
pid.add_measurement(read_data.time.0, pos.0);
|
||||
@ -150,8 +150,8 @@ impl<'a> System<'a> for Sys {
|
||||
let traversal_config = TraversalConfig {
|
||||
node_tolerance,
|
||||
slow_factor,
|
||||
on_ground: physics_state.on_ground.is_some(),
|
||||
in_liquid: physics_state.in_liquid().is_some(),
|
||||
on_ground: physics_state.state.on_ground.is_some(),
|
||||
in_liquid: physics_state.state.in_liquid().is_some(),
|
||||
min_tgt_dist: 1.0,
|
||||
can_climb: body.map_or(false, Body::can_climb),
|
||||
can_fly: body.map_or(false, |b| b.fly_thrust().is_some()),
|
||||
|
@ -184,7 +184,7 @@ fn react_if_on_fire(bdata: &mut BehaviorData) -> bool {
|
||||
|
||||
if is_on_fire
|
||||
&& bdata.agent_data.body.map_or(false, |b| b.is_humanoid())
|
||||
&& bdata.agent_data.physics_state.on_ground.is_some()
|
||||
&& bdata.agent_data.physics_state.state.on_ground.is_some()
|
||||
&& bdata
|
||||
.rng
|
||||
.gen_bool((2.0 * bdata.read_data.dt.0).clamp(0.0, 1.0) as f64)
|
||||
|
@ -44,7 +44,7 @@ impl<'a> System<'a> for Sys {
|
||||
{
|
||||
match object {
|
||||
Object::Bomb { owner } => {
|
||||
if physics.on_surface().is_some() {
|
||||
if physics.state.on_surface().is_some() {
|
||||
server_emitter.emit(ServerEvent::Delete(entity));
|
||||
server_emitter.emit(ServerEvent::Explosion {
|
||||
pos: pos.0,
|
||||
|
@ -54,7 +54,7 @@ impl<'a> System<'a> for Sys {
|
||||
.filter(|(_, owner_pos, owner_physics, pet_pos)| {
|
||||
// Don't teleport pets to the player if they're in the air, nobody wants
|
||||
// pets to go splat :(
|
||||
owner_physics.on_ground.is_some()
|
||||
owner_physics.state.on_ground.is_some()
|
||||
&& owner_pos.0.distance_squared(pet_pos.0) > LOST_PET_DISTANCE_THRESHOLD.powi(2)
|
||||
})
|
||||
.map(|(entity, owner_pos, _, _)| (entity, *owner_pos))
|
||||
|
@ -55,7 +55,7 @@ impl<'a> System<'a> for Sys {
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if physics.map_or(true, |ps| ps.on_ground.is_some()) && velocity.0.z >= 0.0 {
|
||||
if physics.map_or(true, |ps| ps.state.on_ground.is_some()) && velocity.0.z >= 0.0 {
|
||||
for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() {
|
||||
if player_pos.0.distance_squared(waypoint_pos.0)
|
||||
< waypoint_area.radius().powi(2)
|
||||
|
@ -706,17 +706,17 @@ fn selected_entity_window(
|
||||
.spacing([40.0, 4.0])
|
||||
.striped(true)
|
||||
.show(ui, |ui| {
|
||||
two_col_row(ui, "On Ground", physics_state.on_ground.map_or("None".to_owned(), |x| format!("{:?}", x)));
|
||||
two_col_row(ui, "On Ceiling", (if physics_state.on_ceiling { "True" } else { "False " }).to_string());
|
||||
two_col_row(ui, "On Wall", physics_state.on_wall.map_or("-".to_owned(), |x| format!("{:.1},{:.1},{:.1}", x.x, x.y, x.z )));
|
||||
two_col_row(ui, "On Ground", physics_state.state.on_ground.map_or("None".to_owned(), |x| format!("{:?}", x)));
|
||||
two_col_row(ui, "On Ceiling", (if physics_state.state.on_ceiling { "True" } else { "False " }).to_string());
|
||||
two_col_row(ui, "On Wall", physics_state.state.on_wall.map_or("-".to_owned(), |x| format!("{:.1},{:.1},{:.1}", x.x, x.y, x.z )));
|
||||
two_col_row(ui, "Touching Entities", physics_state.touch_entities.len().to_string());
|
||||
two_col_row(ui, "In Fluid", match physics_state.in_fluid {
|
||||
two_col_row(ui, "In Fluid", match physics_state.state.in_fluid {
|
||||
|
||||
Some(Fluid::Air { elevation, .. }) => format!("Air (Elevation: {:.1})", elevation),
|
||||
Some(Fluid::Liquid { depth, kind, .. }) => format!("{:?} (Depth: {:.1})", kind, depth),
|
||||
_ => "None".to_owned() });
|
||||
});
|
||||
two_col_row(ui, "Footwear", match physics_state.footwear{ Friction::Ski => "Ski", Friction::Skate => "Skate", /* Friction::Snowshoe => "Snowshoe", Friction::Spikes => "Spikes", */ Friction::Normal=>"Normal",}.to_string());
|
||||
two_col_row(ui, "Footwear", match physics_state.state.footwear{ Friction::Ski => "Ski", Friction::Skate => "Skate", /* Friction::Snowshoe => "Snowshoe", Friction::Spikes => "Spikes", */ Friction::Normal=>"Normal",}.to_string());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
};
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{Body, CharacterState, PhysicsState, Pos, Vel},
|
||||
comp::{Body, CharacterState, PhysicsState, PhysicsStateFast, Pos, Vel},
|
||||
resources::DeltaTime,
|
||||
terrain::{BlockKind, TerrainChunk},
|
||||
vol::ReadVol,
|
||||
@ -72,6 +72,7 @@ impl EventMapper for MovementEventMapper {
|
||||
.join()
|
||||
.filter(|(_, e_pos, ..)| (e_pos.0.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR)
|
||||
{
|
||||
let physics = &physics.state;
|
||||
if let Some(character) = character {
|
||||
let internal_state = self.event_history.entry(entity).or_default();
|
||||
|
||||
@ -187,7 +188,7 @@ impl MovementEventMapper {
|
||||
/// `SfxEvent`'s which we attach sounds to
|
||||
fn map_movement_event(
|
||||
character_state: &CharacterState,
|
||||
physics_state: &PhysicsState,
|
||||
physics_state: &PhysicsStateFast,
|
||||
previous_state: &PreviousEntityState,
|
||||
vel: Vec3<f32>,
|
||||
underfoot_block_kind: BlockKind,
|
||||
@ -228,7 +229,7 @@ impl MovementEventMapper {
|
||||
|
||||
/// Maps a limited set of movements for other non-humanoid entities
|
||||
fn map_non_humanoid_movement_event(
|
||||
physics_state: &PhysicsState,
|
||||
physics_state: &PhysicsStateFast,
|
||||
vel: Vec3<f32>,
|
||||
underfoot_block_kind: BlockKind,
|
||||
) -> SfxEvent {
|
||||
@ -250,7 +251,7 @@ impl MovementEventMapper {
|
||||
|
||||
/// Maps a limited set of movements for quadruped entities
|
||||
fn map_quadruped_movement_event(
|
||||
physics_state: &PhysicsState,
|
||||
physics_state: &PhysicsStateFast,
|
||||
vel: Vec3<f32>,
|
||||
underfoot_block_kind: BlockKind,
|
||||
) -> SfxEvent {
|
||||
|
@ -3,7 +3,7 @@ use crate::audio::sfx::SfxEvent;
|
||||
use common::{
|
||||
comp::{
|
||||
bird_large, humanoid, quadruped_medium, quadruped_small, Body, CharacterState, InputKind,
|
||||
Ori, PhysicsState,
|
||||
Ori, PhysicsStateFast,
|
||||
},
|
||||
states,
|
||||
terrain::{Block, BlockKind},
|
||||
@ -94,7 +94,7 @@ fn same_previous_event_elapsed_emits() {
|
||||
fn maps_idle() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle(states::idle::Data::default()),
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
@ -116,7 +116,7 @@ fn maps_idle() {
|
||||
fn maps_run_with_sufficient_velocity() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle(states::idle::Data::default()),
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
@ -138,7 +138,7 @@ fn maps_run_with_sufficient_velocity() {
|
||||
fn does_not_map_run_with_insufficient_velocity() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle(states::idle::Data::default()),
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
@ -193,7 +193,7 @@ fn maps_roll() {
|
||||
is_sneaking: false,
|
||||
was_combo: None,
|
||||
}),
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
@ -215,7 +215,7 @@ fn maps_roll() {
|
||||
fn maps_land_on_ground_to_run() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle(states::idle::Data::default()),
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
@ -255,7 +255,7 @@ fn maps_glide() {
|
||||
#[test]
|
||||
fn maps_quadrupeds_running() {
|
||||
let result = MovementEventMapper::map_non_humanoid_movement_event(
|
||||
&PhysicsState {
|
||||
&PhysicsStateFast {
|
||||
on_ground: Some(Block::empty()),
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -767,6 +767,7 @@ impl FigureMgr {
|
||||
.join()
|
||||
.enumerate()
|
||||
{
|
||||
let physics = &physics.state;
|
||||
// Velocity relative to the current ground
|
||||
let rel_vel = anim::vek::Vec3::<f32>::from(vel.0 - physics.ground_vel);
|
||||
|
||||
|
@ -528,7 +528,7 @@ impl Scene {
|
||||
let on_ground = ecs
|
||||
.read_storage::<comp::PhysicsState>()
|
||||
.get(scene_data.viewpoint_entity)
|
||||
.map(|p| p.on_ground.is_some());
|
||||
.map(|p| p.state.on_ground.is_some());
|
||||
|
||||
let (viewpoint_height, viewpoint_eye_height) = scene_data
|
||||
.state
|
||||
|
@ -1061,6 +1061,7 @@ impl PlayState for SessionState {
|
||||
let fluid = ecs
|
||||
.read_storage::<comp::PhysicsState>()
|
||||
.get(entity)?
|
||||
.state
|
||||
.in_fluid?;
|
||||
ecs.read_storage::<Vel>()
|
||||
.get(entity)
|
||||
@ -1220,7 +1221,7 @@ impl PlayState for SessionState {
|
||||
let in_fluid = ecs
|
||||
.read_storage::<comp::PhysicsState>()
|
||||
.get(entity)
|
||||
.and_then(|state| state.in_fluid);
|
||||
.and_then(|state| state.state.in_fluid);
|
||||
let character_state = ecs
|
||||
.read_storage::<comp::CharacterState>()
|
||||
.get(entity)
|
||||
|
Loading…
Reference in New Issue
Block a user