mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/small-fixes' into 'master'
Better world colours, better projectiles, better aiming, many other small improvements See merge request veloren/veloren!1332
This commit is contained in:
commit
bf7afcf5c9
@ -26,6 +26,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Colors for models and figures were adjusted to account for the saturation hack.
|
||||
- Fixed a bug where the closest item would be picked up instead of a selected item.
|
||||
- Fixed a bug where camera zoom in and zoom out distance didn't match.
|
||||
- Overhauled world colours
|
||||
- Improved projectile physics
|
||||
- Improved overhead aiming
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
in vec3 f_pos;
|
||||
in vec3 f_norm;
|
||||
in float pull_down;
|
||||
// in vec2 v_pos_orig;
|
||||
// in vec4 f_shadow;
|
||||
// in vec4 f_square;
|
||||
@ -106,7 +107,7 @@ void main() {
|
||||
// mat4 invfoo = foo * inverse(foo * all_mat);
|
||||
// vec3 old_coord = all_mat * vec4(f_pos.xyz, 1.0);
|
||||
// vec4 new_f_pos = invfoo * (old_coord);//vec4(f_pos, 1.0);
|
||||
vec3 f_col = lod_col(f_pos.xy);
|
||||
vec3 f_col = mix(lod_col(f_pos.xy), vec3(0), clamp(pull_down / 10, 0, 1));
|
||||
// tgt_color = vec4(f_col, 1.0);
|
||||
// return;
|
||||
// vec3 f_col = srgb_to_linear(vec3(1.0));
|
||||
|
@ -29,6 +29,7 @@ uniform u_locals {
|
||||
|
||||
out vec3 f_pos;
|
||||
out vec3 f_norm;
|
||||
out float pull_down;
|
||||
// out vec2 v_pos_orig;
|
||||
// out vec4 f_square;
|
||||
// out vec4 f_shadow;
|
||||
@ -48,7 +49,8 @@ void main() {
|
||||
|
||||
// f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
|
||||
|
||||
f_pos.z -= 1.0 / pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0);
|
||||
pull_down = 1.0 / pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0);
|
||||
f_pos.z -= pull_down;
|
||||
|
||||
// f_pos.z -= 100.0 * pow(1.0 + 0.01 / view_distance.x, -pow(distance(focus_pos.xy, f_pos.xy), 2.0));
|
||||
// f_pos.z = mix(-f_pos.z, f_pos.z, view_distance.x <= distance(focus_pos.xy, f_pos.xy) + 32.0);
|
||||
|
@ -345,7 +345,7 @@ void main() {
|
||||
const float A = 0.055;
|
||||
const float W_INV = 1 / (1 + A);
|
||||
const float W_2 = W_INV * W_INV;//pow(W_INV, 2.4);
|
||||
const float NOISE_FACTOR = 0.02;//pow(0.02, 1.2);
|
||||
const float NOISE_FACTOR = 0.015;//pow(0.02, 1.2);
|
||||
vec3 noise_delta = (sqrt(f_col) * W_INV + noise * NOISE_FACTOR);
|
||||
// noise_delta = noise_delta * noise_delta * W_2 - f_col;
|
||||
// lum = W ⋅ col
|
||||
|
@ -17,13 +17,13 @@
|
||||
Water: None,
|
||||
GreenSludge: None,
|
||||
// Leaves all actually get interpolated.
|
||||
TemperateLeaves: (start: (0, 132, 94), end: (142, 181, 0)),
|
||||
PineLeaves: (start: (0, 60, 50), end: (30, 100, 10)),
|
||||
PalmLeavesInner: (start: (61, 166, 43), end: (29, 130, 32)),
|
||||
PalmLeavesOuter: (start: (62, 171, 38), end: (45, 171, 65)),
|
||||
Acacia: (start: (15, 126, 50), end: (30, 180, 10)),
|
||||
TemperateLeaves: (start: (0, 70, 45), end: (90, 140, 0)),
|
||||
PineLeaves: (start: (0, 60, 50), end: (30, 80, 10)),
|
||||
PalmLeavesInner: (start: (70, 140, 43), end: (55, 140, 32)),
|
||||
PalmLeavesOuter: (start: (60, 130, 38), end: (30, 130, 65)),
|
||||
Acacia: (start: (30, 100, 0), end: (90, 110, 20)),
|
||||
Liana: (start: (0, 125, 107), end: (0, 155, 129)),
|
||||
Mangrove: (start: (32, 56, 22), end: (57, 69, 27)),
|
||||
Mangrove: (start: (15, 80, 10), end: (20, 120, 47)),
|
||||
)
|
||||
|
||||
// Water blocks ignore color now so this isn't used, but just in case this color was worth
|
||||
@ -31,34 +31,35 @@
|
||||
// green_sludge: (30.0, 126.0, 23.0)
|
||||
),
|
||||
column: (
|
||||
cold_grass: (0.0, 0.5, 0.25),
|
||||
warm_grass: (0.4, 0.8, 0.0),
|
||||
cold_grass: (0.0, 0.3, 0.1),
|
||||
warm_grass: (0.5, 0.55, 0.0),
|
||||
dark_grass: (0.15, 0.4, 0.1),
|
||||
wet_grass: (0.1, 0.8, 0.2),
|
||||
cold_stone: (0.57, 0.67, 0.8),
|
||||
hot_stone: (0.07, 0.07, 0.06),
|
||||
warm_stone: (0.77, 0.77, 0.64),
|
||||
cold_stone: (0.4, 0.67, 0.8),
|
||||
hot_stone: (0.05, 0.05, 0.04),
|
||||
warm_stone: (0.30, 0.2, 0.15),
|
||||
beach_sand: (0.8, 0.75, 0.5),
|
||||
desert_sand: (0.7, 0.4, 0.25),
|
||||
snow: (0.8, 0.85, 1.0),
|
||||
desert_sand: (0.6, 0.4, 0.2),
|
||||
snow: (0.75, 0.8, 1.8),
|
||||
snow_moss: (0.35, 0.55, 0.7),
|
||||
|
||||
stone_col: (195, 187, 201),
|
||||
stone_col: (90, 110, 150),
|
||||
|
||||
dirt_low: (0.075, 0.07, 0.3),
|
||||
dirt_high: (0.75, 0.55, 0.1),
|
||||
dirt_high: (0.6, 0.3, 0.05),
|
||||
|
||||
snow_high: (0.01, 0.3, 0.0),
|
||||
warm_stone_high: (0.3, 0.12, 0.2),
|
||||
warm_stone_high: (0.25, 0.22, 0.3),
|
||||
|
||||
grass_high: (0.15, 0.2, 0.15),
|
||||
tropical_high: (0.87, 0.62, 0.56),
|
||||
tropical_high: (0.95, 0.55, 0.50),
|
||||
),
|
||||
// NOTE: I think (but am not sure) that this is the color of stuff below the bottom-most
|
||||
// ground. I'm not sure how easy it is to see.
|
||||
deep_stone_color: (125, 120, 130),
|
||||
layer: (
|
||||
bridge: (80, 80, 100),
|
||||
stalagtite: (200, 200, 200),
|
||||
stalagtite: (140, 150, 200),
|
||||
),
|
||||
site: (
|
||||
castle: (),
|
||||
@ -74,24 +75,25 @@
|
||||
pole: (90, 70, 50),
|
||||
flag: (
|
||||
Evil: (80, 10, 130),
|
||||
Good: (200, 80, 40),
|
||||
Good: (150, 20, 0),
|
||||
),
|
||||
stone: (
|
||||
Evil: (65, 60, 55),
|
||||
Good: (100, 100, 110),
|
||||
Good: (70, 75, 80),
|
||||
),
|
||||
),
|
||||
house: (
|
||||
foundation: (100, 100, 100),
|
||||
foundation: (70, 70, 70),
|
||||
floor: (100, 75, 50),
|
||||
roof: (
|
||||
Roof1: (0x99, 0x5E, 0x54),
|
||||
Roof2: (0x43, 0x63, 0x64),
|
||||
Roof3: (0x76, 0x6D, 0x68),
|
||||
Roof4: (0x7B, 0x41, 0x61),
|
||||
Roof4: (0x55, 0x25, 0x41),
|
||||
Roof5: (0x52, 0x20, 0x20),
|
||||
Roof6: (0x1A, 0x4A, 0x59),
|
||||
Roof7: (0xCC, 0x76, 0x4E),
|
||||
Roof6: (0x05, 0x3A, 0x40),
|
||||
Roof7: (0xCC, 0x56, 0x3E),
|
||||
Roof8: (0x05, 0x48, 0x40),
|
||||
// (0x1D, 0x4D, 0x45),
|
||||
// (0xB3, 0x7D, 0x60),
|
||||
// (0xAC, 0x5D, 0x26),
|
||||
@ -122,18 +124,18 @@
|
||||
Wall9: (0xAE, 0x8D, 0x9C),
|
||||
),
|
||||
support: (
|
||||
Support1: (60, 45, 30),
|
||||
Support2: (0x65, 0x55, 0x56),
|
||||
Support1: (65, 30, 0),
|
||||
Support2: (0x35, 0x25, 0x26),
|
||||
Support3: (0x53, 0x33, 0x13),
|
||||
Support4: (0x58, 0x42, 0x33),
|
||||
Support4: (0x65, 0x30, 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
plot_town_path: (100, 95, 65),
|
||||
plot_town_path: (90, 70, 45),
|
||||
|
||||
plot_field_dirt: (80, 55, 35),
|
||||
plot_field_mound: (70, 80, 30),
|
||||
plot_field_dirt: (55, 20, 5),
|
||||
plot_field_mound: (40, 60, 10),
|
||||
|
||||
wall_low: (130, 100, 0),
|
||||
wall_high :(90, 70, 50),
|
||||
|
BIN
assets/world/tree/mangroves/1.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/1.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/2.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/2.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/3.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/3.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/4.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/4.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/5.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/5.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/6.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/6.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/7.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/7.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/tree/mangroves/8.vox
(Stored with Git LFS)
BIN
assets/world/tree/mangroves/8.vox
(Stored with Git LFS)
Binary file not shown.
@ -139,43 +139,76 @@ impl Body {
|
||||
pub fn radius(&self) -> f32 {
|
||||
// TODO: Improve these values (some might be reliant on more info in inner type)
|
||||
match self {
|
||||
Body::Humanoid(_) => 0.2,
|
||||
Body::QuadrupedSmall(_) => 0.3,
|
||||
Body::QuadrupedMedium(_) => 0.9,
|
||||
Body::Critter(_) => 0.2,
|
||||
Body::BirdMedium(_) => 0.5,
|
||||
Body::FishMedium(_) => 0.5,
|
||||
Body::Dragon(_) => 2.5,
|
||||
Body::BirdSmall(_) => 0.2,
|
||||
Body::FishSmall(_) => 0.2,
|
||||
Body::BipedLarge(_) => 3.0,
|
||||
Body::Golem(_) => 2.5,
|
||||
Body::QuadrupedLow(_) => 1.0,
|
||||
Body::Object(_) => 0.3,
|
||||
Body::Humanoid(_) => 0.35,
|
||||
Body::QuadrupedSmall(_) => 0.4,
|
||||
Body::QuadrupedMedium(body) => match body.species {
|
||||
quadruped_medium::Species::Grolgar => 1.9,
|
||||
quadruped_medium::Species::Tarasque => 2.2,
|
||||
quadruped_medium::Species::Lion => 1.9,
|
||||
quadruped_medium::Species::Saber => 1.8,
|
||||
quadruped_medium::Species::Catoblepas => 1.7,
|
||||
_ => 1.5,
|
||||
},
|
||||
Body::QuadrupedLow(body) => match body.species {
|
||||
quadruped_low::Species::Asp => 1.8,
|
||||
quadruped_low::Species::Monitor => 1.75,
|
||||
quadruped_low::Species::Crocodile => 2.1,
|
||||
quadruped_low::Species::Salamander => 1.9,
|
||||
quadruped_low::Species::Pangolin => 1.3,
|
||||
_ => 1.6,
|
||||
},
|
||||
Body::Critter(_) => 0.3,
|
||||
Body::BirdMedium(_) => 0.35,
|
||||
Body::FishMedium(_) => 0.35,
|
||||
Body::Dragon(_) => 8.0,
|
||||
Body::BirdSmall(_) => 0.3,
|
||||
Body::FishSmall(_) => 0.3,
|
||||
Body::BipedLarge(_) => 0.75,
|
||||
Body::Golem(_) => 0.4,
|
||||
Body::Object(_) => 0.4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> f32 {
|
||||
match self {
|
||||
Body::Humanoid(humanoid) => match humanoid.species {
|
||||
humanoid::Species::Danari => 0.8,
|
||||
humanoid::Species::Dwarf => 0.9,
|
||||
humanoid::Species::Orc => 1.14,
|
||||
humanoid::Species::Undead => 0.95,
|
||||
humanoid::Species::Danari => 1.5,
|
||||
humanoid::Species::Dwarf => 1.55,
|
||||
humanoid::Species::Orc => 1.95,
|
||||
_ => 1.8,
|
||||
},
|
||||
Body::QuadrupedSmall(body) => match body.species {
|
||||
quadruped_small::Species::Dodarock => 1.5,
|
||||
quadruped_small::Species::Holladon => 1.5,
|
||||
quadruped_small::Species::Truffler => 2.0,
|
||||
_ => 1.0,
|
||||
},
|
||||
Body::QuadrupedSmall(_) => 0.6,
|
||||
Body::QuadrupedMedium(_) => 0.5,
|
||||
Body::Critter(_) => 0.4,
|
||||
Body::BirdMedium(_) => 1.2,
|
||||
Body::FishMedium(_) => 1.0,
|
||||
Body::Dragon(_) => 5.0,
|
||||
Body::BirdSmall(_) => 0.4,
|
||||
Body::FishSmall(_) => 0.4,
|
||||
Body::BipedLarge(_) => 5.0,
|
||||
Body::Golem(_) => 5.0,
|
||||
Body::QuadrupedLow(_) => 0.5,
|
||||
Body::Object(_) => 0.6,
|
||||
Body::QuadrupedMedium(body) => match body.species {
|
||||
quadruped_medium::Species::Tarasque => 2.5,
|
||||
quadruped_medium::Species::Lion => 1.8,
|
||||
quadruped_medium::Species::Saber => 1.8,
|
||||
quadruped_medium::Species::Catoblepas => 2.8,
|
||||
_ => 1.6,
|
||||
},
|
||||
Body::QuadrupedLow(body) => match body.species {
|
||||
quadruped_low::Species::Monitor => 1.5,
|
||||
quadruped_low::Species::Tortoise => 2.0,
|
||||
quadruped_low::Species::Rocksnapper => 2.0,
|
||||
quadruped_low::Species::Maneater => 4.0,
|
||||
_ => 1.3,
|
||||
},
|
||||
Body::Critter(_) => 0.7,
|
||||
Body::BirdMedium(body) => match body.species {
|
||||
bird_medium::Species::Cockatrice => 1.8,
|
||||
_ => 1.1,
|
||||
},
|
||||
Body::FishMedium(_) => 1.1,
|
||||
Body::Dragon(_) => 20.0,
|
||||
Body::BirdSmall(_) => 1.1,
|
||||
Body::FishSmall(_) => 0.9,
|
||||
Body::BipedLarge(_) => 4.5,
|
||||
Body::Golem(_) => 5.8,
|
||||
Body::Object(_) => 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,22 @@ pub enum Collider {
|
||||
Point,
|
||||
}
|
||||
|
||||
impl Collider {
|
||||
pub fn get_radius(&self) -> f32 {
|
||||
match self {
|
||||
Collider::Box { radius, .. } => *radius,
|
||||
Collider::Point => 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_z_limits(&self) -> (f32, f32) {
|
||||
match self {
|
||||
Collider::Box { z_min, z_max, .. } => (*z_min, *z_max),
|
||||
Collider::Point => (0.0, 0.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Collider {
|
||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||
}
|
||||
@ -74,16 +90,26 @@ impl Component for Sticky {
|
||||
}
|
||||
|
||||
// PhysicsState
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PhysicsState {
|
||||
pub on_ground: bool,
|
||||
pub on_ceiling: bool,
|
||||
pub on_wall: Option<Vec3<f32>>,
|
||||
pub touch_entity: Option<Uid>,
|
||||
pub touch_entities: Vec<Uid>,
|
||||
pub in_fluid: Option<f32>, // Depth
|
||||
}
|
||||
|
||||
impl PhysicsState {
|
||||
pub fn reset(&mut self) {
|
||||
// Avoid allocation overhead!
|
||||
let mut touch_entities = std::mem::take(&mut self.touch_entities);
|
||||
touch_entities.clear();
|
||||
*self = Self {
|
||||
touch_entities,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_surface(&self) -> Option<Vec3<f32>> {
|
||||
self.on_ground
|
||||
.then_some(-Vec3::unit_z())
|
||||
|
@ -418,7 +418,7 @@ impl Chaser {
|
||||
});
|
||||
|
||||
if !walking_towards_edge {
|
||||
Some(((tgt - pos) * Vec3::new(1.0, 1.0, 0.0), 0.75))
|
||||
Some(((tgt - pos) * Vec3::new(1.0, 1.0, 0.0), 1.0))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl CharacterBehavior for Data {
|
||||
}
|
||||
}
|
||||
|
||||
if self.buildup_duration != Duration::default() && data.physics.touch_entity.is_none() {
|
||||
if self.buildup_duration != Duration::default() && data.physics.touch_entities.is_empty() {
|
||||
// Build up (this will move you forward)
|
||||
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
|
||||
+ (update.vel.0 * Vec3::new(1.0, 1.0, 0.0)
|
||||
|
@ -113,7 +113,7 @@ impl CharacterBehavior for Data {
|
||||
|
||||
// Handling movement
|
||||
if stage_time_active < Duration::from_millis(STAGE_DURATION / 3) {
|
||||
let adjusted_accel = match (self.stage, data.physics.touch_entity.is_none()) {
|
||||
let adjusted_accel = match (self.stage, data.physics.touch_entities.is_empty()) {
|
||||
(Stage::First, true) => INITIAL_ACCEL,
|
||||
(Stage::Second, true) => INITIAL_ACCEL * 0.75,
|
||||
(Stage::Third, true) => INITIAL_ACCEL * 0.75,
|
||||
|
@ -96,20 +96,153 @@ impl<'a> System<'a> for Sys {
|
||||
) {
|
||||
let mut event_emitter = event_bus.emitter();
|
||||
|
||||
// Add physics state components
|
||||
for entity in (
|
||||
// Add/reset physics state components
|
||||
for (entity, _, _, _, _) in (
|
||||
&entities,
|
||||
!&physics_states,
|
||||
&colliders,
|
||||
&positions,
|
||||
&velocities,
|
||||
&orientations,
|
||||
)
|
||||
.join()
|
||||
.map(|(e, _, _, _, _, _)| e)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
let _ = physics_states.insert(entity, Default::default());
|
||||
let _ = physics_states
|
||||
.entry(entity)
|
||||
.map(|e| e.or_insert_with(Default::default));
|
||||
}
|
||||
|
||||
// Apply pushback
|
||||
//
|
||||
// Note: We now do this first because we project velocity ahead. This is slighty
|
||||
// imperfect and implies that we might get edge-cases where entities
|
||||
// standing right next to the edge of a wall may get hit by projectiles
|
||||
// fired into the wall very close to them. However, this sort of thing is
|
||||
// already possible with poorly-defined hitboxes anyway so it's not too
|
||||
// much of a concern.
|
||||
//
|
||||
// If this situation becomes a problem, this code should be integrated with the
|
||||
// terrain collision code below, although that's not trivial to do since
|
||||
// it means the step needs to take into account the speeds of both
|
||||
// entities.
|
||||
for (entity, pos, scale, mass, collider, _, _, physics, projectile) in (
|
||||
&entities,
|
||||
&positions,
|
||||
scales.maybe(),
|
||||
masses.maybe(),
|
||||
colliders.maybe(),
|
||||
!&mountings,
|
||||
stickies.maybe(),
|
||||
&mut physics_states,
|
||||
// TODO: if we need to avoid collisions for other things consider moving whether it
|
||||
// should interact into the collider component or into a separate component
|
||||
projectiles.maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, _, _, _, _, _, sticky, physics, _)| {
|
||||
sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground)
|
||||
})
|
||||
{
|
||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||
let radius = collider.map(|c| c.get_radius()).unwrap_or(0.5);
|
||||
let z_limits = collider.map(|c| c.get_z_limits()).unwrap_or((-0.5, 0.5));
|
||||
let mass = mass.map(|m| m.0).unwrap_or(scale);
|
||||
|
||||
// Group to ignore collisions with
|
||||
let ignore_group = projectile
|
||||
.and_then(|p| p.owner)
|
||||
.and_then(|uid| uid_allocator.retrieve_entity_internal(uid.into()))
|
||||
.and_then(|e| groups.get(e));
|
||||
|
||||
let mut vel_delta = Vec3::zero();
|
||||
|
||||
for (
|
||||
entity_other,
|
||||
other,
|
||||
pos_other,
|
||||
scale_other,
|
||||
mass_other,
|
||||
collider_other,
|
||||
_,
|
||||
group,
|
||||
) in (
|
||||
&entities,
|
||||
&uids,
|
||||
&positions,
|
||||
scales.maybe(),
|
||||
masses.maybe(),
|
||||
colliders.maybe(),
|
||||
!&mountings,
|
||||
groups.maybe(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if ignore_group.is_some() && ignore_group == group {
|
||||
continue;
|
||||
}
|
||||
|
||||
let scale_other = scale_other.map(|s| s.0).unwrap_or(1.0);
|
||||
let radius_other = collider_other.map(|c| c.get_radius()).unwrap_or(0.5);
|
||||
let z_limits_other = collider_other
|
||||
.map(|c| c.get_z_limits())
|
||||
.unwrap_or((-0.5, 0.5));
|
||||
let mass_other = mass_other.map(|m| m.0).unwrap_or(scale_other);
|
||||
if mass_other == 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let collision_dist = scale * radius + scale_other * radius_other;
|
||||
|
||||
let vel = velocities.get(entity).copied().unwrap_or_default().0;
|
||||
let vel_other = velocities.get(entity_other).copied().unwrap_or_default().0;
|
||||
|
||||
// Sanity check: don't try colliding entities that are too far from each other
|
||||
// Note: I think this catches all cases. If you get entity collision problems,
|
||||
// try removing this!
|
||||
if (pos.0 - pos_other.0).xy().magnitude()
|
||||
> ((vel - vel_other) * dt.0).xy().magnitude() + collision_dist
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let min_collision_dist = 0.3;
|
||||
let increments = ((vel - vel_other).magnitude() * dt.0 / min_collision_dist)
|
||||
.max(1.0)
|
||||
.ceil() as usize;
|
||||
let step_delta = 1.0 / increments as f32;
|
||||
let mut collided = false;
|
||||
for i in 0..increments {
|
||||
let factor = i as f32 * step_delta;
|
||||
let pos = pos.0 + vel * dt.0 * factor;
|
||||
let pos_other = pos_other.0 + vel_other * dt.0 * factor;
|
||||
|
||||
let diff = pos.xy() - pos_other.xy();
|
||||
|
||||
if diff.magnitude_squared() <= collision_dist.powf(2.0)
|
||||
&& pos.z + z_limits.1 * scale
|
||||
>= pos_other.z + z_limits_other.0 * scale_other
|
||||
&& pos.z + z_limits.0 * scale
|
||||
<= pos_other.z + z_limits_other.1 * scale_other
|
||||
{
|
||||
if !collided {
|
||||
physics.touch_entities.push(*other);
|
||||
}
|
||||
|
||||
if diff.magnitude_squared() > 0.0 {
|
||||
let force = 40.0 * (collision_dist - diff.magnitude()) * mass_other
|
||||
/ (mass + mass_other);
|
||||
|
||||
vel_delta += Vec3::from(diff.normalized()) * force * step_delta;
|
||||
}
|
||||
|
||||
collided = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change velocity
|
||||
velocities
|
||||
.get_mut(entity)
|
||||
.map(|vel| vel.0 += vel_delta * dt.0);
|
||||
}
|
||||
|
||||
// Apply movement inputs
|
||||
@ -177,16 +310,18 @@ impl<'a> System<'a> for Sys {
|
||||
Vec3::zero()
|
||||
};
|
||||
|
||||
match collider {
|
||||
match *collider {
|
||||
Collider::Box {
|
||||
radius,
|
||||
z_min,
|
||||
z_max,
|
||||
} => {
|
||||
// Scale collider
|
||||
let radius = *radius; // * scale;
|
||||
let z_min = *z_min; // * scale;
|
||||
let z_max = *z_max; // * scale;
|
||||
// TODO: Use scale & actual proportions when pathfinding is good enough to manage irregular entity
|
||||
// sizes
|
||||
let radius = radius.min(0.45); // * scale;
|
||||
let z_min = z_min; // * scale;
|
||||
let z_max = z_max.clamped(1.2, 1.95); // * scale;
|
||||
|
||||
// Probe distances
|
||||
let hdist = radius.ceil() as i32;
|
||||
@ -515,74 +650,5 @@ impl<'a> System<'a> for Sys {
|
||||
land_on_grounds.into_iter().for_each(|(entity, vel)| {
|
||||
event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 });
|
||||
});
|
||||
|
||||
// Apply pushback
|
||||
for (pos, scale, mass, vel, _, _, _, physics, projectile) in (
|
||||
&positions,
|
||||
scales.maybe(),
|
||||
masses.maybe(),
|
||||
&mut velocities,
|
||||
&colliders,
|
||||
!&mountings,
|
||||
stickies.maybe(),
|
||||
&mut physics_states,
|
||||
// TODO: if we need to avoid collisions for other things consider moving whether it
|
||||
// should interact into the collider component or into a separate component
|
||||
projectiles.maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, _, _, _, _, _, sticky, physics, _)| {
|
||||
sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground)
|
||||
})
|
||||
{
|
||||
physics.touch_entity = None;
|
||||
|
||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||
let mass = mass.map(|m| m.0).unwrap_or(scale);
|
||||
|
||||
// Group to ignore collisions with
|
||||
let ignore_group = projectile
|
||||
.and_then(|p| p.owner)
|
||||
.and_then(|uid| uid_allocator.retrieve_entity_internal(uid.into()))
|
||||
.and_then(|e| groups.get(e));
|
||||
|
||||
for (other, pos_other, scale_other, mass_other, _, _, group) in (
|
||||
&uids,
|
||||
&positions,
|
||||
scales.maybe(),
|
||||
masses.maybe(),
|
||||
&colliders,
|
||||
!&mountings,
|
||||
groups.maybe(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if ignore_group.is_some() && ignore_group == group {
|
||||
continue;
|
||||
}
|
||||
|
||||
let scale_other = scale_other.map(|s| s.0).unwrap_or(1.0);
|
||||
|
||||
let mass_other = mass_other.map(|m| m.0).unwrap_or(scale_other);
|
||||
if mass_other == 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let diff = Vec2::<f32>::from(pos.0 - pos_other.0);
|
||||
|
||||
let collision_dist = 0.55 * (scale + scale_other);
|
||||
|
||||
if diff.magnitude_squared() > 0.0
|
||||
&& diff.magnitude_squared() < collision_dist.powf(2.0)
|
||||
&& pos.0.z + 1.6 * scale > pos_other.0.z
|
||||
&& pos.0.z < pos_other.0.z + 1.6 * scale_other
|
||||
{
|
||||
let force = (collision_dist - diff.magnitude()) * 2.0 * mass_other
|
||||
/ (mass + mass_other);
|
||||
vel.0 += Vec3::from(diff.normalized()) * force;
|
||||
physics.touch_entity = Some(*other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,30 +61,13 @@ impl<'a> System<'a> for Sys {
|
||||
)
|
||||
.join()
|
||||
{
|
||||
// Hit something solid
|
||||
if physics.on_wall.is_some() || physics.on_ground || physics.on_ceiling {
|
||||
for effect in projectile.hit_solid.drain(..) {
|
||||
match effect {
|
||||
projectile::Effect::Explode { power } => {
|
||||
server_emitter.emit(ServerEvent::Explosion {
|
||||
pos: pos.0,
|
||||
power,
|
||||
owner: projectile.owner,
|
||||
friendly_damage: false,
|
||||
reagent: None,
|
||||
})
|
||||
},
|
||||
projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy {
|
||||
entity,
|
||||
cause: HealthSource::World,
|
||||
}),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hit entity
|
||||
else if let Some(other) = physics.touch_entity {
|
||||
for effect in projectile.hit_entity.drain(..) {
|
||||
for other in physics.touch_entities.iter().copied() {
|
||||
if projectile.owner == Some(other) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for effect in projectile.hit_entity.iter().cloned() {
|
||||
match effect {
|
||||
projectile::Effect::Damage(healthchange) => {
|
||||
let owner_uid = projectile.owner.unwrap();
|
||||
@ -151,7 +134,31 @@ impl<'a> System<'a> for Sys {
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
} else if let Some(dir) = velocities
|
||||
}
|
||||
|
||||
// Hit something solid
|
||||
if physics.on_wall.is_some() || physics.on_ground || physics.on_ceiling {
|
||||
for effect in projectile.hit_solid.drain(..) {
|
||||
match effect {
|
||||
projectile::Effect::Explode { power } => {
|
||||
server_emitter.emit(ServerEvent::Explosion {
|
||||
pos: pos.0,
|
||||
power,
|
||||
owner: projectile.owner,
|
||||
friendly_damage: false,
|
||||
reagent: None,
|
||||
})
|
||||
},
|
||||
projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy {
|
||||
entity,
|
||||
cause: HealthSource::World,
|
||||
}),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(dir) = velocities
|
||||
.get(entity)
|
||||
.and_then(|vel| vel.0.try_normalized())
|
||||
{
|
||||
|
@ -102,20 +102,15 @@ impl StateExt for State {
|
||||
.with(comp::Vel(Vec3::zero()))
|
||||
.with(comp::Ori::default())
|
||||
.with(comp::Collider::Box {
|
||||
radius: 0.4,
|
||||
radius: body.radius(),
|
||||
z_min: 0.0,
|
||||
z_max: 1.75,
|
||||
z_max: body.height(),
|
||||
})
|
||||
.with(comp::Controller::default())
|
||||
.with(body)
|
||||
.with(stats)
|
||||
.with(comp::Alignment::Npc)
|
||||
.with(comp::Energy::new(500))
|
||||
.with(comp::Collider::Box {
|
||||
radius: 0.4,
|
||||
z_min: 0.0,
|
||||
z_max: 1.75,
|
||||
})
|
||||
.with(comp::Gravity(1.0))
|
||||
.with(comp::CharacterState::default())
|
||||
.with(loadout)
|
||||
@ -127,13 +122,13 @@ impl StateExt for State {
|
||||
.with(pos)
|
||||
.with(comp::Vel(Vec3::zero()))
|
||||
.with(comp::Ori::default())
|
||||
.with(comp::Body::Object(object))
|
||||
.with(comp::Mass(5.0))
|
||||
.with(comp::Collider::Box {
|
||||
radius: 0.4,
|
||||
radius: comp::Body::Object(object).radius(),
|
||||
z_min: 0.0,
|
||||
z_max: 0.9,
|
||||
z_max: comp::Body::Object(object).height(),
|
||||
})
|
||||
.with(comp::Body::Object(object))
|
||||
.with(comp::Gravity(1.0))
|
||||
}
|
||||
|
||||
@ -223,6 +218,11 @@ impl StateExt for State {
|
||||
}),
|
||||
));
|
||||
|
||||
self.write_component(entity, comp::Collider::Box {
|
||||
radius: body.radius(),
|
||||
z_min: 0.0,
|
||||
z_max: body.height(),
|
||||
});
|
||||
self.write_component(entity, body);
|
||||
self.write_component(entity, stats);
|
||||
self.write_component(entity, inventory);
|
||||
|
@ -82,10 +82,7 @@ fn maps_idle() {
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -104,10 +101,7 @@ fn maps_run_with_sufficient_velocity() {
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -126,10 +120,7 @@ fn does_not_map_run_with_insufficient_velocity() {
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -146,13 +137,7 @@ fn does_not_map_run_with_insufficient_velocity() {
|
||||
fn does_not_map_run_with_sufficient_velocity_but_not_on_ground() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: false,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
},
|
||||
&Default::default(),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
time: Instant::now(),
|
||||
@ -173,10 +158,7 @@ fn maps_roll() {
|
||||
}),
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Run,
|
||||
@ -195,10 +177,7 @@ fn maps_land_on_ground_to_run() {
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -215,13 +194,7 @@ fn maps_land_on_ground_to_run() {
|
||||
fn maps_glider_open() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Glide {},
|
||||
&PhysicsState {
|
||||
on_ground: false,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
},
|
||||
&Default::default(),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Jump,
|
||||
time: Instant::now(),
|
||||
@ -237,13 +210,7 @@ fn maps_glider_open() {
|
||||
fn maps_glide() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Glide {},
|
||||
&PhysicsState {
|
||||
on_ground: false,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
},
|
||||
&Default::default(),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Glide,
|
||||
time: Instant::now(),
|
||||
@ -259,13 +226,7 @@ fn maps_glide() {
|
||||
fn maps_glider_close_when_closing_mid_flight() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: false,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
},
|
||||
&Default::default(),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Glide,
|
||||
time: Instant::now(),
|
||||
@ -284,10 +245,7 @@ fn maps_glider_close_when_landing() {
|
||||
&CharacterState::Idle {},
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Glide,
|
||||
@ -305,10 +263,7 @@ fn maps_quadrupeds_running() {
|
||||
let result = MovementEventMapper::map_non_humanoid_movement_event(
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
on_ceiling: false,
|
||||
on_wall: None,
|
||||
touch_entity: None,
|
||||
in_fluid: None,
|
||||
..Default::default()
|
||||
},
|
||||
Vec3::new(0.5, 0.8, 0.0),
|
||||
);
|
||||
|
@ -476,7 +476,7 @@ impl Scene {
|
||||
player_scale * 1.65
|
||||
}
|
||||
},
|
||||
CameraMode::ThirdPerson if scene_data.is_aiming => player_scale * 2.1,
|
||||
CameraMode::ThirdPerson if scene_data.is_aiming => player_scale * 2.2,
|
||||
CameraMode::ThirdPerson => player_scale * 1.65,
|
||||
CameraMode::Freefly => 0.0,
|
||||
};
|
||||
|
@ -238,7 +238,7 @@ impl PlayState for SessionState {
|
||||
(
|
||||
is_aiming,
|
||||
if is_aiming {
|
||||
Vec3::unit_z() * 0.025
|
||||
Vec3::unit_z() * 0.05
|
||||
} else {
|
||||
Vec3::zero()
|
||||
},
|
||||
|
@ -361,12 +361,14 @@ impl<'a> BlockGen<'a> {
|
||||
|
||||
Some(Block::new(
|
||||
BlockKind::Rock,
|
||||
stone_col
|
||||
- Rgb::new(
|
||||
stone_col.map2(
|
||||
Rgb::new(
|
||||
field0.get(wpos) as u8 % 16,
|
||||
field1.get(wpos) as u8 % 16,
|
||||
field2.get(wpos) as u8 % 16,
|
||||
),
|
||||
|stone, x| stone.saturating_sub(x),
|
||||
),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -38,6 +38,7 @@ pub struct Colors {
|
||||
pub beach_sand: (f32, f32, f32),
|
||||
pub desert_sand: (f32, f32, f32),
|
||||
pub snow: (f32, f32, f32),
|
||||
pub snow_moss: (f32, f32, f32),
|
||||
|
||||
pub stone_col: (u8, u8, u8),
|
||||
|
||||
@ -802,6 +803,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
beach_sand,
|
||||
desert_sand,
|
||||
snow,
|
||||
snow_moss,
|
||||
stone_col,
|
||||
dirt_low,
|
||||
dirt_high,
|
||||
@ -839,7 +841,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
warm_grass,
|
||||
marble.sub(0.5).add(1.0.sub(humidity).mul(0.5)).powf(1.5),
|
||||
);
|
||||
let snow_moss = Rgb::lerp(snow, cold_grass, 0.4 + marble.powf(1.5) * 0.6);
|
||||
let snow_moss = Rgb::lerp(snow_moss.into(), cold_grass, 0.4 + marble.powf(1.5) * 0.6);
|
||||
let moss = Rgb::lerp(dark_grass, cold_grass, marble.powf(1.5));
|
||||
let rainforest = Rgb::lerp(wet_grass, warm_grass, marble.powf(1.5));
|
||||
let sand = Rgb::lerp(beach_sand, desert_sand, marble);
|
||||
|
@ -312,20 +312,28 @@ pub fn apply_scatter_to<'a>(
|
||||
});
|
||||
|
||||
if let Some(bk) = bk {
|
||||
let mut z = col_sample.alt as i32 - 4;
|
||||
for _ in 0..8 {
|
||||
if vol
|
||||
.get(Vec3::new(offs.x, offs.y, z))
|
||||
let alt = col_sample.alt as i32;
|
||||
|
||||
// Find the intersection between ground and air, if there is one near the
|
||||
// surface
|
||||
if let Some(solid_end) = (-4..8)
|
||||
.find(|z| {
|
||||
vol.get(Vec3::new(offs.x, offs.y, alt + z))
|
||||
.map(|b| b.is_solid())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.and_then(|solid_start| {
|
||||
(1..8).map(|z| solid_start + z).find(|z| {
|
||||
vol.get(Vec3::new(offs.x, offs.y, alt + z))
|
||||
.map(|b| !b.is_solid())
|
||||
.unwrap_or(true)
|
||||
})
|
||||
})
|
||||
{
|
||||
let _ = vol.set(
|
||||
Vec3::new(offs.x, offs.y, z),
|
||||
Vec3::new(offs.x, offs.y, alt + solid_end),
|
||||
Block::new(bk, Rgb::broadcast(0)),
|
||||
);
|
||||
break;
|
||||
}
|
||||
z += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user