mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Sceptre M2 Revamp
This commit is contained in:
parent
6c2d73c357
commit
1c99542df9
@ -2,5 +2,6 @@ TargetedEffect(
|
|||||||
buildup_duration: 0.5,
|
buildup_duration: 0.5,
|
||||||
recover_duration: 0.5,
|
recover_duration: 0.5,
|
||||||
max_range: 25.0,
|
max_range: 25.0,
|
||||||
effect: heal: 100.0,
|
heal: 100.0,
|
||||||
|
energy_cost:150,
|
||||||
)
|
)
|
@ -10,5 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 25,
|
energy_regen: 25,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
specifier: HealingBeam,
|
specifier: LifestealBeam,
|
||||||
)
|
)
|
@ -76,7 +76,7 @@
|
|||||||
),
|
),
|
||||||
Sceptre: (
|
Sceptre: (
|
||||||
primary: "common.abilities.sceptre.lifestealbeam",
|
primary: "common.abilities.sceptre.lifestealbeam",
|
||||||
secondary: "common.abilities.sceptre.healingbeam",
|
secondary: "common.abilities.sceptre.targetedheal",
|
||||||
abilities: [
|
abilities: [
|
||||||
(Some(Sceptre(UnlockAura)), "common.abilities.sceptre.wardingaura"),
|
(Some(Sceptre(UnlockAura)), "common.abilities.sceptre.wardingaura"),
|
||||||
],
|
],
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
"hud.skill.sc_heal_cost_title": "Stamina Cost",
|
"hud.skill.sc_heal_cost_title": "Stamina Cost",
|
||||||
"hud.skill.sc_heal_cost": "Healing others requires 20% less stamina{SP}",
|
"hud.skill.sc_heal_cost": "Healing others requires 20% less stamina{SP}",
|
||||||
"hud.skill.sc_heal_range_title": "Range",
|
"hud.skill.sc_heal_range_title": "Range",
|
||||||
"hud.skill.sc_heal_range": "Your beam reachs 20% further{SP}",
|
"hud.skill.sc_heal_range": "The duration is decreased by 15%{SP}",
|
||||||
"hud.skill.sc_wardaura_unlock_title": "Warding Aura Unlock",
|
"hud.skill.sc_wardaura_unlock_title": "Warding Aura Unlock",
|
||||||
"hud.skill.sc_wardaura_unlock": "Allows you to ward your allies against enemy attacks{SP}",
|
"hud.skill.sc_wardaura_unlock": "Allows you to ward your allies against enemy attacks{SP}",
|
||||||
"hud.skill.sc_wardaura_strength_title": "Strength",
|
"hud.skill.sc_wardaura_strength_title": "Strength",
|
||||||
|
@ -138,7 +138,7 @@ impl Attack {
|
|||||||
accumulated_damage += applied_damage;
|
accumulated_damage += applied_damage;
|
||||||
emit_outcome(Outcome::Damage { pos: target.pos });
|
emit_outcome(Outcome::Damage { pos: target.pos });
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
emit(ServerEvent::Damage {
|
emit(ServerEvent::HealthChange {
|
||||||
entity: target.entity,
|
entity: target.entity,
|
||||||
change,
|
change,
|
||||||
});
|
});
|
||||||
@ -183,7 +183,7 @@ impl Attack {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
emit(ServerEvent::Damage {
|
emit(ServerEvent::HealthChange {
|
||||||
entity: attacker_entity,
|
entity: attacker_entity,
|
||||||
change,
|
change,
|
||||||
});
|
});
|
||||||
@ -208,7 +208,7 @@ impl Attack {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
emit(ServerEvent::Damage {
|
emit(ServerEvent::HealthChange {
|
||||||
entity: target.entity,
|
entity: target.entity,
|
||||||
change,
|
change,
|
||||||
});
|
});
|
||||||
@ -318,7 +318,7 @@ impl Attack {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
emit(ServerEvent::Damage {
|
emit(ServerEvent::HealthChange {
|
||||||
entity: attacker_entity,
|
entity: attacker_entity,
|
||||||
change,
|
change,
|
||||||
});
|
});
|
||||||
@ -343,7 +343,7 @@ impl Attack {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if change.amount != 0 {
|
if change.amount != 0 {
|
||||||
emit(ServerEvent::Damage {
|
emit(ServerEvent::HealthChange {
|
||||||
entity: target.entity,
|
entity: target.entity,
|
||||||
change,
|
change,
|
||||||
});
|
});
|
||||||
|
@ -30,6 +30,7 @@ pub enum CharacterAbilityType {
|
|||||||
BasicBeam,
|
BasicBeam,
|
||||||
RepeaterRanged,
|
RepeaterRanged,
|
||||||
BasicAura,
|
BasicAura,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&CharacterState> for CharacterAbilityType {
|
impl From<&CharacterState> for CharacterAbilityType {
|
||||||
@ -241,17 +242,6 @@ pub enum CharacterAbility {
|
|||||||
range: f32,
|
range: f32,
|
||||||
energy_cost: f32,
|
energy_cost: f32,
|
||||||
},
|
},
|
||||||
HealingBeam {
|
|
||||||
buildup_duration: f32,
|
|
||||||
recover_duration: f32,
|
|
||||||
beam_duration: f32,
|
|
||||||
heal: f32,
|
|
||||||
tick_rate: f32,
|
|
||||||
range: f32,
|
|
||||||
max_angle: f32,
|
|
||||||
energy_cost: f32,
|
|
||||||
specifier: beam::FrontendSpecifier,
|
|
||||||
},
|
|
||||||
Blink {
|
Blink {
|
||||||
buildup_duration: f32,
|
buildup_duration: f32,
|
||||||
recover_duration: f32,
|
recover_duration: f32,
|
||||||
@ -269,6 +259,7 @@ pub enum CharacterAbility {
|
|||||||
recover_duration: f32,
|
recover_duration: f32,
|
||||||
max_range: f32,
|
max_range: f32,
|
||||||
heal: f32,
|
heal: f32,
|
||||||
|
energy_cost: f32,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,8 +325,15 @@ impl CharacterAbility {
|
|||||||
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
},
|
},
|
||||||
CharacterAbility::HealingBeam { .. } => data.combo.counter() > 0,
|
CharacterAbility::TargetedEffect { energy_cost, .. } => {
|
||||||
_ => true,
|
data.combo.counter() > 0 &&
|
||||||
|
update
|
||||||
|
.energy
|
||||||
|
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
_=> true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,18 +536,6 @@ impl CharacterAbility {
|
|||||||
*recover_duration /= speed;
|
*recover_duration /= speed;
|
||||||
aura.strength *= power;
|
aura.strength *= power;
|
||||||
},
|
},
|
||||||
HealingBeam {
|
|
||||||
ref mut buildup_duration,
|
|
||||||
ref mut recover_duration,
|
|
||||||
ref mut heal,
|
|
||||||
ref mut tick_rate,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
*buildup_duration /= speed;
|
|
||||||
*recover_duration /= speed;
|
|
||||||
*heal *= power;
|
|
||||||
*tick_rate *= speed;
|
|
||||||
},
|
|
||||||
Blink {
|
Blink {
|
||||||
ref mut buildup_duration,
|
ref mut buildup_duration,
|
||||||
ref mut recover_duration,
|
ref mut recover_duration,
|
||||||
@ -594,7 +580,6 @@ impl CharacterAbility {
|
|||||||
| ChargedMelee { energy_cost, .. }
|
| ChargedMelee { energy_cost, .. }
|
||||||
| ChargedRanged { energy_cost, .. }
|
| ChargedRanged { energy_cost, .. }
|
||||||
| Shockwave { energy_cost, .. }
|
| Shockwave { energy_cost, .. }
|
||||||
| HealingBeam { energy_cost, .. }
|
|
||||||
| BasicAura { energy_cost, .. } => *energy_cost as u32,
|
| BasicAura { energy_cost, .. } => *energy_cost as u32,
|
||||||
BasicBeam { energy_drain, .. } => {
|
BasicBeam { energy_drain, .. } => {
|
||||||
if *energy_drain > f32::EPSILON {
|
if *energy_drain > f32::EPSILON {
|
||||||
@ -1077,26 +1062,6 @@ impl CharacterAbility {
|
|||||||
*lifesteal *= 1.15_f32.powi(level.into());
|
*lifesteal *= 1.15_f32.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HealingBeam {
|
|
||||||
ref mut heal,
|
|
||||||
ref mut energy_cost,
|
|
||||||
ref mut range,
|
|
||||||
ref mut beam_duration,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HHeal)) {
|
|
||||||
*heal *= 1.2_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HRange)) {
|
|
||||||
let range_mod = 1.2_f32.powi(level.into());
|
|
||||||
*range *= range_mod;
|
|
||||||
// Duration modified to keep velocity constant
|
|
||||||
*beam_duration *= range_mod;
|
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HCost)) {
|
|
||||||
*energy_cost *= 0.8_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BasicAura {
|
BasicAura {
|
||||||
ref mut aura,
|
ref mut aura,
|
||||||
ref mut range,
|
ref mut range,
|
||||||
@ -1581,32 +1546,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
}),
|
}),
|
||||||
CharacterAbility::HealingBeam {
|
|
||||||
buildup_duration,
|
|
||||||
recover_duration,
|
|
||||||
beam_duration,
|
|
||||||
heal,
|
|
||||||
tick_rate,
|
|
||||||
range,
|
|
||||||
max_angle,
|
|
||||||
energy_cost,
|
|
||||||
specifier,
|
|
||||||
} => CharacterState::HealingBeam(healing_beam::Data {
|
|
||||||
static_data: healing_beam::StaticData {
|
|
||||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
|
||||||
recover_duration: Duration::from_secs_f32(*recover_duration),
|
|
||||||
beam_duration: Duration::from_secs_f32(*beam_duration),
|
|
||||||
heal: *heal,
|
|
||||||
tick_rate: *tick_rate,
|
|
||||||
range: *range,
|
|
||||||
max_angle: *max_angle,
|
|
||||||
energy_cost: *energy_cost,
|
|
||||||
ability_info,
|
|
||||||
specifier: *specifier,
|
|
||||||
},
|
|
||||||
timer: Duration::default(),
|
|
||||||
stage_section: StageSection::Buildup,
|
|
||||||
}),
|
|
||||||
CharacterAbility::Blink {
|
CharacterAbility::Blink {
|
||||||
buildup_duration,
|
buildup_duration,
|
||||||
recover_duration,
|
recover_duration,
|
||||||
@ -1622,6 +1561,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
}),
|
}),
|
||||||
CharacterAbility::TargetedEffect {
|
CharacterAbility::TargetedEffect {
|
||||||
|
energy_cost,
|
||||||
buildup_duration,
|
buildup_duration,
|
||||||
recover_duration,
|
recover_duration,
|
||||||
max_range, heal } => CharacterState::TargetedEffect(targeted_effect::Data {
|
max_range, heal } => CharacterState::TargetedEffect(targeted_effect::Data {
|
||||||
@ -1630,7 +1570,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
recover_duration: Duration::from_secs_f32(*recover_duration),
|
recover_duration: Duration::from_secs_f32(*recover_duration),
|
||||||
max_range: *max_range,
|
max_range: *max_range,
|
||||||
ability_info,
|
ability_info,
|
||||||
heal,
|
heal: *heal,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
|
@ -50,6 +50,5 @@ impl Component for Beam {
|
|||||||
pub enum FrontendSpecifier {
|
pub enum FrontendSpecifier {
|
||||||
Flamethrower,
|
Flamethrower,
|
||||||
LifestealBeam,
|
LifestealBeam,
|
||||||
HealingBeam,
|
|
||||||
Cultist,
|
Cultist,
|
||||||
}
|
}
|
||||||
|
@ -92,8 +92,6 @@ pub enum CharacterState {
|
|||||||
/// beam as a large amount of functionality needed to be special cased
|
/// beam as a large amount of functionality needed to be special cased
|
||||||
/// specifically for the healing beam. There was also functionality present
|
/// specifically for the healing beam. There was also functionality present
|
||||||
/// on basic beam which was unnecessary for the healing beam.
|
/// on basic beam which was unnecessary for the healing beam.
|
||||||
HealingBeam(healing_beam::Data),
|
|
||||||
/// A short teleport that targets either a position or entity
|
|
||||||
Blink(blink::Data),
|
Blink(blink::Data),
|
||||||
/// Summons creatures that fight for the caster
|
/// Summons creatures that fight for the caster
|
||||||
BasicSummon(basic_summon::Data),
|
BasicSummon(basic_summon::Data),
|
||||||
@ -119,7 +117,6 @@ impl CharacterState {
|
|||||||
| CharacterState::Shockwave(_)
|
| CharacterState::Shockwave(_)
|
||||||
| CharacterState::BasicBeam(_)
|
| CharacterState::BasicBeam(_)
|
||||||
| CharacterState::BasicAura(_)
|
| CharacterState::BasicAura(_)
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +139,6 @@ impl CharacterState {
|
|||||||
| CharacterState::Shockwave(_)
|
| CharacterState::Shockwave(_)
|
||||||
| CharacterState::BasicBeam(_)
|
| CharacterState::BasicBeam(_)
|
||||||
| CharacterState::BasicAura(_)
|
| CharacterState::BasicAura(_)
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +159,6 @@ impl CharacterState {
|
|||||||
| CharacterState::Stunned(_)
|
| CharacterState::Stunned(_)
|
||||||
| CharacterState::Wielding
|
| CharacterState::Wielding
|
||||||
| CharacterState::Talk
|
| CharacterState::Talk
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,16 +35,12 @@ pub enum LocalEvent {
|
|||||||
|
|
||||||
#[allow(clippy::large_enum_variant)] // TODO: Pending review in #587
|
#[allow(clippy::large_enum_variant)] // TODO: Pending review in #587
|
||||||
pub enum ServerEvent {
|
pub enum ServerEvent {
|
||||||
HealthChange {
|
|
||||||
entity: EcsEntity,
|
|
||||||
change: comp::HealthChange,
|
|
||||||
},
|
|
||||||
Explosion {
|
Explosion {
|
||||||
pos: Vec3<f32>,
|
pos: Vec3<f32>,
|
||||||
explosion: Explosion,
|
explosion: Explosion,
|
||||||
owner: Option<Uid>,
|
owner: Option<Uid>,
|
||||||
},
|
},
|
||||||
Damage {
|
HealthChange {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
change: comp::HealthChange,
|
change: comp::HealthChange,
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
InventoryAction, Melee, Ori, PhysicsState, Pos, SkillSet, StateUpdate, Stats, Vel,
|
InventoryAction, Melee, Ori, PhysicsState, Pos, SkillSet, StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
uid::Uid,
|
uid::{Uid, UidAllocator},
|
||||||
};
|
};
|
||||||
use specs::{
|
use specs::{
|
||||||
hibitset,
|
hibitset,
|
||||||
@ -95,6 +95,7 @@ pub struct JoinData<'a> {
|
|||||||
pub msm: &'a MaterialStatManifest,
|
pub msm: &'a MaterialStatManifest,
|
||||||
pub combo: &'a Combo,
|
pub combo: &'a Combo,
|
||||||
pub alignment: Option<&'a comp::Alignment>,
|
pub alignment: Option<&'a comp::Alignment>,
|
||||||
|
pub uid_allocator: &'a UidAllocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
type RestrictedMut<'a, C> = PairedStorage<
|
type RestrictedMut<'a, C> = PairedStorage<
|
||||||
@ -125,6 +126,7 @@ pub struct JoinStruct<'a> {
|
|||||||
pub skill_set: &'a SkillSet,
|
pub skill_set: &'a SkillSet,
|
||||||
pub combo: &'a Combo,
|
pub combo: &'a Combo,
|
||||||
pub alignment: Option<&'a comp::Alignment>,
|
pub alignment: Option<&'a comp::Alignment>,
|
||||||
|
pub uid_allocator: &'a UidAllocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> JoinData<'a> {
|
impl<'a> JoinData<'a> {
|
||||||
@ -156,6 +158,7 @@ impl<'a> JoinData<'a> {
|
|||||||
msm,
|
msm,
|
||||||
combo: j.combo,
|
combo: j.combo,
|
||||||
alignment: j.alignment,
|
alignment: j.alignment,
|
||||||
|
uid_allocator: j.uid_allocator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,163 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
combat::{Attack, AttackEffect, CombatEffect, CombatRequirement, GroupTarget},
|
|
||||||
comp::{beam, CharacterState, Ori, Pos, StateUpdate},
|
|
||||||
event::ServerEvent,
|
|
||||||
states::{
|
|
||||||
behavior::{CharacterBehavior, JoinData},
|
|
||||||
utils::*,
|
|
||||||
},
|
|
||||||
uid::Uid,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::time::Duration;
|
|
||||||
use vek::*;
|
|
||||||
|
|
||||||
/// Separated out to condense update portions of character state
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct StaticData {
|
|
||||||
/// How long until state should deal damage or heal
|
|
||||||
pub buildup_duration: Duration,
|
|
||||||
/// How long the state has until exiting
|
|
||||||
pub recover_duration: Duration,
|
|
||||||
/// How long each beam segment persists for
|
|
||||||
pub beam_duration: Duration,
|
|
||||||
/// Base healing per tick
|
|
||||||
pub heal: f32,
|
|
||||||
/// Ticks of healing per second
|
|
||||||
pub tick_rate: f32,
|
|
||||||
/// Max range
|
|
||||||
pub range: f32,
|
|
||||||
/// Max angle (45.0 will give you a 90.0 angle window)
|
|
||||||
pub max_angle: f32,
|
|
||||||
/// Energy consumed per second for heal ticks
|
|
||||||
pub energy_cost: f32,
|
|
||||||
/// What key is used to press ability
|
|
||||||
pub ability_info: AbilityInfo,
|
|
||||||
/// Used to specify the beam to the frontend
|
|
||||||
pub specifier: beam::FrontendSpecifier,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct Data {
|
|
||||||
/// Struct containing data that does not change over the course of the
|
|
||||||
/// character state
|
|
||||||
pub static_data: StaticData,
|
|
||||||
/// Timer for each stage
|
|
||||||
pub timer: Duration,
|
|
||||||
/// What section the character stage is in
|
|
||||||
pub stage_section: StageSection,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CharacterBehavior for Data {
|
|
||||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
|
||||||
let mut update = StateUpdate::from(data);
|
|
||||||
|
|
||||||
handle_move(data, &mut update, 0.4);
|
|
||||||
handle_jump(data, &mut update, 1.0);
|
|
||||||
|
|
||||||
match self.stage_section {
|
|
||||||
StageSection::Buildup => {
|
|
||||||
if self.timer < self.static_data.buildup_duration {
|
|
||||||
// Build up
|
|
||||||
update.character = CharacterState::HealingBeam(Data {
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Creates beam
|
|
||||||
data.updater.insert(data.entity, beam::Beam {
|
|
||||||
hit_entities: Vec::<Uid>::new(),
|
|
||||||
tick_dur: Duration::from_secs_f32(1.0 / self.static_data.tick_rate),
|
|
||||||
timer: Duration::default(),
|
|
||||||
});
|
|
||||||
// Build up
|
|
||||||
update.character = CharacterState::HealingBeam(Data {
|
|
||||||
timer: Duration::default(),
|
|
||||||
stage_section: StageSection::Cast,
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StageSection::Cast => {
|
|
||||||
if input_is_pressed(data, self.static_data.ability_info.input) {
|
|
||||||
let speed =
|
|
||||||
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
|
|
||||||
let heal = AttackEffect::new(
|
|
||||||
Some(GroupTarget::InGroup),
|
|
||||||
CombatEffect::Heal(self.static_data.heal),
|
|
||||||
)
|
|
||||||
.with_requirement(CombatRequirement::Energy(self.static_data.energy_cost))
|
|
||||||
.with_requirement(CombatRequirement::Combo(1));
|
|
||||||
let attack = Attack::default().with_effect(heal);
|
|
||||||
|
|
||||||
let properties = beam::Properties {
|
|
||||||
attack,
|
|
||||||
angle: self.static_data.max_angle.to_radians(),
|
|
||||||
speed,
|
|
||||||
duration: self.static_data.beam_duration,
|
|
||||||
owner: Some(*data.uid),
|
|
||||||
specifier: self.static_data.specifier,
|
|
||||||
};
|
|
||||||
// Gets offsets
|
|
||||||
let body_offsets = Vec3::new(
|
|
||||||
(data.body.radius() + 0.2) * data.inputs.look_dir.x,
|
|
||||||
(data.body.radius() + 0.2) * data.inputs.look_dir.y,
|
|
||||||
data.body.eye_height() * 0.6,
|
|
||||||
);
|
|
||||||
let pos = Pos(data.pos.0 + body_offsets);
|
|
||||||
// Create beam segment
|
|
||||||
update.server_events.push_front(ServerEvent::BeamSegment {
|
|
||||||
properties,
|
|
||||||
pos,
|
|
||||||
ori: Ori::from(data.inputs.look_dir),
|
|
||||||
});
|
|
||||||
update.character = CharacterState::HealingBeam(Data {
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
update.character = CharacterState::HealingBeam(Data {
|
|
||||||
timer: Duration::default(),
|
|
||||||
stage_section: StageSection::Recover,
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StageSection::Recover => {
|
|
||||||
if self.timer < self.static_data.recover_duration {
|
|
||||||
update.character = CharacterState::HealingBeam(Data {
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Done
|
|
||||||
update.character = CharacterState::Wielding;
|
|
||||||
// Make sure attack component is removed
|
|
||||||
data.updater.remove::<beam::Beam>(data.entity);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
// If it somehow ends up in an incorrect stage section
|
|
||||||
update.character = CharacterState::Wielding;
|
|
||||||
// Make sure attack component is removed
|
|
||||||
data.updater.remove::<beam::Beam>(data.entity);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// At end of state logic so an interrupt isn't overwritten
|
|
||||||
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
|
||||||
handle_state_interrupt(data, &mut update, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
update
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ pub mod dash_melee;
|
|||||||
pub mod equipping;
|
pub mod equipping;
|
||||||
pub mod glide;
|
pub mod glide;
|
||||||
pub mod glide_wield;
|
pub mod glide_wield;
|
||||||
pub mod healing_beam;
|
|
||||||
pub mod idle;
|
pub mod idle;
|
||||||
pub mod leap_melee;
|
pub mod leap_melee;
|
||||||
pub mod repeater_ranged;
|
pub mod repeater_ranged;
|
||||||
|
@ -8,6 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use specs::saveload::MarkerAllocator;
|
||||||
|
|
||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -16,12 +17,12 @@ pub struct StaticData {
|
|||||||
pub buildup_duration: Duration,
|
pub buildup_duration: Duration,
|
||||||
/// How long the state recovers for
|
/// How long the state recovers for
|
||||||
pub recover_duration: Duration,
|
pub recover_duration: Duration,
|
||||||
/// What the max range of the teleport is
|
/// What the max range of the heal is
|
||||||
pub max_range: f32,
|
pub max_range: f32,
|
||||||
/// Miscellaneous information about the ability
|
/// Miscellaneous information about the ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
/// Heal
|
/// Heal
|
||||||
pub heal: HealthChange,
|
pub heal: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -53,12 +54,18 @@ impl CharacterBehavior for Data {
|
|||||||
// Heals a target
|
// Heals a target
|
||||||
if let Some(input_attr) = self.static_data.ability_info.input_attr {
|
if let Some(input_attr) = self.static_data.ability_info.input_attr {
|
||||||
if let Some(target) = input_attr.target_entity {
|
if let Some(target) = input_attr.target_entity {
|
||||||
|
if let Some(target) = data.uid_allocator.retrieve_entity_internal(target.into()) {
|
||||||
update.server_events.push_front(ServerEvent::HealthChange {
|
update.server_events.push_front(ServerEvent::HealthChange {
|
||||||
entity: target,
|
entity: target,
|
||||||
change: HealthChange {
|
change: HealthChange {
|
||||||
amount: self.static_data.heal as i32,
|
amount: self.static_data.heal as i32,
|
||||||
cause: HealthSource::Heal { by: Some(*data.uid) },
|
cause: HealthSource::Heal { by: Some(*data.uid) },
|
||||||
}});
|
}});
|
||||||
|
update.server_events.push_front(ServerEvent::ComboChange {
|
||||||
|
entity: data.entity,
|
||||||
|
change: -1,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Transitions to recover section of stage
|
// Transitions to recover section of stage
|
||||||
|
@ -132,7 +132,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
(health.maximum() as f32 * *accumulated) as i32
|
(health.maximum() as f32 * *accumulated) as i32
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::HealthChange {
|
||||||
entity,
|
entity,
|
||||||
change: HealthChange { amount, cause },
|
change: HealthChange { amount, cause },
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,7 @@ use common::{
|
|||||||
behavior::{CharacterBehavior, JoinData, JoinStruct},
|
behavior::{CharacterBehavior, JoinData, JoinStruct},
|
||||||
},
|
},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
|
uid::UidAllocator,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -77,6 +78,7 @@ pub struct ReadData<'a> {
|
|||||||
msm: Read<'a, MaterialStatManifest>,
|
msm: Read<'a, MaterialStatManifest>,
|
||||||
combos: ReadStorage<'a, Combo>,
|
combos: ReadStorage<'a, Combo>,
|
||||||
alignments: ReadStorage<'a, comp::Alignment>,
|
alignments: ReadStorage<'a, comp::Alignment>,
|
||||||
|
uid_allocator: Read<'a, UidAllocator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Character Behavior System
|
/// ## Character Behavior System
|
||||||
@ -265,6 +267,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
skill_set: &skill_set,
|
skill_set: &skill_set,
|
||||||
combo: &combo,
|
combo: &combo,
|
||||||
alignment: read_data.alignments.get(entity),
|
alignment: read_data.alignments.get(entity),
|
||||||
|
uid_allocator: &read_data.uid_allocator,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for action in actions {
|
for action in actions {
|
||||||
@ -311,7 +315,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::Shockwave(data) => data.handle_event(&j, action),
|
CharacterState::Shockwave(data) => data.handle_event(&j, action),
|
||||||
CharacterState::BasicBeam(data) => data.handle_event(&j, action),
|
CharacterState::BasicBeam(data) => data.handle_event(&j, action),
|
||||||
CharacterState::BasicAura(data) => data.handle_event(&j, action),
|
CharacterState::BasicAura(data) => data.handle_event(&j, action),
|
||||||
CharacterState::HealingBeam(data) => data.handle_event(&j, action),
|
|
||||||
CharacterState::Blink(data) => data.handle_event(&j, action),
|
CharacterState::Blink(data) => data.handle_event(&j, action),
|
||||||
CharacterState::BasicSummon(data) => data.handle_event(&j, action),
|
CharacterState::BasicSummon(data) => data.handle_event(&j, action),
|
||||||
CharacterState::TargetedEffect(data) => data.handle_event(&j, action),
|
CharacterState::TargetedEffect(data) => data.handle_event(&j, action),
|
||||||
@ -366,7 +369,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::Shockwave(data) => data.behavior(&j),
|
CharacterState::Shockwave(data) => data.behavior(&j),
|
||||||
CharacterState::BasicBeam(data) => data.behavior(&j),
|
CharacterState::BasicBeam(data) => data.behavior(&j),
|
||||||
CharacterState::BasicAura(data) => data.behavior(&j),
|
CharacterState::BasicAura(data) => data.behavior(&j),
|
||||||
CharacterState::HealingBeam(data) => data.behavior(&j),
|
|
||||||
CharacterState::Blink(data) => data.behavior(&j),
|
CharacterState::Blink(data) => data.behavior(&j),
|
||||||
CharacterState::BasicSummon(data) => data.behavior(&j),
|
CharacterState::BasicSummon(data) => data.behavior(&j),
|
||||||
CharacterState::TargetedEffect(data) => data.behavior(&j),
|
CharacterState::TargetedEffect(data) => data.behavior(&j),
|
||||||
|
@ -246,7 +246,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
| CharacterState::Shockwave { .. }
|
| CharacterState::Shockwave { .. }
|
||||||
| CharacterState::BasicBeam { .. }
|
| CharacterState::BasicBeam { .. }
|
||||||
| CharacterState::BasicAura { .. }
|
| CharacterState::BasicAura { .. }
|
||||||
| CharacterState::HealingBeam { .. }
|
|
||||||
| CharacterState::Blink { .. }
|
| CharacterState::Blink { .. }
|
||||||
| CharacterState::TargetedEffect { .. }
|
| CharacterState::TargetedEffect { .. }
|
||||||
| CharacterState::BasicSummon { .. } => {
|
| CharacterState::BasicSummon { .. } => {
|
||||||
|
@ -92,7 +92,7 @@ impl Server {
|
|||||||
ServerEvent::Knockback { entity, impulse } => {
|
ServerEvent::Knockback { entity, impulse } => {
|
||||||
handle_knockback(&self, entity, impulse)
|
handle_knockback(&self, entity, impulse)
|
||||||
},
|
},
|
||||||
ServerEvent::Damage { entity, change } => handle_damage(&self, entity, change),
|
ServerEvent::HealthChange { entity, change } => handle_damage(&self, entity, change),
|
||||||
ServerEvent::PoiseChange {
|
ServerEvent::PoiseChange {
|
||||||
entity,
|
entity,
|
||||||
change,
|
change,
|
||||||
|
@ -390,7 +390,7 @@ impl SfxMgr {
|
|||||||
audio.play_sfx(file_ref, *pos, None);
|
audio.play_sfx(file_ref, *pos, None);
|
||||||
},
|
},
|
||||||
Outcome::Beam { pos, specifier } => match specifier {
|
Outcome::Beam { pos, specifier } => match specifier {
|
||||||
beam::FrontendSpecifier::LifestealBeam | beam::FrontendSpecifier::HealingBeam => {
|
beam::FrontendSpecifier::LifestealBeam => {
|
||||||
let file_ref = "voxygen.audio.sfx.abilities.sceptre_channeling";
|
let file_ref = "voxygen.audio.sfx.abilities.sceptre_channeling";
|
||||||
if thread_rng().gen_bool(0.5) {
|
if thread_rng().gen_bool(0.5) {
|
||||||
audio.play_sfx(file_ref, *pos, None);
|
audio.play_sfx(file_ref, *pos, None);
|
||||||
|
@ -110,7 +110,6 @@ pub enum ParticleMode {
|
|||||||
Firefly = 11,
|
Firefly = 11,
|
||||||
Bee = 12,
|
Bee = 12,
|
||||||
GroundShockwave = 13,
|
GroundShockwave = 13,
|
||||||
HealingBeam = 14,
|
|
||||||
EnergyNature = 15,
|
EnergyNature = 15,
|
||||||
FlameThrower = 16,
|
FlameThrower = 16,
|
||||||
FireShockwave = 17,
|
FireShockwave = 17,
|
||||||
|
@ -1284,32 +1284,6 @@ impl FigureMgr {
|
|||||||
skeleton_attr,
|
skeleton_attr,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
CharacterState::HealingBeam(s) => {
|
|
||||||
let stage_time = s.timer.as_secs_f32();
|
|
||||||
let stage_progress = match s.stage_section {
|
|
||||||
StageSection::Buildup => {
|
|
||||||
stage_time / s.static_data.buildup_duration.as_secs_f32()
|
|
||||||
},
|
|
||||||
StageSection::Cast => s.timer.as_secs_f32(),
|
|
||||||
StageSection::Recover => {
|
|
||||||
stage_time / s.static_data.recover_duration.as_secs_f32()
|
|
||||||
},
|
|
||||||
_ => 0.0,
|
|
||||||
};
|
|
||||||
anim::character::BeamAnimation::update_skeleton(
|
|
||||||
&target_base,
|
|
||||||
(
|
|
||||||
Some(s.static_data.ability_info),
|
|
||||||
hands,
|
|
||||||
time,
|
|
||||||
rel_vel.magnitude(),
|
|
||||||
Some(s.stage_section),
|
|
||||||
),
|
|
||||||
stage_progress,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
CharacterState::ComboMelee(s) => {
|
CharacterState::ComboMelee(s) => {
|
||||||
let stage_index = (s.stage - 1) as usize;
|
let stage_index = (s.stage - 1) as usize;
|
||||||
let stage_time = s.timer.as_secs_f32();
|
let stage_time = s.timer.as_secs_f32();
|
||||||
|
@ -718,19 +718,6 @@ impl ParticleMgr {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
beam::FrontendSpecifier::HealingBeam => {
|
|
||||||
// Emit a light when using healing
|
|
||||||
lights.push(Light::new(pos.0, Rgb::new(0.1, 1.0, 0.15), 1.0));
|
|
||||||
for i in 0..beam_tick_count {
|
|
||||||
self.particles.push(Particle::new_directed(
|
|
||||||
beam.properties.duration,
|
|
||||||
time + i as f64 / 1000.0,
|
|
||||||
ParticleMode::HealingBeam,
|
|
||||||
pos.0,
|
|
||||||
pos.0 + *ori.look_dir() * range,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beam::FrontendSpecifier::LifestealBeam => {
|
beam::FrontendSpecifier::LifestealBeam => {
|
||||||
// Emit a light when using lifesteal beam
|
// Emit a light when using lifesteal beam
|
||||||
lights.push(Light::new(pos.0, Rgb::new(0.8, 1.0, 0.5), 1.0));
|
lights.push(Light::new(pos.0, Rgb::new(0.8, 1.0, 0.5), 1.0));
|
||||||
|
Loading…
Reference in New Issue
Block a user