veloren/common/src/comp/projectile.rs

296 lines
9.4 KiB
Rust
Raw Normal View History

use crate::{
comp::buff::{BuffCategory, BuffData, BuffKind},
2020-11-13 03:50:40 +00:00
effect::{self, BuffEffect},
uid::Uid,
Damage, DamageSource, Explosion, GroupTarget, Knockback, KnockbackDir, RadiusEffect,
};
use serde::{Deserialize, Serialize};
use specs::Component;
use specs_idvs::IdvStorage;
use std::time::Duration;
2019-09-17 12:43:19 +00:00
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2019-09-17 12:43:19 +00:00
pub enum Effect {
Damage(Option<GroupTarget>, Damage),
2020-10-18 18:21:58 +00:00
Knockback(Knockback),
2020-03-27 16:07:19 +00:00
RewardEnergy(u32),
Explode(Explosion),
2019-09-17 12:43:19 +00:00
Vanish,
2019-09-28 19:35:28 +00:00
Stick,
Possess,
Buff {
buff: BuffEffect,
chance: Option<f32>,
},
2019-09-17 12:43:19 +00:00
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2019-09-17 12:43:19 +00:00
pub struct Projectile {
2019-11-04 00:57:36 +00:00
// TODO: use SmallVec for these effects
2020-04-26 15:16:35 +00:00
pub hit_solid: Vec<Effect>,
2019-09-17 12:43:19 +00:00
pub hit_entity: Vec<Effect>,
/// Time left until the projectile will despawn
pub time_left: Duration,
pub owner: Option<Uid>,
/// Whether projectile collides with entities in the same group as its
/// owner
pub ignore_group: bool,
2019-09-17 12:43:19 +00:00
}
impl Component for Projectile {
type Storage = IdvStorage<Self>;
2019-09-17 12:43:19 +00:00
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ProjectileConstructor {
Arrow {
damage: f32,
knockback: f32,
energy_regen: u32,
},
Fireball {
damage: f32,
radius: f32,
energy_regen: u32,
},
2020-12-24 17:54:00 +00:00
Firebolt {
damage: f32,
energy_regen: u32,
},
Heal {
heal: f32,
damage: f32,
radius: f32,
},
Possess,
}
impl ProjectileConstructor {
pub fn create_projectile(self, owner: Option<Uid>) -> Projectile {
use ProjectileConstructor::*;
match self {
Arrow {
damage,
knockback,
energy_regen,
} => {
let buff = BuffEffect {
kind: BuffKind::Bleeding,
data: BuffData {
strength: damage / 2.0,
duration: Some(Duration::from_secs(5)),
},
cat_ids: vec![BuffCategory::Physical],
};
Projectile {
hit_solid: vec![Effect::Stick],
hit_entity: vec![
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Projectile,
value: damage,
}),
Effect::Knockback(Knockback {
strength: knockback,
direction: KnockbackDir::Away,
}),
Effect::RewardEnergy(energy_regen),
Effect::Vanish,
Effect::Buff {
buff,
chance: Some(0.10),
},
],
time_left: Duration::from_secs(15),
owner,
ignore_group: true,
}
},
Fireball {
damage,
radius,
energy_regen,
} => Projectile {
hit_solid: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
),
RadiusEffect::TerrainDestruction(2.0),
],
radius,
energy_regen,
}),
Effect::Vanish,
],
hit_entity: vec![
Effect::Explode(Explosion {
effects: vec![RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
2020-11-13 03:50:40 +00:00
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
)],
radius,
energy_regen,
}),
Effect::Vanish,
],
2020-12-24 17:54:00 +00:00
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
},
Firebolt {
damage,
energy_regen,
} => Projectile {
hit_solid: vec![Effect::Vanish],
hit_entity: vec![
Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Energy,
value: damage,
}),
Effect::RewardEnergy(energy_regen),
Effect::Vanish,
],
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
},
Heal {
heal,
damage,
radius,
} => Projectile {
hit_solid: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
2020-11-13 03:50:40 +00:00
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
2020-11-13 03:50:40 +00:00
effect::Effect::Damage(Damage {
source: DamageSource::Healing,
value: heal,
}),
),
],
radius,
energy_regen: 0,
}),
Effect::Vanish,
],
hit_entity: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
2020-11-13 03:50:40 +00:00
effect::Effect::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
2020-11-13 03:50:40 +00:00
effect::Effect::Damage(Damage {
source: DamageSource::Healing,
value: heal,
}),
),
],
radius,
energy_regen: 0,
}),
Effect::Vanish,
],
2020-12-24 17:54:00 +00:00
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
},
Possess => Projectile {
hit_solid: vec![Effect::Stick],
hit_entity: vec![Effect::Stick, Effect::Possess],
time_left: Duration::from_secs(10),
owner,
ignore_group: false,
},
}
}
2020-12-25 16:28:35 +00:00
pub fn modified_projectile(
mut self,
power: f32,
regen: f32,
range: f32,
heal_power: f32,
) -> Self {
use ProjectileConstructor::*;
match self {
2020-12-23 02:28:55 +00:00
Arrow {
ref mut damage,
ref mut energy_regen,
..
} => {
*damage *= power;
2020-12-23 02:28:55 +00:00
*energy_regen = (*energy_regen as f32 * regen) as u32;
},
2020-12-24 17:54:00 +00:00
Fireball {
ref mut damage,
ref mut energy_regen,
ref mut radius,
..
} => {
*damage *= power;
*energy_regen = (*energy_regen as f32 * regen) as u32;
*radius *= range;
},
Firebolt {
ref mut damage,
ref mut energy_regen,
..
} => {
*damage *= power;
2020-12-24 17:54:00 +00:00
*energy_regen = (*energy_regen as f32 * regen) as u32;
},
Heal {
ref mut damage,
ref mut heal,
2020-12-24 17:54:00 +00:00
ref mut radius,
..
} => {
*damage *= power;
2020-12-25 16:28:35 +00:00
*heal *= heal_power;
2020-12-24 17:54:00 +00:00
*radius *= range;
},
Possess => {},
}
self
}
2020-12-24 17:54:00 +00:00
pub fn fireball_to_firebolt(self) -> Self {
if let ProjectileConstructor::Fireball {
damage,
energy_regen,
..
} = self
{
ProjectileConstructor::Firebolt {
damage,
energy_regen: energy_regen * 2,
}
} else {
self
}
}
}