2020-11-09 04:04:51 +00:00
|
|
|
use crate::{
|
2021-01-29 00:04:44 +00:00
|
|
|
combat::{
|
|
|
|
Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource,
|
|
|
|
EffectComponent, GroupTarget, Knockback, KnockbackDir,
|
|
|
|
},
|
|
|
|
effect,
|
2020-12-13 17:11:55 +00:00
|
|
|
uid::Uid,
|
2021-01-29 00:04:44 +00:00
|
|
|
Explosion, RadiusEffect,
|
2020-11-09 04:04:51 +00:00
|
|
|
};
|
2020-07-06 14:23:08 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-01-07 20:25:12 +00:00
|
|
|
use specs::Component;
|
2020-07-06 05:56:02 +00:00
|
|
|
use specs_idvs::IdvStorage;
|
2019-10-06 17:30:06 +00:00
|
|
|
use std::time::Duration;
|
2019-09-17 12:43:19 +00:00
|
|
|
|
2021-01-29 00:04:44 +00:00
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
2019-09-17 12:43:19 +00:00
|
|
|
pub enum Effect {
|
2021-01-29 00:04:44 +00:00
|
|
|
Attack(Attack),
|
|
|
|
//Knockback(Knockback),
|
|
|
|
//RewardEnergy(u32),
|
2020-10-06 02:19:41 +00:00
|
|
|
Explode(Explosion),
|
2019-09-17 12:43:19 +00:00
|
|
|
Vanish,
|
2019-09-28 19:35:28 +00:00
|
|
|
Stick,
|
2019-10-11 23:30:05 +00:00
|
|
|
Possess,
|
2021-01-29 00:04:44 +00:00
|
|
|
/*Buff {
|
|
|
|
* buff: BuffEffect,
|
|
|
|
* chance: Option<f32>, */
|
|
|
|
/* */
|
2019-09-17 12:43:19 +00:00
|
|
|
}
|
|
|
|
|
2021-01-29 00:04:44 +00:00
|
|
|
#[derive(Debug, 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>,
|
2019-10-06 17:30:06 +00:00
|
|
|
/// Time left until the projectile will despawn
|
|
|
|
pub time_left: Duration,
|
2020-03-16 11:32:57 +00:00
|
|
|
pub owner: Option<Uid>,
|
2020-09-19 08:47:40 +00:00
|
|
|
/// 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 {
|
2021-01-07 20:25:12 +00:00
|
|
|
type Storage = IdvStorage<Self>;
|
2019-09-17 12:43:19 +00:00
|
|
|
}
|
2020-11-09 04:04:51 +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,
|
|
|
|
},
|
2020-11-09 04:04:51 +00:00
|
|
|
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,
|
|
|
|
} => {
|
2021-01-29 00:04:44 +00:00
|
|
|
let damage = Damage {
|
|
|
|
source: DamageSource::Projectile,
|
|
|
|
value: damage,
|
2020-11-09 04:04:51 +00:00
|
|
|
};
|
2021-01-29 00:04:44 +00:00
|
|
|
let knockback = AttackEffect::Knockback(Knockback {
|
|
|
|
strength: knockback,
|
|
|
|
direction: KnockbackDir::Away,
|
|
|
|
});
|
|
|
|
let energy = AttackEffect::EnergyReward(energy_regen);
|
|
|
|
let energy = EffectComponent::new(None, energy)
|
|
|
|
.with_requirement(CombatRequirement::AnyDamage);
|
|
|
|
let buff = AttackEffect::Buff(CombatBuff::default_physical());
|
|
|
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup))
|
|
|
|
.with_effect(knockback)
|
|
|
|
.with_effect(buff);
|
|
|
|
let attack = Attack::default()
|
|
|
|
.with_damage(damage)
|
|
|
|
.with_crit(0.5, 1.2)
|
|
|
|
.with_effect(energy);
|
|
|
|
|
2020-11-09 04:04:51 +00:00
|
|
|
Projectile {
|
|
|
|
hit_solid: vec![Effect::Stick],
|
2021-01-29 00:04:44 +00:00
|
|
|
hit_entity: vec![Effect::Attack(attack), Effect::Vanish],
|
2020-11-09 04:04:51 +00:00
|
|
|
time_left: Duration::from_secs(15),
|
|
|
|
owner,
|
|
|
|
ignore_group: true,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Fireball {
|
|
|
|
damage,
|
|
|
|
radius,
|
|
|
|
energy_regen,
|
|
|
|
} => Projectile {
|
|
|
|
hit_solid: vec![
|
|
|
|
Effect::Explode(Explosion {
|
2020-11-19 00:23:13 +00:00
|
|
|
effects: vec![
|
|
|
|
RadiusEffect::Entity(
|
|
|
|
Some(GroupTarget::OutOfGroup),
|
|
|
|
effect::Effect::Damage(Damage {
|
|
|
|
source: DamageSource::Explosion,
|
|
|
|
value: damage,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
RadiusEffect::TerrainDestruction(2.0),
|
|
|
|
],
|
2020-11-09 04:04:51 +00:00
|
|
|
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 {
|
2020-11-09 04:04:51 +00:00
|
|
|
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,
|
2021-01-29 00:04:44 +00:00
|
|
|
} => {
|
|
|
|
let damage = Damage {
|
|
|
|
source: DamageSource::Energy,
|
|
|
|
value: damage,
|
|
|
|
};
|
|
|
|
let energy = AttackEffect::EnergyReward(energy_regen);
|
|
|
|
let energy = EffectComponent::new(None, energy)
|
|
|
|
.with_requirement(CombatRequirement::AnyDamage);
|
|
|
|
let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup));
|
|
|
|
let attack = Attack::default().with_damage(damage).with_effect(energy);
|
|
|
|
|
|
|
|
Projectile {
|
|
|
|
hit_solid: vec![Effect::Vanish],
|
|
|
|
hit_entity: vec![Effect::Attack(attack), Effect::Vanish],
|
|
|
|
time_left: Duration::from_secs(10),
|
|
|
|
owner,
|
|
|
|
ignore_group: true,
|
|
|
|
}
|
2020-11-09 04:04:51 +00:00
|
|
|
},
|
|
|
|
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 {
|
2020-11-09 04:04:51 +00:00
|
|
|
source: DamageSource::Explosion,
|
|
|
|
value: damage,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
RadiusEffect::Entity(
|
|
|
|
Some(GroupTarget::InGroup),
|
2020-11-13 03:50:40 +00:00
|
|
|
effect::Effect::Damage(Damage {
|
2020-11-09 04:04:51 +00:00
|
|
|
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 {
|
2020-11-09 04:04:51 +00:00
|
|
|
source: DamageSource::Explosion,
|
|
|
|
value: damage,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
RadiusEffect::Entity(
|
|
|
|
Some(GroupTarget::InGroup),
|
2020-11-13 03:50:40 +00:00
|
|
|
effect::Effect::Damage(Damage {
|
2020-11-09 04:04:51 +00:00
|
|
|
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),
|
2020-11-09 04:04:51 +00:00
|
|
|
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-11-13 03:24:19 +00:00
|
|
|
|
2020-12-25 16:28:35 +00:00
|
|
|
pub fn modified_projectile(
|
|
|
|
mut self,
|
|
|
|
power: f32,
|
|
|
|
regen: f32,
|
|
|
|
range: f32,
|
|
|
|
heal_power: f32,
|
|
|
|
) -> Self {
|
2020-11-13 03:24:19 +00:00
|
|
|
use ProjectileConstructor::*;
|
|
|
|
match self {
|
2020-12-23 02:28:55 +00:00
|
|
|
Arrow {
|
|
|
|
ref mut damage,
|
|
|
|
ref mut energy_regen,
|
|
|
|
..
|
|
|
|
} => {
|
2020-11-13 03:24:19 +00:00
|
|
|
*damage *= power;
|
2020-12-23 02:28:55 +00:00
|
|
|
*energy_regen = (*energy_regen as f32 * regen) as u32;
|
2020-11-13 03:24:19 +00:00
|
|
|
},
|
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,
|
|
|
|
..
|
|
|
|
} => {
|
2020-11-13 03:24:19 +00:00
|
|
|
*damage *= power;
|
2020-12-24 17:54:00 +00:00
|
|
|
*energy_regen = (*energy_regen as f32 * regen) as u32;
|
2020-11-13 03:24:19 +00:00
|
|
|
},
|
|
|
|
Heal {
|
|
|
|
ref mut damage,
|
|
|
|
ref mut heal,
|
2020-12-24 17:54:00 +00:00
|
|
|
ref mut radius,
|
2020-11-13 03:24:19 +00:00
|
|
|
..
|
|
|
|
} => {
|
|
|
|
*damage *= power;
|
2020-12-25 16:28:35 +00:00
|
|
|
*heal *= heal_power;
|
2020-12-24 17:54:00 +00:00
|
|
|
*radius *= range;
|
2020-11-13 03:24:19 +00:00
|
|
|
},
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2020-11-09 04:04:51 +00:00
|
|
|
}
|