Split adjusted_by_skills by toolkind

This commit is contained in:
juliancoffee
2021-08-16 12:16:20 +03:00
parent a2e0426d45
commit 81bbc8c31f
2 changed files with 520 additions and 513 deletions

View File

@ -15,7 +15,7 @@ use crate::{
terrain::SpriteKind, terrain::SpriteKind,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::{convert::TryFrom, time::Duration};
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum CharacterAbilityType { pub enum CharacterAbilityType {
@ -886,18 +886,72 @@ impl CharacterAbility {
} }
} }
#[must_use = "method returns new ability and doesn't mutate the original value"]
#[warn(clippy::pedantic)]
pub fn adjusted_by_skills( pub fn adjusted_by_skills(
mut self, mut self,
skillset: &skills::SkillSet, skillset: &skills::SkillSet,
tool: Option<ToolKind>, tool: Option<ToolKind>,
) -> Self { ) -> Self {
use skills::Skill::{self, *}; use skills::Skill;
use CharacterAbility::*;
match tool { match tool {
Some(ToolKind::Sword) => { Some(ToolKind::Sword) => self.adjusted_by_sword_skills(skillset),
use skills::SwordSkill::*; Some(ToolKind::Axe) => self.adjusted_by_axe_skills(skillset),
Some(ToolKind::Hammer) => self.adjusted_by_hammer_skills(skillset),
Some(ToolKind::Bow) => self.adjusted_by_bow_skills(skillset),
Some(ToolKind::Staff) => self.adjusted_by_staff_skills(skillset),
Some(ToolKind::Sceptre) => self.adjusted_by_sceptre_skills(skillset),
Some(ToolKind::Pick) => {
use skills::MiningSkill::Speed;
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(_) => {},
}
self
}
#[warn(clippy::pedantic)]
fn adjusted_by_sword_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{Skill::Sword, SwordSkill::*};
match self { match self {
ComboMelee { CharacterAbility::ComboMelee {
ref mut is_interruptible, ref mut is_interruptible,
ref mut speed_increase, ref mut speed_increase,
ref mut max_speed_increase, ref mut max_speed_increase,
@ -907,36 +961,30 @@ impl CharacterAbility {
.. ..
} => { } => {
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks)); *is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
let speed_segments = Sword(TsSpeed).max_level().map_or(1, |l| l + 1) as f32;
let speed_level = if skillset.has_skill(Sword(TsCombo)) { if skillset.has_skill(Sword(TsCombo)) {
skillset let speed_segments = Sword(TsSpeed)
.skill_level(Sword(TsSpeed)) .max_level()
.unwrap_or(None) .map_or(1.0, |l| f32::from(l) + 1.0);
.map_or(1, |l| l + 1) as f32 let speed_level = f32::from(skillset.skill_level_or(Sword(TsSpeed), 0));
*speed_increase = (speed_level + 1.0) / speed_segments;
*max_speed_increase = (speed_level + 1.0) / speed_segments;
} else { } else {
0.0 *speed_increase = 0.0;
}; *max_speed_increase = 0.0;
{
*speed_increase *= speed_level / speed_segments;
*max_speed_increase *= speed_level / speed_segments;
} }
let energy_level =
if let Ok(Some(level)) = skillset.skill_level(Sword(TsRegen)) { let energy_level = skillset.skill_level_or(Sword(TsRegen), 0);
level
} else { let stages = u16::try_from(stage_data.len())
0 .expect("number of stages can't be more than u16");
};
*max_energy_gain = *max_energy_gain *max_energy_gain *= f32::from((energy_level + 1) * stages - 1)
* ((energy_level + 1) * stage_data.len() as u16 - 1) as f32 * f32::from(stages - 1)
/ (Sword(TsRegen).max_level().unwrap() + 1) as f32 / f32::from(Sword(TsRegen).max_level().unwrap() + 1);
* (stage_data.len() - 1) as f32; *scales_from_combo = skillset.skill_level_or(Sword(TsDamage), 0).into();
*scales_from_combo = skillset
.skill_level(Sword(TsDamage))
.unwrap_or(None)
.unwrap_or(0)
.into();
}, },
DashMelee { CharacterAbility::DashMelee {
ref mut is_interruptible, ref mut is_interruptible,
ref mut energy_cost, ref mut energy_cost,
ref mut energy_drain, ref mut energy_drain,
@ -964,7 +1012,7 @@ impl CharacterAbility {
} }
*charge_through = skillset.has_skill(Sword(DInfinite)); *charge_through = skillset.has_skill(Sword(DInfinite));
}, },
SpinMelee { CharacterAbility::SpinMelee {
ref mut is_interruptible, ref mut is_interruptible,
ref mut base_damage, ref mut base_damage,
ref mut swing_duration, ref mut swing_duration,
@ -982,19 +1030,20 @@ impl CharacterAbility {
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 *= 0.75_f32.powi(level.into());
} }
*num_spins = skillset let spin_level = skillset.skill_level_or(Sword(SSpins), 0);
.skill_level(Sword(SSpins)) *num_spins = u32::from(spin_level) + 1;
.unwrap_or(None)
.unwrap_or(0) as u32
+ 1;
}, },
_ => {}, _ => {},
} }
}, }
Some(ToolKind::Axe) => {
use skills::AxeSkill::*; #[warn(clippy::pedantic)]
fn adjusted_by_axe_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{AxeSkill::*, Skill::Axe};
match self { match self {
ComboMelee { CharacterAbility::ComboMelee {
ref mut speed_increase, ref mut speed_increase,
ref mut max_speed_increase, ref mut max_speed_increase,
ref mut stage_data, ref mut stage_data,
@ -1005,32 +1054,22 @@ impl CharacterAbility {
if !skillset.has_skill(Axe(DsCombo)) { if !skillset.has_skill(Axe(DsCombo)) {
stage_data.pop(); stage_data.pop();
} }
let speed_segments = Axe(DsSpeed).max_level().unwrap_or(1) as f32; let speed_segments = f32::from(Axe(DsSpeed).max_level().unwrap_or(1));
let speed_level = skillset let speed_level = f32::from(skillset.skill_level_or(Axe(DsSpeed), 0));
.skill_level(Axe(DsSpeed))
.unwrap_or(None)
.unwrap_or(0) as f32;
{
*speed_increase *= speed_level / speed_segments; *speed_increase *= speed_level / speed_segments;
*max_speed_increase *= speed_level / speed_segments; *max_speed_increase *= speed_level / speed_segments;
}
let energy_level = let energy_level = skillset.skill_level_or(Axe(DsRegen), 0);
if let Ok(Some(level)) = skillset.skill_level(Axe(DsRegen)) {
level let stages = u16::try_from(stage_data.len())
} else { .expect("number of stages can't be more than u16");
0
}; *max_energy_gain *= f32::from((energy_level + 1) * stages - 1).max(1.0)
*max_energy_gain = *max_energy_gain * f32::from(stages - 1).max(1.0)
* ((energy_level + 1) * stage_data.len() as u16 - 1).max(1) as f32 / f32::from(Axe(DsRegen).max_level().unwrap() + 1);
/ (Axe(DsRegen).max_level().unwrap() + 1) as f32 *scales_from_combo = skillset.skill_level_or(Axe(DsDamage), 0).into();
* (stage_data.len() - 1).max(1) as f32;
*scales_from_combo = skillset
.skill_level(Axe(DsDamage))
.unwrap_or(None)
.unwrap_or(0)
.into();
}, },
SpinMelee { CharacterAbility::SpinMelee {
ref mut base_damage, ref mut base_damage,
ref mut swing_duration, ref mut swing_duration,
ref mut energy_cost, ref mut energy_cost,
@ -1054,7 +1093,7 @@ impl CharacterAbility {
*energy_cost *= 0.75_f32.powi(level.into()); *energy_cost *= 0.75_f32.powi(level.into());
} }
}, },
LeapMelee { CharacterAbility::LeapMelee {
ref mut base_damage, ref mut base_damage,
ref mut knockback, ref mut knockback,
ref mut energy_cost, ref mut energy_cost,
@ -1078,11 +1117,14 @@ impl CharacterAbility {
}, },
_ => {}, _ => {},
} }
}, }
Some(ToolKind::Hammer) => {
use skills::HammerSkill::*; #[warn(clippy::pedantic)]
fn adjusted_by_hammer_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{HammerSkill::*, Skill::Hammer};
match self { match self {
ComboMelee { CharacterAbility::ComboMelee {
ref mut speed_increase, ref mut speed_increase,
ref mut max_speed_increase, ref mut max_speed_increase,
ref mut stage_data, ref mut stage_data,
@ -1094,34 +1136,24 @@ impl CharacterAbility {
*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(1.5_f32.powi(level.into())))
.collect::<Vec<combo_melee::Stage<f32>>>(); .collect::<Vec<_>>();
} }
let speed_segments = Hammer(SsSpeed).max_level().unwrap_or(1) as f32; let speed_segments = f32::from(Hammer(SsSpeed).max_level().unwrap_or(1));
let speed_level = skillset let speed_level = f32::from(skillset.skill_level_or(Hammer(SsSpeed), 0));
.skill_level(Hammer(SsSpeed))
.unwrap_or(None)
.unwrap_or(0) as f32;
{
*speed_increase *= speed_level / speed_segments; *speed_increase *= speed_level / speed_segments;
*max_speed_increase *= speed_level / speed_segments; *max_speed_increase *= speed_level / speed_segments;
}
let energy_level = let energy_level = skillset.skill_level_or(Hammer(SsRegen), 0);
if let Ok(Some(level)) = skillset.skill_level(Hammer(SsRegen)) {
level let stages = u16::try_from(stage_data.len())
} else { .expect("number of stages can't be more than u16");
0
}; *max_energy_gain *= f32::from((energy_level + 1) * stages)
*max_energy_gain = *max_energy_gain / f32::from((Hammer(SsRegen).max_level().unwrap() + 1) * stages);
* ((energy_level + 1) * stage_data.len() as u16) as f32
/ ((Hammer(SsRegen).max_level().unwrap() + 1) * stage_data.len() as u16) *scales_from_combo = skillset.skill_level_or(Hammer(SsDamage), 0).into();
as f32;
*scales_from_combo = skillset
.skill_level(Hammer(SsDamage))
.unwrap_or(None)
.unwrap_or(0)
.into();
}, },
ChargedMelee { CharacterAbility::ChargedMelee {
ref mut scaled_damage, ref mut scaled_damage,
ref mut scaled_knockback, ref mut scaled_knockback,
ref mut energy_drain, ref mut energy_drain,
@ -1141,7 +1173,7 @@ impl CharacterAbility {
*charge_duration /= 1.25_f32.powi(level.into()); *charge_duration /= 1.25_f32.powi(level.into());
} }
}, },
LeapMelee { CharacterAbility::LeapMelee {
ref mut base_damage, ref mut base_damage,
ref mut knockback, ref mut knockback,
ref mut energy_cost, ref mut energy_cost,
@ -1164,16 +1196,20 @@ impl CharacterAbility {
*vertical_leap_strength *= 1.25_f32.powi(level.into()); *vertical_leap_strength *= 1.25_f32.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 * level as f32; *range += 1.0 * f32::from(level);
} }
}, },
_ => {}, _ => {},
} }
}, }
Some(ToolKind::Bow) => {
use skills::BowSkill::*; #[warn(clippy::pedantic)]
fn adjusted_by_bow_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{BowSkill::*, Skill::Bow};
match self { match self {
ChargedRanged { CharacterAbility::ChargedRanged {
ref mut initial_damage, ref mut initial_damage,
ref mut scaled_damage, ref mut scaled_damage,
ref mut initial_regen, ref mut initial_regen,
@ -1213,7 +1249,7 @@ impl CharacterAbility {
*move_speed *= 1.1_f32.powi(level.into()); *move_speed *= 1.1_f32.powi(level.into());
} }
}, },
RepeaterRanged { CharacterAbility::RepeaterRanged {
ref mut energy_cost, ref mut energy_cost,
ref mut projectile, ref mut projectile,
ref mut max_speed, ref mut max_speed,
@ -1234,7 +1270,7 @@ impl CharacterAbility {
*max_speed *= 1.2_f32.powi(level.into()); *max_speed *= 1.2_f32.powi(level.into());
} }
}, },
BasicRanged { CharacterAbility::BasicRanged {
ref mut projectile, ref mut projectile,
ref mut energy_cost, ref mut energy_cost,
ref mut num_projectiles, ref mut num_projectiles,
@ -1253,7 +1289,7 @@ impl CharacterAbility {
*energy_cost *= 0.8_f32.powi(level.into()); *energy_cost *= 0.8_f32.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 += level as u32; *num_projectiles += u32::from(level);
} }
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 *= 0.8_f32.powi(level.into());
@ -1261,31 +1297,26 @@ impl CharacterAbility {
}, },
_ => {}, _ => {},
} }
}, }
Some(ToolKind::Staff) => {
use skills::StaffSkill::*; #[warn(clippy::pedantic)]
fn adjusted_by_staff_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{Skill::Staff, StaffSkill::*};
match self { match self {
BasicRanged { CharacterAbility::BasicRanged {
ref mut projectile, .. ref mut projectile, ..
} => { } => {
let damage_level = skillset let damage_level = skillset.skill_level_or(Staff(BDamage), 0);
.skill_level(Staff(BDamage)) let regen_level = skillset.skill_level_or(Staff(BRegen), 0);
.unwrap_or(None) let range_level = skillset.skill_level_or(Staff(BRadius), 0);
.unwrap_or(0);
let regen_level = skillset
.skill_level(Staff(BRegen))
.unwrap_or(None)
.unwrap_or(0);
let range_level = skillset
.skill_level(Staff(BRadius))
.unwrap_or(None)
.unwrap_or(0);
let power = 1.2_f32.powi(damage_level.into()); let power = 1.2_f32.powi(damage_level.into());
let regen = 1.2_f32.powi(regen_level.into()); let regen = 1.2_f32.powi(regen_level.into());
let range = 1.15_f32.powi(range_level.into()); let range = 1.15_f32.powi(range_level.into());
*projectile = projectile.modified_projectile(power, regen, range); *projectile = projectile.modified_projectile(power, regen, range);
}, },
BasicBeam { CharacterAbility::BasicBeam {
ref mut damage, ref mut damage,
ref mut range, ref mut range,
ref mut energy_drain, ref mut energy_drain,
@ -1310,7 +1341,7 @@ impl CharacterAbility {
*beam_duration *= duration_mod; *beam_duration *= duration_mod;
} }
}, },
Shockwave { CharacterAbility::Shockwave {
ref mut damage, ref mut damage,
ref mut knockback, ref mut knockback,
ref mut shockwave_duration, ref mut shockwave_duration,
@ -1332,11 +1363,14 @@ impl CharacterAbility {
}, },
_ => {}, _ => {},
} }
}, }
Some(ToolKind::Sceptre) => {
use skills::SceptreSkill::*; #[warn(clippy::pedantic)]
fn adjusted_by_sceptre_skills(&mut self, skillset: &skills::SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{SceptreSkill::*, Skill::Sceptre};
match self { match self {
BasicBeam { CharacterAbility::BasicBeam {
ref mut damage, ref mut damage,
ref mut range, ref mut range,
ref mut beam_duration, ref mut beam_duration,
@ -1362,14 +1396,13 @@ impl CharacterAbility {
*lifesteal *= 1.15_f32.powi(level.into()); *lifesteal *= 1.15_f32.powi(level.into());
} }
}, },
BasicAura { CharacterAbility::BasicAura {
ref mut aura, ref mut aura,
ref mut range, ref mut range,
ref mut energy_cost, ref mut energy_cost,
ref specifier, specifier: aura::Specifier::WardingAura,
.. ..
} => { } => {
if matches!(*specifier, aura::Specifier::WardingAura) {
if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) { if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) {
aura.strength *= 1.15_f32.powi(level.into()); aura.strength *= 1.15_f32.powi(level.into());
} }
@ -1382,7 +1415,14 @@ impl CharacterAbility {
if let Ok(Some(level)) = skillset.skill_level(Sceptre(ACost)) { if let Ok(Some(level)) = skillset.skill_level(Sceptre(ACost)) {
*energy_cost *= 0.85_f32.powi(level.into()); *energy_cost *= 0.85_f32.powi(level.into());
} }
} else if matches!(*specifier, aura::Specifier::HealingAura) { },
CharacterAbility::BasicAura {
ref mut aura,
ref mut range,
ref mut energy_cost,
specifier: aura::Specifier::HealingAura,
..
} => {
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 *= 1.15_f32.powi(level.into());
} }
@ -1395,51 +1435,9 @@ impl CharacterAbility {
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 *= 0.85_f32.powi(level.into());
} }
}
}, },
_ => {}, _ => {},
} }
},
Some(ToolKind::Pick) => {
use skills::MiningSkill::*;
if let BasicMelee {
ref mut buildup_duration,
ref mut swing_duration,
ref mut recover_duration,
..
} = self
{
if let Ok(Some(level)) = skillset.skill_level(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::*;
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(_) => {},
}
self
} }
} }

View File

@ -956,6 +956,15 @@ impl SkillSet {
} }
} }
/// Returns the level of the skill or passed value as default
pub fn skill_level_or(&self, skill: Skill, default: u16) -> u16 {
if let Ok(Some(level)) = self.skill_level(skill) {
level
} else {
default
}
}
/// Checks the next level of a skill /// Checks the next level of a skill
fn next_skill_level(&self, skill: Skill) -> Option<u16> { fn next_skill_level(&self, skill: Skill) -> Option<u16> {
if let Ok(level) = self.skill_level(skill) { if let Ok(level) = self.skill_level(skill) {