mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
autodelete of summoned sprites
This commit is contained in:
parent
b127cff26c
commit
650ef9a5e2
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -6177,6 +6177,15 @@ dependencies = [
|
|||||||
"num_threads",
|
"num_threads",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "timer-queue"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13756c29c43d836ff576221498bf4916b0d2f7ea24cd47d3531b70dc4341f038"
|
||||||
|
dependencies = [
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-keccak"
|
name = "tiny-keccak"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@ -6826,6 +6835,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"specs",
|
"specs",
|
||||||
"tar",
|
"tar",
|
||||||
|
"timer-queue",
|
||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"vek 0.15.8",
|
"vek 0.15.8",
|
||||||
|
@ -3,6 +3,7 @@ SpriteSummon(
|
|||||||
cast_duration: 0.4,
|
cast_duration: 0.4,
|
||||||
recover_duration: 0.3,
|
recover_duration: 0.3,
|
||||||
sprite: EnsnaringWeb,
|
sprite: EnsnaringWeb,
|
||||||
|
del_timeout: None,
|
||||||
summon_distance: (0, 10),
|
summon_distance: (0, 10),
|
||||||
sparseness: 0.76,
|
sparseness: 0.76,
|
||||||
)
|
)
|
@ -3,6 +3,7 @@ SpriteSummon(
|
|||||||
cast_duration: 0.4,
|
cast_duration: 0.4,
|
||||||
recover_duration: 0.3,
|
recover_duration: 0.3,
|
||||||
sprite: EnsnaringWeb,
|
sprite: EnsnaringWeb,
|
||||||
|
del_timeout: None,
|
||||||
summon_distance: (0, 9),
|
summon_distance: (0, 9),
|
||||||
sparseness: 0.8,
|
sparseness: 0.8,
|
||||||
)
|
)
|
@ -3,6 +3,7 @@ SpriteSummon(
|
|||||||
cast_duration: 0.1,
|
cast_duration: 0.1,
|
||||||
recover_duration: 0.9,
|
recover_duration: 0.9,
|
||||||
sprite: SeaUrchin,
|
sprite: SeaUrchin,
|
||||||
|
del_timeout: Some((4, 5)),
|
||||||
summon_distance: (5, 3.1),
|
summon_distance: (5, 3.1),
|
||||||
sparseness: 0.2,
|
sparseness: 0.2,
|
||||||
)
|
)
|
@ -3,6 +3,7 @@ SpriteSummon(
|
|||||||
cast_duration: 0.4,
|
cast_duration: 0.4,
|
||||||
recover_duration: 0.3,
|
recover_duration: 0.3,
|
||||||
sprite: EnsnaringVines,
|
sprite: EnsnaringVines,
|
||||||
|
del_timeout: None,
|
||||||
summon_distance: (0, 25),
|
summon_distance: (0, 25),
|
||||||
sparseness: 0.67,
|
sparseness: 0.67,
|
||||||
)
|
)
|
@ -700,6 +700,7 @@ pub enum CharacterAbility {
|
|||||||
cast_duration: f32,
|
cast_duration: f32,
|
||||||
recover_duration: f32,
|
recover_duration: f32,
|
||||||
sprite: SpriteKind,
|
sprite: SpriteKind,
|
||||||
|
del_timeout: Option<(f32, f32)>,
|
||||||
summon_distance: (f32, f32),
|
summon_distance: (f32, f32),
|
||||||
sparseness: f64,
|
sparseness: f64,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -1275,6 +1276,7 @@ impl CharacterAbility {
|
|||||||
ref mut cast_duration,
|
ref mut cast_duration,
|
||||||
ref mut recover_duration,
|
ref mut recover_duration,
|
||||||
sprite: _,
|
sprite: _,
|
||||||
|
del_timeout: _,
|
||||||
summon_distance: (ref mut inner_dist, ref mut outer_dist),
|
summon_distance: (ref mut inner_dist, ref mut outer_dist),
|
||||||
sparseness: _,
|
sparseness: _,
|
||||||
meta: _,
|
meta: _,
|
||||||
@ -2508,6 +2510,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
|||||||
cast_duration,
|
cast_duration,
|
||||||
recover_duration,
|
recover_duration,
|
||||||
sprite,
|
sprite,
|
||||||
|
del_timeout,
|
||||||
summon_distance,
|
summon_distance,
|
||||||
sparseness,
|
sparseness,
|
||||||
meta: _,
|
meta: _,
|
||||||
@ -2517,6 +2520,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
|||||||
cast_duration: Duration::from_secs_f32(*cast_duration),
|
cast_duration: Duration::from_secs_f32(*cast_duration),
|
||||||
recover_duration: Duration::from_secs_f32(*recover_duration),
|
recover_duration: Duration::from_secs_f32(*recover_duration),
|
||||||
sprite: *sprite,
|
sprite: *sprite,
|
||||||
|
del_timeout: *del_timeout,
|
||||||
summon_distance: *summon_distance,
|
summon_distance: *summon_distance,
|
||||||
sparseness: *sparseness,
|
sparseness: *sparseness,
|
||||||
ability_info,
|
ability_info,
|
||||||
|
@ -208,6 +208,7 @@ pub enum ServerEvent {
|
|||||||
CreateSprite {
|
CreateSprite {
|
||||||
pos: Vec3<i32>,
|
pos: Vec3<i32>,
|
||||||
sprite: SpriteKind,
|
sprite: SpriteKind,
|
||||||
|
del_timeout: Option<(f32, f32)>,
|
||||||
},
|
},
|
||||||
TamePet {
|
TamePet {
|
||||||
pet_entity: EcsEntity,
|
pet_entity: EcsEntity,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{combat::DamageContributor, comp, uid::Uid, DamageSource};
|
use crate::{combat::DamageContributor, comp, uid::Uid, DamageSource, terrain::SpriteKind};
|
||||||
use comp::{beam, item::Reagent, poise::PoiseState, skillset::SkillGroupKind, UtteranceKind};
|
use comp::{beam, item::Reagent, poise::PoiseState, skillset::SkillGroupKind, UtteranceKind};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -97,6 +97,10 @@ pub enum Outcome {
|
|||||||
pos: Vec3<f32>,
|
pos: Vec3<f32>,
|
||||||
wielded: bool,
|
wielded: bool,
|
||||||
},
|
},
|
||||||
|
SpriteDelete {
|
||||||
|
pos: Vec3<f32>,
|
||||||
|
sprite: SpriteKind,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Outcome {
|
impl Outcome {
|
||||||
@ -115,6 +119,7 @@ impl Outcome {
|
|||||||
| Outcome::PoiseChange { pos, .. }
|
| Outcome::PoiseChange { pos, .. }
|
||||||
| Outcome::GroundSlam { pos }
|
| Outcome::GroundSlam { pos }
|
||||||
| Outcome::Utterance { pos, .. }
|
| Outcome::Utterance { pos, .. }
|
||||||
|
| Outcome::SpriteDelete { pos, .. }
|
||||||
| Outcome::Glider { pos, .. } => Some(*pos),
|
| Outcome::Glider { pos, .. } => Some(*pos),
|
||||||
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
|
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
|
||||||
Outcome::ExpChange { .. }
|
Outcome::ExpChange { .. }
|
||||||
|
@ -25,6 +25,8 @@ pub struct StaticData {
|
|||||||
pub recover_duration: Duration,
|
pub recover_duration: Duration,
|
||||||
/// What kind of sprite is created by this state
|
/// What kind of sprite is created by this state
|
||||||
pub sprite: SpriteKind,
|
pub sprite: SpriteKind,
|
||||||
|
/// Duration until sprite-delete begins (in sec), randomization-range of sprite-delete-time (in sec)
|
||||||
|
pub del_timeout: Option<(f32, f32)>,
|
||||||
/// Range that sprites are created relative to the summonner
|
/// Range that sprites are created relative to the summonner
|
||||||
pub summon_distance: (f32, f32),
|
pub summon_distance: (f32, f32),
|
||||||
/// Chance that sprite is not created on a particular square
|
/// Chance that sprite is not created on a particular square
|
||||||
@ -127,6 +129,7 @@ impl CharacterBehavior for Data {
|
|||||||
output_events.emit_server(ServerEvent::CreateSprite {
|
output_events.emit_server(ServerEvent::CreateSprite {
|
||||||
pos: Vec3::new(sprite_pos.x, sprite_pos.y, z + i),
|
pos: Vec3::new(sprite_pos.x, sprite_pos.y, z + i),
|
||||||
sprite: self.static_data.sprite,
|
sprite: self.static_data.sprite,
|
||||||
|
del_timeout: self.static_data.del_timeout,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ tar = { version = "0.4.37", optional = true }
|
|||||||
wasmer = { version = "2.0.0", optional = true, default-features = false, features = ["wat", "default-cranelift", "default-universal"] }
|
wasmer = { version = "2.0.0", optional = true, default-features = false, features = ["wat", "default-cranelift", "default-universal"] }
|
||||||
bincode = { version = "1.3.1", optional = true }
|
bincode = { version = "1.3.1", optional = true }
|
||||||
plugin-api = { package = "veloren-plugin-api", path = "../../plugin/api", optional = true }
|
plugin-api = { package = "veloren-plugin-api", path = "../../plugin/api", optional = true }
|
||||||
|
timer-queue = "0.1.0"
|
||||||
|
|
||||||
# Tweak running code
|
# Tweak running code
|
||||||
#inline_tweak = { version = "1.0.8", features = ["release_tweak"] }
|
#inline_tweak = { version = "1.0.8", features = ["release_tweak"] }
|
||||||
|
@ -36,18 +36,20 @@ use specs::{
|
|||||||
Component, DispatcherBuilder, Entity as EcsEntity, WorldExt,
|
Component, DispatcherBuilder, Entity as EcsEntity, WorldExt,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use timer_queue::TimerQueue;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// How much faster should an in-game day be compared to a real day?
|
/// How much faster should an in-game day be compared to a real day?
|
||||||
// TODO: Don't hard-code this.
|
// TODO: Don't hard-code this.
|
||||||
const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
|
const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
|
||||||
|
|
||||||
/// At what point should we stop speeding up physics to compensate for lag? If
|
/// At what point should we stop speeding up physics to compensate for lag? If
|
||||||
/// we speed physics up too fast, we'd skip important physics events like
|
/// we speed physics up too fast, we'd skip important physics events like
|
||||||
/// collisions. This constant determines the upper limit. If delta time exceeds
|
/// collisions. This constant determines the upper limit. If delta time exceeds
|
||||||
/// this value, the game's physics will begin to produce time lag. Ideally, we'd
|
/// this value, the game's physics will begin to produce time lag. Ideally, we'd
|
||||||
/// avoid such a situation.
|
/// avoid such a situation.
|
||||||
const MAX_DELTA_TIME: f32 = 1.0;
|
const MAX_DELTA_TIME: f32 = 1.0;
|
||||||
|
/// convert seconds to milliseconds to use in TimerQueue
|
||||||
|
const SECONDS_TO_MILLISECONDS: f64 = 1000.0;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BlockChange {
|
pub struct BlockChange {
|
||||||
@ -69,6 +71,29 @@ impl BlockChange {
|
|||||||
pub fn clear(&mut self) { self.blocks.clear(); }
|
pub fn clear(&mut self) { self.blocks.clear(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ScheduledBlockChange {
|
||||||
|
changes: TimerQueue<HashMap<Vec3<i32>, Block>>,
|
||||||
|
outcomes: TimerQueue<HashMap<Vec3<i32>, Block>>,
|
||||||
|
}
|
||||||
|
impl ScheduledBlockChange {
|
||||||
|
pub fn set(&mut self, pos: Vec3<i32>, block: Block, replace_time: f64) {
|
||||||
|
let timer = self.changes.insert(
|
||||||
|
(replace_time * SECONDS_TO_MILLISECONDS) as u64,
|
||||||
|
HashMap::new(),
|
||||||
|
);
|
||||||
|
self.changes.get_mut(timer).insert(pos, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outcome_set(&mut self, pos: Vec3<i32>, block: Block, replace_time: f64) {
|
||||||
|
let outcome_timer = self.outcomes.insert(
|
||||||
|
(replace_time * SECONDS_TO_MILLISECONDS) as u64,
|
||||||
|
HashMap::new(),
|
||||||
|
);
|
||||||
|
self.outcomes.get_mut(outcome_timer).insert(pos, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TerrainChanges {
|
pub struct TerrainChanges {
|
||||||
pub new_chunks: HashSet<Vec2<i32>>,
|
pub new_chunks: HashSet<Vec2<i32>>,
|
||||||
@ -234,6 +259,7 @@ impl State {
|
|||||||
ecs.insert(PlayerEntity(None));
|
ecs.insert(PlayerEntity(None));
|
||||||
ecs.insert(TerrainGrid::new(map_size_lg, default_chunk).unwrap());
|
ecs.insert(TerrainGrid::new(map_size_lg, default_chunk).unwrap());
|
||||||
ecs.insert(BlockChange::default());
|
ecs.insert(BlockChange::default());
|
||||||
|
ecs.insert(ScheduledBlockChange::default());
|
||||||
ecs.insert(crate::build_areas::BuildAreas::default());
|
ecs.insert(crate::build_areas::BuildAreas::default());
|
||||||
ecs.insert(TerrainChanges::default());
|
ecs.insert(TerrainChanges::default());
|
||||||
ecs.insert(EventBus::<LocalEvent>::default());
|
ecs.insert(EventBus::<LocalEvent>::default());
|
||||||
@ -415,6 +441,23 @@ impl State {
|
|||||||
self.ecs.write_resource::<BlockChange>().set(pos, block);
|
self.ecs.write_resource::<BlockChange>().set(pos, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a block in this state's terrain (used to delete temporary summoned
|
||||||
|
/// sprites after a timeout).
|
||||||
|
pub fn schedule_set_block(
|
||||||
|
&self,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
block: Block,
|
||||||
|
sprite_block: Block,
|
||||||
|
replace_time: f64,
|
||||||
|
) {
|
||||||
|
self.ecs
|
||||||
|
.write_resource::<ScheduledBlockChange>()
|
||||||
|
.set(pos, block, replace_time);
|
||||||
|
self.ecs
|
||||||
|
.write_resource::<ScheduledBlockChange>()
|
||||||
|
.outcome_set(pos, sprite_block, replace_time);
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if the block at given position `pos` has already been modified
|
/// Check if the block at given position `pos` has already been modified
|
||||||
/// this tick.
|
/// this tick.
|
||||||
pub fn can_set_block(&self, pos: Vec3<i32>) -> bool {
|
pub fn can_set_block(&self, pos: Vec3<i32>) -> bool {
|
||||||
@ -500,6 +543,28 @@ impl State {
|
|||||||
let mut terrain = self.ecs.write_resource::<TerrainGrid>();
|
let mut terrain = self.ecs.write_resource::<TerrainGrid>();
|
||||||
let mut modified_blocks =
|
let mut modified_blocks =
|
||||||
std::mem::take(&mut self.ecs.write_resource::<BlockChange>().blocks);
|
std::mem::take(&mut self.ecs.write_resource::<BlockChange>().blocks);
|
||||||
|
|
||||||
|
let mut scheduled_changes = self.ecs.write_resource::<ScheduledBlockChange>();
|
||||||
|
let current_time: f64 = self.ecs.read_resource::<Time>().0 * SECONDS_TO_MILLISECONDS;
|
||||||
|
while let Some(changes) = scheduled_changes.changes.poll(current_time as u64) {
|
||||||
|
modified_blocks.extend(changes.iter());
|
||||||
|
}
|
||||||
|
let outcome = self.ecs.read_resource::<EventBus<Outcome>>();
|
||||||
|
while let Some(outcomes) = scheduled_changes.outcomes.poll(current_time as u64) {
|
||||||
|
for (pos, block) in outcomes.iter() {
|
||||||
|
let offset_dir = Vec3::<i32>::zero() - pos;
|
||||||
|
let offset = offset_dir
|
||||||
|
/ Vec3::new(offset_dir.x.abs(), offset_dir.y.abs(), offset_dir.z.abs());
|
||||||
|
let outcome_pos = Vec3::new(pos.x as f32, pos.y as f32, pos.z as f32)
|
||||||
|
- (Vec3::new(offset.x as f32, offset.y as f32, offset.z as f32) / 2.0);
|
||||||
|
if let Some(sprite) = block.get_sprite() {
|
||||||
|
outcome.emit_now(Outcome::SpriteDelete {
|
||||||
|
pos: outcome_pos,
|
||||||
|
sprite,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Apply block modifications
|
// Apply block modifications
|
||||||
// Only include in `TerrainChanges` if successful
|
// Only include in `TerrainChanges` if successful
|
||||||
modified_blocks.retain(|pos, block| {
|
modified_blocks.retain(|pos, block| {
|
||||||
|
@ -23,7 +23,7 @@ use common::{
|
|||||||
};
|
};
|
||||||
use common_net::sync::WorldSyncExt;
|
use common_net::sync::WorldSyncExt;
|
||||||
|
|
||||||
use crate::{state_ext::StateExt, Server};
|
use crate::{state_ext::StateExt, Server, Time};
|
||||||
|
|
||||||
use crate::pet::tame_pet;
|
use crate::pet::tame_pet;
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
@ -293,16 +293,32 @@ pub fn handle_sound(server: &mut Server, sound: &Sound) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_create_sprite(server: &mut Server, pos: Vec3<i32>, sprite: SpriteKind) {
|
pub fn handle_create_sprite(
|
||||||
|
server: &mut Server,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
sprite: SpriteKind,
|
||||||
|
del_timeout: Option<(f32, f32)>,
|
||||||
|
) {
|
||||||
let state = server.state_mut();
|
let state = server.state_mut();
|
||||||
if state.can_set_block(pos) {
|
if state.can_set_block(pos) {
|
||||||
let block = state.terrain().get(pos).ok().copied();
|
let block = state.terrain().get(pos).ok().copied();
|
||||||
if block.map_or(false, |b| (*b).is_air()) {
|
if block.map_or(false, |b| (*b).is_air()) {
|
||||||
let new_block = state
|
let old_block = block.unwrap_or_else(|| Block::air(SpriteKind::Empty));
|
||||||
.get_block(pos)
|
let new_block = old_block.with_sprite(sprite);
|
||||||
.unwrap_or_else(|| Block::air(SpriteKind::Empty))
|
state.set_block(pos, new_block);
|
||||||
.with_sprite(sprite);
|
// Remove sprite after del_timeout and offset if specified
|
||||||
server.state.set_block(pos, new_block);
|
if let Some((timeout, del_offset)) = del_timeout {
|
||||||
|
use rand::Rng;
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let offset = rng.gen_range(0.0..del_offset);
|
||||||
|
let current_time: f64 = state.ecs().read_resource::<Time>().0;
|
||||||
|
let replace_time = current_time + (timeout + offset) as f64;
|
||||||
|
if old_block != new_block {
|
||||||
|
server
|
||||||
|
.state
|
||||||
|
.schedule_set_block(pos, old_block, new_block, replace_time)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,9 +267,11 @@ impl Server {
|
|||||||
self.state.create_safezone(range, pos).build();
|
self.state.create_safezone(range, pos).build();
|
||||||
},
|
},
|
||||||
ServerEvent::Sound { sound } => handle_sound(self, &sound),
|
ServerEvent::Sound { sound } => handle_sound(self, &sound),
|
||||||
ServerEvent::CreateSprite { pos, sprite } => {
|
ServerEvent::CreateSprite {
|
||||||
handle_create_sprite(self, pos, sprite)
|
pos,
|
||||||
},
|
sprite,
|
||||||
|
del_timeout,
|
||||||
|
} => handle_create_sprite(self, pos, sprite, del_timeout),
|
||||||
ServerEvent::TamePet {
|
ServerEvent::TamePet {
|
||||||
pet_entity,
|
pet_entity,
|
||||||
owner_entity,
|
owner_entity,
|
||||||
|
@ -101,7 +101,7 @@ use common::{
|
|||||||
InventoryUpdateEvent, UtteranceKind,
|
InventoryUpdateEvent, UtteranceKind,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
terrain::{BlockKind, TerrainChunk},
|
terrain::{BlockKind, SpriteKind, TerrainChunk},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
DamageSource,
|
DamageSource,
|
||||||
};
|
};
|
||||||
@ -585,6 +585,23 @@ impl SfxMgr {
|
|||||||
audio.emit_sfx(sfx_trigger_item, *pos, Some(1.0), underwater);
|
audio.emit_sfx(sfx_trigger_item, *pos, Some(1.0), underwater);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Outcome::SpriteDelete { pos, sprite } => {
|
||||||
|
match sprite {
|
||||||
|
SpriteKind::SeaUrchin => {
|
||||||
|
let power = (0.6 - pos.distance(audio.listener.pos) / 5_000.0)
|
||||||
|
.max(0.0)
|
||||||
|
.powi(7);
|
||||||
|
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Explosion);
|
||||||
|
audio.emit_sfx(
|
||||||
|
sfx_trigger_item,
|
||||||
|
*pos,
|
||||||
|
Some((power.abs() / 2.5).min(0.3)),
|
||||||
|
underwater,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
},
|
||||||
Outcome::ExpChange { .. }
|
Outcome::ExpChange { .. }
|
||||||
| Outcome::ComboChange { .. }
|
| Outcome::ComboChange { .. }
|
||||||
| Outcome::SummonedCreature { .. } => {},
|
| Outcome::SummonedCreature { .. } => {},
|
||||||
|
@ -19,7 +19,7 @@ use common::{
|
|||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
states::{self, utils::StageSection},
|
states::{self, utils::StageSection},
|
||||||
terrain::{Block, TerrainChunk, TerrainGrid},
|
terrain::{Block, SpriteKind, TerrainChunk, TerrainGrid},
|
||||||
uid::UidAllocator,
|
uid::UidAllocator,
|
||||||
vol::{ReadVol, RectRasterableVol, SizedVol},
|
vol::{ReadVol, RectRasterableVol, SizedVol},
|
||||||
};
|
};
|
||||||
@ -74,6 +74,21 @@ impl ParticleMgr {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
Outcome::SpriteDelete { pos, sprite } => match sprite {
|
||||||
|
SpriteKind::SeaUrchin => {
|
||||||
|
self.particles.resize_with(self.particles.len() + 10, || {
|
||||||
|
Particle::new_directed(
|
||||||
|
Duration::from_secs_f32(rng.gen_range(0.1..0.5)),
|
||||||
|
time,
|
||||||
|
ParticleMode::Steam,
|
||||||
|
*pos + Vec3::new(0.0, 0.0, rng.gen_range(0.0..1.5)),
|
||||||
|
*pos,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SpriteKind::EnsnaringVines => {},
|
||||||
|
_ => {},
|
||||||
|
},
|
||||||
Outcome::Explosion {
|
Outcome::Explosion {
|
||||||
pos,
|
pos,
|
||||||
power,
|
power,
|
||||||
|
Loading…
Reference in New Issue
Block a user