diff --git a/assets/common/abilities/custom/harvester/ensnaringvines.ron b/assets/common/abilities/custom/harvester/ensnaringvines.ron index e4e5fd979d..b040d57b6a 100644 --- a/assets/common/abilities/custom/harvester/ensnaringvines.ron +++ b/assets/common/abilities/custom/harvester/ensnaringvines.ron @@ -4,4 +4,5 @@ SpriteSummon( recover_duration: 0.3, sprite: EnsnaringVines, summon_distance: (0, 25), + sparseness: 0.5, ) \ No newline at end of file diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 72e31105f4..d8b1413fa7 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -301,6 +301,7 @@ pub enum CharacterAbility { recover_duration: f32, sprite: SpriteKind, summon_distance: (f32, f32), + sparseness: f64, }, } @@ -1811,6 +1812,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { recover_duration, sprite, summon_distance, + sparseness, } => CharacterState::SpriteSummon(sprite_summon::Data { static_data: sprite_summon::StaticData { buildup_duration: Duration::from_secs_f32(*buildup_duration), @@ -1818,6 +1820,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { recover_duration: Duration::from_secs_f32(*recover_duration), sprite: *sprite, summon_distance: *summon_distance, + sparseness: *sparseness, ability_info, }, timer: Duration::default(), diff --git a/common/src/states/sprite_summon.rs b/common/src/states/sprite_summon.rs index 0139c4fa15..1a3610e8bd 100644 --- a/common/src/states/sprite_summon.rs +++ b/common/src/states/sprite_summon.rs @@ -9,6 +9,7 @@ use crate::{ terrain::{Block, SpriteKind}, vol::ReadVol, }; +use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use std::time::Duration; use vek::*; @@ -26,6 +27,8 @@ pub struct StaticData { pub sprite: SpriteKind, /// Range that sprites are created relative to the summonner pub summon_distance: (f32, f32), + /// Chance that sprite is not created on a particular square + pub sparseness: f64, /// Miscellaneous information about the ability pub ability_info: AbilityInfo, } @@ -77,43 +80,50 @@ impl CharacterBehavior for Data { let summon_distance = summon_distance.round() as i32; // Only summons sprites if summon distance is greater than achieved radius - if summon_distance > self.achieved_radius { + for radius in self.achieved_radius..=summon_distance { + // 1 added to make range correct, too lazy to add 1 to both variables above + let radius = radius + 1; // Creates a spiral iterator for the newly achieved radius - let spiral = Spiral2d::new().edge_radius(summon_distance); + let spiral = Spiral2d::new().edge_radius(radius); for point in spiral { - // The coordinates of where the sprite is created - let sprite_pos = Vec3::new( - data.pos.0.x.floor() as i32 + point.x, - data.pos.0.y.floor() as i32 + point.y, - data.pos.0.z.floor() as i32, - ); + // If square is not sparse, generate sprite + if !thread_rng().gen_bool(self.static_data.sparseness) { + // The coordinates of where the sprite is created + let sprite_pos = Vec3::new( + data.pos.0.x.floor() as i32 + point.x, + data.pos.0.y.floor() as i32 + point.y, + data.pos.0.z.floor() as i32, + ); - // Check for collision in z up to 10 blocks up or down - let obstacle_z = data - .terrain - .ray( - sprite_pos.map(|x| x as f32 + 0.5) + Vec3::unit_z() * 10.0, - sprite_pos.map(|x| x as f32 + 0.5) - Vec3::unit_z() * 10.0, - ) - .until(|b| { - // Until reaching a solid block that is not the created sprite - Block::is_solid(b) - && b.get_sprite() != Some(self.static_data.sprite) - }) - .cast() - .0; + // Check for collision in z up to 10 blocks up or down + let obstacle_z = data + .terrain + .ray( + sprite_pos.map(|x| x as f32 + 0.5) + Vec3::unit_z() * 10.0, + sprite_pos.map(|x| x as f32 + 0.5) - Vec3::unit_z() * 10.0, + ) + .until(|b| { + // Until reaching a solid block that is not the created + // sprite + Block::is_solid(b) + && b.get_sprite() != Some(self.static_data.sprite) + }) + .cast() + .0; - // z height relative to caster - let z = sprite_pos.z + (10.5 - obstacle_z).ceil() as i32; + // z height relative to caster + let z = sprite_pos.z + (10.5 - obstacle_z).ceil() as i32; - // Location sprite will be created - let sprite_pos = Vec3::new(sprite_pos.x as i32, sprite_pos.y as i32, z); + // Location sprite will be created + let sprite_pos = + Vec3::new(sprite_pos.x as i32, sprite_pos.y as i32, z); - // Send server event to create sprite - update.server_events.push_front(ServerEvent::CreateSprite { - pos: sprite_pos, - sprite: self.static_data.sprite, - }); + // Send server event to create sprite + update.server_events.push_front(ServerEvent::CreateSprite { + pos: sprite_pos, + sprite: self.static_data.sprite, + }); + } } }