mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Better surface swimming, no underwater sprites
This commit is contained in:
parent
c1b07465cf
commit
6992194ad4
@ -396,7 +396,7 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn pick_up(&mut self, entity: EcsEntity) {
|
||||
if let Some(uid) = self.state.read_component_copied(entity) {
|
||||
if let Some(uid) = self.state.read_component_cloned(entity) {
|
||||
self.singleton_stream
|
||||
.send(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Pickup(uid),
|
||||
@ -520,7 +520,7 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn mount(&mut self, entity: EcsEntity) {
|
||||
if let Some(uid) = self.state.read_component_copied(entity) {
|
||||
if let Some(uid) = self.state.read_component_cloned(entity) {
|
||||
self.singleton_stream
|
||||
.send(ClientMsg::ControlEvent(ControlEvent::Mount(uid)))
|
||||
.unwrap();
|
||||
@ -1294,7 +1294,7 @@ impl Client {
|
||||
pub fn entity(&self) -> EcsEntity { self.entity }
|
||||
|
||||
/// Get the player's Uid.
|
||||
pub fn uid(&self) -> Option<Uid> { self.state.read_component_copied(self.entity) }
|
||||
pub fn uid(&self) -> Option<Uid> { self.state.read_component_cloned(self.entity) }
|
||||
|
||||
/// Get the client state
|
||||
pub fn get_client_state(&self) -> ClientState { self.client_state }
|
||||
@ -1347,7 +1347,7 @@ impl Client {
|
||||
pub fn is_admin(&self) -> bool {
|
||||
let client_uid = self
|
||||
.state
|
||||
.read_component_copied::<Uid>(self.entity)
|
||||
.read_component_cloned::<Uid>(self.entity)
|
||||
.expect("Client doesn't have a Uid!!!");
|
||||
|
||||
self.player_list
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::{path::Chaser, sync::Uid, comp::Body};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, Entity as EcsEntity};
|
||||
use specs_idvs::IdvStorage;
|
||||
use vek::*;
|
||||
|
@ -80,7 +80,7 @@ pub struct PhysicsState {
|
||||
pub on_ceiling: bool,
|
||||
pub on_wall: Option<Vec3<f32>>,
|
||||
pub touch_entity: Option<Uid>,
|
||||
pub in_fluid: bool,
|
||||
pub in_fluid: Option<f32>, // Depth
|
||||
}
|
||||
|
||||
impl PhysicsState {
|
||||
|
@ -199,8 +199,8 @@ impl State {
|
||||
}
|
||||
|
||||
/// Read a component attributed to a particular entity.
|
||||
pub fn read_component_copied<C: Component + Copy>(&self, entity: EcsEntity) -> Option<C> {
|
||||
self.ecs.read_storage().get(entity).copied()
|
||||
pub fn read_component_cloned<C: Component + Copy>(&self, entity: EcsEntity) -> Option<C> {
|
||||
self.ecs.read_storage().get(entity).cloned()
|
||||
}
|
||||
|
||||
/// Get a read-only reference to the storage of a particular component type.
|
||||
|
@ -24,7 +24,7 @@ impl CharacterBehavior for Data {
|
||||
update.character = CharacterState::GlideWield;
|
||||
return update;
|
||||
}
|
||||
if data.physics.in_fluid {
|
||||
if data.physics.in_fluid.map(|depth| depth > 0.5).unwrap_or(false) {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
// If there is a wall in front of character and they are trying to climb go to
|
||||
|
@ -19,7 +19,7 @@ impl CharacterBehavior for Data {
|
||||
if !data.physics.on_ground {
|
||||
update.character = CharacterState::Glide;
|
||||
}
|
||||
if data.physics.in_fluid {
|
||||
if data.physics.in_fluid.map(|depth| depth > 0.5).unwrap_or(false) {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
sys::{character_behavior::JoinData, phys::GRAVITY},
|
||||
util::Dir,
|
||||
};
|
||||
use vek::vec::Vec2;
|
||||
use vek::*;
|
||||
|
||||
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
|
||||
const BASE_HUMANOID_AIR_ACCEL: f32 = 8.0;
|
||||
@ -67,8 +67,8 @@ impl Body {
|
||||
|
||||
/// Handles updating `Components` to move player based on state of `JoinData`
|
||||
pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
if data.physics.in_fluid {
|
||||
swim_move(data, update, efficiency);
|
||||
if let Some(depth) = data.physics.in_fluid {
|
||||
swim_move(data, update, efficiency, depth);
|
||||
} else {
|
||||
basic_move(data, update, efficiency);
|
||||
}
|
||||
@ -104,7 +104,7 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, rate: f32)
|
||||
}
|
||||
|
||||
/// Updates components to move player as if theyre swimming
|
||||
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth: f32) {
|
||||
// Update velocity
|
||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
||||
* data.inputs.move_dir
|
||||
@ -120,7 +120,7 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
// Swim
|
||||
if data.inputs.swimup.is_pressed() {
|
||||
update.vel.0.z =
|
||||
(update.vel.0.z + data.dt.0 * GRAVITY * 4.0).min(BASE_HUMANOID_WATER_SPEED);
|
||||
(update.vel.0.z + data.dt.0 * GRAVITY * 4.0 * depth.clamped(0.0, 1.0).powf(3.0)).min(BASE_HUMANOID_WATER_SPEED);
|
||||
}
|
||||
// Swim
|
||||
if data.inputs.swimdown.is_pressed() {
|
||||
@ -192,14 +192,14 @@ pub fn attempt_swap_loadout(data: &JoinData, update: &mut StateUpdate) {
|
||||
|
||||
/// Checks that player can wield the glider and updates `CharacterState` if so
|
||||
pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground && !data.physics.in_fluid && data.body.is_humanoid() {
|
||||
if data.physics.on_ground && !data.physics.in_fluid.map(|depth| depth > 1.0).unwrap_or(false) && data.body.is_humanoid() {
|
||||
update.character = CharacterState::GlideWield;
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that player can jump and sends jump event if so
|
||||
pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
|
||||
if data.inputs.jump.is_pressed() && data.physics.on_ground && !data.physics.in_fluid {
|
||||
if data.inputs.jump.is_pressed() && data.physics.on_ground && !data.physics.in_fluid.map(|depth| depth > 1.0).unwrap_or(false) {
|
||||
update
|
||||
.local_events
|
||||
.push_front(LocalEvent::Jump(data.entity));
|
||||
|
@ -241,7 +241,8 @@ impl<'a> System<'a> for Sys {
|
||||
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
||||
* speed.min(0.2 + (dist - AVG_FOLLOW_DIST) / 8.0);
|
||||
inputs.jump.set_state(bearing.z > 1.5);
|
||||
inputs.swim.set_state(bearing.z > 0.5);
|
||||
inputs.swimup.set_state(bearing.z > 0.5);
|
||||
inputs.swimdown.set_state(bearing.z < 0.5);
|
||||
}
|
||||
} else {
|
||||
do_idle = true;
|
||||
@ -331,7 +332,8 @@ impl<'a> System<'a> for Sys {
|
||||
.unwrap_or(Vec2::zero())
|
||||
* speed;
|
||||
inputs.jump.set_state(bearing.z > 1.5);
|
||||
inputs.swim.set_state(bearing.z > 0.5);
|
||||
inputs.swimup.set_state(bearing.z > 0.5);
|
||||
inputs.swimdown.set_state(bearing.z < 0.5);
|
||||
}
|
||||
} else {
|
||||
do_idle = true;
|
||||
@ -399,7 +401,8 @@ impl<'a> System<'a> for Sys {
|
||||
.unwrap_or(Vec2::zero())
|
||||
* speed;
|
||||
inputs.jump.set_state(bearing.z > 1.5);
|
||||
inputs.swim.set_state(bearing.z > 0.5);
|
||||
inputs.swimup.set_state(bearing.z > 0.5);
|
||||
inputs.swimdown.set_state(bearing.z < 0.5);
|
||||
}
|
||||
|
||||
if dist_sqrd < 16.0f32.powf(2.0)
|
||||
|
@ -13,6 +13,7 @@ use specs::{
|
||||
saveload::MarkerAllocator, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage,
|
||||
};
|
||||
use vek::*;
|
||||
use std::ops::Range;
|
||||
|
||||
pub const GRAVITY: f32 = 9.81 * 5.0;
|
||||
const BOUYANCY: f32 = 1.0;
|
||||
@ -123,7 +124,7 @@ impl<'a> System<'a> for Sys {
|
||||
} else {
|
||||
0.0
|
||||
})
|
||||
.max(if physics_state.in_fluid {
|
||||
.max(if physics_state.in_fluid.is_some() {
|
||||
FRIC_FLUID
|
||||
} else {
|
||||
0.0
|
||||
@ -133,7 +134,7 @@ impl<'a> System<'a> for Sys {
|
||||
.is_some();
|
||||
let downward_force = if !in_loaded_chunk {
|
||||
0.0 // No gravity in unloaded chunks
|
||||
} else if physics_state.in_fluid {
|
||||
} else if physics_state.in_fluid.map(|depth| depth > 0.75).unwrap_or(false) {
|
||||
(1.0 - BOUYANCY) * GRAVITY
|
||||
} else {
|
||||
GRAVITY
|
||||
@ -175,31 +176,47 @@ impl<'a> System<'a> for Sys {
|
||||
.flatten()
|
||||
.flatten();
|
||||
|
||||
// Function for determining whether the player at a specific position collides
|
||||
// with the ground
|
||||
let collision_with = |pos: Vec3<f32>,
|
||||
hit: &dyn Fn(&Block) -> bool,
|
||||
near_iter| {
|
||||
for (i, j, k) in near_iter {
|
||||
let block_pos = pos.map(|e| e.floor() as i32) + Vec3::new(i, j, k);
|
||||
// Function for iterating over the blocks the player at a specific position collides
|
||||
// with
|
||||
fn collision_iter<'a>(
|
||||
pos: Vec3<f32>,
|
||||
terrain: &'a TerrainGrid,
|
||||
hit: &'a dyn Fn(&Block) -> bool,
|
||||
near_iter: impl Iterator<Item=(i32, i32, i32)> + 'a,
|
||||
radius: f32,
|
||||
z_range: Range<f32>,
|
||||
) -> impl Iterator<Item=Aabb<f32>> + 'a {
|
||||
near_iter
|
||||
.filter_map(move |(i, j, k)| {
|
||||
let block_pos = pos.map(|e| e.floor() as i32) + Vec3::new(i, j, k);
|
||||
|
||||
if let Some(block) = terrain.get(block_pos).ok().copied().filter(hit) {
|
||||
let player_aabb = Aabb {
|
||||
min: pos + Vec3::new(-radius, -radius, z_min),
|
||||
max: pos + Vec3::new(radius, radius, z_max),
|
||||
};
|
||||
let block_aabb = Aabb {
|
||||
min: block_pos.map(|e| e as f32),
|
||||
max: block_pos.map(|e| e as f32)
|
||||
+ Vec3::new(1.0, 1.0, block.get_height()),
|
||||
};
|
||||
if let Some(block) = terrain.get(block_pos).ok().copied().filter(hit) {
|
||||
let player_aabb = Aabb {
|
||||
min: pos + Vec3::new(-radius, -radius, z_range.start),
|
||||
max: pos + Vec3::new(radius, radius, z_range.end),
|
||||
};
|
||||
let block_aabb = Aabb {
|
||||
min: block_pos.map(|e| e as f32),
|
||||
max: block_pos.map(|e| e as f32)
|
||||
+ Vec3::new(1.0, 1.0, block.get_height()),
|
||||
};
|
||||
|
||||
if player_aabb.collides_with_aabb(block_aabb) {
|
||||
return true;
|
||||
if player_aabb.collides_with_aabb(block_aabb) {
|
||||
return Some(block_aabb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
|
||||
None
|
||||
})
|
||||
};
|
||||
|
||||
// Function for determining whether the player at a specific position collides
|
||||
// with blocks with the given criteria
|
||||
let collision_with = |pos: Vec3<f32>,
|
||||
hit: &dyn Fn(&Block) -> bool,
|
||||
near_iter|
|
||||
{
|
||||
collision_iter(pos, &terrain, hit, near_iter, radius, z_min..z_max).count() > 0
|
||||
};
|
||||
|
||||
let was_on_ground = physics_state.on_ground;
|
||||
@ -400,8 +417,9 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
// Figure out if we're in water
|
||||
physics_state.in_fluid =
|
||||
collision_with(pos.0, &|block| block.is_fluid(), near_iter.clone());
|
||||
physics_state.in_fluid = collision_iter(pos.0, &terrain, &|block| block.is_fluid(), near_iter.clone(), radius, z_min..z_max)
|
||||
.max_by_key(|block_aabb| (block_aabb.max.z * 100.0) as i32)
|
||||
.map(|block_aabb| block_aabb.max.z - pos.0.z);
|
||||
},
|
||||
Collider::Point => {
|
||||
let (dist, block) = terrain.ray(pos.0, pos.0 + pos_delta).ignore_error().cast();
|
||||
|
@ -262,7 +262,7 @@ fn handle_jump(
|
||||
action: &ChatCommand,
|
||||
) {
|
||||
if let Ok((x, y, z)) = scan_fmt!(&args, &action.arg_fmt(), f32, f32, f32) {
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(current_pos) => {
|
||||
server
|
||||
.state
|
||||
@ -287,7 +287,7 @@ fn handle_goto(
|
||||
if let Ok((x, y, z)) = scan_fmt!(&args, &action.arg_fmt(), f32, f32, f32) {
|
||||
if server
|
||||
.state
|
||||
.read_component_copied::<comp::Pos>(target)
|
||||
.read_component_cloned::<comp::Pos>(target)
|
||||
.is_some()
|
||||
{
|
||||
server
|
||||
@ -498,9 +498,9 @@ fn handle_tp(
|
||||
);
|
||||
return;
|
||||
};
|
||||
if let Some(_pos) = server.state.read_component_copied::<comp::Pos>(target) {
|
||||
if let Some(_pos) = server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
if let Some(player) = opt_player {
|
||||
if let Some(pos) = server.state.read_component_copied::<comp::Pos>(player) {
|
||||
if let Some(pos) = server.state.read_component_cloned::<comp::Pos>(player) {
|
||||
server.state.write_component(target, pos);
|
||||
server.state.write_component(target, comp::ForceUpdate);
|
||||
} else {
|
||||
@ -545,7 +545,7 @@ fn handle_spawn(
|
||||
(Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount, opt_ai) => {
|
||||
let uid = server
|
||||
.state
|
||||
.read_component_copied(target)
|
||||
.read_component_cloned(target)
|
||||
.expect("Expected player to have a UID");
|
||||
if let Some(alignment) = parse_alignment(uid, &opt_align) {
|
||||
let amount = opt_amount
|
||||
@ -556,7 +556,7 @@ fn handle_spawn(
|
||||
|
||||
let ai = opt_ai.unwrap_or_else(|| "true".to_string());
|
||||
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(pos) => {
|
||||
let agent =
|
||||
if let comp::Alignment::Owned(_) | comp::Alignment::Npc = alignment {
|
||||
@ -666,7 +666,7 @@ fn handle_spawn_training_dummy(
|
||||
_args: String,
|
||||
_action: &ChatCommand,
|
||||
) {
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(pos) => {
|
||||
let vel = Vec3::new(
|
||||
rand::thread_rng().gen_range(-2.0, 3.0),
|
||||
@ -707,7 +707,7 @@ fn handle_spawn_campfire(
|
||||
_args: String,
|
||||
_action: &ChatCommand,
|
||||
) {
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(pos) => {
|
||||
server
|
||||
.state
|
||||
@ -1066,7 +1066,7 @@ fn handle_explosion(
|
||||
|
||||
let ecs = server.state.ecs();
|
||||
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(pos) => {
|
||||
ecs.read_resource::<EventBus<ServerEvent>>()
|
||||
.emit_now(ServerEvent::Explosion {
|
||||
@ -1090,7 +1090,7 @@ fn handle_waypoint(
|
||||
_args: String,
|
||||
_action: &ChatCommand,
|
||||
) {
|
||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||
match server.state.read_component_cloned::<comp::Pos>(target) {
|
||||
Some(pos) => {
|
||||
let time = server.state.ecs().read_resource();
|
||||
let _ = server
|
||||
@ -1126,7 +1126,7 @@ fn handle_adminify(
|
||||
Some(player) => {
|
||||
let is_admin = if server
|
||||
.state
|
||||
.read_component_copied::<comp::Admin>(player)
|
||||
.read_component_cloned::<comp::Admin>(player)
|
||||
.is_some()
|
||||
{
|
||||
ecs.write_storage::<comp::Admin>().remove(player);
|
||||
@ -1670,7 +1670,7 @@ fn handle_remove_lights(
|
||||
action: &ChatCommand,
|
||||
) {
|
||||
let opt_radius = scan_fmt_some!(&args, &action.arg_fmt(), f32);
|
||||
let opt_player_pos = server.state.read_component_copied::<comp::Pos>(target);
|
||||
let opt_player_pos = server.state.read_component_cloned::<comp::Pos>(target);
|
||||
let mut to_delete = vec![];
|
||||
|
||||
match opt_player_pos {
|
||||
|
@ -251,7 +251,7 @@ pub fn handle_respawn(server: &Server, entity: EcsEntity) {
|
||||
.is_some()
|
||||
{
|
||||
let respawn_point = state
|
||||
.read_component_copied::<comp::Waypoint>(entity)
|
||||
.read_component_cloned::<comp::Waypoint>(entity)
|
||||
.map(|wp| wp.get_pos())
|
||||
.unwrap_or(state.ecs().read_resource::<SpawnPoint>().0);
|
||||
|
||||
|
@ -167,10 +167,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
thrown_items.push((
|
||||
*pos,
|
||||
state
|
||||
.read_component_copied::<comp::Vel>(entity)
|
||||
.read_component_cloned::<comp::Vel>(entity)
|
||||
.unwrap_or_default(),
|
||||
state
|
||||
.read_component_copied::<comp::Ori>(entity)
|
||||
.read_component_cloned::<comp::Ori>(entity)
|
||||
.unwrap_or_default(),
|
||||
*kind,
|
||||
));
|
||||
@ -185,7 +185,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
state.read_storage::<comp::Pos>().get(entity)
|
||||
{
|
||||
let uid = state
|
||||
.read_component_copied(entity)
|
||||
.read_component_cloned(entity)
|
||||
.expect("Expected player to have a UID");
|
||||
if (
|
||||
&state.read_storage::<comp::Alignment>(),
|
||||
@ -341,7 +341,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
dropped_items.push((
|
||||
*pos,
|
||||
state
|
||||
.read_component_copied::<comp::Ori>(entity)
|
||||
.read_component_cloned::<comp::Ori>(entity)
|
||||
.unwrap_or_default(),
|
||||
item,
|
||||
));
|
||||
@ -373,10 +373,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
for _ in 0..amount {
|
||||
dropped_items.push((
|
||||
state
|
||||
.read_component_copied::<comp::Pos>(entity)
|
||||
.read_component_cloned::<comp::Pos>(entity)
|
||||
.unwrap_or_default(),
|
||||
state
|
||||
.read_component_copied::<comp::Ori>(entity)
|
||||
.read_component_cloned::<comp::Ori>(entity)
|
||||
.unwrap_or_default(),
|
||||
item.clone(),
|
||||
));
|
||||
@ -407,7 +407,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
+ Vec3::unit_z() * 15.0
|
||||
+ Vec3::<f32>::zero().map(|_| rand::thread_rng().gen::<f32>() - 0.5) * 4.0;
|
||||
|
||||
let uid = state.read_component_copied::<Uid>(entity);
|
||||
let uid = state.read_component_cloned::<Uid>(entity);
|
||||
|
||||
let mut new_entity = state
|
||||
.create_object(Default::default(), match kind {
|
||||
|
@ -20,7 +20,7 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity) {
|
||||
// Note: If other `ServerEvent`s are referring to this entity they will be
|
||||
// disrupted
|
||||
let maybe_client = state.ecs().write_storage::<Client>().remove(entity);
|
||||
let maybe_uid = state.read_component_copied::<Uid>(entity);
|
||||
let maybe_uid = state.read_component_cloned::<Uid>(entity);
|
||||
let maybe_player = state.ecs().write_storage::<comp::Player>().remove(entity);
|
||||
let maybe_group = state
|
||||
.ecs()
|
||||
|
@ -173,7 +173,7 @@ impl StateExt for State {
|
||||
self.write_component(entity, comp::CharacterState::default());
|
||||
self.write_component(
|
||||
entity,
|
||||
comp::Alignment::Owned(self.read_component_copied(entity).unwrap()),
|
||||
comp::Alignment::Owned(self.read_component_cloned(entity).unwrap()),
|
||||
);
|
||||
|
||||
// Set the character id for the player
|
||||
@ -213,7 +213,7 @@ impl StateExt for State {
|
||||
|
||||
// Notify clients of a player list update
|
||||
let client_uid = self
|
||||
.read_component_copied::<Uid>(entity)
|
||||
.read_component_cloned::<Uid>(entity)
|
||||
.map(|u| u)
|
||||
.expect("Client doesn't have a Uid!!!");
|
||||
|
||||
|
@ -505,7 +505,7 @@ impl<'a> Widget for Social<'a> {
|
||||
})
|
||||
.or_else(|| {
|
||||
self.selected_entity
|
||||
.and_then(|s| self.client.state().read_component_copied(s.0))
|
||||
.and_then(|s| self.client.state().read_component_cloned(s.0))
|
||||
})
|
||||
.filter(|selected| {
|
||||
// Prevent inviting entities already in the same group
|
||||
@ -564,7 +564,7 @@ impl<'a> Widget for Social<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
} // End of Online Tab
|
||||
} // End of Online Tab
|
||||
|
||||
events
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::character::StandAnimation::update_skeleton(
|
||||
@ -823,7 +823,7 @@ impl FigureMgr {
|
||||
)
|
||||
},
|
||||
CharacterState::Wielding { .. } => {
|
||||
if physics.in_fluid {
|
||||
if physics.in_fluid.is_some() {
|
||||
anim::character::SwimWieldAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, second_tool_kind, vel.0.magnitude(), time),
|
||||
@ -949,7 +949,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => {
|
||||
@ -1047,7 +1047,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => {
|
||||
@ -1143,7 +1143,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => {
|
||||
@ -1237,7 +1237,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::bird_medium::IdleAnimation::update_skeleton(
|
||||
@ -1329,7 +1329,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::fish_medium::IdleAnimation::update_skeleton(
|
||||
@ -1404,7 +1404,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::dragon::IdleAnimation::update_skeleton(
|
||||
@ -1478,7 +1478,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::critter::IdleAnimation::update_skeleton(
|
||||
@ -1553,7 +1553,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::bird_small::IdleAnimation::update_skeleton(
|
||||
@ -1628,7 +1628,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::fish_small::IdleAnimation::update_skeleton(
|
||||
@ -1703,7 +1703,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::biped_large::IdleAnimation::update_skeleton(
|
||||
@ -1795,7 +1795,7 @@ impl FigureMgr {
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
physics.in_fluid.is_some(), // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => anim::golem::IdleAnimation::update_skeleton(
|
||||
|
@ -31,49 +31,44 @@ pub fn apply_scatter_to<'a>(
|
||||
chunk: &SimChunk,
|
||||
) {
|
||||
use BlockKind::*;
|
||||
let scatter: &[(_, fn(&SimChunk) -> (f32, Option<(f32, f32)>))] = &[
|
||||
let scatter: &[(_, bool, fn(&SimChunk) -> (f32, Option<(f32, f32)>))] = &[
|
||||
// (density, Option<(wavelen, threshold)>)
|
||||
(BlueFlower, |c| {
|
||||
(BlueFlower, false, |c| {
|
||||
(
|
||||
close(c.temp, -0.3, 0.7).min(close(c.humidity, 0.6, 0.35)) * 0.05,
|
||||
Some((48.0, 0.6)),
|
||||
)
|
||||
}),
|
||||
(PinkFlower, |c| {
|
||||
(PinkFlower, false, |c| {
|
||||
(
|
||||
close(c.temp, 0.15, 0.5).min(close(c.humidity, 0.6, 0.35)) * 0.05,
|
||||
Some((48.0, 0.6)),
|
||||
)
|
||||
}),
|
||||
(DeadBush, |c| {
|
||||
(DeadBush, false, |c| {
|
||||
(
|
||||
close(c.temp, 0.8, 0.3).min(close(c.humidity, 0.0, 0.4)) * 0.015,
|
||||
None,
|
||||
)
|
||||
}),
|
||||
(Twigs, |c| ((c.tree_density - 0.5).max(0.0) * 0.0025, None)),
|
||||
(Stones, |c| ((c.rockiness - 0.5).max(0.0) * 0.005, None)),
|
||||
(ShortGrass, |c| {
|
||||
(
|
||||
close(c.temp, 0.3, 0.4).min(close(c.humidity, 0.6, 0.35)) * 0.05,
|
||||
Some((48.0, 0.4)),
|
||||
)
|
||||
}),
|
||||
(MediumGrass, |c| {
|
||||
(Twigs, false, |c| ((c.tree_density - 0.5).max(0.0) * 0.0025, None)),
|
||||
(Stones, false, |c| ((c.rockiness - 0.5).max(0.0) * 0.005, None)),
|
||||
(ShortGrass, false, |c| (close(c.temp, 0.3, 0.4).min(close(c.humidity, 0.6, 0.35)) * 0.05, Some((48.0, 0.4)))),
|
||||
(MediumGrass, false, |c| {
|
||||
(
|
||||
close(c.temp, 0.0, 0.6).min(close(c.humidity, 0.6, 0.35)) * 0.05,
|
||||
Some((48.0, 0.2)),
|
||||
)
|
||||
}),
|
||||
(LongGrass, |c| {
|
||||
(LongGrass, false, |c| {
|
||||
(
|
||||
close(c.temp, 0.4, 0.4).min(close(c.humidity, 0.8, 0.2)) * 0.05,
|
||||
Some((48.0, 0.1)),
|
||||
)
|
||||
}),
|
||||
(GrassSnow, |c| {
|
||||
(GrassSnow, false, |c| {
|
||||
(
|
||||
close(c.temp, -0.4, 0.4).min(close(c.rockiness, 0.0, 0.5)),
|
||||
close(c.temp, -0.4, 0.4).min(close(c.rockiness, 0.0, 0.5)) * 0.1,
|
||||
Some((48.0, 0.6)),
|
||||
)
|
||||
}),
|
||||
@ -92,7 +87,9 @@ pub fn apply_scatter_to<'a>(
|
||||
continue;
|
||||
};
|
||||
|
||||
let bk = scatter.iter().enumerate().find_map(|(i, (bk, f))| {
|
||||
let underwater = col_sample.water_level > col_sample.alt;
|
||||
|
||||
let bk = scatter.iter().enumerate().find_map(|(i, (bk, is_underwater, f))| {
|
||||
let (density, patch) = f(chunk);
|
||||
if density <= 0.0
|
||||
|| patch
|
||||
@ -105,6 +102,7 @@ pub fn apply_scatter_to<'a>(
|
||||
})
|
||||
.unwrap_or(false)
|
||||
|| !RandomField::new(i as u32).chance(Vec3::new(wpos2d.x, wpos2d.y, 0), density)
|
||||
|| underwater != *is_underwater
|
||||
{
|
||||
None
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user