Ice particles for Wendigo

This commit is contained in:
Sam
2021-02-16 00:18:05 -05:00
committed by jshipsey
parent ce3b2141e1
commit 53b0ba286a
15 changed files with 138 additions and 76 deletions

View File

@ -2,12 +2,11 @@ BasicRanged(
energy_cost: 0, energy_cost: 0,
buildup_duration: 0.5, buildup_duration: 0.5,
recover_duration: 0.35, recover_duration: 0.35,
projectile: Fireball( projectile: Frostball(
damage: 100.0, damage: 100.0,
radius: 5.0, radius: 5.0,
energy_regen: 50,
), ),
projectile_body: Object(BoltFire), projectile_body: Object(BoltFire), // TODO: Get ice projectile model
/*projectile_light: Some(LightEmitter { /*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(), col: (1.0, 0.75, 0.11).into(),
..Default::default() ..Default::default()

View File

@ -93,7 +93,7 @@
abilities: [], abilities: [],
), ),
Unique(WendigoMagic): ( Unique(WendigoMagic): (
primary: "common.abilities.unique.wendigomagic.firebomb", primary: "common.abilities.unique.wendigomagic.frostbomb",
secondary: "common.abilities.unique.wendigomagic.singlestrike", secondary: "common.abilities.unique.wendigomagic.singlestrike",
skills: [], skills: [],
), ),

View File

@ -58,6 +58,7 @@ const int FIRE_SHOCKWAVE = 16;
const int FIRE_BOWL = 17; const int FIRE_BOWL = 17;
const int SNOW = 18; const int SNOW = 18;
const int EXPLOSION = 19; const int EXPLOSION = 19;
const int ICE = 20;
// meters per second squared (acceleration) // meters per second squared (acceleration)
const float earth_gravity = 9.807; const float earth_gravity = 9.807;
@ -324,7 +325,7 @@ void main() {
attr = Attr( attr = Attr(
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time), spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time),
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))), vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
vec4(vec3(0.4, 1.6 + 0.3 * sin(tick.x * 10 - lifetime * 3 + 4), 1.0 + 0.15 * sin(tick.x * 5 - lifetime * 5)), start_end(1.0, 0.0) /*0.3*/), vec4(vec3(0.4, 1.6 + 0.3 * sin(tick.x * 10 - lifetime * 3 + 4), 1.0 + 0.15 * sin(tick.x * 5 - lifetime * 5)), 1 /*0.3*/),
spin_in_axis(inst_dir, tick.z) spin_in_axis(inst_dir, tick.z)
); );
} else if (inst_mode == ENERGY_NATURE) { } else if (inst_mode == ENERGY_NATURE) {
@ -333,7 +334,7 @@ void main() {
inst_dir * slow_end(0.03) + spiral_motion(vec3(rand1, rand2, rand3), inst_dir * slow_end(0.03) + spiral_motion(vec3(rand1, rand2, rand3),
0.2 * (rand4 + 1.3) * slow_end(0.02), percent() * 3 * (rand4 + 4.0) + rand0, 1.0, 0.0), 0.2 * (rand4 + 1.3) * slow_end(0.02), percent() * 3 * (rand4 + 4.0) + rand0, 1.0, 0.0),
vec3(1.0), vec3(1.0),
vec4(vec3(0, 2.5, 1.5 + rand7 * 0.7), start_end(1.0, 0.0)), vec4(vec3(0, 2.5, 1.5 + rand7 * 0.7), 1),
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3) spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
); );
} else if (inst_mode == FLAMETHROWER) { } else if (inst_mode == FLAMETHROWER) {
@ -341,7 +342,7 @@ void main() {
attr = Attr( attr = Attr(
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (lifetime * 5 + 0.25), (inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (lifetime * 5 + 0.25),
vec3((2.5 * (1 - slow_start(0.3)))), vec3((2.5 * (1 - slow_start(0.3)))),
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, start_end(1.0, 0.0)), vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9) spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
); );
} else if (inst_mode == EXPLOSION) { } else if (inst_mode == EXPLOSION) {
@ -349,7 +350,15 @@ void main() {
attr = Attr( attr = Attr(
inst_dir * ((rand0+1.0)/2 + 0.4) * slow_end(2.0) + 0.3 * grav_vel(earth_gravity), inst_dir * ((rand0+1.0)/2 + 0.4) * slow_end(2.0) + 0.3 * grav_vel(earth_gravity),
vec3((3 * (1 - slow_start(0.1)))), vec3((3 * (1 - slow_start(0.1)))),
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, start_end(1.0, 0.0)), vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
);
} else if (inst_mode == ICE) {
f_reflect = 0.0; // Ice doesn't reflect to look like magic
attr = Attr(
inst_dir * ((rand0+1.0)/2 + 0.4) * slow_end(2.0) + 0.3 * grav_vel(earth_gravity),
vec3((3 * (1 - slow_start(0.1)))),
vec4(0.2, 1.6 + rand5 * 0.3 - 0.4 * percent(), 3, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9) spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
); );
} else if (inst_mode == FIRE_SHOCKWAVE) { } else if (inst_mode == FIRE_SHOCKWAVE) {
@ -357,7 +366,7 @@ void main() {
attr = Attr( attr = Attr(
vec3(rand0, rand1, lifetime * 10 + rand2), vec3(rand0, rand1, lifetime * 10 + rand2),
vec3((5 * (1 - slow_start(0.5)))), vec3((5 * (1 - slow_start(0.5)))),
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, start_end(1.0, 0.0)), vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
spin_in_axis(vec3(rand3, rand4, rand5), rand6) spin_in_axis(vec3(rand3, rand4, rand5), rand6)
); );
} else { } else {

View File

@ -3,6 +3,7 @@ use crate::{
Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage, Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage,
DamageSource, GroupTarget, Knockback, KnockbackDir, DamageSource, GroupTarget, Knockback, KnockbackDir,
}, },
comp::item::Reagent,
uid::Uid, uid::Uid,
Explosion, RadiusEffect, Explosion, RadiusEffect,
}; };
@ -49,6 +50,10 @@ pub enum ProjectileConstructor {
radius: f32, radius: f32,
energy_regen: f32, energy_regen: f32,
}, },
Frostball {
damage: f32,
radius: f32,
},
Firebolt { Firebolt {
damage: f32, damage: f32,
energy_regen: f32, energy_regen: f32,
@ -124,6 +129,34 @@ impl ProjectileConstructor {
RadiusEffect::TerrainDestruction(2.0), RadiusEffect::TerrainDestruction(2.0),
], ],
radius, radius,
reagent: Some(Reagent::Red),
};
Projectile {
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
hit_entity: vec![Effect::Explode(explosion), Effect::Vanish],
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
}
},
Frostball {
damage,
radius,
} => {
let damage = AttackDamage::new(
Damage {
source: DamageSource::Explosion,
value: damage,
},
Some(GroupTarget::OutOfGroup),
);
let attack = Attack::default().with_damage(damage);
let explosion = Explosion {
effects: vec![
RadiusEffect::Attack(attack),
],
radius,
reagent: Some(Reagent::Blue),
}; };
Projectile { Projectile {
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish], hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
@ -173,6 +206,7 @@ impl ProjectileConstructor {
let explosion = Explosion { let explosion = Explosion {
effects: vec![RadiusEffect::Attack(attack)], effects: vec![RadiusEffect::Attack(attack)],
radius, radius,
reagent: Some(Reagent::Green),
}; };
Projectile { Projectile {
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish], hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
@ -219,6 +253,14 @@ impl ProjectileConstructor {
*energy_regen *= regen; *energy_regen *= regen;
*radius *= range; *radius *= range;
}, },
Frostball {
ref mut damage,
ref mut radius,
..
} => {
*damage *= power;
*radius *= range;
},
Firebolt { Firebolt {
ref mut damage, ref mut damage,
ref mut energy_regen, ref mut energy_regen,

View File

@ -39,7 +39,6 @@ pub enum ServerEvent {
pos: Vec3<f32>, pos: Vec3<f32>,
explosion: Explosion, explosion: Explosion,
owner: Option<Uid>, owner: Option<Uid>,
reagent: Option<Reagent>,
}, },
Damage { Damage {
entity: EcsEntity, entity: EcsEntity,

View File

@ -1,10 +1,11 @@
use crate::{combat::Attack, effect::Effect}; use crate::{combat::Attack, effect::Effect, comp::item::Reagent};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Explosion { pub struct Explosion {
pub effects: Vec<RadiusEffect>, pub effects: Vec<RadiusEffect>,
pub radius: f32, pub radius: f32,
pub reagent: Option<Reagent>,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]

View File

@ -127,7 +127,6 @@ impl<'a> System<'a> for Sys {
pos: pos.0, pos: pos.0,
explosion: e, explosion: e,
owner: projectile.owner, owner: projectile.owner,
reagent: None,
}) })
}, },
projectile::Effect::Vanish => { projectile::Effect::Vanish => {
@ -163,7 +162,6 @@ impl<'a> System<'a> for Sys {
pos: pos.0, pos: pos.0,
explosion: e, explosion: e,
owner: projectile.owner, owner: projectile.owner,
reagent: None,
}) })
}, },
projectile::Effect::Vanish => { projectile::Effect::Vanish => {

View File

@ -1374,9 +1374,9 @@ fn handle_explosion(
RadiusEffect::TerrainDestruction(power), RadiusEffect::TerrainDestruction(power),
], ],
radius: 3.0 * power, radius: 3.0 * power,
reagent: None,
}, },
owner: ecs.read_storage::<Uid>().get(target).copied(), owner: ecs.read_storage::<Uid>().get(target).copied(),
reagent: None,
}) })
}, },
None => server.notify_client( None => server.notify_client(

View File

@ -29,7 +29,6 @@ use common::{
}; };
use common_net::{msg::ServerGeneral, sync::WorldSyncExt}; use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
use common_sys::state::BlockChange; use common_sys::state::BlockChange;
use comp::item::Reagent;
use hashbrown::HashSet; use hashbrown::HashSet;
use rand::prelude::*; use rand::prelude::*;
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt}; use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
@ -577,19 +576,13 @@ pub fn handle_explosion(
pos: Vec3<f32>, pos: Vec3<f32>,
explosion: Explosion, explosion: Explosion,
owner: Option<Uid>, owner: Option<Uid>,
reagent: Option<Reagent>,
) { ) {
// Go through all other entities // Go through all other entities
let ecs = &server.state.ecs(); let ecs = &server.state.ecs();
// Add an outcome // Add an outcome
// Uses radius as outcome power, makes negative if explosion has healing effect // Uses radius as outcome power for now
let outcome_power = explosion.radius let outcome_power = explosion.radius;
* if explosion.effects.iter().any(|e| matches!(e, RadiusEffect::Attack(a) if a.effects().any(|e| matches!(e.effect(), combat::CombatEffect::Heal(h) if *h > 0.0)))) {
-1.0
} else {
1.0
};
ecs.write_resource::<Vec<Outcome>>() ecs.write_resource::<Vec<Outcome>>()
.push(Outcome::Explosion { .push(Outcome::Explosion {
pos, pos,
@ -599,7 +592,7 @@ pub fn handle_explosion(
.effects .effects
.iter() .iter()
.any(|e| matches!(e, RadiusEffect::Attack(_))), .any(|e| matches!(e, RadiusEffect::Attack(_))),
reagent, reagent: explosion.reagent,
}); });
let owner_entity = owner.and_then(|uid| { let owner_entity = owner.and_then(|uid| {
ecs.read_resource::<UidAllocator>() ecs.read_resource::<UidAllocator>()

View File

@ -64,8 +64,7 @@ impl Server {
pos, pos,
explosion, explosion,
owner, owner,
reagent, } => handle_explosion(&self, pos, explosion, owner),
} => handle_explosion(&self, pos, explosion, owner, reagent),
ServerEvent::Shoot { ServerEvent::Shoot {
entity, entity,
dir, dir,

View File

@ -60,9 +60,9 @@ impl<'a> System<'a> for Sys {
RadiusEffect::TerrainDestruction(4.0), RadiusEffect::TerrainDestruction(4.0),
], ],
radius: 12.0, radius: 12.0,
reagent: None,
}, },
owner: *owner, owner: *owner,
reagent: None,
}); });
} }
}, },
@ -87,9 +87,9 @@ impl<'a> System<'a> for Sys {
RadiusEffect::TerrainDestruction(4.0), RadiusEffect::TerrainDestruction(4.0),
], ],
radius: 12.0, radius: 12.0,
reagent: Some(*reagent),
}, },
owner: *owner, owner: *owner,
reagent: Some(*reagent),
}); });
} }
}, },

