Added projectile constructor. Removed a bunch of cloning.

This commit is contained in:
Sam 2020-11-08 22:04:51 -06:00
parent abf7301a89
commit 770aaf6b93
11 changed files with 226 additions and 306 deletions

View File

@ -2,31 +2,10 @@ BasicRanged(
energy_cost: 0,
buildup_duration: 100,
recover_duration: 400,
projectile: (
hit_solid: [Stick],
hit_entity: [
Damage(Some(OutOfGroup), (
source: Projectile,
value: 40.0,
)),
Knockback(Away(10.0)),
RewardEnergy(50),
Vanish,
Buff(
buff: (
kind: Bleeding,
data: (
strength: 20.0,
duration: Some(5), // secs
),
cat_ids: [Physical],
),
chance: Some(0.10),
),
],
time_left: 15, // seconds
owner: None,
ignore_group: true,
projectile: Arrow(
damage: 40.0,
knockback: 10.0,
energy_regen: 50,
),
projectile_body: Object(Arrow),
projectile_light: None,

View File

@ -5,30 +5,10 @@ RepeaterRanged(
shoot_duration: 200,
recover_duration: 800,
leap: Some(5.0),
projectile: (
hit_solid: [Stick],
hit_entity: [
Damage(Some(OutOfGroup), (
source: Projectile,
value: 40.0,
)),
Knockback(Away(10.0)),
Vanish,
Buff(
buff: (
kind: Bleeding,
data: (
strength: 20.0,
duration: Some(5), // secs
),
cat_ids: [Physical],
),
chance: Some(0.10),
),
],
time_left: 15, // seconds
owner: None,
ignore_group: true,
projectile: Arrow(
damage: 40.0,
knockback: 10.0,
energy_regen: 0,
),
projectile_body: Object(Arrow),
projectile_light: None,

View File

@ -2,56 +2,10 @@ BasicRanged(
energy_cost: 800,
buildup_duration: 800,
recover_duration: 50,
projectile: (
hit_solid: [
Explode((
effects: [
Entity(
Some(OutOfGroup),
Damage((
source: Explosion,
value: 50.0,
)),
),
Entity(
Some(InGroup),
Damage((
source: Healing,
value: 140.0,
)),
),
],
radius: 6.0,
energy_regen: 0,
)),
Vanish,
],
hit_entity: [
Explode((
effects: [
Entity(
Some(OutOfGroup),
Damage((
source: Explosion,
value: 50.0,
)),
),
Entity(
Some(InGroup),
Damage((
source: Healing,
value: 140.0,
)),
),
],
radius: 6.0,
energy_regen: 0,
)),
Vanish,
],
time_left: 20, // seconds
owner: None,
ignore_group: true,
projectile: Heal(
heal: 140.0,
damage: 50.0,
radius: 6.0,
),
projectile_body: Object(BoltNature),
/*projectile_light: Some(LightEmitter {

View File

@ -2,38 +2,10 @@ BasicRanged(
energy_cost: 0,
buildup_duration: 500,
recover_duration: 350,
projectile: (
hit_solid: [
Explode((
effects: [Entity(
Some(OutOfGroup),
Damage((
source: Explosion,
value: 100.0,
)),
)],
radius: 5.0,
energy_regen: 50,
)),
Vanish,
],
hit_entity: vec![
Explode((
effects: [Entity(
Some(OutOfGroup),
Damage((
source: Explosion,
value: 100.0,
)),
)],
radius: 5.0,
energy_regen: 50,
)),
Vanish,
],
time_left: 20, // seconds
owner: None,
ignore_group: true,
projectile: Fireball(
damage: 100.0,
radius: 5.0,
energy_regen: 0,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {

View File

@ -1,7 +1,8 @@
use crate::{
comp::{
item::{armor::Protection, Item, ItemKind},
Body, CharacterState, EnergySource, Gravity, LightEmitter, Projectile, StateUpdate,
projectile::ProjectileConstructor,
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
},
states::{
utils::{AbilityKey, StageSection},
@ -71,7 +72,7 @@ pub enum CharacterAbility {
energy_cost: u32,
buildup_duration: Duration,
recover_duration: Duration,
projectile: Projectile,
projectile: ProjectileConstructor,
projectile_body: Body,
projectile_light: Option<LightEmitter>,
projectile_gravity: Option<Gravity>,
@ -85,7 +86,7 @@ pub enum CharacterAbility {
shoot_duration: Duration,
recover_duration: Duration,
leap: Option<f32>,
projectile: Projectile,
projectile: ProjectileConstructor,
projectile_body: Body,
projectile_light: Option<LightEmitter>,
projectile_gravity: Option<Gravity>,
@ -418,7 +419,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
static_data: basic_ranged::StaticData {
buildup_duration: *buildup_duration,
recover_duration: *recover_duration,
projectile: projectile.clone(),
projectile: *projectile,
projectile_body: *projectile_body,
projectile_light: *projectile_light,
projectile_gravity: *projectile_gravity,
@ -681,7 +682,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
shoot_duration: *shoot_duration,
recover_duration: *recover_duration,
leap: *leap,
projectile: projectile.clone(),
projectile: *projectile,
projectile_body: *projectile_body,
projectile_light: *projectile_light,
projectile_gravity: *projectile_gravity,

View File

@ -3,13 +3,11 @@
use crate::{
comp::{
body::object,
buff::{BuffCategory, BuffData, BuffKind},
projectile, Body, CharacterAbility, Gravity, LightEmitter, Projectile,
body::object, projectile::ProjectileConstructor, Body, CharacterAbility, Gravity,
LightEmitter,
},
effect::{BuffEffect, Effect},
states::combo_melee,
Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect,
Knockback,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -95,6 +93,7 @@ impl Tool {
Duration::from_millis(millis).div_f32(self.base_speed())
}
// TODO: Before merging ron file branch, ensure these are double checked against ron files.
pub fn get_abilities(&self) -> Vec<CharacterAbility> {
use CharacterAbility::*;
use ToolKind::*;
@ -313,31 +312,10 @@ impl Tool {
energy_cost: 0,
buildup_duration: self.adjusted_duration(200),
recover_duration: self.adjusted_duration(300),
projectile: Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Projectile,
value: 40.0 * self.base_power(),
}),
projectile::Effect::Knockback(Knockback::Away(10.0)),
projectile::Effect::RewardEnergy(50),
projectile::Effect::Vanish,
projectile::Effect::Buff {
buff: BuffEffect {
kind: BuffKind::Bleeding,
data: BuffData {
strength: 20.0 * self.base_power(),
duration: Some(Duration::from_secs(5)),
},
cat_ids: vec![BuffCategory::Physical],
},
chance: Some(0.10),
},
],
time_left: Duration::from_secs(15),
owner: None,
ignore_group: true,
projectile: ProjectileConstructor::Arrow {
damage: 40.0 * self.base_power(),
knockback: 10.0,
energy_regen: 50,
},
projectile_body: Body::Object(object::Body::Arrow),
projectile_light: None,
@ -369,30 +347,10 @@ impl Tool {
shoot_duration: self.adjusted_duration(200),
recover_duration: self.adjusted_duration(800),
leap: Some(5.0),
projectile: Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), Damage {
source: DamageSource::Projectile,
value: 40.0 * self.base_power(),
}),
projectile::Effect::Knockback(Knockback::Away(10.0)),
projectile::Effect::Vanish,
projectile::Effect::Buff {
buff: BuffEffect {
kind: BuffKind::Bleeding,
data: BuffData {
strength: 20.0 * self.base_power(),
duration: Some(Duration::from_secs(5)),
},
cat_ids: vec![BuffCategory::Physical],
},
chance: Some(0.10),
},
],
time_left: Duration::from_secs(15),
owner: None,
ignore_group: true,
projectile: ProjectileConstructor::Arrow {
damage: 40.0 * self.base_power(),
knockback: 10.0,
energy_regen: 0,
},
projectile_body: Body::Object(object::Body::Arrow),
projectile_light: None,
@ -430,56 +388,10 @@ impl Tool {
energy_cost: 800,
buildup_duration: self.adjusted_duration(800),
recover_duration: self.adjusted_duration(50),
projectile: Projectile {
hit_solid: vec![
projectile::Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 50.0 * self.base_power(),
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
Effect::Damage(Damage {
source: DamageSource::Healing,
value: 140.0 * self.base_power(),
}),
),
],
radius: 3.0 + 2.5 * self.base_power(),
energy_regen: 0,
}),
projectile::Effect::Vanish,
],
hit_entity: vec![
projectile::Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 50.0 * self.base_power(),
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
Effect::Damage(Damage {
source: DamageSource::Healing,
value: 140.0 * self.base_power(),
}),
),
],
radius: 3.0 + 2.5 * self.base_power(),
energy_regen: 0,
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(20),
owner: None,
ignore_group: true,
projectile: ProjectileConstructor::Heal {
heal: 140.0 * self.base_power(),
damage: 50.0 * self.base_power(),
radius: 3.0 + 2.5 * self.base_power(),
},
projectile_body: Body::Object(object::Body::BoltNature),
projectile_light: Some(LightEmitter {
@ -496,38 +408,10 @@ impl Tool {
energy_cost: 0,
buildup_duration: self.adjusted_duration(500),
recover_duration: self.adjusted_duration(350),
projectile: Projectile {
hit_solid: vec![
projectile::Effect::Explode(Explosion {
effects: vec![RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 100.0 * self.base_power(),
}),
)],
radius: 5.0,
energy_regen: 50,
}),
projectile::Effect::Vanish,
],
hit_entity: vec![
projectile::Effect::Explode(Explosion {
effects: vec![RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
Effect::Damage(Damage {
source: DamageSource::Explosion,
value: 100.0 * self.base_power(),
}),
)],
radius: 5.0,
energy_regen: 50,
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(20),
owner: None,
ignore_group: true,
projectile: ProjectileConstructor::Fireball {
damage: 100.0 * self.base_power(),
radius: 5.0,
energy_regen: 50,
},
projectile_body: Body::Object(object::Body::BoltFire),
projectile_light: Some(LightEmitter {
@ -628,13 +512,7 @@ impl Tool {
energy_cost: 0,
buildup_duration: Duration::from_millis(0),
recover_duration: self.adjusted_duration(10),
projectile: Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![projectile::Effect::Stick, projectile::Effect::Possess],
time_left: Duration::from_secs(10),
owner: None,
ignore_group: false,
},
projectile: ProjectileConstructor::Possess,
projectile_body: Body::Object(object::Body::ArrowSnake),
projectile_light: Some(LightEmitter {
col: (0.0, 1.0, 0.33).into(),

View File

@ -61,7 +61,7 @@ pub use phys::{
Sticky, Vel,
};
pub use player::Player;
pub use projectile::Projectile;
pub use projectile::{Projectile, ProjectileConstructor};
pub use shockwave::{Shockwave, ShockwaveHitEntities};
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
pub use stats::{Exp, Level, Stats};

View File

@ -1,4 +1,9 @@
use crate::{effect::BuffEffect, sync::Uid, Damage, Explosion, GroupTarget, Knockback};
use crate::{
comp::buff::{BuffCategory, BuffData, BuffKind},
effect::{BuffEffect, Effect as EffectB},
sync::Uid,
Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect,
};
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage};
use specs_idvs::IdvStorage;
@ -35,3 +40,163 @@ pub struct Projectile {
impl Component for Projectile {
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
}
#[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,
},
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::Away(knockback)),
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),
EffectB::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
)],
radius,
energy_regen,
}),
Effect::Vanish,
],
hit_entity: vec![
Effect::Explode(Explosion {
effects: vec![RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
EffectB::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
)],
radius,
energy_regen,
}),
Effect::Vanish,
],
time_left: Duration::from_secs(20),
owner,
ignore_group: true,
},
Heal {
heal,
damage,
radius,
} => Projectile {
hit_solid: vec![
Effect::Explode(Explosion {
effects: vec![
RadiusEffect::Entity(
Some(GroupTarget::OutOfGroup),
EffectB::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
EffectB::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),
EffectB::Damage(Damage {
source: DamageSource::Explosion,
value: damage,
}),
),
RadiusEffect::Entity(
Some(GroupTarget::InGroup),
EffectB::Damage(Damage {
source: DamageSource::Healing,
value: heal,
}),
),
],
radius,
energy_regen: 0,
}),
Effect::Vanish,
],
time_left: Duration::from_secs(20),
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,
},
}
}
}

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate},
comp::{Body, CharacterState, Gravity, LightEmitter, ProjectileConstructor, StateUpdate},
event::ServerEvent,
states::utils::*,
sys::character_behavior::{CharacterBehavior, JoinData},
@ -8,14 +8,14 @@ use serde::{Deserialize, Serialize};
use std::time::Duration;
/// Separated out to condense update portions of character state
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct StaticData {
/// How much buildup is required before the attack
pub buildup_duration: Duration,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Projectile variables
pub projectile: Projectile,
pub projectile: ProjectileConstructor,
pub projectile_body: Body,
pub projectile_light: Option<LightEmitter>,
pub projectile_gravity: Option<Gravity>,
@ -54,7 +54,6 @@ impl CharacterBehavior for Data {
if self.timer < self.static_data.buildup_duration {
// Build up
update.character = CharacterState::BasicRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
@ -64,7 +63,6 @@ impl CharacterBehavior for Data {
} else {
// Transitions to recover section of stage
update.character = CharacterState::BasicRanged(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: StageSection::Recover,
..*self
@ -74,8 +72,10 @@ impl CharacterBehavior for Data {
StageSection::Recover => {
if !self.exhausted {
// Fire
let mut projectile = self.static_data.projectile.clone();
projectile.owner = Some(*data.uid);
let projectile = self
.static_data
.projectile
.create_projectile(Some(*data.uid));
update.server_events.push_front(ServerEvent::Shoot {
entity: data.entity,
dir: data.inputs.look_dir,
@ -87,7 +87,6 @@ impl CharacterBehavior for Data {
});
update.character = CharacterState::BasicRanged(Data {
static_data: self.static_data.clone(),
exhausted: true,
continue_next: false,
..*self
@ -118,7 +117,6 @@ impl CharacterBehavior for Data {
} else if self.continue_next {
// Restarts character state
update.character = CharacterState::BasicRanged(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: StageSection::Buildup,
exhausted: false,

View File

@ -99,7 +99,7 @@ impl CharacterBehavior for Data {
* (self.static_data.max_knockback - self.static_data.initial_knockback)
as f32);
// Fire
let mut projectile = Projectile {
let projectile = Projectile {
hit_solid: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), damage),
@ -118,10 +118,9 @@ impl CharacterBehavior for Data {
},
],
time_left: Duration::from_secs(15),
owner: None,
owner: Some(*data.uid),
ignore_group: true,
};
projectile.owner = Some(*data.uid);
update.server_events.push_front(ServerEvent::Shoot {
entity: data.entity,
dir: data.inputs.look_dir,

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate},
comp::{Body, CharacterState, Gravity, LightEmitter, ProjectileConstructor, StateUpdate},
event::ServerEvent,
states::utils::{StageSection, *},
sys::character_behavior::*,
@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use std::time::Duration;
use vek::Vec3;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
/// Separated out to condense update portions of character state
pub struct StaticData {
/// How long the state is in movement
@ -23,7 +23,7 @@ pub struct StaticData {
/// Whether there should be a jump and how strong the leap is
pub leap: Option<f32>,
/// Projectile options
pub projectile: Projectile,
pub projectile: ProjectileConstructor,
pub projectile_body: Body,
pub projectile_light: Option<LightEmitter>,
pub projectile_gravity: Option<Gravity>,
@ -71,7 +71,6 @@ impl CharacterBehavior for Data {
if self.timer < self.static_data.movement_duration {
// Do movement
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
@ -81,7 +80,6 @@ impl CharacterBehavior for Data {
} else {
// Transition to buildup
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: StageSection::Buildup,
..*self
@ -101,7 +99,6 @@ impl CharacterBehavior for Data {
if self.timer < self.static_data.buildup_duration {
// Buildup to attack
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
@ -111,7 +108,6 @@ impl CharacterBehavior for Data {
} else {
// Transition to shoot
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: StageSection::Shoot,
..*self
@ -125,8 +121,10 @@ impl CharacterBehavior for Data {
}
if self.reps_remaining > 0 {
// Fire
let mut projectile = self.static_data.projectile.clone();
projectile.owner = Some(*data.uid);
let projectile = self
.static_data
.projectile
.create_projectile(Some(*data.uid));
update.server_events.push_front(ServerEvent::Shoot {
entity: data.entity,
// Provides slight variation to projectile direction
@ -155,7 +153,6 @@ impl CharacterBehavior for Data {
// Shoot projectiles
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
@ -166,7 +163,6 @@ impl CharacterBehavior for Data {
} else if self.timer < self.static_data.shoot_duration {
// Finish shooting
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
@ -176,7 +172,6 @@ impl CharacterBehavior for Data {
} else {
// Transition to recover
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: StageSection::Recover,
..*self
@ -190,7 +185,6 @@ impl CharacterBehavior for Data {
} else if self.timer < self.static_data.recover_duration {
// Recover from attack
update.character = CharacterState::RepeaterRanged(Data {
static_data: self.static_data.clone(),
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))