mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'juliancoffee/explode_vines' into 'master'
Make Fireballs explode EnsnaringVines See merge request veloren/veloren!2758
This commit is contained in:
commit
1fd25c22dd
@ -13,7 +13,12 @@ pub struct Ray<'a, V: ReadVol, F: FnMut(&V::Vox) -> bool, G: RayForEach<V::Vox>>
|
||||
ignore_error: bool,
|
||||
}
|
||||
|
||||
impl<'a, V: ReadVol, F: FnMut(&V::Vox) -> bool, G: RayForEach<V::Vox>> Ray<'a, V, F, G> {
|
||||
impl<'a, V, F, G> Ray<'a, V, F, G>
|
||||
where
|
||||
V: ReadVol,
|
||||
F: FnMut(&V::Vox) -> bool,
|
||||
G: RayForEach<V::Vox>,
|
||||
{
|
||||
pub fn new(vol: &'a V, from: Vec3<f32>, to: Vec3<f32>, until: F) -> Self {
|
||||
Self {
|
||||
vol,
|
||||
|
@ -243,6 +243,7 @@ impl Block {
|
||||
| SpriteKind::Loom
|
||||
| SpriteKind::SpinningWheel
|
||||
| SpriteKind::TanningRack => None,
|
||||
SpriteKind::EnsnaringVines => Some(0.1),
|
||||
_ => Some(0.25),
|
||||
}),
|
||||
}
|
||||
|
@ -318,8 +318,7 @@ impl<'a> PhysicsData<'a> {
|
||||
char_state_maybe,
|
||||
)| {
|
||||
let is_sticky = sticky.is_some();
|
||||
// Code reviewers: remind me to check why on_ground was true instead of false here?
|
||||
let is_mid_air = physics.on_wall.is_none() && physics.on_ground.is_some();
|
||||
let is_mid_air = physics.on_surface().is_none();
|
||||
let mut entity_entity_collision_checks = 0;
|
||||
let mut entity_entity_collisions = 0;
|
||||
|
||||
@ -425,25 +424,43 @@ impl<'a> PhysicsData<'a> {
|
||||
entity_entity_collisions += 1;
|
||||
}
|
||||
|
||||
// Don't apply e2e pushback to entities that are in a forced movement state
|
||||
// (e.g. roll, leapmelee). This allows leaps to work properly (since you won't
|
||||
// get pushed away before delivering the hit), and allows rolling through an
|
||||
// enemy when trapped (e.g. with minotaur). This allows using e2e pushback to
|
||||
// gain speed by jumping out of a roll while in the middle of a collider, this
|
||||
// is an intentional combat mechanic.
|
||||
let forced_movement = matches!(char_state_maybe, Some(cs) if cs.is_forced_movement());
|
||||
|
||||
// Don't apply repulsive force to projectiles or if we're colliding with a
|
||||
// terrain-like entity, or if we are a terrain-like entity
|
||||
// Don't apply e2e pushback to entities
|
||||
// that are in a forced movement state
|
||||
// (e.g. roll, leapmelee).
|
||||
//
|
||||
// Don't apply force when entity is a sticky which is on the
|
||||
// This allows leaps to work properly
|
||||
// (since you won't get pushed away before
|
||||
// delivering the hit), and allows
|
||||
// rolling through an enemy when trapped
|
||||
// (e.g. with minotaur).
|
||||
//
|
||||
// This allows using e2e pushback to
|
||||
// gain speed by jumping out of a roll
|
||||
// while in the middle of a collider, this
|
||||
// is an intentional combat mechanic.
|
||||
let forced_movement = matches!(
|
||||
char_state_maybe,
|
||||
Some(cs) if cs.is_forced_movement());
|
||||
|
||||
// Don't apply repulsive force
|
||||
// to projectiles
|
||||
//
|
||||
// or if we're colliding with a
|
||||
// terrain-like entity,
|
||||
//
|
||||
// or if we are a terrain-like entity
|
||||
//
|
||||
// Don't apply force when entity
|
||||
// is a sticky which is on the
|
||||
// ground (or on the wall)
|
||||
if !forced_movement
|
||||
&& (!is_sticky
|
||||
|| is_mid_air)
|
||||
&& (!is_sticky || is_mid_air)
|
||||
&& diff.magnitude_squared() > 0.0
|
||||
&& !is_projectile
|
||||
&& !matches!(collider_other,Some(Collider::Voxel { .. }))
|
||||
&& !matches!(
|
||||
collider_other,
|
||||
Some(Collider::Voxel { .. })
|
||||
)
|
||||
&& !matches!(collider, Some(Collider::Voxel { .. }))
|
||||
{
|
||||
let force = 400.0
|
||||
@ -892,7 +909,8 @@ impl<'a> PhysicsData<'a> {
|
||||
.try_normalized()
|
||||
.unwrap_or_else(Vec3::zero);
|
||||
|
||||
// See whether we're on the top/bottom of a block, or the side
|
||||
// See whether we're on the top/bottom of a block,
|
||||
// or the side
|
||||
if block_rpos.z.abs()
|
||||
> block_rpos.xy().map(|e| e.abs()).reduce_partial_max()
|
||||
{
|
||||
@ -942,11 +960,12 @@ impl<'a> PhysicsData<'a> {
|
||||
},
|
||||
}
|
||||
|
||||
// Compute center and radius of tick path bounding sphere for the entity
|
||||
// for broad checks of whether it will collide with a voxel collider
|
||||
// Compute center and radius of tick path bounding sphere
|
||||
// for the entity for broad checks of whether it will
|
||||
// collide with a voxel collider
|
||||
let path_sphere = {
|
||||
// TODO: duplicated with maintain_pushback_cache, make a common function
|
||||
// to call to compute all this info?
|
||||
// TODO: duplicated with maintain_pushback_cache,
|
||||
// make a common function to call to compute all this info?
|
||||
let z_limits = calc_z_limit(character_state, Some(collider));
|
||||
let z_limits = (z_limits.0 * scale, z_limits.1 * scale);
|
||||
let half_height = (z_limits.1 - z_limits.0) / 2.0;
|
||||
|
@ -157,8 +157,19 @@ impl<'a> System<'a> for Sys {
|
||||
for effect in projectile.hit_solid.drain(..) {
|
||||
match effect {
|
||||
projectile::Effect::Explode(e) => {
|
||||
// We offset position a little back on the way,
|
||||
// so if we hit non-exploadable block
|
||||
// we still can affect blocks around it.
|
||||
//
|
||||
// TODO: orientation of fallen projectile is
|
||||
// fragile heuristic for direction, find more
|
||||
// robust method.
|
||||
let projectile_direction = orientations
|
||||
.get(entity)
|
||||
.map_or_else(Vec3::zero, |ori| ori.look_vec());
|
||||
let offset = -0.2 * projectile_direction;
|
||||
server_emitter.emit(ServerEvent::Explosion {
|
||||
pos: pos.0,
|
||||
pos: pos.0 + offset,
|
||||
explosion: e,
|
||||
owner: projectile.owner,
|
||||
});
|
||||
|
@ -34,6 +34,7 @@ use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
|
||||
use common_state::BlockChange;
|
||||
use comp::chat::GenericChatMsg;
|
||||
use hashbrown::HashSet;
|
||||
use rand::Rng;
|
||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||
use tracing::error;
|
||||
use vek::{Vec2, Vec3};
|
||||
@ -738,6 +739,8 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
((horiz_dist.max(vert_distance).max(0.0) / radius).min(1.0) - 1.0).abs()
|
||||
}
|
||||
|
||||
// TODO: Faster RNG?
|
||||
let mut rng = rand::thread_rng();
|
||||
for effect in explosion.effects {
|
||||
match effect {
|
||||
RadiusEffect::TerrainDestruction(power) => {
|
||||
@ -748,17 +751,16 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
let color_range = power * 2.7;
|
||||
for _ in 0..RAYS {
|
||||
let dir = Vec3::new(
|
||||
rand::random::<f32>() - 0.5,
|
||||
rand::random::<f32>() - 0.5,
|
||||
rand::random::<f32>() - 0.5,
|
||||
rng.gen::<f32>() - 0.5,
|
||||
rng.gen::<f32>() - 0.5,
|
||||
rng.gen::<f32>() - 0.5,
|
||||
)
|
||||
.normalized();
|
||||
|
||||
let _ = ecs
|
||||
.read_resource::<TerrainGrid>()
|
||||
.ray(pos, pos + dir * color_range)
|
||||
// TODO: Faster RNG
|
||||
.until(|_| rand::random::<f32>() < 0.05)
|
||||
.until(|_| rng.gen::<f32>() < 0.05)
|
||||
.for_each(|_: &Block, pos| touched_blocks.push(pos))
|
||||
.cast();
|
||||
}
|
||||
@ -790,21 +792,31 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
// Destroy terrain
|
||||
for _ in 0..RAYS {
|
||||
let dir = Vec3::new(
|
||||
rand::random::<f32>() - 0.5,
|
||||
rand::random::<f32>() - 0.5,
|
||||
rand::random::<f32>() - 0.15,
|
||||
rng.gen::<f32>() - 0.5,
|
||||
rng.gen::<f32>() - 0.5,
|
||||
rng.gen::<f32>() - 0.15,
|
||||
)
|
||||
.normalized();
|
||||
|
||||
let mut ray_energy = power;
|
||||
|
||||
let terrain = ecs.read_resource::<TerrainGrid>();
|
||||
let from = pos;
|
||||
let to = pos + dir * power;
|
||||
let _ = terrain
|
||||
.ray(pos, pos + dir * power)
|
||||
// TODO: Faster RNG
|
||||
.ray(from, to)
|
||||
.until(|block: &Block| {
|
||||
let stop = block.is_liquid() || block.explode_power().is_none() || ray_energy <= 0.0;
|
||||
ray_energy -= block.explode_power().unwrap_or(0.0) + rand::random::<f32>() * 0.1;
|
||||
// Stop if:
|
||||
// 1) Block is liquid
|
||||
// 2) Consumed all energy
|
||||
// 3) Can't explode block (for example we hit stone wall)
|
||||
let stop = block.is_liquid()
|
||||
|| block.explode_power().is_none()
|
||||
|| ray_energy <= 0.0;
|
||||
|
||||
ray_energy -=
|
||||
block.explode_power().unwrap_or(0.0) + rng.gen::<f32>() * 0.1;
|
||||
|
||||
stop
|
||||
})
|
||||
.for_each(|block: &Block, pos| {
|
||||
|
Loading…
Reference in New Issue
Block a user