diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 28609dfd55..84acb0980f 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -5,7 +5,8 @@ use crate::{ self, aura, beam, buff, inventory::item::tool::{Stats, ToolKind}, projectile::ProjectileConstructor, - skills, Body, CharacterState, EnergySource, LightEmitter, StateUpdate, + skills::{self, SKILL_MODIFIERS}, + Body, CharacterState, EnergySource, LightEmitter, StateUpdate, }, states::{ behavior::JoinData, @@ -909,7 +910,7 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_mining_skills(&mut self, skillset: &skills::SkillSet) { - use skills::{MiningSkill::Speed, MiningTreeModifiers, Skill}; + use skills::{MiningSkill::Speed, Skill}; if let CharacterAbility::BasicMelee { ref mut buildup_duration, @@ -919,7 +920,8 @@ impl CharacterAbility { } = self { if let Ok(Some(level)) = skillset.skill_level(Skill::Pick(Speed)) { - let modifiers = MiningTreeModifiers::get(); + let modifiers = SKILL_MODIFIERS.mining_tree; + let speed = modifiers.speed.powi(level.into()); *buildup_duration /= speed; *swing_duration /= speed; @@ -930,8 +932,8 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_general_skills(&mut self, skillset: &skills::SkillSet) { - use skills::{GeneralTreeModifiers, Skill}; - const GENERAL_MODIFIERS: GeneralTreeModifiers = GeneralTreeModifiers::get(); + use skills::Skill; + if let CharacterAbility::Roll { ref mut energy_cost, ref mut roll_strength, @@ -940,7 +942,9 @@ impl CharacterAbility { } = self { use skills::RollSkill::{Cost, Duration, Strength}; - let modifiers = GENERAL_MODIFIERS.roll; + + let modifiers = SKILL_MODIFIERS.general_tree.roll; + if let Ok(Some(level)) = skillset.skill_level(Skill::Roll(Cost)) { *energy_cost *= modifiers.energy_cost.powi(level.into()); } @@ -956,9 +960,7 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_sword_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{Skill::Sword, SwordSkill::*, SwordTreeModifiers}; - - const SWORD_MODIFIERS: SwordTreeModifiers = SwordTreeModifiers::get(); + use skills::{Skill::Sword, SwordSkill::*}; match self { CharacterAbility::ComboMelee { @@ -1004,7 +1006,7 @@ impl CharacterAbility { ref mut charge_through, .. } => { - let modifiers = SWORD_MODIFIERS.dash; + let modifiers = SKILL_MODIFIERS.sword_tree.dash; *is_interruptible = skillset.has_skill(Sword(InterruptingAttacks)); if let Ok(Some(level)) = skillset.skill_level(Sword(DCost)) { *energy_cost *= modifiers.energy_cost.powi(level.into()); @@ -1031,7 +1033,7 @@ impl CharacterAbility { ref mut num_spins, .. } => { - let modifiers = SWORD_MODIFIERS.spin; + let modifiers = SKILL_MODIFIERS.sword_tree.spin; *is_interruptible = skillset.has_skill(Sword(InterruptingAttacks)); if let Ok(Some(level)) = skillset.skill_level(Sword(SDamage)) { *base_damage *= modifiers.base_damage.powi(level.into()); @@ -1052,9 +1054,7 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_axe_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{AxeSkill::*, AxeTreeModifiers, Skill::Axe}; - - const AXE_MODIFIERS: AxeTreeModifiers = AxeTreeModifiers::get(); + use skills::{AxeSkill::*, Skill::Axe}; match self { CharacterAbility::ComboMelee { @@ -1091,7 +1091,8 @@ impl CharacterAbility { ref mut movement_behavior, .. } => { - let modifiers = AXE_MODIFIERS.spin; + let modifiers = SKILL_MODIFIERS.axe_tree.spin; + *is_infinite = skillset.has_skill(Axe(SInfinite)); *movement_behavior = if skillset.has_skill(Axe(SHelicopter)) { spin_melee::MovementBehavior::AxeHover @@ -1116,7 +1117,7 @@ impl CharacterAbility { ref mut vertical_leap_strength, .. } => { - let modifiers = AXE_MODIFIERS.leap; + let modifiers = SKILL_MODIFIERS.axe_tree.leap; if let Ok(Some(level)) = skillset.skill_level(Axe(LDamage)) { *base_damage *= modifiers.base_damage.powi(level.into()); } @@ -1139,9 +1140,7 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_hammer_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{HammerSkill::*, HammerTreeModifiers, Skill::Hammer}; - - const HAMMER_MODIFIERS: HammerTreeModifiers = HammerTreeModifiers::get(); + use skills::{HammerSkill::*, Skill::Hammer}; match self { CharacterAbility::ComboMelee { @@ -1152,7 +1151,8 @@ impl CharacterAbility { ref mut scales_from_combo, .. } => { - let modifiers = HAMMER_MODIFIERS.single_strike; + let modifiers = SKILL_MODIFIERS.hammer_tree.single_strike; + if let Ok(Some(level)) = skillset.skill_level(Hammer(SsKnockback)) { *stage_data = (*stage_data) .iter() @@ -1181,7 +1181,8 @@ impl CharacterAbility { ref mut charge_duration, .. } => { - let modifiers = HAMMER_MODIFIERS.charged; + let modifiers = SKILL_MODIFIERS.hammer_tree.charged; + if let Ok(Some(level)) = skillset.skill_level(Hammer(CDamage)) { *scaled_damage *= modifiers.scaled_damage.powi(level.into()); } @@ -1205,7 +1206,7 @@ impl CharacterAbility { ref mut range, .. } => { - let modifiers = HAMMER_MODIFIERS.leap; + let modifiers = SKILL_MODIFIERS.hammer_tree.leap; if let Ok(Some(level)) = skillset.skill_level(Hammer(LDamage)) { *base_damage *= modifiers.base_damage.powi(level.into()); } @@ -1231,9 +1232,9 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_bow_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{BowSkill::*, BowTreeModifiers, Skill::Bow}; + use skills::{BowSkill::*, Skill::Bow}; - const BOW_MODIFIERS: BowTreeModifiers = BowTreeModifiers::get(); + let projectile_speed_modifier = SKILL_MODIFIERS.bow_tree.universal.projectile_speed; match self { CharacterAbility::ChargedRanged { ref mut initial_damage, @@ -1248,8 +1249,7 @@ impl CharacterAbility { ref mut charge_duration, .. } => { - let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed; - let modifiers = BOW_MODIFIERS.charged; + let modifiers = SKILL_MODIFIERS.bow_tree.charged; if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) { let projectile_speed_scaling = projectile_speed_modifier.powi(level.into()); *initial_projectile_speed *= projectile_speed_scaling; @@ -1285,8 +1285,7 @@ impl CharacterAbility { ref mut projectile_speed, .. } => { - let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed; - let modifiers = BOW_MODIFIERS.repeater; + let modifiers = SKILL_MODIFIERS.bow_tree.repeater; if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) { *projectile_speed *= projectile_speed_modifier.powi(level.into()); } @@ -1309,8 +1308,7 @@ impl CharacterAbility { ref mut projectile_speed, .. } => { - let projectile_speed_modifier = BOW_MODIFIERS.universal.projectile_speed; - let modifiers = BOW_MODIFIERS.shotgun; + let modifiers = SKILL_MODIFIERS.bow_tree.shotgun; if let Ok(Some(level)) = skillset.skill_level(Bow(ProjSpeed)) { *projectile_speed *= projectile_speed_modifier.powi(level.into()); } @@ -1335,14 +1333,13 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_staff_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{Skill::Staff, StaffSkill::*, StaffTreeModifiers}; + use skills::{Skill::Staff, StaffSkill::*}; - const STAFF_MODIFIERS: StaffTreeModifiers = StaffTreeModifiers::get(); match self { CharacterAbility::BasicRanged { ref mut projectile, .. } => { - let modifiers = STAFF_MODIFIERS.fireball; + let modifiers = SKILL_MODIFIERS.staff_tree.fireball; let damage_level = skillset.skill_level_or(Staff(BDamage), 0); let regen_level = skillset.skill_level_or(Staff(BRegen), 0); let range_level = skillset.skill_level_or(Staff(BRadius), 0); @@ -1358,7 +1355,7 @@ impl CharacterAbility { ref mut beam_duration, .. } => { - let modifiers = STAFF_MODIFIERS.flamethrower; + let modifiers = SKILL_MODIFIERS.staff_tree.flamethrower; if let Ok(Some(level)) = skillset.skill_level(Staff(FDamage)) { *damage *= modifiers.damage.powi(level.into()); } @@ -1384,7 +1381,7 @@ impl CharacterAbility { ref mut energy_cost, .. } => { - let modifiers = STAFF_MODIFIERS.shockwave; + let modifiers = SKILL_MODIFIERS.staff_tree.shockwave; if let Ok(Some(level)) = skillset.skill_level(Staff(SDamage)) { *damage *= modifiers.damage.powi(level.into()); } @@ -1406,9 +1403,8 @@ impl CharacterAbility { #[warn(clippy::pedantic)] fn adjusted_by_sceptre_skills(&mut self, skillset: &skills::SkillSet) { #![allow(clippy::enum_glob_use)] - use skills::{SceptreSkill::*, SceptreTreeModifiers, Skill::Sceptre}; + use skills::{SceptreSkill::*, Skill::Sceptre}; - const SCEPTRE_MODIFIERS: SceptreTreeModifiers = SceptreTreeModifiers::get(); match self { CharacterAbility::BasicBeam { ref mut damage, @@ -1418,7 +1414,7 @@ impl CharacterAbility { ref mut energy_regen, .. } => { - let modifiers = SCEPTRE_MODIFIERS.beam; + let modifiers = SKILL_MODIFIERS.sceptre_tree.beam; if let Ok(Some(level)) = skillset.skill_level(Sceptre(LDamage)) { *damage *= modifiers.damage.powi(level.into()); } @@ -1444,7 +1440,7 @@ impl CharacterAbility { specifier: aura::Specifier::HealingAura, .. } => { - let modifiers = SCEPTRE_MODIFIERS.healing_aura; + let modifiers = SKILL_MODIFIERS.sceptre_tree.healing_aura; if let Ok(Some(level)) = skillset.skill_level(Sceptre(HHeal)) { aura.strength *= modifiers.strength.powi(level.into()); } @@ -1467,7 +1463,7 @@ impl CharacterAbility { specifier: aura::Specifier::WardingAura, .. } => { - let modifiers = SCEPTRE_MODIFIERS.warding_aura; + let modifiers = SKILL_MODIFIERS.sceptre_tree.warding_aura; if let Ok(Some(level)) = skillset.skill_level(Sceptre(AStrength)) { aura.strength *= modifiers.strength.powi(level.into()); } diff --git a/common/src/comp/skills.rs b/common/src/comp/skills.rs index 3c29b04877..ec3994698f 100644 --- a/common/src/comp/skills.rs +++ b/common/src/comp/skills.rs @@ -125,6 +125,9 @@ pub enum Skill { /// /// NOTE: Just adding constant does nothing, you need to use it in both /// ECS systems and Diary. +// TODO: make it lazy_static and move to .ron? +pub const SKILL_MODIFIERS: SkillTreeModifiers = SkillTreeModifiers::get(); + pub struct SkillTreeModifiers { pub sword_tree: SwordTreeModifiers, pub axe_tree: AxeTreeModifiers, @@ -136,6 +139,21 @@ pub struct SkillTreeModifiers { pub general_tree: GeneralTreeModifiers, } +impl SkillTreeModifiers { + const fn get() -> Self { + Self { + sword_tree: SwordTreeModifiers::get(), + axe_tree: AxeTreeModifiers::get(), + hammer_tree: HammerTreeModifiers::get(), + bow_tree: BowTreeModifiers::get(), + staff_tree: StaffTreeModifiers::get(), + sceptre_tree: SceptreTreeModifiers::get(), + mining_tree: MiningTreeModifiers::get(), + general_tree: GeneralTreeModifiers::get(), + } + } +} + pub struct SwordTreeModifiers { pub dash: SwordDashModifiers, pub spin: SwordSpinModifiers, @@ -157,7 +175,7 @@ pub struct SwordSpinModifiers { } impl SwordTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { dash: SwordDashModifiers { energy_cost: 0.75, @@ -196,7 +214,7 @@ pub struct AxeLeapModifiers { } impl AxeTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { spin: AxeSpinModifiers { base_damage: 1.3, @@ -239,7 +257,7 @@ pub struct HammerLeapModifiers { } impl HammerTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { single_strike: HammerStrikeModifiers { knockback: 1.5 }, charged: HammerChargedModifers { @@ -293,7 +311,7 @@ pub struct BowShotgunModifiers { } impl BowTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { universal: BowUniversalModifiers { projectile_speed: 1.2, @@ -347,7 +365,7 @@ pub struct StaffShockwaveModifiers { } impl StaffTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { fireball: StaffFireballModifiers { power: 1.2, @@ -398,7 +416,7 @@ pub struct SceptreWardingAuraModifiers { } impl SceptreTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { beam: SceptreBeamModifiers { damage: 1.2, @@ -424,12 +442,12 @@ impl SceptreTreeModifiers { pub struct MiningTreeModifiers { pub speed: f32, - pub gem_gain: f32, - pub ore_gain: f32, + pub gem_gain: f64, + pub ore_gain: f64, } impl MiningTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { speed: 1.1, gem_gain: 0.05, @@ -460,7 +478,7 @@ pub struct ClimbTreeModifiers { } impl GeneralTreeModifiers { - pub const fn get() -> Self { + const fn get() -> Self { Self { roll: RollTreeModifiers { energy_cost: 0.9, diff --git a/common/src/states/climb.rs b/common/src/states/climb.rs index 160cebdfdb..e0d2ddfb11 100644 --- a/common/src/states/climb.rs +++ b/common/src/states/climb.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ - skills::{ClimbSkill::*, GeneralTreeModifiers, Skill}, + skills::{ClimbSkill::*, Skill, SKILL_MODIFIERS}, CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate, }, consts::GRAVITY, @@ -30,8 +30,7 @@ pub struct Data { impl Data { pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self { - const GENERAL_MODIFIERS: GeneralTreeModifiers = GeneralTreeModifiers::get(); - let modifiers = GENERAL_MODIFIERS.climb; + let modifiers = SKILL_MODIFIERS.general_tree.climb; let mut data = Data::default(); if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) { data.static_data.energy_cost *= modifiers.energy_cost.powi(level.into()); diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 3a82895d64..d2c2db8b1f 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -5,7 +5,7 @@ use crate::{ inventory::slot::{EquipSlot, Slot}, item::{Hands, ItemKind, Tool, ToolKind}, quadruped_low, quadruped_medium, quadruped_small, - skills::{GeneralTreeModifiers, Skill, SwimSkill}, + skills::{Skill, SwimSkill, SKILL_MODIFIERS}, theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind, InventoryAction, StateUpdate, }, @@ -375,8 +375,7 @@ fn swim_move( let mut water_accel = force / data.mass.0; if let Ok(Some(level)) = data.skill_set.skill_level(Skill::Swim(SwimSkill::Speed)) { - const GENERAL_MOFIDIERS: GeneralTreeModifiers = GeneralTreeModifiers::get(); - let modifiers = GENERAL_MOFIDIERS.swim; + let modifiers = SKILL_MODIFIERS.general_tree.swim; water_accel *= modifiers.speed.powi(level.into()); } diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index ed836a90c0..cf748dd14b 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -349,25 +349,32 @@ pub fn handle_mine_block( xp_pools: HashSet::from_iter(vec![SkillGroupKind::Weapon(tool)]), }); } - use common::comp::skills::{MiningSkill, Skill}; + use common::comp::skills::{MiningSkill, Skill, SKILL_MODIFIERS}; use rand::Rng; let mut rng = rand::thread_rng(); - if item.item_definition_id().contains("mineral.ore.") - && rng.gen_bool( - 0.05 * f64::from( - skillset.skill_level_or(Skill::Pick(MiningSkill::OreGain), 0), - ), - ) - { - let _ = item.increase_amount(1); - } - if item.item_definition_id().contains("mineral.gem.") - && rng.gen_bool( - 0.05 * f64::from( - skillset.skill_level_or(Skill::Pick(MiningSkill::GemGain), 0), - ), - ) - { + + let need_double_ore = |rng: &mut rand::rngs::ThreadRng| { + let chance_mod = SKILL_MODIFIERS.mining_tree.ore_gain; + let skill_level = + skillset.skill_level_or(Skill::Pick(MiningSkill::OreGain), 0); + + rng.gen_bool(chance_mod * f64::from(skill_level)) + }; + let need_double_gem = |rng: &mut rand::rngs::ThreadRng| { + let chance_mod = SKILL_MODIFIERS.mining_tree.gem_gain; + let skill_level = + skillset.skill_level_or(Skill::Pick(MiningSkill::GemGain), 0); + + rng.gen_bool(chance_mod * f64::from(skill_level)) + }; + + let double_gain = (item.item_definition_id().contains("mineral.ore.") + && need_double_ore(&mut rng)) + || (item.item_definition_id().contains("mineral.gem.") + && need_double_gem(&mut rng)); + + if double_gain { + // Ignore non-stackable errors let _ = item.increase_amount(1); } }