Add a new particle mode for potion sickness.

This commit is contained in:
Avi Weinstock 2023-01-18 19:11:55 -05:00
parent dc6e61983c
commit aba6f6654e
4 changed files with 75 additions and 25 deletions

View File

@ -78,6 +78,7 @@ const int BLACK_SMOKE = 37;
const int LIGHTNING = 38;
const int STEAM = 39;
const int BARRELORGAN = 40;
const int POTION_SICKNESS = 41;
// meters per second squared (acceleration)
const float earth_gravity = 9.807;
@ -95,6 +96,12 @@ vec3 linear_motion(vec3 init_offs, vec3 vel) {
return init_offs + vel * lifetime;
}
vec3 quadratic_bezier_motion(vec3 start, vec3 ctrl0, vec3 end) {
float t = lifetime;
float u = 1 - lifetime;
return u*u*start + t*u*ctrl0 + t*t*end;
}
vec3 grav_vel(float grav) {
return vec3(0, 0, -grav * lifetime);
}
@ -637,6 +644,18 @@ void main() {
spin_in_axis(vec3(1,0,0),0)
);
break;
case POTION_SICKNESS:
attr = Attr(
quadratic_bezier_motion(
vec3(0.0),
vec3(inst_dir.xy, 0.0),
inst_dir
),
vec3((2.0 * (1 - slow_start(0.8)))),
vec4(0.075, 0.625, 0, 1),
spin_in_axis(vec3(1,0,0),0)
);
break;
default:
attr = Attr(
linear_motion(

View File

@ -436,6 +436,13 @@ impl Buff {
source,
}
}
/// Calculate how much time has elapsed since the buff was applied (if the
/// buff has a finite duration, otherwise insufficient information
/// exists to track that)
pub fn elapsed(&self) -> Option<Duration> {
self.data.duration.zip_with(self.time, |x, y| x - y)
}
}
#[cfg(not(target_arch = "wasm32"))]

View File

@ -92,6 +92,7 @@ pub enum ParticleMode {
Lightning = 38,
Steam = 39,
BarrelOrgan = 40,
PotionSickness = 41,
}
impl ParticleMode {

View File

@ -1148,11 +1148,12 @@ impl ParticleMgr {
let time = state.get_time();
let mut rng = thread_rng();
for (interp, pos, buffs, body) in (
for (interp, pos, buffs, body, ori) in (
ecs.read_storage::<Interpolated>().maybe(),
&ecs.read_storage::<Pos>(),
&ecs.read_storage::<comp::Buffs>(),
&ecs.read_storage::<Body>(),
&ecs.read_storage::<Ori>(),
)
.join()
{
@ -1161,28 +1162,10 @@ impl ParticleMgr {
for (buff_kind, buff_ids) in buffs.kinds.iter() {
use buff::BuffKind;
match buff_kind {
BuffKind::Cursed | BuffKind::Burning | BuffKind::PotionSickness => {
let mut multiplicity = if buff_kind.stacks() {
buff_ids.len()
} else {
1
};
if let BuffKind::PotionSickness = buff_kind {
// Only show particles for potion sickness at the beginning
if buff_ids
.iter()
.filter_map(|id| buffs.buffs.get(id))
.all(|buff| buff.delay.is_none())
{
multiplicity = 0;
}
}
BuffKind::Cursed | BuffKind::Burning => {
self.particles.resize_with(
self.particles.len()
+ multiplicity
* usize::from(
self.scheduler.heartbeats(Duration::from_millis(15)),
),
+ usize::from(self.scheduler.heartbeats(Duration::from_millis(15))),
|| {
let start_pos = pos
+ Vec3::unit_z() * body.height() * 0.25
@ -1198,10 +1181,10 @@ impl ParticleMgr {
Particle::new_directed(
Duration::from_secs(1),
time,
match buff_kind {
BuffKind::Cursed => ParticleMode::CultistFlame,
BuffKind::PotionSickness => ParticleMode::Blood,
_ => ParticleMode::FlameThrower,
if matches!(buff_kind, BuffKind::Cursed) {
ParticleMode::CultistFlame
} else {
ParticleMode::FlameThrower
},
start_pos,
end_pos,
@ -1209,6 +1192,46 @@ impl ParticleMgr {
},
);
},
BuffKind::PotionSickness => {
let mut multiplicity = 0;
// Only show particles for potion sickness at the beginning, after the
// drinking animation finishes
if buff_ids
.iter()
.filter_map(|id| buffs.buffs.get(id))
.any(|buff| {
matches!(buff.elapsed(), Some(dur) if Duration::from_secs(1) <= dur && dur <= Duration::from_secs_f32(1.5))
})
{
multiplicity = 1;
}
self.particles.resize_with(
self.particles.len()
+ multiplicity
* usize::from(
self.scheduler.heartbeats(Duration::from_millis(25)),
),
|| {
let start_pos = pos + Vec3::unit_z() * body.eye_height();
let (radius, theta) =
(rng.gen_range(0.0f32..1.0).sqrt(), rng.gen_range(0.0..TAU));
let end_pos = pos
+ *ori.look_dir()
+ Vec3::<f32>::new(
radius * theta.cos(),
radius * theta.sin(),
0.0,
) * 0.25;
Particle::new_directed(
Duration::from_secs(1),
time,
ParticleMode::PotionSickness,
start_pos,
end_pos,
)
},
);
},
BuffKind::Frenzied => {
self.particles.resize_with(
self.particles.len()