mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
SkillTreeModifiers data structs
This commit is contained in:
parent
1ff99dcc34
commit
b1bac83319
@ -893,7 +893,6 @@ impl CharacterAbility {
|
|||||||
skillset: &skills::SkillSet,
|
skillset: &skills::SkillSet,
|
||||||
tool: Option<ToolKind>,
|
tool: Option<ToolKind>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
use skills::Skill;
|
|
||||||
match tool {
|
match tool {
|
||||||
Some(ToolKind::Sword) => self.adjusted_by_sword_skills(skillset),
|
Some(ToolKind::Sword) => self.adjusted_by_sword_skills(skillset),
|
||||||
Some(ToolKind::Axe) => self.adjusted_by_axe_skills(skillset),
|
Some(ToolKind::Axe) => self.adjusted_by_axe_skills(skillset),
|
||||||
@ -901,54 +900,65 @@ impl CharacterAbility {
|
|||||||
Some(ToolKind::Bow) => self.adjusted_by_bow_skills(skillset),
|
Some(ToolKind::Bow) => self.adjusted_by_bow_skills(skillset),
|
||||||
Some(ToolKind::Staff) => self.adjusted_by_staff_skills(skillset),
|
Some(ToolKind::Staff) => self.adjusted_by_staff_skills(skillset),
|
||||||
Some(ToolKind::Sceptre) => self.adjusted_by_sceptre_skills(skillset),
|
Some(ToolKind::Sceptre) => self.adjusted_by_sceptre_skills(skillset),
|
||||||
Some(ToolKind::Pick) => {
|
Some(ToolKind::Pick) => self.adjusted_by_mining_skills(skillset),
|
||||||
use skills::MiningSkill::Speed;
|
None => self.adjusted_by_general_skills(skillset),
|
||||||
|
|
||||||
if let CharacterAbility::BasicMelee {
|
|
||||||
ref mut buildup_duration,
|
|
||||||
ref mut swing_duration,
|
|
||||||
ref mut recover_duration,
|
|
||||||
..
|
|
||||||
} = self
|
|
||||||
{
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Skill::Pick(Speed)) {
|
|
||||||
let speed = 1.1_f32.powi(level.into());
|
|
||||||
*buildup_duration /= speed;
|
|
||||||
*swing_duration /= speed;
|
|
||||||
*recover_duration /= speed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
if let CharacterAbility::Roll {
|
|
||||||
ref mut energy_cost,
|
|
||||||
ref mut roll_strength,
|
|
||||||
ref mut movement_duration,
|
|
||||||
..
|
|
||||||
} = self
|
|
||||||
{
|
|
||||||
use skills::RollSkill::{Cost, Duration, Strength};
|
|
||||||
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Cost)) {
|
|
||||||
*energy_cost *= 0.9_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Strength)) {
|
|
||||||
*roll_strength *= 1.1_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Duration)) {
|
|
||||||
*movement_duration *= 1.1_f32.powi(level.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(_) => {},
|
Some(_) => {},
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[warn(clippy::pedantic)]
|
||||||
|
fn adjusted_by_mining_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
|
use skills::{MiningSkill::Speed, MiningTreeModifiers, Skill};
|
||||||
|
|
||||||
|
if let CharacterAbility::BasicMelee {
|
||||||
|
ref mut buildup_duration,
|
||||||
|
ref mut swing_duration,
|
||||||
|
ref mut recover_duration,
|
||||||
|
..
|
||||||
|
} = self
|
||||||
|
{
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Skill::Pick(Speed)) {
|
||||||
|
let modifiers = MiningTreeModifiers::get();
|
||||||
|
let speed = modifiers.speed.powi(level.into());
|
||||||
|
*buildup_duration /= speed;
|
||||||
|
*swing_duration /= speed;
|
||||||
|
*recover_duration /= speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[warn(clippy::pedantic)]
|
||||||
|
fn adjusted_by_general_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
|
use skills::{GeneralTreeModifiers, Skill};
|
||||||
|
const GENERAL_MODIFIERS: GeneralTreeModifiers = GeneralTreeModifiers::get();
|
||||||
|
if let CharacterAbility::Roll {
|
||||||
|
ref mut energy_cost,
|
||||||
|
ref mut roll_strength,
|
||||||
|
ref mut movement_duration,
|
||||||
|
..
|
||||||
|
} = self
|
||||||
|
{
|
||||||
|
use skills::RollSkill::{Cost, Duration, Strength};
|
||||||
|
let modifiers = GENERAL_MODIFIERS.roll;
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Cost)) {
|
||||||
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Strength)) {
|
||||||
|
*roll_strength *= modifiers.strength.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Duration)) {
|
||||||
|
*movement_duration *= modifiers.duration.powi(level.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_sword_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_sword_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{Skill::Sword, SwordSkill::*};
|
use skills::{Skill::Sword, SwordSkill::*, SwordTreeModifiers};
|
||||||
|
|
||||||
|
const SWORD_MODIFIERS: SwordTreeModifiers = SwordTreeModifiers::get();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::ComboMelee {
|
CharacterAbility::ComboMelee {
|
||||||
@ -994,21 +1004,22 @@ impl CharacterAbility {
|
|||||||
ref mut charge_through,
|
ref mut charge_through,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = SWORD_MODIFIERS.dash;
|
||||||
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
|
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(DCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(DCost)) {
|
||||||
*energy_cost *= 0.75_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(DDrain)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(DDrain)) {
|
||||||
*energy_drain *= 0.75_f32.powi(level.into());
|
*energy_drain *= modifiers.energy_drain.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(DDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(DDamage)) {
|
||||||
*base_damage *= 1.2_f32.powi(level.into());
|
*base_damage *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(DScaling)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(DScaling)) {
|
||||||
*scaled_damage *= 1.2_f32.powi(level.into());
|
*scaled_damage *= modifiers.scaled_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if skillset.has_skill(Sword(DSpeed)) {
|
if skillset.has_skill(Sword(DSpeed)) {
|
||||||
*forward_speed *= 1.15;
|
*forward_speed *= modifiers.forward_speed;
|
||||||
}
|
}
|
||||||
*charge_through = skillset.has_skill(Sword(DInfinite));
|
*charge_through = skillset.has_skill(Sword(DInfinite));
|
||||||
},
|
},
|
||||||
@ -1020,18 +1031,19 @@ impl CharacterAbility {
|
|||||||
ref mut num_spins,
|
ref mut num_spins,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = SWORD_MODIFIERS.spin;
|
||||||
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
|
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(SDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(SDamage)) {
|
||||||
*base_damage *= 1.4_f32.powi(level.into());
|
*base_damage *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(SSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(SSpeed)) {
|
||||||
*swing_duration *= 0.8_f32.powi(level.into());
|
*swing_duration *= modifiers.swing_duration.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sword(SCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sword(SCost)) {
|
||||||
*energy_cost *= 0.75_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
let spin_level = skillset.skill_level_or(Sword(SSpins), 0);
|
let spin_level = skillset.skill_level_or(Sword(SSpins), 0);
|
||||||
*num_spins = u32::from(spin_level) + 1;
|
*num_spins = u32::from(spin_level) * modifiers.num + 1;
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -1040,7 +1052,9 @@ impl CharacterAbility {
|
|||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_axe_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_axe_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{AxeSkill::*, Skill::Axe};
|
use skills::{AxeSkill::*, AxeTreeModifiers, Skill::Axe};
|
||||||
|
|
||||||
|
const AXE_MODIFIERS: AxeTreeModifiers = AxeTreeModifiers::get();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::ComboMelee {
|
CharacterAbility::ComboMelee {
|
||||||
@ -1077,6 +1091,7 @@ impl CharacterAbility {
|
|||||||
ref mut movement_behavior,
|
ref mut movement_behavior,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = AXE_MODIFIERS.spin;
|
||||||
*is_infinite = skillset.has_skill(Axe(SInfinite));
|
*is_infinite = skillset.has_skill(Axe(SInfinite));
|
||||||
*movement_behavior = if skillset.has_skill(Axe(SHelicopter)) {
|
*movement_behavior = if skillset.has_skill(Axe(SHelicopter)) {
|
||||||
spin_melee::MovementBehavior::AxeHover
|
spin_melee::MovementBehavior::AxeHover
|
||||||
@ -1084,13 +1099,13 @@ impl CharacterAbility {
|
|||||||
spin_melee::MovementBehavior::ForwardGround
|
spin_melee::MovementBehavior::ForwardGround
|
||||||
};
|
};
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(SDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(SDamage)) {
|
||||||
*base_damage *= 1.3_f32.powi(level.into());
|
*base_damage *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(SSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(SSpeed)) {
|
||||||
*swing_duration *= 0.8_f32.powi(level.into());
|
*swing_duration *= modifiers.swing_duration.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(SCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(SCost)) {
|
||||||
*energy_cost *= 0.75_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CharacterAbility::LeapMelee {
|
CharacterAbility::LeapMelee {
|
||||||
@ -1101,18 +1116,20 @@ impl CharacterAbility {
|
|||||||
ref mut vertical_leap_strength,
|
ref mut vertical_leap_strength,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = AXE_MODIFIERS.leap;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(LDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(LDamage)) {
|
||||||
*base_damage *= 1.35_f32.powi(level.into());
|
*base_damage *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(LKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(LKnockback)) {
|
||||||
*knockback *= 1.4_f32.powi(level.into());
|
*knockback *= modifiers.knockback.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(LCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(LCost)) {
|
||||||
*energy_cost *= 0.75_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Axe(LDistance)) {
|
if let Ok(Some(level)) = skillset.skill_level(Axe(LDistance)) {
|
||||||
*forward_leap_strength *= 1.2_f32.powi(level.into());
|
let strength = modifiers.leap_strength;
|
||||||
*vertical_leap_strength *= 1.2_f32.powi(level.into());
|
*forward_leap_strength *= strength.powi(level.into());
|
||||||
|
*vertical_leap_strength *= strength.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -1122,7 +1139,10 @@ impl CharacterAbility {
|
|||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_hammer_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_hammer_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{HammerSkill::*, Skill::Hammer};
|
use skills::{HammerSkill::*, HammerTreeModifiers, Skill::Hammer};
|
||||||
|
|
||||||
|
const HAMMER_MODIFIERS: HammerTreeModifiers = HammerTreeModifiers::get();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::ComboMelee {
|
CharacterAbility::ComboMelee {
|
||||||
ref mut speed_increase,
|
ref mut speed_increase,
|
||||||
@ -1132,10 +1152,11 @@ impl CharacterAbility {
|
|||||||
ref mut scales_from_combo,
|
ref mut scales_from_combo,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = HAMMER_MODIFIERS.single_strike;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(SsKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(SsKnockback)) {
|
||||||
*stage_data = (*stage_data)
|
*stage_data = (*stage_data)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.modify_strike(1.5_f32.powi(level.into())))
|
.map(|s| s.modify_strike(modifiers.knockback.powi(level.into())))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
let speed_segments = f32::from(Hammer(SsSpeed).max_level().unwrap_or(1));
|
let speed_segments = f32::from(Hammer(SsSpeed).max_level().unwrap_or(1));
|
||||||
@ -1160,17 +1181,19 @@ impl CharacterAbility {
|
|||||||
ref mut charge_duration,
|
ref mut charge_duration,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = HAMMER_MODIFIERS.charged;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(CDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(CDamage)) {
|
||||||
*scaled_damage *= 1.25_f32.powi(level.into());
|
*scaled_damage *= modifiers.scaled_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(CKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(CKnockback)) {
|
||||||
*scaled_knockback *= 1.5_f32.powi(level.into());
|
*scaled_knockback *= modifiers.scaled_knockback.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(CDrain)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(CDrain)) {
|
||||||
*energy_drain *= 0.75_f32.powi(level.into());
|
*energy_drain *= modifiers.energy_drain.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(CSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(CSpeed)) {
|
||||||
*charge_duration /= 1.25_f32.powi(level.into());
|
let charge_time = 1.0 / modifiers.charge_rate;
|
||||||
|
*charge_duration *= charge_time.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CharacterAbility::LeapMelee {
|
CharacterAbility::LeapMelee {
|
||||||
@ -1182,21 +1205,23 @@ impl CharacterAbility {
|
|||||||
ref mut range,
|
ref mut range,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = HAMMER_MODIFIERS.leap;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(LDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(LDamage)) {
|
||||||
*base_damage *= 1.4_f32.powi(level.into());
|
*base_damage *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(LKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(LKnockback)) {
|
||||||
*knockback *= 1.5_f32.powi(level.into());
|
*knockback *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(LCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(LCost)) {
|
||||||
*energy_cost *= 0.75_f32.powi(level.into());
|
*energy_cost *= modifiers.base_damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(LDistance)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(LDistance)) {
|
||||||
*forward_leap_strength *= 1.25_f32.powi(level.into());
|
let strength = modifiers.leap_strength;
|
||||||
*vertical_leap_strength *= 1.25_f32.powi(level.into());
|
*forward_leap_strength *= strength.powi(level.into());
|
||||||
|
*vertical_leap_strength *= strength.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Hammer(LRange)) {
|
if let Ok(Some(level)) = skillset.skill_level(Hammer(LRange)) {
|
||||||
*range += 1.0 * f32::from(level);
|
*range += modifiers.range * f32::from(level);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -1206,8 +1231,9 @@ impl CharacterAbility {
|
|||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_bow_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_bow_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{BowSkill::*, Skill::Bow};
|
use skills::{BowSkill::*, BowTreeModifiers, Skill::Bow};
|
||||||
|
|
||||||
|
const BOW_MODIFIERS: BowTreeModifiers = BowTreeModifiers::get();
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::ChargedRanged {
|
CharacterAbility::ChargedRanged {
|
||||||
ref mut initial_damage,
|
ref mut initial_damage,
|
||||||
@ -1222,31 +1248,34 @@ impl CharacterAbility {
|
|||||||
ref mut charge_duration,
|
ref mut charge_duration,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed;
|
||||||
|
let modifiers = BOW_MODIFIERS.charged;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
||||||
let projectile_speed_scaling = 1.2_f32.powi(level.into());
|
let projectile_speed_scaling = projectile_speed_modifier.powi(level.into());
|
||||||
*initial_projectile_speed *= projectile_speed_scaling;
|
*initial_projectile_speed *= projectile_speed_scaling;
|
||||||
*scaled_projectile_speed *= projectile_speed_scaling;
|
*scaled_projectile_speed *= projectile_speed_scaling;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(CDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(CDamage)) {
|
||||||
let damage_scaling = 1.2_f32.powi(level.into());
|
let damage_scaling = modifiers.damage_scaling.powi(level.into());
|
||||||
*initial_damage *= damage_scaling;
|
*initial_damage *= damage_scaling;
|
||||||
*scaled_damage *= damage_scaling;
|
*scaled_damage *= damage_scaling;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(CRegen)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(CRegen)) {
|
||||||
let regen_scaling = 1.2_f32.powi(level.into());
|
let regen_scaling = modifiers.regen_scaling.powi(level.into());
|
||||||
*initial_regen *= regen_scaling;
|
*initial_regen *= regen_scaling;
|
||||||
*scaled_regen *= regen_scaling;
|
*scaled_regen *= regen_scaling;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(CKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(CKnockback)) {
|
||||||
let knockback_scaling = 1.2_f32.powi(level.into());
|
let knockback_scaling = modifiers.knockback_scaling.powi(level.into());
|
||||||
*initial_knockback *= knockback_scaling;
|
*initial_knockback *= knockback_scaling;
|
||||||
*scaled_knockback *= knockback_scaling;
|
*scaled_knockback *= knockback_scaling;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(CSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(CSpeed)) {
|
||||||
*charge_duration /= 1.1_f32.powi(level.into());
|
let charge_time = 1.0 / modifiers.charge_rate;
|
||||||
|
*charge_duration *= charge_time.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(CMove)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(CMove)) {
|
||||||
*move_speed *= 1.1_f32.powi(level.into());
|
*move_speed *= modifiers.charge_rate.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CharacterAbility::RepeaterRanged {
|
CharacterAbility::RepeaterRanged {
|
||||||
@ -1256,18 +1285,20 @@ impl CharacterAbility {
|
|||||||
ref mut projectile_speed,
|
ref mut projectile_speed,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed;
|
||||||
|
let modifiers = BOW_MODIFIERS.repeater;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
||||||
*projectile_speed *= 1.2_f32.powi(level.into());
|
*projectile_speed *= projectile_speed_modifier.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(RDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(RDamage)) {
|
||||||
let power = 1.2_f32.powi(level.into());
|
let power = modifiers.power.powi(level.into());
|
||||||
*projectile = projectile.modified_projectile(power, 1_f32, 1_f32);
|
*projectile = projectile.modified_projectile(power, 1_f32, 1_f32);
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(RCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(RCost)) {
|
||||||
*energy_cost *= 0.8_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(RSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(RSpeed)) {
|
||||||
*max_speed *= 1.2_f32.powi(level.into());
|
*max_speed *= modifiers.max_speed.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CharacterAbility::BasicRanged {
|
CharacterAbility::BasicRanged {
|
||||||
@ -1278,21 +1309,23 @@ impl CharacterAbility {
|
|||||||
ref mut projectile_speed,
|
ref mut projectile_speed,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed;
|
||||||
|
let modifiers = BOW_MODIFIERS.shotgun;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) {
|
||||||
*projectile_speed *= 1.2_f32.powi(level.into());
|
*projectile_speed *= projectile_speed_modifier.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(SDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(SDamage)) {
|
||||||
let power = 1.2_f32.powi(level.into());
|
let power = modifiers.power.powi(level.into());
|
||||||
*projectile = projectile.modified_projectile(power, 1_f32, 1_f32);
|
*projectile = projectile.modified_projectile(power, 1_f32, 1_f32);
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(SCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(SCost)) {
|
||||||
*energy_cost *= 0.8_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(SArrows)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(SArrows)) {
|
||||||
*num_projectiles += u32::from(level);
|
*num_projectiles += u32::from(level) * modifiers.num_projectiles;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Bow(SSpread)) {
|
if let Ok(Some(level)) = skillset.skill_level(Bow(SSpread)) {
|
||||||
*projectile_spread *= 0.8_f32.powi(level.into());
|
*projectile_spread *= modifiers.spread.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -1302,18 +1335,20 @@ impl CharacterAbility {
|
|||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_staff_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_staff_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{Skill::Staff, StaffSkill::*};
|
use skills::{Skill::Staff, StaffSkill::*, StaffTreeModifiers};
|
||||||
|
|
||||||
|
const STAFF_MODIFIERS: StaffTreeModifiers = StaffTreeModifiers::get();
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::BasicRanged {
|
CharacterAbility::BasicRanged {
|
||||||
ref mut projectile, ..
|
ref mut projectile, ..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = STAFF_MODIFIERS.fireball;
|
||||||
let damage_level = skillset.skill_level_or(Staff(BDamage), 0);
|
let damage_level = skillset.skill_level_or(Staff(BDamage), 0);
|
||||||
let regen_level = skillset.skill_level_or(Staff(BRegen), 0);
|
let regen_level = skillset.skill_level_or(Staff(BRegen), 0);
|
||||||
let range_level = skillset.skill_level_or(Staff(BRadius), 0);
|
let range_level = skillset.skill_level_or(Staff(BRadius), 0);
|
||||||
let power = 1.2_f32.powi(damage_level.into());
|
let power = modifiers.power.powi(damage_level.into());
|
||||||
let regen = 1.2_f32.powi(regen_level.into());
|
let regen = modifiers.power.powi(regen_level.into());
|
||||||
let range = 1.15_f32.powi(range_level.into());
|
let range = modifiers.power.powi(range_level.into());
|
||||||
*projectile = projectile.modified_projectile(power, regen, range);
|
*projectile = projectile.modified_projectile(power, regen, range);
|
||||||
},
|
},
|
||||||
CharacterAbility::BasicBeam {
|
CharacterAbility::BasicBeam {
|
||||||
@ -1323,20 +1358,21 @@ impl CharacterAbility {
|
|||||||
ref mut beam_duration,
|
ref mut beam_duration,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = STAFF_MODIFIERS.flamethrower;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(FDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(FDamage)) {
|
||||||
*damage *= 1.3_f32.powi(level.into());
|
*damage *= modifiers.damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(FRange)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(FRange)) {
|
||||||
let range_mod = 1.25_f32.powi(level.into());
|
let range_mod = modifiers.range.powi(level.into());
|
||||||
*range *= range_mod;
|
*range *= range_mod;
|
||||||
// Duration modified to keep velocity constant
|
// Duration modified to keep velocity constant
|
||||||
*beam_duration *= range_mod;
|
*beam_duration *= range_mod;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(FDrain)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(FDrain)) {
|
||||||
*energy_drain *= 0.8_f32.powi(level.into());
|
*energy_drain *= modifiers.energy_drain.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(FVelocity)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(FVelocity)) {
|
||||||
let velocity_increase = 1.25_f32.powi(level.into());
|
let velocity_increase = modifiers.velocity.powi(level.into());
|
||||||
let duration_mod = 1.0 / (1.0 + velocity_increase);
|
let duration_mod = 1.0 / (1.0 + velocity_increase);
|
||||||
*beam_duration *= duration_mod;
|
*beam_duration *= duration_mod;
|
||||||
}
|
}
|
||||||
@ -1348,17 +1384,19 @@ impl CharacterAbility {
|
|||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = STAFF_MODIFIERS.shockwave;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(SDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(SDamage)) {
|
||||||
*damage *= 1.3_f32.powi(level.into());
|
*damage *= modifiers.damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(SKnockback)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(SKnockback)) {
|
||||||
*knockback = knockback.modify_strength(1.3_f32.powi(level.into()));
|
let knockback_mod = modifiers.knockback.powi(level.into());
|
||||||
|
*knockback = knockback.modify_strength(knockback_mod);
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(SRange)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(SRange)) {
|
||||||
*shockwave_duration *= 1.2_f32.powi(level.into());
|
*shockwave_duration *= modifiers.duration.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Staff(SCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Staff(SCost)) {
|
||||||
*energy_cost *= 0.8_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -1368,7 +1406,9 @@ impl CharacterAbility {
|
|||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_sceptre_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_sceptre_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
#![allow(clippy::enum_glob_use)]
|
#![allow(clippy::enum_glob_use)]
|
||||||
use skills::{SceptreSkill::*, Skill::Sceptre};
|
use skills::{SceptreSkill::*, SceptreTreeModifiers, Skill::Sceptre};
|
||||||
|
|
||||||
|
const SCEPTRE_MODIFIERS: SceptreTreeModifiers = SceptreTreeModifiers::get();
|
||||||
match self {
|
match self {
|
||||||
CharacterAbility::BasicBeam {
|
CharacterAbility::BasicBeam {
|
||||||
ref mut damage,
|
ref mut damage,
|
||||||
@ -1378,42 +1418,23 @@ impl CharacterAbility {
|
|||||||
ref mut energy_regen,
|
ref mut energy_regen,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = SCEPTRE_MODIFIERS.beam;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LDamage)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LDamage)) {
|
||||||
*damage *= 1.2_f32.powi(level.into());
|
*damage *= modifiers.damage.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LRange)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LRange)) {
|
||||||
let range_mod = 1.2_f32.powi(level.into());
|
let range_mod = modifiers.range.powi(level.into());
|
||||||
*range *= range_mod;
|
*range *= range_mod;
|
||||||
// Duration modified to keep velocity constant
|
// Duration modified to keep velocity constant
|
||||||
*beam_duration *= range_mod;
|
*beam_duration *= range_mod;
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LRegen)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(LRegen)) {
|
||||||
*energy_regen *= 1.2_f32.powi(level.into());
|
*energy_regen *= modifiers.energy_regen.powi(level.into());
|
||||||
}
|
}
|
||||||
if let (Ok(Some(level)), Some(CombatEffect::Lifesteal(ref mut lifesteal))) =
|
if let (Ok(Some(level)), Some(CombatEffect::Lifesteal(ref mut lifesteal))) =
|
||||||
(skillset.skill_level(Sceptre(LLifesteal)), damage_effect)
|
(skillset.skill_level(Sceptre(LLifesteal)), damage_effect)
|
||||||
{
|
{
|
||||||
*lifesteal *= 1.15_f32.powi(level.into());
|
*lifesteal *= modifiers.lifesteal.powi(level.into());
|
||||||
}
|
|
||||||
},
|
|
||||||
CharacterAbility::BasicAura {
|
|
||||||
ref mut aura,
|
|
||||||
ref mut range,
|
|
||||||
ref mut energy_cost,
|
|
||||||
specifier: aura::Specifier::WardingAura,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
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)) {
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CharacterAbility::BasicAura {
|
CharacterAbility::BasicAura {
|
||||||
@ -1423,17 +1444,43 @@ impl CharacterAbility {
|
|||||||
specifier: aura::Specifier::HealingAura,
|
specifier: aura::Specifier::HealingAura,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let modifiers = SCEPTRE_MODIFIERS.healing_aura;
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HHeal)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HHeal)) {
|
||||||
aura.strength *= 1.15_f32.powi(level.into());
|
aura.strength *= modifiers.strength.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HDuration)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HDuration)) {
|
||||||
aura.duration.map(|dur| dur * 1.2_f32.powi(level.into()));
|
if let Some(ref mut duration) = aura.duration {
|
||||||
|
*duration *= modifiers.duration.powi(level.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HRange)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HRange)) {
|
||||||
*range *= 1.25_f32.powi(level.into());
|
*range *= modifiers.range.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HCost)) {
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(HCost)) {
|
||||||
*energy_cost *= 0.85_f32.powi(level.into());
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CharacterAbility::BasicAura {
|
||||||
|
ref mut aura,
|
||||||
|
ref mut range,
|
||||||
|
ref mut energy_cost,
|
||||||
|
specifier: aura::Specifier::WardingAura,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let modifiers = SCEPTRE_MODIFIERS.warding_aura;
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) {
|
||||||
|
aura.strength *= modifiers.strength.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ADuration)) {
|
||||||
|
if let Some(ref mut duration) = aura.duration {
|
||||||
|
*duration *= modifiers.duration.powi(level.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ARange)) {
|
||||||
|
*range *= modifiers.range.powi(level.into());
|
||||||
|
}
|
||||||
|
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ACost)) {
|
||||||
|
*energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
@ -366,6 +366,7 @@ impl ProjectileConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: split this to three methods per stat
|
||||||
pub fn modified_projectile(mut self, power: f32, regen: f32, range: f32) -> Self {
|
pub fn modified_projectile(mut self, power: f32, regen: f32, range: f32) -> Self {
|
||||||
use ProjectileConstructor::*;
|
use ProjectileConstructor::*;
|
||||||
match self {
|
match self {
|
||||||
|
@ -47,9 +47,10 @@ impl Asset for SkillPrerequisitesMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// Determines the skills that comprise each skill group - this data is used to determine
|
// Determines the skills that comprise each skill group.
|
||||||
// which of a player's skill groups a particular skill should be added to when a skill unlock
|
//
|
||||||
// is requested.
|
// This data is used to determine which of a player's skill groups a
|
||||||
|
// particular skill should be added to when a skill unlock is requested.
|
||||||
pub static ref SKILL_GROUP_DEFS: HashMap<SkillGroupKind, SkillGroupDef> = {
|
pub static ref SKILL_GROUP_DEFS: HashMap<SkillGroupKind, SkillGroupDef> = {
|
||||||
let map = SkillTreeMap::load_expect_cloned(
|
let map = SkillTreeMap::load_expect_cloned(
|
||||||
"common.skill_trees.skills_skill-groups_manifest",
|
"common.skill_trees.skills_skill-groups_manifest",
|
||||||
@ -98,6 +99,8 @@ lazy_static! {
|
|||||||
/// kind of active ability, or a passive effect etc. Obviously because this is
|
/// kind of active ability, or a passive effect etc. Obviously because this is
|
||||||
/// an enum it doesn't describe what the skill actually -does-, this will be
|
/// an enum it doesn't describe what the skill actually -does-, this will be
|
||||||
/// handled by dedicated ECS systems.
|
/// handled by dedicated ECS systems.
|
||||||
|
// NOTE: if skill does use some constant, add it to corresponding
|
||||||
|
// SkillTree Modifiers below.
|
||||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Skill {
|
pub enum Skill {
|
||||||
General(GeneralSkill),
|
General(GeneralSkill),
|
||||||
@ -114,6 +117,365 @@ pub enum Skill {
|
|||||||
Pick(MiningSkill),
|
Pick(MiningSkill),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tree of modifiers that represent how stats are
|
||||||
|
/// changed per each skill level.
|
||||||
|
///
|
||||||
|
/// It's used as bridge between ECS systems
|
||||||
|
/// and voxygen Diary for skill descriptions and helps to sync them.
|
||||||
|
///
|
||||||
|
/// NOTE: Just adding constant does nothing, you need to use it in both
|
||||||
|
/// ECS systems and Diary.
|
||||||
|
pub struct SkillTreeModifiers {
|
||||||
|
pub sword_tree: SwordTreeModifiers,
|
||||||
|
pub axe_tree: AxeTreeModifiers,
|
||||||
|
pub hammer_tree: HammerTreeModifiers,
|
||||||
|
pub bow_tree: BowTreeModifiers,
|
||||||
|
pub staff_tree: StaffTreeModifiers,
|
||||||
|
pub sceptre_tree: SceptreTreeModifiers,
|
||||||
|
pub mining_tree: MiningTreeModifiers,
|
||||||
|
pub general_tree: GeneralTreeModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SwordTreeModifiers {
|
||||||
|
pub dash: SwordDashModifiers,
|
||||||
|
pub spin: SwordSpinModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SwordDashModifiers {
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub energy_drain: f32,
|
||||||
|
pub base_damage: f32,
|
||||||
|
pub scaled_damage: f32,
|
||||||
|
pub forward_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SwordSpinModifiers {
|
||||||
|
pub base_damage: f32,
|
||||||
|
pub swing_duration: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub num: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SwordTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
dash: SwordDashModifiers {
|
||||||
|
energy_cost: 0.75,
|
||||||
|
energy_drain: 0.75,
|
||||||
|
base_damage: 1.2,
|
||||||
|
scaled_damage: 1.2,
|
||||||
|
forward_speed: 1.15,
|
||||||
|
},
|
||||||
|
spin: SwordSpinModifiers {
|
||||||
|
base_damage: 1.4,
|
||||||
|
swing_duration: 0.8,
|
||||||
|
energy_cost: 0.75,
|
||||||
|
num: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AxeTreeModifiers {
|
||||||
|
pub spin: AxeSpinModifiers,
|
||||||
|
pub leap: AxeLeapModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AxeSpinModifiers {
|
||||||
|
pub base_damage: f32,
|
||||||
|
pub swing_duration: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AxeLeapModifiers {
|
||||||
|
pub base_damage: f32,
|
||||||
|
pub knockback: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
// TODO: split to forward and vertical?
|
||||||
|
pub leap_strength: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AxeTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
spin: AxeSpinModifiers {
|
||||||
|
base_damage: 1.3,
|
||||||
|
swing_duration: 0.8,
|
||||||
|
energy_cost: 0.75,
|
||||||
|
},
|
||||||
|
leap: AxeLeapModifiers {
|
||||||
|
base_damage: 1.35,
|
||||||
|
knockback: 1.4,
|
||||||
|
energy_cost: 0.75,
|
||||||
|
leap_strength: 1.2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HammerTreeModifiers {
|
||||||
|
pub single_strike: HammerStrikeModifiers,
|
||||||
|
pub charged: HammerChargedModifers,
|
||||||
|
pub leap: HammerLeapModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HammerStrikeModifiers {
|
||||||
|
pub knockback: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HammerChargedModifers {
|
||||||
|
pub scaled_damage: f32,
|
||||||
|
pub scaled_knockback: f32,
|
||||||
|
pub energy_drain: f32,
|
||||||
|
pub charge_rate: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HammerLeapModifiers {
|
||||||
|
pub base_damage: f32,
|
||||||
|
pub knockback: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub leap_strength: f32,
|
||||||
|
pub range: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HammerTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
single_strike: HammerStrikeModifiers { knockback: 1.5 },
|
||||||
|
charged: HammerChargedModifers {
|
||||||
|
scaled_damage: 1.25,
|
||||||
|
scaled_knockback: 1.5,
|
||||||
|
energy_drain: 0.75,
|
||||||
|
charge_rate: 1.25,
|
||||||
|
},
|
||||||
|
leap: HammerLeapModifiers {
|
||||||
|
base_damage: 1.4,
|
||||||
|
knockback: 1.5,
|
||||||
|
energy_cost: 0.75,
|
||||||
|
leap_strength: 1.25,
|
||||||
|
range: 1.0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BowTreeModifiers {
|
||||||
|
pub universal: BowUniversalModifiers,
|
||||||
|
pub charged: BowChargedModifiers,
|
||||||
|
pub repeater: BowRepeaterModifiers,
|
||||||
|
pub shotgun: BowShotgunModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BowUniversalModifiers {
|
||||||
|
// TODO: split per abilities?
|
||||||
|
pub projectile_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BowChargedModifiers {
|
||||||
|
pub damage_scaling: f32,
|
||||||
|
pub regen_scaling: f32,
|
||||||
|
pub knockback_scaling: f32,
|
||||||
|
pub charge_rate: f32,
|
||||||
|
pub move_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BowRepeaterModifiers {
|
||||||
|
pub power: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub max_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BowShotgunModifiers {
|
||||||
|
pub power: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub num_projectiles: u32,
|
||||||
|
pub spread: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BowTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
universal: BowUniversalModifiers {
|
||||||
|
projectile_speed: 1.2,
|
||||||
|
},
|
||||||
|
charged: BowChargedModifiers {
|
||||||
|
damage_scaling: 1.2,
|
||||||
|
regen_scaling: 1.2,
|
||||||
|
knockback_scaling: 1.2,
|
||||||
|
charge_rate: 1.1,
|
||||||
|
move_speed: 1.1,
|
||||||
|
},
|
||||||
|
repeater: BowRepeaterModifiers {
|
||||||
|
power: 1.2,
|
||||||
|
energy_cost: 0.8,
|
||||||
|
max_speed: 1.2,
|
||||||
|
},
|
||||||
|
shotgun: BowShotgunModifiers {
|
||||||
|
power: 1.2,
|
||||||
|
energy_cost: 1.2,
|
||||||
|
num_projectiles: 1,
|
||||||
|
spread: 0.8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StaffTreeModifiers {
|
||||||
|
pub fireball: StaffFireballModifiers,
|
||||||
|
pub flamethrower: StaffFlamethrowerModifiers,
|
||||||
|
pub shockwave: StaffShockwaveModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StaffFireballModifiers {
|
||||||
|
pub power: f32,
|
||||||
|
pub regen: f32,
|
||||||
|
pub range: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StaffFlamethrowerModifiers {
|
||||||
|
pub damage: f32,
|
||||||
|
pub range: f32,
|
||||||
|
pub energy_drain: f32,
|
||||||
|
pub velocity: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StaffShockwaveModifiers {
|
||||||
|
pub damage: f32,
|
||||||
|
pub knockback: f32,
|
||||||
|
pub duration: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaffTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
fireball: StaffFireballModifiers {
|
||||||
|
power: 1.2,
|
||||||
|
regen: 1.2,
|
||||||
|
range: 1.15,
|
||||||
|
},
|
||||||
|
flamethrower: StaffFlamethrowerModifiers {
|
||||||
|
damage: 1.3,
|
||||||
|
range: 1.25,
|
||||||
|
energy_drain: 0.8,
|
||||||
|
velocity: 1.25,
|
||||||
|
},
|
||||||
|
shockwave: StaffShockwaveModifiers {
|
||||||
|
damage: 1.3,
|
||||||
|
knockback: 1.3,
|
||||||
|
duration: 1.2,
|
||||||
|
energy_cost: 0.8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SceptreTreeModifiers {
|
||||||
|
pub beam: SceptreBeamModifiers,
|
||||||
|
pub healing_aura: SceptreHealingAuraModifiers,
|
||||||
|
pub warding_aura: SceptreWardingAuraModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SceptreBeamModifiers {
|
||||||
|
pub damage: f32,
|
||||||
|
pub range: f32,
|
||||||
|
pub energy_regen: f32,
|
||||||
|
pub lifesteal: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SceptreHealingAuraModifiers {
|
||||||
|
pub strength: f32,
|
||||||
|
pub duration: f32,
|
||||||
|
pub range: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SceptreWardingAuraModifiers {
|
||||||
|
pub strength: f32,
|
||||||
|
pub duration: f32,
|
||||||
|
pub range: f32,
|
||||||
|
pub energy_cost: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SceptreTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
beam: SceptreBeamModifiers {
|
||||||
|
damage: 1.2,
|
||||||
|
range: 1.2,
|
||||||
|
energy_regen: 1.2,
|
||||||
|
lifesteal: 1.15,
|
||||||
|
},
|
||||||
|
healing_aura: SceptreHealingAuraModifiers {
|
||||||
|
strength: 1.15,
|
||||||
|
duration: 1.2,
|
||||||
|
range: 1.25,
|
||||||
|
energy_cost: 0.85,
|
||||||
|
},
|
||||||
|
warding_aura: SceptreWardingAuraModifiers {
|
||||||
|
strength: 1.15,
|
||||||
|
duration: 1.2,
|
||||||
|
range: 1.25,
|
||||||
|
energy_cost: 0.85,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MiningTreeModifiers {
|
||||||
|
pub speed: f32,
|
||||||
|
pub gem_gain: f32,
|
||||||
|
pub ore_gain: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MiningTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
speed: 1.1,
|
||||||
|
gem_gain: 0.05,
|
||||||
|
ore_gain: 0.05,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GeneralTreeModifiers {
|
||||||
|
pub roll: RollTreeModifiers,
|
||||||
|
pub swim: SwimTreeModifiers,
|
||||||
|
pub climb: ClimbTreeModifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RollTreeModifiers {
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub strength: f32,
|
||||||
|
pub duration: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SwimTreeModifiers {
|
||||||
|
pub speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ClimbTreeModifiers {
|
||||||
|
pub energy_cost: f32,
|
||||||
|
pub speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GeneralTreeModifiers {
|
||||||
|
pub const fn get() -> Self {
|
||||||
|
Self {
|
||||||
|
roll: RollTreeModifiers {
|
||||||
|
energy_cost: 0.9,
|
||||||
|
strength: 1.1,
|
||||||
|
duration: 1.1,
|
||||||
|
},
|
||||||
|
swim: SwimTreeModifiers { speed: 1.25 },
|
||||||
|
climb: ClimbTreeModifiers {
|
||||||
|
energy_cost: 0.8,
|
||||||
|
speed: 1.2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Enum which returned as result from `boost` function
|
/// Enum which returned as result from `boost` function
|
||||||
/// `Number` can represent values from -inf to +inf,
|
/// `Number` can represent values from -inf to +inf,
|
||||||
/// but it should generaly be in range -50..50
|
/// but it should generaly be in range -50..50
|
||||||
@ -123,6 +485,8 @@ pub enum Skill {
|
|||||||
///
|
///
|
||||||
/// Number(15) says that some value
|
/// Number(15) says that some value
|
||||||
/// will be increased by 15% (for example damage)
|
/// will be increased by 15% (for example damage)
|
||||||
|
// TODO: move it to voxygen diary code
|
||||||
|
// (and inline directly to formating skill descriptions)
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum BoostValue {
|
pub enum BoostValue {
|
||||||
Number(i16),
|
Number(i16),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
skills::{ClimbSkill::*, Skill},
|
skills::{ClimbSkill::*, GeneralTreeModifiers, Skill},
|
||||||
CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate,
|
CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate,
|
||||||
},
|
},
|
||||||
consts::GRAVITY,
|
consts::GRAVITY,
|
||||||
@ -30,12 +30,14 @@ pub struct Data {
|
|||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
|
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
|
||||||
|
const GENERAL_MODIFIERS: GeneralTreeModifiers = GeneralTreeModifiers::get();
|
||||||
|
let modifiers = GENERAL_MODIFIERS.climb;
|
||||||
let mut data = Data::default();
|
let mut data = Data::default();
|
||||||
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) {
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) {
|
||||||
data.static_data.energy_cost *= 0.8_f32.powi(level.into());
|
data.static_data.energy_cost *= modifiers.energy_cost.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Speed)) {
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Speed)) {
|
||||||
data.static_data.movement_speed *= 1.2_f32.powi(level.into());
|
data.static_data.movement_speed *= modifiers.speed.powi(level.into());
|
||||||
}
|
}
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@ impl Stage<f32> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: name it as using knockback
|
||||||
pub fn modify_strike(mut self, knockback_mult: f32) -> Self {
|
pub fn modify_strike(mut self, knockback_mult: f32) -> Self {
|
||||||
self.knockback *= knockback_mult;
|
self.knockback *= knockback_mult;
|
||||||
self
|
self
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
inventory::slot::{EquipSlot, Slot},
|
inventory::slot::{EquipSlot, Slot},
|
||||||
item::{Hands, ItemKind, Tool, ToolKind},
|
item::{Hands, ItemKind, Tool, ToolKind},
|
||||||
quadruped_low, quadruped_medium, quadruped_small,
|
quadruped_low, quadruped_medium, quadruped_small,
|
||||||
skills::{Skill, SwimSkill},
|
skills::{GeneralTreeModifiers, Skill, SwimSkill},
|
||||||
theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind,
|
theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind,
|
||||||
InventoryAction, StateUpdate,
|
InventoryAction, StateUpdate,
|
||||||
},
|
},
|
||||||
@ -375,7 +375,9 @@ fn swim_move(
|
|||||||
let mut water_accel = force / data.mass.0;
|
let mut water_accel = force / data.mass.0;
|
||||||
|
|
||||||
if let Ok(Some(level)) = data.skill_set.skill_level(Skill::Swim(SwimSkill::Speed)) {
|
if let Ok(Some(level)) = data.skill_set.skill_level(Skill::Swim(SwimSkill::Speed)) {
|
||||||
water_accel *= 1.25_f32.powi(level.into());
|
const GENERAL_MOFIDIERS: GeneralTreeModifiers = GeneralTreeModifiers::get();
|
||||||
|
let modifiers = GENERAL_MOFIDIERS.swim;
|
||||||
|
water_accel *= modifiers.speed.powi(level.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir = if data.body.can_strafe() {
|
let dir = if data.body.can_strafe() {
|
||||||
|
@ -354,22 +354,18 @@ pub fn handle_mine_block(
|
|||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
if item.item_definition_id().contains("mineral.ore.")
|
if item.item_definition_id().contains("mineral.ore.")
|
||||||
&& rng.gen_bool(
|
&& rng.gen_bool(
|
||||||
0.05 * skillset
|
0.05 * f64::from(
|
||||||
.skill_level(Skill::Pick(MiningSkill::OreGain))
|
skillset.skill_level_or(Skill::Pick(MiningSkill::OreGain), 0),
|
||||||
.ok()
|
),
|
||||||
.flatten()
|
|
||||||
.unwrap_or(0) as f64,
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let _ = item.increase_amount(1);
|
let _ = item.increase_amount(1);
|
||||||
}
|
}
|
||||||
if item.item_definition_id().contains("mineral.gem.")
|
if item.item_definition_id().contains("mineral.gem.")
|
||||||
&& rng.gen_bool(
|
&& rng.gen_bool(
|
||||||
0.05 * skillset
|
0.05 * f64::from(
|
||||||
.skill_level(Skill::Pick(MiningSkill::GemGain))
|
skillset.skill_level_or(Skill::Pick(MiningSkill::GemGain), 0),
|
||||||
.ok()
|
),
|
||||||
.flatten()
|
|
||||||
.unwrap_or(0) as f64,
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let _ = item.increase_amount(1);
|
let _ = item.increase_amount(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user