mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'knightresspaladin/healing-aura' into 'master'
Knightresspaladin/healing aura See merge request veloren/veloren!2587
This commit is contained in:
commit
f38cde9d40
@ -79,7 +79,7 @@
|
|||||||
),
|
),
|
||||||
Tool(Sceptre): (
|
Tool(Sceptre): (
|
||||||
primary: "common.abilities.sceptre.lifestealbeam",
|
primary: "common.abilities.sceptre.lifestealbeam",
|
||||||
secondary: "common.abilities.sceptre.healingbeam",
|
secondary: "common.abilities.sceptre.healingaura",
|
||||||
abilities: [
|
abilities: [
|
||||||
(Some(Sceptre(UnlockAura)), "common.abilities.sceptre.wardingaura"),
|
(Some(Sceptre(UnlockAura)), "common.abilities.sceptre.wardingaura"),
|
||||||
],
|
],
|
||||||
@ -191,7 +191,7 @@
|
|||||||
abilities: [],
|
abilities: [],
|
||||||
),
|
),
|
||||||
Custom("Quad Low Beam"): (
|
Custom("Quad Low Beam"): (
|
||||||
primary: "common.abilities.custom.quadlowbeam.healingbeam",
|
primary: "common.abilities.custom.quadlowbeam.lifestealbeam",
|
||||||
secondary: "common.abilities.custom.quadlowbreathe.triplestrike",
|
secondary: "common.abilities.custom.quadlowbreathe.triplestrike",
|
||||||
abilities: [
|
abilities: [
|
||||||
(None, "common.abilities.custom.quadlowbreathe.dash"),
|
(None, "common.abilities.custom.quadlowbreathe.dash"),
|
||||||
|
@ -11,5 +11,5 @@ BasicBeam(
|
|||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
ori_rate: 0.3,
|
ori_rate: 0.3,
|
||||||
specifier: HealingBeam,
|
specifier: LifestealBeam,
|
||||||
)
|
)
|
17
assets/common/abilities/sceptre/healingaura.ron
Normal file
17
assets/common/abilities/sceptre/healingaura.ron
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
BasicAura(
|
||||||
|
buildup_duration: 0.25,
|
||||||
|
cast_duration: 0.5,
|
||||||
|
recover_duration: 0.25,
|
||||||
|
targets: InGroup,
|
||||||
|
aura: (
|
||||||
|
kind: Regeneration,
|
||||||
|
strength: 2.0,
|
||||||
|
duration: Some(10.0),
|
||||||
|
category: Magical,
|
||||||
|
),
|
||||||
|
aura_duration: 1.0,
|
||||||
|
range: 25.0,
|
||||||
|
energy_cost: 200,
|
||||||
|
scales_with_combo: true,
|
||||||
|
specifier: HealingAura,
|
||||||
|
)
|
@ -1,11 +0,0 @@
|
|||||||
HealingBeam(
|
|
||||||
buildup_duration: 0.25,
|
|
||||||
recover_duration: 0.25,
|
|
||||||
beam_duration: 1.0,
|
|
||||||
heal: 40,
|
|
||||||
tick_rate: 2.0,
|
|
||||||
range: 25.0,
|
|
||||||
max_angle: 1.0,
|
|
||||||
energy_cost: 75,
|
|
||||||
specifier: HealingBeam,
|
|
||||||
)
|
|
@ -12,4 +12,6 @@ BasicAura(
|
|||||||
aura_duration: 1.0,
|
aura_duration: 1.0,
|
||||||
range: 25.0,
|
range: 25.0,
|
||||||
energy_cost: 400,
|
energy_cost: 400,
|
||||||
)
|
scales_with_combo: false,
|
||||||
|
specifier: WardingAura,
|
||||||
|
)
|
||||||
|
@ -64,8 +64,9 @@
|
|||||||
Sceptre(LLifesteal): Some(3),
|
Sceptre(LLifesteal): Some(3),
|
||||||
Sceptre(LRegen): Some(2),
|
Sceptre(LRegen): Some(2),
|
||||||
Sceptre(HHeal): Some(3),
|
Sceptre(HHeal): Some(3),
|
||||||
Sceptre(HCost): Some(2),
|
|
||||||
Sceptre(HRange): Some(2),
|
Sceptre(HRange): Some(2),
|
||||||
|
Sceptre(HDuration): Some(2),
|
||||||
|
Sceptre(HCost): Some(2),
|
||||||
Sceptre(AStrength): Some(2),
|
Sceptre(AStrength): Some(2),
|
||||||
Sceptre(ADuration): Some(2),
|
Sceptre(ADuration): Some(2),
|
||||||
Sceptre(ARange): Some(2),
|
Sceptre(ARange): Some(2),
|
||||||
|
@ -101,8 +101,9 @@
|
|||||||
Sceptre(LLifesteal),
|
Sceptre(LLifesteal),
|
||||||
Sceptre(LRegen),
|
Sceptre(LRegen),
|
||||||
Sceptre(HHeal),
|
Sceptre(HHeal),
|
||||||
Sceptre(HCost),
|
|
||||||
Sceptre(HRange),
|
Sceptre(HRange),
|
||||||
|
Sceptre(HDuration),
|
||||||
|
Sceptre(HCost),
|
||||||
Sceptre(UnlockAura),
|
Sceptre(UnlockAura),
|
||||||
Sceptre(AStrength),
|
Sceptre(AStrength),
|
||||||
Sceptre(ADuration),
|
Sceptre(ADuration),
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
// Heal
|
// Heal
|
||||||
Skill((Sceptre(HHeal), Some(1))),
|
Skill((Sceptre(HHeal), Some(1))),
|
||||||
Skill((Sceptre(HCost), Some(1))),
|
Skill((Sceptre(HDuration), Some(1))),
|
||||||
Skill((Sceptre(HRange), Some(1))),
|
Skill((Sceptre(HRange), Some(1))),
|
||||||
|
Skill((Sceptre(HCost), Some(1))),
|
||||||
// Ward
|
// Ward
|
||||||
Skill((Sceptre(UnlockAura), None)),
|
Skill((Sceptre(UnlockAura), None)),
|
||||||
Skill((Sceptre(AStrength), Some(1))),
|
Skill((Sceptre(AStrength), Some(1))),
|
||||||
|
@ -802,7 +802,7 @@
|
|||||||
],
|
],
|
||||||
threshold: 0.2,
|
threshold: 0.2,
|
||||||
),
|
),
|
||||||
HealingBeam: (
|
SceptreBeam: (
|
||||||
files: [
|
files: [
|
||||||
"voxygen.audio.sfx.abilities.sceptre_channeling",
|
"voxygen.audio.sfx.abilities.sceptre_channeling",
|
||||||
],
|
],
|
||||||
|
BIN
assets/voxygen/element/skills/heal_aoe.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/skills/heal_aoe.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/skills/sceptre_protection.png
(Stored with Git LFS)
BIN
assets/voxygen/element/skills/sceptre_protection.png
(Stored with Git LFS)
Binary file not shown.
@ -54,14 +54,16 @@
|
|||||||
"hud.skill.sc_lifesteal_lifesteal": "Convert an additional {boost}% of damage into health{SP}",
|
"hud.skill.sc_lifesteal_lifesteal": "Convert an additional {boost}% of damage into health{SP}",
|
||||||
"hud.skill.sc_lifesteal_regen_title": "Stamina Regen",
|
"hud.skill.sc_lifesteal_regen_title": "Stamina Regen",
|
||||||
"hud.skill.sc_lifesteal_regen": "Replenish your stamina by an additional {boost}%{SP}",
|
"hud.skill.sc_lifesteal_regen": "Replenish your stamina by an additional {boost}%{SP}",
|
||||||
"hud.skill.sc_heal_title": "Healing Beam",
|
"hud.skill.sc_heal_title": "Healing Aura",
|
||||||
"hud.skill.sc_heal": "Heal your allies using the blood of your enemies",
|
"hud.skill.sc_heal": "Heal your allies using the blood of your enemies, requires combo to activate",
|
||||||
"hud.skill.sc_heal_heal_title": "Heal",
|
"hud.skill.sc_heal_heal_title": "Heal",
|
||||||
"hud.skill.sc_heal_heal": "Increases the amount you heal others by {boost}%{SP}",
|
"hud.skill.sc_heal_heal": "Increases the amount you heal by {boost}%{SP}",
|
||||||
"hud.skill.sc_heal_cost_title": "Stamina Cost",
|
"hud.skill.sc_heal_cost_title": "Stamina Cost",
|
||||||
"hud.skill.sc_heal_cost": "Healing others requires {boost}% less stamina{SP}",
|
"hud.skill.sc_heal_cost": "Healing requires {boost}% less stamina{SP}",
|
||||||
"hud.skill.sc_heal_range_title": "Range",
|
"hud.skill.sc_heal_duration_title": "Duration",
|
||||||
"hud.skill.sc_heal_range": "Your beam reachs {boost}% further{SP}",
|
"hud.skill.sc_heal_duration": "The effects of your healing aura last {boost}% longer{SP}",
|
||||||
|
"hud.skill.sc_heal_range_title": "Radius",
|
||||||
|
"hud.skill.sc_heal_range": "Your healing aura reachs {boost}% further{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",
|
||||||
|
@ -52,7 +52,7 @@ const int LEAF = 10;
|
|||||||
const int FIREFLY = 11;
|
const int FIREFLY = 11;
|
||||||
const int BEE = 12;
|
const int BEE = 12;
|
||||||
const int GROUND_SHOCKWAVE = 13;
|
const int GROUND_SHOCKWAVE = 13;
|
||||||
const int HEALING_BEAM = 14;
|
const int ENERGY_HEALING = 14;
|
||||||
const int ENERGY_NATURE = 15;
|
const int ENERGY_NATURE = 15;
|
||||||
const int FLAMETHROWER = 16;
|
const int FLAMETHROWER = 16;
|
||||||
const int FIRE_SHOCKWAVE = 17;
|
const int FIRE_SHOCKWAVE = 17;
|
||||||
@ -380,13 +380,14 @@ void main() {
|
|||||||
spin_in_axis(vec3(1,0,0),0)
|
spin_in_axis(vec3(1,0,0),0)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case HEALING_BEAM:
|
case ENERGY_HEALING:
|
||||||
f_reflect = 0.0;
|
f_reflect = 0.0;
|
||||||
|
float spiral_radius = start_end(1 - pow(abs(rand5), 5), 1) * length(inst_dir);
|
||||||
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(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2),
|
||||||
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
|
vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)),
|
||||||
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*/),
|
vec4(vec3(0, 1.7, 0.7), 1),
|
||||||
spin_in_axis(inst_dir, tick.z)
|
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case LIFESTEAL_BEAM:
|
case LIFESTEAL_BEAM:
|
||||||
@ -402,7 +403,7 @@ void main() {
|
|||||||
break;
|
break;
|
||||||
case ENERGY_NATURE:
|
case ENERGY_NATURE:
|
||||||
f_reflect = 0.0;
|
f_reflect = 0.0;
|
||||||
float spiral_radius = start_end(1 - pow(abs(rand5), 5), 1) * length(inst_dir);
|
spiral_radius = start_end(1 - pow(abs(rand5), 5), 1) * length(inst_dir);
|
||||||
attr = Attr(
|
attr = Attr(
|
||||||
spiral_motion(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2),
|
spiral_motion(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2),
|
||||||
vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)),
|
vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)),
|
||||||
|
@ -264,17 +264,8 @@ pub enum CharacterAbility {
|
|||||||
aura_duration: f32,
|
aura_duration: f32,
|
||||||
range: f32,
|
range: f32,
|
||||||
energy_cost: f32,
|
energy_cost: f32,
|
||||||
},
|
scales_with_combo: bool,
|
||||||
HealingBeam {
|
specifier: aura::Specifier,
|
||||||
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,
|
||||||
@ -356,7 +347,6 @@ impl CharacterAbility {
|
|||||||
| CharacterAbility::ChargedRanged { energy_cost, .. }
|
| CharacterAbility::ChargedRanged { energy_cost, .. }
|
||||||
| CharacterAbility::ChargedMelee { energy_cost, .. }
|
| CharacterAbility::ChargedMelee { energy_cost, .. }
|
||||||
| CharacterAbility::Shockwave { energy_cost, .. }
|
| CharacterAbility::Shockwave { energy_cost, .. }
|
||||||
| CharacterAbility::BasicAura { energy_cost, .. }
|
|
||||||
| CharacterAbility::BasicBlock { energy_cost, .. }
|
| CharacterAbility::BasicBlock { energy_cost, .. }
|
||||||
| CharacterAbility::SelfBuff { energy_cost, .. } => update
|
| CharacterAbility::SelfBuff { energy_cost, .. } => update
|
||||||
.energy
|
.energy
|
||||||
@ -373,7 +363,17 @@ 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::BasicAura {
|
||||||
|
energy_cost,
|
||||||
|
scales_with_combo,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
((*scales_with_combo && data.combo.counter() > 0) | !*scales_with_combo)
|
||||||
|
&& update
|
||||||
|
.energy
|
||||||
|
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||||
|
.is_ok()
|
||||||
|
},
|
||||||
CharacterAbility::ComboMelee { .. }
|
CharacterAbility::ComboMelee { .. }
|
||||||
| CharacterAbility::Boost { .. }
|
| CharacterAbility::Boost { .. }
|
||||||
| CharacterAbility::BasicBeam { .. }
|
| CharacterAbility::BasicBeam { .. }
|
||||||
@ -782,6 +782,8 @@ impl CharacterAbility {
|
|||||||
aura_duration: _,
|
aura_duration: _,
|
||||||
ref mut range,
|
ref mut range,
|
||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
|
scales_with_combo: _,
|
||||||
|
specifier: _,
|
||||||
} => {
|
} => {
|
||||||
*buildup_duration /= stats.speed;
|
*buildup_duration /= stats.speed;
|
||||||
*cast_duration /= stats.speed;
|
*cast_duration /= stats.speed;
|
||||||
@ -792,26 +794,6 @@ impl CharacterAbility {
|
|||||||
*range *= stats.range;
|
*range *= stats.range;
|
||||||
*energy_cost /= stats.energy_efficiency;
|
*energy_cost /= stats.energy_efficiency;
|
||||||
},
|
},
|
||||||
HealingBeam {
|
|
||||||
ref mut buildup_duration,
|
|
||||||
ref mut recover_duration,
|
|
||||||
ref mut beam_duration,
|
|
||||||
ref mut heal,
|
|
||||||
ref mut tick_rate,
|
|
||||||
ref mut range,
|
|
||||||
max_angle: _,
|
|
||||||
ref mut energy_cost,
|
|
||||||
specifier: _,
|
|
||||||
} => {
|
|
||||||
*buildup_duration /= stats.speed;
|
|
||||||
*recover_duration /= stats.speed;
|
|
||||||
*heal *= stats.power;
|
|
||||||
*tick_rate *= stats.speed;
|
|
||||||
*range *= stats.range;
|
|
||||||
// Duration modified to keep velocity constant
|
|
||||||
*beam_duration *= stats.range;
|
|
||||||
*energy_cost /= stats.energy_efficiency;
|
|
||||||
},
|
|
||||||
Blink {
|
Blink {
|
||||||
ref mut buildup_duration,
|
ref mut buildup_duration,
|
||||||
ref mut recover_duration,
|
ref mut recover_duration,
|
||||||
@ -886,7 +868,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, .. }
|
| BasicAura { energy_cost, .. }
|
||||||
| BasicBlock { energy_cost, .. }
|
| BasicBlock { energy_cost, .. }
|
||||||
| SelfBuff { energy_cost, .. } => *energy_cost as u32,
|
| SelfBuff { energy_cost, .. } => *energy_cost as u32,
|
||||||
@ -1381,45 +1362,39 @@ 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,
|
||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
|
ref specifier,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) {
|
if matches!(*specifier, aura::Specifier::WardingAura) {
|
||||||
aura.strength *= 1.15_f32.powi(level.into());
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) {
|
||||||
}
|
aura.strength *= 1.15_f32.powi(level.into());
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ADuration)) {
|
}
|
||||||
if let Some(ref mut duration) = aura.duration {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ADuration)) {
|
||||||
*duration *= 1.2_f32.powi(level.into());
|
aura.duration.map(|dur| dur * 1.2_f32.powi(level.into()));
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ARange)) {
|
||||||
|
*range *= 1.25_f32.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ACost)) {
|
||||||
|
*energy_cost *= 0.85_f32.powi(level.into());
|
||||||
|
}
|
||||||
|
} else if matches!(*specifier, aura::Specifier::HealingAura) {
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HHeal)) {
|
||||||
|
aura.strength *= 1.15_f32.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HDuration)) {
|
||||||
|
aura.duration.map(|dur| dur * 1.2_f32.powi(level.into()));
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HRange)) {
|
||||||
|
*range *= 1.25_f32.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HCost)) {
|
||||||
|
*energy_cost *= 0.85_f32.powi(level.into());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ARange)) {
|
|
||||||
*range *= 1.25_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ACost)) {
|
|
||||||
*energy_cost *= 0.85_f32.powi(level.into());
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -1935,6 +1910,8 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
aura_duration,
|
aura_duration,
|
||||||
range,
|
range,
|
||||||
energy_cost: _,
|
energy_cost: _,
|
||||||
|
scales_with_combo,
|
||||||
|
specifier,
|
||||||
} => CharacterState::BasicAura(basic_aura::Data {
|
} => CharacterState::BasicAura(basic_aura::Data {
|
||||||
static_data: basic_aura::StaticData {
|
static_data: basic_aura::StaticData {
|
||||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||||
@ -1945,31 +1922,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
aura_duration: Duration::from_secs_f32(*aura_duration),
|
aura_duration: Duration::from_secs_f32(*aura_duration),
|
||||||
range: *range,
|
range: *range,
|
||||||
ability_info,
|
ability_info,
|
||||||
},
|
scales_with_combo: *scales_with_combo,
|
||||||
timer: Duration::default(),
|
|
||||||
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,
|
specifier: *specifier,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
|
@ -71,6 +71,12 @@ pub enum AuraTarget {
|
|||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum Specifier {
|
||||||
|
WardingAura,
|
||||||
|
HealingAura,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<(Option<GroupTarget>, Option<&Uid>)> for AuraTarget {
|
impl From<(Option<GroupTarget>, Option<&Uid>)> for AuraTarget {
|
||||||
fn from((target, uid): (Option<GroupTarget>, Option<&Uid>)) -> Self {
|
fn from((target, uid): (Option<GroupTarget>, Option<&Uid>)) -> Self {
|
||||||
match (target, uid) {
|
match (target, uid) {
|
||||||
|
@ -50,7 +50,6 @@ impl Component for Beam {
|
|||||||
pub enum FrontendSpecifier {
|
pub enum FrontendSpecifier {
|
||||||
Flamethrower,
|
Flamethrower,
|
||||||
LifestealBeam,
|
LifestealBeam,
|
||||||
HealingBeam,
|
|
||||||
Cultist,
|
Cultist,
|
||||||
ClayGolem,
|
ClayGolem,
|
||||||
Bubbles,
|
Bubbles,
|
||||||
|
@ -93,11 +93,6 @@ pub enum CharacterState {
|
|||||||
BasicBeam(basic_beam::Data),
|
BasicBeam(basic_beam::Data),
|
||||||
/// Creates an aura that persists as long as you are actively casting
|
/// Creates an aura that persists as long as you are actively casting
|
||||||
BasicAura(basic_aura::Data),
|
BasicAura(basic_aura::Data),
|
||||||
/// A directed beam that heals targets in range. This is separate from basic
|
|
||||||
/// beam as a large amount of functionality needed to be special cased
|
|
||||||
/// specifically for the healing beam. There was also functionality present
|
|
||||||
/// on basic beam which was unnecessary for the healing beam.
|
|
||||||
HealingBeam(healing_beam::Data),
|
|
||||||
/// A short teleport that targets either a position or entity
|
/// 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
|
||||||
@ -128,7 +123,6 @@ impl CharacterState {
|
|||||||
| CharacterState::Shockwave(_)
|
| CharacterState::Shockwave(_)
|
||||||
| CharacterState::BasicBeam(_)
|
| CharacterState::BasicBeam(_)
|
||||||
| CharacterState::BasicAura(_)
|
| CharacterState::BasicAura(_)
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
| CharacterState::SelfBuff(_)
|
| CharacterState::SelfBuff(_)
|
||||||
| CharacterState::Blink(_)
|
| CharacterState::Blink(_)
|
||||||
| CharacterState::BasicSummon(_)
|
| CharacterState::BasicSummon(_)
|
||||||
@ -155,7 +149,6 @@ impl CharacterState {
|
|||||||
| CharacterState::Shockwave(_)
|
| CharacterState::Shockwave(_)
|
||||||
| CharacterState::BasicBeam(_)
|
| CharacterState::BasicBeam(_)
|
||||||
| CharacterState::BasicAura(_)
|
| CharacterState::BasicAura(_)
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
| CharacterState::SelfBuff(_)
|
| CharacterState::SelfBuff(_)
|
||||||
| CharacterState::Blink(_)
|
| CharacterState::Blink(_)
|
||||||
| CharacterState::BasicSummon(_)
|
| CharacterState::BasicSummon(_)
|
||||||
@ -181,7 +174,6 @@ impl CharacterState {
|
|||||||
| CharacterState::UseItem(_)
|
| CharacterState::UseItem(_)
|
||||||
| CharacterState::Wielding
|
| CharacterState::Wielding
|
||||||
| CharacterState::Talk
|
| CharacterState::Talk
|
||||||
| CharacterState::HealingBeam(_)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,8 +478,9 @@ pub enum SceptreSkill {
|
|||||||
LRegen,
|
LRegen,
|
||||||
// Healing beam upgrades
|
// Healing beam upgrades
|
||||||
HHeal,
|
HHeal,
|
||||||
HCost,
|
|
||||||
HRange,
|
HRange,
|
||||||
|
HDuration,
|
||||||
|
HCost,
|
||||||
// Warding aura upgrades
|
// Warding aura upgrades
|
||||||
UnlockAura,
|
UnlockAura,
|
||||||
AStrength,
|
AStrength,
|
||||||
@ -499,6 +500,7 @@ impl Boost for SceptreSkill {
|
|||||||
// Healing beam upgrades
|
// Healing beam upgrades
|
||||||
Self::HHeal => 20.into(),
|
Self::HHeal => 20.into(),
|
||||||
Self::HRange => 20.into(),
|
Self::HRange => 20.into(),
|
||||||
|
Self::HDuration => 20.into(),
|
||||||
Self::HCost => (-20_i16).into(),
|
Self::HCost => (-20_i16).into(),
|
||||||
// Warding aura upgrades
|
// Warding aura upgrades
|
||||||
Self::AStrength => 15.into(),
|
Self::AStrength => 15.into(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
combat::GroupTarget,
|
combat::GroupTarget,
|
||||||
comp::{
|
comp::{
|
||||||
aura::{AuraBuffConstructor, AuraChange, AuraTarget},
|
aura::{AuraBuffConstructor, AuraChange, AuraKind, AuraTarget, Specifier},
|
||||||
CharacterState, StateUpdate,
|
CharacterState, StateUpdate,
|
||||||
},
|
},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
@ -32,6 +32,10 @@ pub struct StaticData {
|
|||||||
pub range: f32,
|
pub range: f32,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
|
/// Whether the aura's effect scales with the user's current combo
|
||||||
|
pub scales_with_combo: bool,
|
||||||
|
/// Used to specify aura to the frontend
|
||||||
|
pub specifier: Specifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -65,12 +69,29 @@ impl CharacterBehavior for Data {
|
|||||||
// Creates aura
|
// Creates aura
|
||||||
let targets =
|
let targets =
|
||||||
AuraTarget::from((Some(self.static_data.targets), Some(data.uid)));
|
AuraTarget::from((Some(self.static_data.targets), Some(data.uid)));
|
||||||
let aura = self.static_data.aura.to_aura(
|
let mut aura = self.static_data.aura.to_aura(
|
||||||
data.uid,
|
data.uid,
|
||||||
self.static_data.range,
|
self.static_data.range,
|
||||||
Some(self.static_data.aura_duration),
|
Some(self.static_data.aura_duration),
|
||||||
targets,
|
targets,
|
||||||
);
|
);
|
||||||
|
if self.static_data.scales_with_combo {
|
||||||
|
let combo = data.combo.counter();
|
||||||
|
match aura.aura_kind {
|
||||||
|
AuraKind::Buff {
|
||||||
|
kind: _,
|
||||||
|
ref mut data,
|
||||||
|
category: _,
|
||||||
|
source: _,
|
||||||
|
} => {
|
||||||
|
data.strength *= 1.0 + (combo as f32).log(2.0_f32);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
update.server_events.push_front(ServerEvent::ComboChange {
|
||||||
|
entity: data.entity,
|
||||||
|
change: -(combo as i32),
|
||||||
|
});
|
||||||
|
}
|
||||||
update.server_events.push_front(ServerEvent::Aura {
|
update.server_events.push_front(ServerEvent::Aura {
|
||||||
entity: data.entity,
|
entity: data.entity,
|
||||||
aura_change: AuraChange::Add(aura),
|
aura_change: AuraChange::Add(aura),
|
||||||
|
@ -1,155 +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_orientation(data, &mut update, 0.6);
|
|
||||||
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: tick_attack_or_default(data, self.timer, None),
|
|
||||||
..*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: tick_attack_or_default(data, self.timer, None),
|
|
||||||
..*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: tick_attack_or_default(data, self.timer, None),
|
|
||||||
..*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;
|
||||||
|
@ -339,7 +339,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::SelfBuff(data) => data.handle_event(&j, action),
|
CharacterState::SelfBuff(data) => data.handle_event(&j, action),
|
||||||
@ -396,7 +395,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::SelfBuff(data) => data.behavior(&j),
|
CharacterState::SelfBuff(data) => data.behavior(&j),
|
||||||
|
@ -276,7 +276,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::BasicSummon { .. }
|
| CharacterState::BasicSummon { .. }
|
||||||
| CharacterState::SelfBuff { .. }
|
| CharacterState::SelfBuff { .. }
|
||||||
|
@ -122,8 +122,9 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String {
|
|||||||
Sceptre(SceptreSkill::LLifesteal) => "Sceptre LLifesteal",
|
Sceptre(SceptreSkill::LLifesteal) => "Sceptre LLifesteal",
|
||||||
Sceptre(SceptreSkill::LRegen) => "Sceptre LRegen",
|
Sceptre(SceptreSkill::LRegen) => "Sceptre LRegen",
|
||||||
Sceptre(SceptreSkill::HHeal) => "Sceptre HHeal",
|
Sceptre(SceptreSkill::HHeal) => "Sceptre HHeal",
|
||||||
Sceptre(SceptreSkill::HCost) => "Sceptre HCost",
|
Sceptre(SceptreSkill::HDuration) => "Sceptre HDuration",
|
||||||
Sceptre(SceptreSkill::HRange) => "Sceptre HRange",
|
Sceptre(SceptreSkill::HRange) => "Sceptre HRange",
|
||||||
|
Sceptre(SceptreSkill::HCost) => "Sceptre HCost",
|
||||||
Sceptre(SceptreSkill::UnlockAura) => "Sceptre UnlockAura",
|
Sceptre(SceptreSkill::UnlockAura) => "Sceptre UnlockAura",
|
||||||
Sceptre(SceptreSkill::AStrength) => "Sceptre AStrength",
|
Sceptre(SceptreSkill::AStrength) => "Sceptre AStrength",
|
||||||
Sceptre(SceptreSkill::ADuration) => "Sceptre ADuration",
|
Sceptre(SceptreSkill::ADuration) => "Sceptre ADuration",
|
||||||
@ -245,8 +246,9 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill {
|
|||||||
"Sceptre LLifesteal" => Sceptre(SceptreSkill::LLifesteal),
|
"Sceptre LLifesteal" => Sceptre(SceptreSkill::LLifesteal),
|
||||||
"Sceptre LRegen" => Sceptre(SceptreSkill::LRegen),
|
"Sceptre LRegen" => Sceptre(SceptreSkill::LRegen),
|
||||||
"Sceptre HHeal" => Sceptre(SceptreSkill::HHeal),
|
"Sceptre HHeal" => Sceptre(SceptreSkill::HHeal),
|
||||||
"Sceptre HCost" => Sceptre(SceptreSkill::HCost),
|
"Sceptre HDuration" => Sceptre(SceptreSkill::HDuration),
|
||||||
"Sceptre HRange" => Sceptre(SceptreSkill::HRange),
|
"Sceptre HRange" => Sceptre(SceptreSkill::HRange),
|
||||||
|
"Sceptre HCost" => Sceptre(SceptreSkill::HCost),
|
||||||
"Sceptre UnlockAura" => Sceptre(SceptreSkill::UnlockAura),
|
"Sceptre UnlockAura" => Sceptre(SceptreSkill::UnlockAura),
|
||||||
"Sceptre AStrength" => Sceptre(SceptreSkill::AStrength),
|
"Sceptre AStrength" => Sceptre(SceptreSkill::AStrength),
|
||||||
"Sceptre ADuration" => Sceptre(SceptreSkill::ADuration),
|
"Sceptre ADuration" => Sceptre(SceptreSkill::ADuration),
|
||||||
|
@ -18,9 +18,9 @@ use common::{
|
|||||||
},
|
},
|
||||||
skills::{AxeSkill, BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill},
|
skills::{AxeSkill, BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill},
|
||||||
Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterAbility,
|
Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterAbility,
|
||||||
CharacterState, ControlAction, ControlEvent, Controller, Energy, Health, HealthChange,
|
CharacterState, Combo, ControlAction, ControlEvent, Controller, Energy, Health,
|
||||||
InputKind, Inventory, InventoryAction, LightEmitter, MountState, Ori, PhysicsState, Pos,
|
HealthChange, InputKind, Inventory, InventoryAction, LightEmitter, MountState, Ori,
|
||||||
Scale, SkillSet, Stats, UnresolvedChatMsg, UtteranceKind, Vel,
|
PhysicsState, Pos, Scale, SkillSet, Stats, UnresolvedChatMsg, UtteranceKind, Vel,
|
||||||
},
|
},
|
||||||
consts::GRAVITY,
|
consts::GRAVITY,
|
||||||
effect::{BuffEffect, Effect},
|
effect::{BuffEffect, Effect},
|
||||||
@ -160,6 +160,7 @@ pub struct ReadData<'a> {
|
|||||||
world: ReadExpect<'a, Arc<world::World>>,
|
world: ReadExpect<'a, Arc<world::World>>,
|
||||||
rtsim_entities: ReadStorage<'a, RtSimEntity>,
|
rtsim_entities: ReadStorage<'a, RtSimEntity>,
|
||||||
buffs: ReadStorage<'a, Buffs>,
|
buffs: ReadStorage<'a, Buffs>,
|
||||||
|
combos: ReadStorage<'a, Combo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is 3.1 to last longer than the last damage timer (3.0 seconds)
|
// This is 3.1 to last longer than the last damage timer (3.0 seconds)
|
||||||
@ -2467,6 +2468,7 @@ impl<'a> AgentData<'a> {
|
|||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
) {
|
) {
|
||||||
const DESIRED_ENERGY_LEVEL: u32 = 500;
|
const DESIRED_ENERGY_LEVEL: u32 = 500;
|
||||||
|
const DESIRED_COMBO_LEVEL: u32 = 8;
|
||||||
// Logic to use abilities
|
// Logic to use abilities
|
||||||
if attack_data.dist_sqrd > attack_data.min_attack_dist.powi(2)
|
if attack_data.dist_sqrd > attack_data.min_attack_dist.powi(2)
|
||||||
&& can_see_tgt(
|
&& can_see_tgt(
|
||||||
@ -2478,7 +2480,23 @@ impl<'a> AgentData<'a> {
|
|||||||
{
|
{
|
||||||
// If far enough away, and can see target, check which skill is appropriate to
|
// If far enough away, and can see target, check which skill is appropriate to
|
||||||
// use
|
// use
|
||||||
if self
|
if self.energy.current() > DESIRED_ENERGY_LEVEL
|
||||||
|
&& read_data
|
||||||
|
.combos
|
||||||
|
.get(*self.entity)
|
||||||
|
.map_or(false, |c| c.counter() >= DESIRED_COMBO_LEVEL)
|
||||||
|
&& !read_data.buffs.get(*self.entity).iter().any(|buff| {
|
||||||
|
buff.iter_kind(BuffKind::Regeneration)
|
||||||
|
.peekable()
|
||||||
|
.peek()
|
||||||
|
.is_some()
|
||||||
|
})
|
||||||
|
{
|
||||||
|
// If have enough energy and combo to use healing aura, do so
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
|
} else if self
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Sceptre(SceptreSkill::UnlockAura))
|
.has_skill(Skill::Sceptre(SceptreSkill::UnlockAura))
|
||||||
&& self.energy.current() > DESIRED_ENERGY_LEVEL
|
&& self.energy.current() > DESIRED_ENERGY_LEVEL
|
||||||
|
@ -175,7 +175,7 @@ pub enum SfxEvent {
|
|||||||
Parry,
|
Parry,
|
||||||
Block,
|
Block,
|
||||||
BreakBlock,
|
BreakBlock,
|
||||||
HealingBeam,
|
SceptreBeam,
|
||||||
SkillPointGain,
|
SkillPointGain,
|
||||||
ArrowHit,
|
ArrowHit,
|
||||||
ArrowMiss,
|
ArrowMiss,
|
||||||
@ -479,9 +479,9 @@ impl SfxMgr {
|
|||||||
audio.emit_sfx(sfx_trigger_item, *pos, None, false);
|
audio.emit_sfx(sfx_trigger_item, *pos, None, false);
|
||||||
},
|
},
|
||||||
Outcome::Beam { pos, specifier } => match specifier {
|
Outcome::Beam { pos, specifier } => match specifier {
|
||||||
beam::FrontendSpecifier::LifestealBeam | beam::FrontendSpecifier::HealingBeam => {
|
beam::FrontendSpecifier::LifestealBeam => {
|
||||||
if thread_rng().gen_bool(0.5) {
|
if thread_rng().gen_bool(0.5) {
|
||||||
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::HealingBeam);
|
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::SceptreBeam);
|
||||||
audio.emit_sfx(sfx_trigger_item, *pos, None, false);
|
audio.emit_sfx(sfx_trigger_item, *pos, None, false);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -144,6 +144,7 @@ widget_ids! {
|
|||||||
skill_sceptre_heal_1,
|
skill_sceptre_heal_1,
|
||||||
skill_sceptre_heal_2,
|
skill_sceptre_heal_2,
|
||||||
skill_sceptre_heal_3,
|
skill_sceptre_heal_3,
|
||||||
|
skill_sceptre_heal_4,
|
||||||
skill_sceptre_aura_0,
|
skill_sceptre_aura_0,
|
||||||
skill_sceptre_aura_1,
|
skill_sceptre_aura_1,
|
||||||
skill_sceptre_aura_2,
|
skill_sceptre_aura_2,
|
||||||
@ -551,7 +552,7 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
SelectedSkillTree::Weapon(ToolKind::Hammer) => 5,
|
SelectedSkillTree::Weapon(ToolKind::Hammer) => 5,
|
||||||
SelectedSkillTree::Weapon(ToolKind::Bow) => 4,
|
SelectedSkillTree::Weapon(ToolKind::Bow) => 4,
|
||||||
SelectedSkillTree::Weapon(ToolKind::Staff) => 5,
|
SelectedSkillTree::Weapon(ToolKind::Staff) => 5,
|
||||||
SelectedSkillTree::Weapon(ToolKind::Sceptre) => 4,
|
SelectedSkillTree::Weapon(ToolKind::Sceptre) => 5,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
let skills_bot_l = match sel_tab {
|
let skills_bot_l = match sel_tab {
|
||||||
@ -1912,10 +1913,10 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
&diary_tooltip,
|
&diary_tooltip,
|
||||||
);
|
);
|
||||||
self.create_unlock_skill_button(
|
self.create_unlock_skill_button(
|
||||||
Skill::Sceptre(HCost),
|
Skill::Sceptre(HDuration),
|
||||||
self.imgs.heal_cost_skill,
|
self.imgs.heal_duration_skill,
|
||||||
state.skills_top_r[2],
|
state.skills_top_r[2],
|
||||||
"sc_heal_cost",
|
"sc_heal_duration",
|
||||||
state.skill_sceptre_heal_2,
|
state.skill_sceptre_heal_2,
|
||||||
ui,
|
ui,
|
||||||
&mut events,
|
&mut events,
|
||||||
@ -1923,7 +1924,7 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
);
|
);
|
||||||
self.create_unlock_skill_button(
|
self.create_unlock_skill_button(
|
||||||
Skill::Sceptre(HRange),
|
Skill::Sceptre(HRange),
|
||||||
self.imgs.heal_distance_skill,
|
self.imgs.heal_radius_skill,
|
||||||
state.skills_top_r[3],
|
state.skills_top_r[3],
|
||||||
"sc_heal_range",
|
"sc_heal_range",
|
||||||
state.skill_sceptre_heal_3,
|
state.skill_sceptre_heal_3,
|
||||||
@ -1931,6 +1932,16 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
&mut events,
|
&mut events,
|
||||||
&diary_tooltip,
|
&diary_tooltip,
|
||||||
);
|
);
|
||||||
|
self.create_unlock_skill_button(
|
||||||
|
Skill::Sceptre(HCost),
|
||||||
|
self.imgs.heal_cost_skill,
|
||||||
|
state.skills_top_r[4],
|
||||||
|
"sc_heal_cost",
|
||||||
|
state.skill_sceptre_heal_4,
|
||||||
|
ui,
|
||||||
|
&mut events,
|
||||||
|
&diary_tooltip,
|
||||||
|
);
|
||||||
// Bottom left skills
|
// Bottom left skills
|
||||||
self.create_unlock_skill_button(
|
self.create_unlock_skill_button(
|
||||||
Skill::Sceptre(UnlockAura),
|
Skill::Sceptre(UnlockAura),
|
||||||
|
@ -494,7 +494,7 @@ image_ids! {
|
|||||||
snake_arrow_0: "voxygen.element.skills.snake",
|
snake_arrow_0: "voxygen.element.skills.snake",
|
||||||
skill_sceptre_lifesteal: "voxygen.element.skills.lifesteal",
|
skill_sceptre_lifesteal: "voxygen.element.skills.lifesteal",
|
||||||
sword_whirlwind: "voxygen.element.skills.sword_whirlwind",
|
sword_whirlwind: "voxygen.element.skills.sword_whirlwind",
|
||||||
skill_sceptre_heal: "voxygen.element.skills.heal_0",
|
skill_sceptre_heal: "voxygen.element.skills.heal_aoe",
|
||||||
hammerleap: "voxygen.element.skills.skill_hammerleap",
|
hammerleap: "voxygen.element.skills.skill_hammerleap",
|
||||||
skill_axe_leap_slash: "voxygen.element.skills.skill_axe_leap_slash",
|
skill_axe_leap_slash: "voxygen.element.skills.skill_axe_leap_slash",
|
||||||
skill_bow_jump_burst: "voxygen.element.skills.skill_bow_jump_burst",
|
skill_bow_jump_burst: "voxygen.element.skills.skill_bow_jump_burst",
|
||||||
|
@ -64,7 +64,7 @@ pub enum ParticleMode {
|
|||||||
Firefly = 11,
|
Firefly = 11,
|
||||||
Bee = 12,
|
Bee = 12,
|
||||||
GroundShockwave = 13,
|
GroundShockwave = 13,
|
||||||
HealingBeam = 14,
|
EnergyHealing = 14,
|
||||||
EnergyNature = 15,
|
EnergyNature = 15,
|
||||||
FlameThrower = 16,
|
FlameThrower = 16,
|
||||||
FireShockwave = 17,
|
FireShockwave = 17,
|
||||||
|
@ -1302,32 +1302,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();
|
||||||
|
@ -826,20 +826,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));
|
|
||||||
self.particles.reserve(beam_tick_count as usize);
|
|
||||||
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));
|
||||||
@ -956,6 +942,28 @@ impl ParticleMgr {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
aura::AuraKind::Buff {
|
||||||
|
kind: buff::BuffKind::Regeneration,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5));
|
||||||
|
self.particles.resize_with(
|
||||||
|
self.particles.len()
|
||||||
|
+ aura.radius.powi(2) as usize * usize::from(heartbeats) / 300,
|
||||||
|
|| {
|
||||||
|
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
|
||||||
|
let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32);
|
||||||
|
let max_dur = Duration::from_secs(1);
|
||||||
|
Particle::new_directed(
|
||||||
|
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
|
||||||
|
time,
|
||||||
|
ParticleMode::EnergyHealing,
|
||||||
|
pos.0,
|
||||||
|
pos.0 + init_pos,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user