Implemented bow skill tree.

This commit is contained in:
Sam 2020-12-22 21:28:55 -05:00
parent 4dfe14c103
commit 662a08defc
14 changed files with 225 additions and 11 deletions

View File

@ -5,7 +5,7 @@ BasicRanged(
projectile: Arrow( projectile: Arrow(
damage: 80.0, damage: 80.0,
knockback: 5.0, knockback: 5.0,
energy_regen: 100, energy_regen: 50,
), ),
projectile_body: Object(Arrow), projectile_body: Object(Arrow),
projectile_light: None, projectile_light: None,

View File

@ -14,4 +14,5 @@ ChargedRanged(
projectile_gravity: Some(Gravity(0.2)), projectile_gravity: Some(Gravity(0.2)),
initial_projectile_speed: 100.0, initial_projectile_speed: 100.0,
scaled_projectile_speed: 400.0, scaled_projectile_speed: 400.0,
move_speed: 0.3,
) )

View File

@ -14,5 +14,5 @@ RepeaterRanged(
projectile_light: None, projectile_light: None,
projectile_gravity: Some(Gravity(0.2)), projectile_gravity: Some(Gravity(0.2)),
projectile_speed: 100.0, projectile_speed: 100.0,
reps_remaining: 5, reps_remaining: 3,
) )

View File

@ -3,7 +3,7 @@ ItemDef(
description: "Shouldn't this be a hammer?", description: "Shouldn't this be a hammer?",
kind: Tool( kind: Tool(
( (
kind: Hammer, kind: Bow,
stats: ( stats: (
equip_time_millis: 0, equip_time_millis: 0,
power: 1000.0, power: 1000.0,

View File

@ -34,4 +34,16 @@
Hammer(LDistance): Some(2), Hammer(LDistance): Some(2),
Hammer(LKnockback): Some(2), Hammer(LKnockback): Some(2),
Hammer(LRange): 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),
}) })

View File

@ -39,4 +39,14 @@
Hammer(LDistance): {Hammer(LUnlockLeap): None}, Hammer(LDistance): {Hammer(LUnlockLeap): None},
Hammer(LKnockback): {Hammer(LUnlockLeap): None}, Hammer(LKnockback): {Hammer(LUnlockLeap): None},
Hammer(LRange): {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},
}) })

View File