View File

@ -91,7 +91,7 @@ use client::Client;
use common::{ use common::{
assets::{self, AssetExt, AssetHandle}, assets::{self, AssetExt, AssetHandle},
comp::{ comp::{
item::{ItemKind, ToolKind}, item::{ItemKind, Reagent, ToolKind},
object, Body, CharacterAbilityType, InventoryUpdateEvent, object, Body, CharacterAbilityType, InventoryUpdateEvent,
}, },
outcome::Outcome, outcome::Outcome,
@ -298,9 +298,10 @@ impl SfxMgr {
pos, pos,
power, power,
is_attack, is_attack,
reagent,
.. ..
} => { } => {
let file_ref = if *is_attack && *power < 0.0 { let file_ref = if *is_attack && matches!(reagent, Some(Reagent::Green)) {
"voxygen.audio.sfx.abilities.heal_bomb" "voxygen.audio.sfx.abilities.heal_bomb"
} else { } else {
"voxygen.audio.sfx.explosion" "voxygen.audio.sfx.explosion"

View File

@ -116,6 +116,7 @@ pub enum ParticleMode {
FireBowl = 17, FireBowl = 17,
Snow = 18, Snow = 18,
Explosion = 19, Explosion = 19,
Ice = 20,
} }
impl ParticleMode { impl ParticleMode {

View File

@ -406,9 +406,9 @@ impl Scene {
Outcome::Explosion { Outcome::Explosion {
pos, pos,
power, power,
radius: _, is_attack,
is_attack: _,
reagent, reagent,
..
} => self.event_lights.push(EventLight { } => self.event_lights.push(EventLight {
light: Light::new( light: Light::new(
*pos, *pos,
@ -416,20 +416,19 @@ impl Scene {
Some(Reagent::Blue) => Rgb::new(0.15, 0.4, 1.0), Some(Reagent::Blue) => Rgb::new(0.15, 0.4, 1.0),
Some(Reagent::Green) => Rgb::new(0.0, 1.0, 0.0), Some(Reagent::Green) => Rgb::new(0.0, 1.0, 0.0),
Some(Reagent::Purple) => Rgb::new(0.7, 0.0, 1.0), Some(Reagent::Purple) => Rgb::new(0.7, 0.0, 1.0),
Some(Reagent::Red) => Rgb::new(1.0, 0.0, 0.0), Some(Reagent::Red) => if *is_attack {
Some(Reagent::Yellow) => Rgb::new(1.0, 1.0, 0.0), Rgb::new(1.0, 0.5, 0.0)
None => { } else {
if *power < 0.0 { Rgb::new(1.0, 0.0, 0.0)
Rgb::new(0.0, 1.0, 0.0)
} else {
Rgb::new(1.0, 0.5, 0.0)
}
}, },
Some(Reagent::Yellow) => Rgb::new(1.0, 1.0, 0.0),
None => Rgb::new(1.0, 0.5, 0.0),
}, },
power.abs() power
* match reagent { * if *is_attack || reagent.is_none() {
Some(_) => 5.0, 2.5
None => 2.5, } else {
5.0
}, },
), ),
timeout: match reagent { timeout: match reagent {

View File

@ -62,38 +62,59 @@ impl ParticleMgr {
reagent, reagent,
} => { } => {
if *is_attack { if *is_attack {
if *power < 0.0 { match reagent {
self.particles.resize_with( Some(Reagent::Green) => {
self.particles.len() + (60.0 * power.abs()) as usize, self.particles.resize_with(
|| { self.particles.len() + (60.0 * power.abs()) as usize,
Particle::new_directed( || {
Duration::from_secs_f32(rng.gen_range(0.2..3.0)), Particle::new_directed(
time, Duration::from_secs_f32(rng.gen_range(0.2..3.0)),
ParticleMode::EnergyNature, time,
*pos, ParticleMode::EnergyNature,
*pos + Vec3::<f32>::zero() *pos,
.map(|_| rng.gen_range(-1.0..1.0)) *pos + Vec3::<f32>::zero()
.normalized() .map(|_| rng.gen_range(-1.0..1.0))
* rng.gen_range(1.0..*radius), .normalized()
) * rng.gen_range(1.0..*radius),
}, )
); },
} else { );
self.particles.resize_with( },
self.particles.len() + (75.0 * power.abs()) as usize, Some(Reagent::Red) => {
|| { self.particles.resize_with(
Particle::new_directed( self.particles.len() + (75.0 * power.abs()) as usize,
Duration::from_millis(500), || {
time, Particle::new_directed(
ParticleMode::Explosion, Duration::from_millis(500),
*pos, time,
*pos + Vec3::<f32>::zero() ParticleMode::Explosion,
.map(|_| rng.gen_range(-1.0..1.0)) *pos,
.normalized() *pos + Vec3::<f32>::zero()
* *radius, .map(|_| rng.gen_range(-1.0..1.0))
) .normalized()
}, * *radius,
); )
},
);
},
Some(Reagent::Blue) => {
self.particles.resize_with(
self.particles.len() + (75.0 * power.abs()) as usize,
|| {
Particle::new_directed(
Duration::from_millis(500),
time,
ParticleMode::Ice,
*pos,
*pos + Vec3::<f32>::zero()
.map(|_| rng.gen_range(-1.0..1.0))
.normalized()
* *radius,
)
},
);
},
_ => {},
} }
} else { } else {
self.particles.resize_with( self.particles.resize_with(