diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/basic.ron index 9492e92013..5c0c42499a 100644 --- a/assets/common/abilities/bow/basic.ron +++ b/assets/common/abilities/bow/basic.ron @@ -5,7 +5,7 @@ BasicRanged( projectile: Arrow( damage: 80.0, knockback: 5.0, - energy_regen: 100, + energy_regen: 50, ), projectile_body: Object(Arrow), projectile_light: None, diff --git a/assets/common/abilities/bow/charged.ron b/assets/common/abilities/bow/charged.ron index 3162c4631e..6e52bd3103 100644 --- a/assets/common/abilities/bow/charged.ron +++ b/assets/common/abilities/bow/charged.ron @@ -14,4 +14,5 @@ ChargedRanged( projectile_gravity: Some(Gravity(0.2)), initial_projectile_speed: 100.0, scaled_projectile_speed: 400.0, + move_speed: 0.3, ) diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index 619c326200..18dc6d0bd2 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -14,5 +14,5 @@ RepeaterRanged( projectile_light: None, projectile_gravity: Some(Gravity(0.2)), projectile_speed: 100.0, - reps_remaining: 5, + reps_remaining: 3, ) \ No newline at end of file diff --git a/assets/common/items/debug/cultist_purp_2h_boss-0.ron b/assets/common/items/debug/cultist_purp_2h_boss-0.ron index ad1c227278..d53c82b1ff 100644 --- a/assets/common/items/debug/cultist_purp_2h_boss-0.ron +++ b/assets/common/items/debug/cultist_purp_2h_boss-0.ron @@ -3,7 +3,7 @@ ItemDef( description: "Shouldn't this be a hammer?", kind: Tool( ( - kind: Hammer, + kind: Bow, stats: ( equip_time_millis: 0, power: 1000.0, diff --git a/assets/common/skill_trees/skill_max_levels.ron b/assets/common/skill_trees/skill_max_levels.ron index 289c7dbb5a..81c0683d41 100644 --- a/assets/common/skill_trees/skill_max_levels.ron +++ b/assets/common/skill_trees/skill_max_levels.ron @@ -34,4 +34,16 @@ Hammer(LDistance): Some(2), Hammer(LKnockback): Some(2), Hammer(LRange): Some(2), + Bow(ProjSpeed): Some(2), + Bow(BDamage): Some(3), + Bow(BRegen): Some(2), + Bow(CDamage): Some(3), + Bow(CKnockback): Some(2), + Bow(CProjSpeed): Some(2), + Bow(CDrain): Some(2), + Bow(CSpeed): Some(2), + Bow(CMove): Some(2), + Bow(RDamage): Some(2), + Bow(RArrows): Some(2), + Bow(RCost): Some(2), }) \ No newline at end of file diff --git a/assets/common/skill_trees/skill_prerequisites.ron b/assets/common/skill_trees/skill_prerequisites.ron index 81c9fb7495..8c7a67a594 100644 --- a/assets/common/skill_trees/skill_prerequisites.ron +++ b/assets/common/skill_trees/skill_prerequisites.ron @@ -39,4 +39,14 @@ Hammer(LDistance): {Hammer(LUnlockLeap): None}, Hammer(LKnockback): {Hammer(LUnlockLeap): None}, Hammer(LRange): {Hammer(LUnlockLeap): None}, + Bow(BRegen): {Bow(BDamage): Some(1)}, + Bow(CKnockback): {Bow(CDamage): Some(1)}, + Bow(CProjSpeed): {Bow(CDamage): Some(1)}, + Bow(CDrain): {Bow(CDamage): Some(1)}, + Bow(CSpeed): {Bow(CDamage): Some(1)}, + Bow(CMove): {Bow(CDamage): Some(1)}, + Bow(RDamage): {Bow(UnlockRepeater): None}, + Bow(RLeap): {Bow(UnlockRepeater): None}, + Bow(RArrows): {Bow(UnlockRepeater): None}, + Bow(RCost): {Bow(UnlockRepeater): None}, }) \ No newline at end of file diff --git a/assets/common/skill_trees/skills_skill-groups_manifest.ron b/assets/common/skill_trees/skills_skill-groups_manifest.ron index 79ffa9f91e..ba72a766ee 100644 --- a/assets/common/skill_trees/skills_skill-groups_manifest.ron +++ b/assets/common/skill_trees/skills_skill-groups_manifest.ron @@ -59,7 +59,20 @@ Hammer(LRange), ], Weapon(Bow): [ + Bow(ProjSpeed), + Bow(BDamage), + Bow(BRegen), + Bow(CDamage), + Bow(CKnockback), + Bow(CProjSpeed), + Bow(CDrain), + Bow(CSpeed), + Bow(CMove), Bow(UnlockRepeater), + Bow(RDamage), + Bow(RLeap), + Bow(RArrows), + Bow(RCost), ], Weapon(Staff): [ Staff(UnlockShockwave), diff --git a/client/src/lib.rs b/client/src/lib.rs index a0632f7cf2..d19453c464 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1186,6 +1186,64 @@ impl Client { SkillGroupType::Weapon(Bow), ))); }, + "@unlock bow proj speed" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::ProjSpeed, + ))); + }, + "@unlock bow basic damage" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::BDamage, + ))); + }, + "@unlock bow basic regen" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::BRegen))); + }, + "@unlock bow charged damage" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::CDamage, + ))); + }, + "@unlock bow charged knockback" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::CKnockback, + ))); + }, + "@unlock bow charged proj speed" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::CProjSpeed, + ))); + }, + "@unlock bow charged drain" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::CDrain))); + }, + "@unlock bow charged speed" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::CSpeed))); + }, + "@unlock bow charged move" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::CMove))); + }, + "@unlock bow repeater" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::UnlockRepeater, + ))); + }, + "@unlock bow repeater damage" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::RDamage, + ))); + }, + "@unlock bow repeater leap" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::RLeap))); + }, + "@unlock bow repeater arrows" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow( + BowSkill::RArrows, + ))); + }, + "@unlock bow repeater cost" => { + self.send_msg(ClientGeneral::UnlockSkill(Skill::Bow(BowSkill::RCost))); + }, "@unlock staff" => { self.send_msg(ClientGeneral::UnlockSkill(Skill::UnlockGroup( SkillGroupType::Weapon(Staff), diff --git a/common/src/combat.rs b/common/src/combat.rs index f23c8a1525..8cb01feba9 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -87,9 +87,9 @@ impl Damage { }, DamageSource::Projectile => { // Critical hit - if rand::random() { + /*if rand::random() { damage *= 1.2; - } + }*/ // Armor damage *= 1.0 - damage_reduction; diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 2eca470c80..ae7787486c 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -189,6 +189,7 @@ pub enum CharacterAbility { projectile_gravity: Option, initial_projectile_speed: f32, scaled_projectile_speed: f32, + move_speed: f32, }, Shockwave { energy_cost: u32, @@ -335,7 +336,7 @@ impl CharacterAbility { } => { *buildup_duration = (*buildup_duration as f32 / speed) as u64; *recover_duration = (*recover_duration as f32 / speed) as u64; - *projectile = projectile.modified_projectile(power); + *projectile = projectile.modified_projectile(power, 1_f32); }, RepeaterRanged { ref mut movement_duration, @@ -349,7 +350,7 @@ impl CharacterAbility { *buildup_duration = (*buildup_duration as f32 / speed) as u64; *shoot_duration = (*shoot_duration as f32 / speed) as u64; *recover_duration = (*recover_duration as f32 / speed) as u64; - *projectile = projectile.modified_projectile(power); + *projectile = projectile.modified_projectile(power, 1_f32); }, Boost { ref mut movement_duration, @@ -810,6 +811,90 @@ impl CharacterAbility { _ => {}, } }, + ToolKind::Bow => { + use skills::BowSkill::*; + match self { + BasicRanged { + ref mut projectile, + ref mut projectile_speed, + .. + } => { + if let Some(level) = skills.get(&Bow(ProjSpeed)).copied().flatten() { + *projectile_speed *= 1.5_f32.powi(level.into()); + } + { + let damage_level = + skills.get(&Bow(BDamage)).copied().flatten().unwrap_or(0); + let regen_level = + skills.get(&Bow(BRegen)).copied().flatten().unwrap_or(0); + let power = 1.3_f32.powi(damage_level.into()); + let regen = 1.5_f32.powi(regen_level.into()); + *projectile = projectile.modified_projectile(power, regen); + } + }, + ChargedRanged { + ref mut scaled_damage, + ref mut scaled_knockback, + ref mut energy_drain, + ref mut speed, + ref mut initial_projectile_speed, + ref mut scaled_projectile_speed, + ref mut move_speed, + .. + } => { + if let Some(level) = skills.get(&Bow(ProjSpeed)).copied().flatten() { + *initial_projectile_speed *= 1.5_f32.powi(level.into()); + } + if let Some(level) = skills.get(&Bow(CDamage)).copied().flatten() { + *scaled_damage = + (*scaled_damage as f32 * 1.25_f32.powi(level.into())) as u32; + } + if let Some(level) = skills.get(&Bow(CKnockback)).copied().flatten() { + *scaled_knockback *= 1.5_f32.powi(level.into()); + } + if let Some(level) = skills.get(&Bow(CProjSpeed)).copied().flatten() { + *scaled_projectile_speed *= 1.2_f32.powi(level.into()); + } + if let Some(level) = skills.get(&Bow(CDrain)).copied().flatten() { + *energy_drain = + (*energy_drain as f32 * 0.75_f32.powi(level.into())) as u32; + } + if let Some(level) = skills.get(&Bow(CSpeed)).copied().flatten() { + *speed *= 1.25_f32.powi(level.into()); + } + if let Some(level) = skills.get(&Bow(CMove)).copied().flatten() { + *move_speed *= 1.25_f32.powi(level.into()); + } + }, + RepeaterRanged { + ref mut energy_cost, + ref mut leap, + ref mut projectile, + ref mut reps_remaining, + ref mut projectile_speed, + .. + } => { + if let Some(level) = skills.get(&Bow(ProjSpeed)).copied().flatten() { + *projectile_speed *= 1.5_f32.powi(level.into()); + } + if let Some(level) = skills.get(&Bow(RDamage)).copied().flatten() { + let power = 1.3_f32.powi(level.into()); + *projectile = projectile.modified_projectile(power, 1_f32); + } + if !skills.contains_key(&Bow(RLeap)) { + *leap = None; + } + if let Some(level) = skills.get(&Bow(RArrows)).copied().flatten() { + *reps_remaining += level as u32; + } + if let Some(level) = skills.get(&Bow(RCost)).copied().flatten() { + *energy_cost = + (*energy_cost as f32 * 0.75_f32.powi(level.into())) as u32; + } + }, + _ => {}, + } + }, _ => {}, } } @@ -1085,6 +1170,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { projectile_gravity, initial_projectile_speed, scaled_projectile_speed, + move_speed, } => CharacterState::ChargedRanged(charged_ranged::Data { static_data: charged_ranged::StaticData { buildup_duration: Duration::from_millis(*buildup_duration), @@ -1101,6 +1187,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { projectile_gravity: *projectile_gravity, initial_projectile_speed: *initial_projectile_speed, scaled_projectile_speed: *scaled_projectile_speed, + move_speed: *move_speed, ability_key: key, }, timer: Duration::default(), diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 3927ea0638..d0239718b4 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -203,11 +203,16 @@ impl ProjectileConstructor { } } - pub fn modified_projectile(mut self, power: f32) -> Self { + pub fn modified_projectile(mut self, power: f32, regen: f32) -> Self { use ProjectileConstructor::*; match self { - Arrow { ref mut damage, .. } => { + Arrow { + ref mut damage, + ref mut energy_regen, + .. + } => { *damage *= power; + *energy_regen = (*energy_regen as f32 * regen) as u32; }, Fireball { ref mut damage, .. } => { *damage *= power; diff --git a/common/src/comp/skills.rs b/common/src/comp/skills.rs index dbf5537f57..fef5217b15 100644 --- a/common/src/comp/skills.rs +++ b/common/src/comp/skills.rs @@ -142,7 +142,24 @@ pub enum HammerSkill { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub enum BowSkill { + // Passives + ProjSpeed, + // Basic ranged upgrades + BDamage, + BRegen, + // Charged ranged upgrades + CDamage, + CKnockback, + CProjSpeed, + CDrain, + CSpeed, + CMove, + // Repeater upgrades UnlockRepeater, + RDamage, + RLeap, + RArrows, + RCost, } #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index b48c5a26a2..90c0ec468b 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -42,6 +42,8 @@ pub struct StaticData { pub projectile_gravity: Option, pub initial_projectile_speed: f32, pub scaled_projectile_speed: f32, + /// Move speed efficiency + pub move_speed: f32, /// What key is used to press ability pub ability_key: AbilityKey, } @@ -63,7 +65,7 @@ impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_move(data, &mut update, 0.3); + handle_move(data, &mut update, self.static_data.move_speed); handle_jump(data, &mut update); if !ability_key_is_pressed(data, self.static_data.ability_key) { handle_interrupt(data, &mut update, false); diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 3d8f4ed359..e8841a4281 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -3,7 +3,7 @@ use crate::{ inventory::slot::EquipSlot, item::{Hands, ItemKind, Tool, ToolKind}, quadruped_low, quadruped_medium, - skills::{AxeSkill, HammerSkill, Skill, SwordSkill}, + skills::{AxeSkill, BowSkill, HammerSkill, Skill, SwordSkill}, theropod, Body, CharacterState, StateUpdate, }, consts::{FRIC_GROUND, GRAVITY}, @@ -512,6 +512,15 @@ pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) { { None }, + Some(ToolKind::Bow) + if !&data + .stats + .skill_set + .skills + .contains_key(&Skill::Bow(BowSkill::UnlockRepeater)) => + { + None + }, _ => Some(s), }) .map(|a| {