@ -59,7 +59,20 @@
Hammer(LRange), Hammer(LRange),
], ],
Weapon(Bow): [ Weapon(Bow): [
Bow(ProjSpeed),
Bow(BDamage),
Bow(BRegen),
Bow(CDamage),
Bow(CKnockback),
Bow(CProjSpeed),
Bow(CDrain),
Bow(CSpeed),
Bow(CMove),
Bow(UnlockRepeater), Bow(UnlockRepeater),
Bow(RDamage),
Bow(RLeap),
Bow(RArrows),
Bow(RCost),
], ],
Weapon(Staff): [ Weapon(Staff): [
Staff(UnlockShockwave), Staff(UnlockShockwave),

View File

@ -1186,6 +1186,64 @@ impl Client {
SkillGroupType::Weapon(Bow), 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" => { "@unlock staff" => {
self.send_msg(ClientGeneral::UnlockSkill(Skill::UnlockGroup( self.send_msg(ClientGeneral::UnlockSkill(Skill::UnlockGroup(
SkillGroupType::Weapon(Staff), SkillGroupType::Weapon(Staff),

View File

@ -87,9 +87,9 @@ impl Damage {
}, },
DamageSource::Projectile => { DamageSource::Projectile => {
// Critical hit // Critical hit
if rand::random() { /*if rand::random() {
damage *= 1.2; damage *= 1.2;
} }*/
// Armor // Armor
damage *= 1.0 - damage_reduction; damage *= 1.0 - damage_reduction;

View File

@ -189,6 +189,7 @@ pub enum CharacterAbility {
projectile_gravity: Option<Gravity>, projectile_gravity: Option<Gravity>,
initial_projectile_speed: f32, initial_projectile_speed: f32,
scaled_projectile_speed: f32, scaled_projectile_speed: f32,
move_speed: f32,
}, },
Shockwave { Shockwave {
energy_cost: u32, energy_cost: u32,
@ -335,7 +336,7 @@ impl CharacterAbility {
} => { } => {
*buildup_duration = (*buildup_duration as f32 / speed) as u64; *buildup_duration = (*buildup_duration as f32 / speed) as u64;
*recover_duration = (*recover_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 { RepeaterRanged {
ref mut movement_duration, ref mut movement_duration,
@ -349,7 +350,7 @@ impl CharacterAbility {
*buildup_duration = (*buildup_duration as f32 / speed) as u64; *buildup_duration = (*buildup_duration as f32 / speed) as u64;
*shoot_duration = (*shoot_duration as f32 / speed) as u64; *shoot_duration = (*shoot_duration as f32 / speed) as u64;
*recover_duration = (*recover_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 { Boost {
ref mut movement_duration, 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, projectile_gravity,
initial_projectile_speed, initial_projectile_speed,
scaled_projectile_speed, scaled_projectile_speed,
move_speed,
} => CharacterState::ChargedRanged(charged_ranged::Data { } => CharacterState::ChargedRanged(charged_ranged::Data {
static_data: charged_ranged::StaticData { static_data: charged_ranged::StaticData {
buildup_duration: Duration::from_millis(*buildup_duration), buildup_duration: Duration::from_millis(*buildup_duration),
@ -1101,6 +1187,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
projectile_gravity: *projectile_gravity, projectile_gravity: *projectile_gravity,
initial_projectile_speed: *initial_projectile_speed, initial_projectile_speed: *initial_projectile_speed,
scaled_projectile_speed: *scaled_projectile_speed, scaled_projectile_speed: *scaled_projectile_speed,
move_speed: *move_speed,
ability_key: key, ability_key: key,
}, },
timer: Duration::default(), timer: Duration::default(),

View File

@ -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::*; use ProjectileConstructor::*;
match self { match self {
Arrow { ref mut damage, .. } => { Arrow {
ref mut damage,
ref mut energy_regen,
..
} => {
*damage *= power; *damage *= power;
*energy_regen = (*energy_regen as f32 * regen) as u32;
}, },
Fireball { ref mut damage, .. } => { Fireball { ref mut damage, .. } => {
*damage *= power; *damage *= power;

View File

@ -142,7 +142,24 @@ pub enum HammerSkill {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub enum BowSkill { pub enum BowSkill {
// Passives
ProjSpeed,
// Basic ranged upgrades
BDamage,
BRegen,
// Charged ranged upgrades
CDamage,
CKnockback,
CProjSpeed,
CDrain,
CSpeed,
CMove,
// Repeater upgrades
UnlockRepeater, UnlockRepeater,
RDamage,
RLeap,
RArrows,
RCost,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -42,6 +42,8 @@ pub struct StaticData {
pub projectile_gravity: Option<Gravity>, pub projectile_gravity: Option<Gravity>,
pub initial_projectile_speed: f32, pub initial_projectile_speed: f32,
pub scaled_projectile_speed: f32, pub scaled_projectile_speed: f32,
/// Move speed efficiency
pub move_speed: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_key: AbilityKey,
} }
@ -63,7 +65,7 @@ impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate { fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data); 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); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);

View File

@ -3,7 +3,7 @@ use crate::{
inventory::slot::EquipSlot, inventory::slot::EquipSlot,
item::{Hands, ItemKind, Tool, ToolKind}, item::{Hands, ItemKind, Tool, ToolKind},
quadruped_low, quadruped_medium, quadruped_low, quadruped_medium,
skills::{AxeSkill, HammerSkill, Skill, SwordSkill}, skills::{AxeSkill, BowSkill, HammerSkill, Skill, SwordSkill},
theropod, Body, CharacterState, StateUpdate, theropod, Body, CharacterState, StateUpdate,
}, },
consts::{FRIC_GROUND, GRAVITY}, consts::{FRIC_GROUND, GRAVITY},
@ -512,6 +512,15 @@ pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) {
{ {
None None
}, },
Some(ToolKind::Bow)
if !&data
.stats
.skill_set
.skills
.contains_key(&Skill::Bow(BowSkill::UnlockRepeater)) =>
{
None
},
_ => Some(s), _ => Some(s),
}) })
.map(|a| { .map(|a| {