From 86b9e2d8e6b6d585a93f133049f38fc4f089886a Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 10 Aug 2021 19:53:39 +0300 Subject: [PATCH] Make Fireballs explode EnsnaringVines --- common/src/ray.rs | 7 ++- common/src/terrain/block.rs | 1 + common/systems/src/phys.rs | 61 ++++++++++++++++-------- common/systems/src/projectile.rs | 9 +++- server/src/events/entity_manipulation.rs | 36 +++++++++----- 5 files changed, 80 insertions(+), 34 deletions(-) diff --git a/common/src/ray.rs b/common/src/ray.rs index 2188658269..53bf7a9bc2 100644 --- a/common/src/ray.rs +++ b/common/src/ray.rs @@ -13,7 +13,12 @@ pub struct Ray<'a, V: ReadVol, F: FnMut(&V::Vox) -> bool, G: RayForEach> ignore_error: bool, } -impl<'a, V: ReadVol, F: FnMut(&V::Vox) -> bool, G: RayForEach> 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, +{ pub fn new(vol: &'a V, from: Vec3, to: Vec3, until: F) -> Self { Self { vol, diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index c2822b31b5..ab2241fecb 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -243,6 +243,7 @@ impl Block { | SpriteKind::Loom | SpriteKind::SpinningWheel | SpriteKind::TanningRack => None, + SpriteKind::EnsnaringVines => Some(0.1), _ => Some(0.25), }), } diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 6255abc1bb..a252eb244b 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -318,7 +318,8 @@ 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? + // 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 mut entity_entity_collision_checks = 0; let mut entity_entity_collisions = 0; @@ -425,25 +426,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 +911,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 +962,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; diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index 4b48cf0d4d..daa4ac59fe 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -157,8 +157,15 @@ 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. + 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, }); diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index c9e4fbff3f..5c90d6f24e 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -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, 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, explosion: Explosion, o let color_range = power * 2.7; for _ in 0..RAYS { let dir = Vec3::new( - rand::random::() - 0.5, - rand::random::() - 0.5, - rand::random::() - 0.5, + rng.gen::() - 0.5, + rng.gen::() - 0.5, + rng.gen::() - 0.5, ) .normalized(); let _ = ecs .read_resource::() .ray(pos, pos + dir * color_range) - // TODO: Faster RNG - .until(|_| rand::random::() < 0.05) + .until(|_| rng.gen::() < 0.05) .for_each(|_: &Block, pos| touched_blocks.push(pos)) .cast(); } @@ -790,21 +792,31 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o // Destroy terrain for _ in 0..RAYS { let dir = Vec3::new( - rand::random::() - 0.5, - rand::random::() - 0.5, - rand::random::() - 0.15, + rng.gen::() - 0.5, + rng.gen::() - 0.5, + rng.gen::() - 0.15, ) .normalized(); let mut ray_energy = power; let terrain = ecs.read_resource::(); + 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::() * 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::() * 0.1; + stop }) .for_each(|block: &Block, pos| {