Merge branch 'sam/melee-constructor' into 'master'

Melee Constructor

See merge request veloren/veloren!3111
This commit is contained in:
Samuel Keiffer 2022-01-19 06:36:51 +00:00
commit c3e92b6c7a
51 changed files with 1140 additions and 1105 deletions

View File

@ -4,18 +4,16 @@ LeapMelee(
movement_duration: 0.2, movement_duration: 0.2,
swing_duration: 0.2, swing_duration: 0.2,
recover_duration: 0.2, recover_duration: 0.2,
base_damage: 30.0, melee_constructor: (
base_poise_damage: 0, kind: Slash(
knockback: 12.0, damage: 30.0,
range: 4.5, poise: 0.0,
max_angle: 30.0, knockback: 12.0,
energy_regen: 0.0,
),
range: 4.5,
angle: 30.0,
),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 8.0, vertical_leap_strength: 8.0,
damage_kind: Slashing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -2,16 +2,16 @@ SpinMelee(
buildup_duration: 0.2, buildup_duration: 0.2,
swing_duration: 0.6, swing_duration: 0.6,
recover_duration: 0.2, recover_duration: 0.2,
base_damage: 8.0, melee_constructor: (
base_poise_damage: 10, kind: Slash(
knockback: ( strength: 0.0, direction: Away), damage: 8.0,
range: 3.5, poise: 10.0,
damage_effect: Some(Buff(( knockback: 0.0,
kind: Bleeding, energy_regen: 0.0,
dur_secs: 10.0, ),
strength: DamageFraction(0.1), range: 3.5,
chance: 0.1, angle: 360.0,
))), ),
energy_cost: 10.0, energy_cost: 10.0,
is_infinite: true, is_infinite: true,
movement_behavior: AxeHover, movement_behavior: AxeHover,
@ -19,6 +19,4 @@ SpinMelee(
forward_speed: 0.0, forward_speed: 0.0,
num_spins: 1, num_spins: 1,
specifier: None, specifier: None,
target: Some(OutOfGroup),
damage_kind: Slashing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 12.0, melee_constructor: (
scaled_damage: 18.0, kind: Bash(
base_poise_damage: 25, damage: 12.0,
scaled_poise_damage: 0, poise: 25.0,
base_knockback: 4.0, knockback: 4.0,
scaled_knockback: 17.0, energy_regen: 0.0,
range: 2.5, ),
angle: 45.0, scaled: Some(Bash(
damage: 18.0,
poise: 0.0,
knockback: 17.0,
energy_regen: 0.0,
)),
range: 2.5,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 4.0, forward_speed: 4.0,
buildup_duration: 0.8, buildup_duration: 0.8,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.25, buildup_duration: 0.25,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.25, recover_duration: 0.25,
knockback: ( strength: 25.0, direction: Away), melee_constructor: (
base_damage: 20.0, kind: Slash(
base_poise_damage: 40, damage: 20.0,
range: 5.0, poise: 40.0,
max_angle: 120.0, knockback: 25.0,
damage_effect: Some(Buff(( energy_regen: 0.0,
kind: Bleeding, ),
dur_secs: 10.0, range: 5.0,
strength: DamageFraction(0.1), angle: 120.0,
chance: 0.1, ),
))),
damage_kind: Slashing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 8.0, melee_constructor: (
scaled_damage: 15.0, kind: Bash(
base_poise_damage: 50, damage: 8.0,
scaled_poise_damage: 100, poise: 50.0,
base_knockback: 6.0, knockback: 6.0,
scaled_knockback: 12.0, energy_regen: 0.0,
range: 2.0, ),
angle: 20.0, scaled: Some(Bash(
damage: 15.0,
poise: 100.0,
knockback: 12.0,
energy_regen: 0.0,
)),
range: 2.0,
angle: 20.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 1.9, forward_speed: 1.9,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.8, buildup_duration: 0.8,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.5, recover_duration: 0.5,
base_damage: 20.0, melee_constructor: (
base_poise_damage: 50, kind: Bash(
knockback: ( strength: 10.0, direction: Away), damage: 20.0,
range: 4.0, poise: 50.0,
max_angle: 45.0, knockback: 10.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 4.0,
angle: 45.0,
),
) )

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.7, buildup_duration: 0.7,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.6, recover_duration: 0.6,
base_damage: 7.0, melee_constructor: (
base_poise_damage: 10, kind: Slash(
knockback: ( strength: 10.0, direction: Away), damage: 7.0,
range: 4.0, poise: 10.0,
max_angle: 60.0, knockback: 10.0,
damage_effect: Some(Buff(( energy_regen: 0.0,
kind: Bleeding, ),
dur_secs: 2.0, range: 4.0,
strength: DamageFraction(0.5), angle: 60.0,
chance: 0.1, ),
))),
damage_kind: Slashing,
) )

View File

@ -1,17 +1,24 @@
ChargedMelee( ChargedMelee(
energy_cost: 0, energy_cost: 0,
energy_drain: 0, energy_drain: 0,
initial_damage: 5.0, melee_constructor: (
scaled_damage: 45.0, kind: Bash(
initial_poise_damage: 50, damage: 5.0,
scaled_poise_damage: 150, poise: 50.0,
initial_knockback: 0.0, knockback: 0.0,
scaled_knockback: 0.0, energy_regen: 0.0,
range: 3.5, ),
max_angle: 45.0, scaled: Some(Bash(
damage: 45.0,
poise: 150.0,
knockback: 0.0,
energy_regen: 0.0,
)),
range: 3.5,
angle: 45.0,
),
charge_duration: 1.5, charge_duration: 1.5,
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.8, hit_timing: 0.8,
recover_duration: 0.5, recover_duration: 0.5,
damage_kind: Crushing,
) )

View File

@ -2,11 +2,15 @@ SpinMelee(
buildup_duration: 0.8, buildup_duration: 0.8,
swing_duration: 0.5, swing_duration: 0.5,
recover_duration: 0.6, recover_duration: 0.6,
base_damage: 20.0, melee_constructor: (
base_poise_damage: 1.0, kind: NecroticVortex(
knockback: ( strength: 7.0, direction: Towards), damage: 20.0,
range: 16.0, pull: 7.0,
damage_effect: Some(Lifesteal(2.0)), lifesteal: 2.0,
),
range: 16.0,
angle: 360.0,
),
energy_cost: 0.0, energy_cost: 0.0,
is_infinite: true, is_infinite: true,
movement_behavior: Stationary, movement_behavior: Stationary,
@ -14,6 +18,4 @@ SpinMelee(
forward_speed: 0.0, forward_speed: 0.0,
num_spins: 1, num_spins: 1,
specifier: Some(CultistVortex), specifier: Some(CultistVortex),
target: None,
damage_kind: Energy,
) )

View File

@ -1,13 +1,27 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 15.0, melee_constructor: (
scaled_damage: 60.0, kind: Stab(
base_poise_damage: 25, damage: 15.0,
scaled_poise_damage: 100, poise: 25.0,
base_knockback: 10.0, knockback: 10.0,
scaled_knockback: 30.0, energy_regen: 0.0,
range: 5.0, ),
angle: 90.0, scaled: Some(Stab(
damage: 60.0,
poise: 100.0,
knockback: 30.0,
energy_regen: 0.0,
)),
range: 5.0,
angle: 90.0,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 15.0,
strength: DamageFraction(0.3),
chance: 0.25,
))),
),
energy_drain: 0, energy_drain: 0,
forward_speed: 5.0, forward_speed: 5.0,
buildup_duration: 0.4, buildup_duration: 0.4,
@ -17,11 +31,4 @@ DashMelee(
ori_modifier: 0.1, ori_modifier: 0.1,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Piercing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.3),
chance: 0.25,
))),
) )

View File

@ -1,24 +1,25 @@
ChargedMelee( ChargedMelee(
energy_cost: 0, energy_cost: 0,
energy_drain: 0, energy_drain: 0,
initial_damage: 5.0, melee_constructor: (
scaled_damage: 45.0, kind: Slash(
initial_poise_damage: 50, damage: 5.0,
scaled_poise_damage: 150, poise: 50.0,
initial_knockback: 0.0, knockback: 0.0,
scaled_knockback: 0.0, energy_regen: 0.0,
range: 5.0, ),
max_angle: 45.0, scaled: Some(Slash(
damage: 45.0,
poise: 150.0,
knockback: 0.0,
energy_regen: 0.0,
)),
range: 5.0,
angle: 45.0,
),
charge_duration: 1.5, charge_duration: 1.5,
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.8, hit_timing: 0.8,
recover_duration: 0.5, recover_duration: 0.5,
specifier: Some(GroundCleave), specifier: Some(GroundCleave),
damage_kind: Slashing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.3, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.6, recover_duration: 0.6,
base_damage: 15.0, melee_constructor: (
base_poise_damage: 60.0, kind: Slash(
knockback: ( strength: 15.0, direction: Away), damage: 15.0,
range: 5.0, poise: 60.0,
max_angle: 60.0, knockback: 15.0,
damage_effect: Some(Buff(( energy_regen: 0.0,
kind: Crippled, ),
dur_secs: 10.0, range: 5.0,
strength: Value(0.5), angle: 60.0,
chance: 1.0, ),
))),
damage_kind: Slashing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 8.0, melee_constructor: (
scaled_damage: 16.0, kind: Slash(
base_poise_damage: 0, damage: 8.0,
scaled_poise_damage: 0, poise: 0.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 2.0, ),
angle: 15.0, scaled: Some(Slash(
damage: 16.0,
poise: 0.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 2.0,
angle: 15.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 3.0, forward_speed: 3.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: true, is_interruptible: true,
damage_kind: Slashing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 8.0, melee_constructor: (
scaled_damage: 15.0, kind: Bash(
base_poise_damage: 25, damage: 8.0,
scaled_poise_damage: 0, poise: 25.0,
base_knockback: 4.0, knockback: 4.0,
scaled_knockback: 17.0, energy_regen: 0.0,
range: 2.5, ),
angle: 45.0, scaled: Some(Bash(
damage: 15.0,
poise: 0.0,
knockback: 17.0,
energy_regen: 0.0,
)),
range: 2.5,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 4.0, forward_speed: 4.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 4.0, melee_constructor: (
scaled_damage: 8.0, kind: Bash(
base_poise_damage: 30, damage: 4.0,
scaled_poise_damage: 0, poise: 30.0,
base_knockback: 2.0, knockback: 2.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 2.0, ),
angle: 45.0, scaled: Some(Bash(
damage: 8.0,
poise: 0.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 2.0,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 2.0, forward_speed: 2.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -1,17 +1,24 @@
ChargedMelee( ChargedMelee(
energy_cost: 0, energy_cost: 0,
energy_drain: 0, energy_drain: 0,
initial_damage: 4.0, melee_constructor: (
scaled_damage: 20.0, kind: Bash(
initial_poise_damage: 30, damage: 4.0,
scaled_poise_damage: 80, poise: 30.0,
initial_knockback: 10.0, knockback: 10.0,
scaled_knockback: 20.0, energy_regen: 0.0,
range: 6.0, ),
max_angle: 90.0, scaled: Some(Bash(
damage: 20.0,
poise: 80.0,
knockback: 20.0,
energy_regen: 0.0,
)),
range: 6.0,
angle: 90.0,
),
charge_duration: 0.8, charge_duration: 0.8,
swing_duration: 0.7, swing_duration: 0.7,
hit_timing: 0.9, hit_timing: 0.9,
recover_duration: 0.7, recover_duration: 0.7,
damage_kind: Crushing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 7.0, melee_constructor: (
scaled_damage: 28.0, kind: Bash(
base_poise_damage: 28, damage: 7.0,
scaled_poise_damage: 40, poise: 28.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 17.0, energy_regen: 0.0,
range: 2.5, ),
angle: 45.0, scaled: Some(Bash(
damage: 28.0,
poise: 40.0,
knockback: 17.0,
energy_regen: 0.0,
)),
range: 2.5,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 2.0, forward_speed: 2.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.65, buildup_duration: 0.65,
swing_duration: 0.3, swing_duration: 0.3,
recover_duration: 0.35, recover_duration: 0.35,
base_damage: 10.0, melee_constructor: (
base_poise_damage: 28, kind: Bash(
knockback: ( strength: 25.0, direction: Away), damage: 10.0,
range: 0.8, poise: 28.0,
max_angle: 50.0, knockback: 25.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 0.8,
angle: 50.0,
),
) )

View File

@ -4,12 +4,16 @@ LeapMelee(
movement_duration: 0.4, movement_duration: 0.4,
swing_duration: 0.075, swing_duration: 0.075,
recover_duration: 0.2, recover_duration: 0.2,
base_damage: 12.0, melee_constructor: (
base_poise_damage: 60, kind: Bash(
knockback: 4.0, damage: 12.0,
range: 4.5, poise: 60.0,
max_angle: 180.0, knockback: 4.0,
energy_regen: 0.0,
),
range: 4.5,
angle: 180.0,
),
forward_leap_strength: 40.0, forward_leap_strength: 40.0,
vertical_leap_strength: 10.0, vertical_leap_strength: 10.0,
damage_kind: Crushing,
) )

View File

@ -4,11 +4,16 @@ LeapMelee(
movement_duration: 0.3, movement_duration: 0.3,
swing_duration: 0.075, swing_duration: 0.075,
recover_duration: 0.125, recover_duration: 0.125,
base_damage: 8.0, melee_constructor: (
base_poise_damage: 30, kind: Bash(
knockback: 2.0, damage: 8.0,
range: 4.5, poise: 30.0,
max_angle: 180.0, knockback: 2.0,
energy_regen: 0.0,
),
range: 4.5,
angle: 180.0,
),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 5.0, vertical_leap_strength: 5.0,
damage_kind: Crushing, damage_kind: Crushing,

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 7.5, melee_constructor: (
scaled_damage: 2.0, kind: Bash(
base_poise_damage: 28, damage: 7.5,
scaled_poise_damage: 28, poise: 28.0,
base_knockback: 3.0, knockback: 3.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 2.0, ),
angle: 45.0, scaled: Some(Bash(
damage: 2.0,
poise: 28.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 2.0,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 2.5, forward_speed: 2.5,
buildup_duration: 1.2, buildup_duration: 1.2,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -2,11 +2,16 @@ SpinMelee(
buildup_duration: 0.1, buildup_duration: 0.1,
swing_duration: 0.3, swing_duration: 0.3,
recover_duration: 0.1, recover_duration: 0.1,
base_damage: 50.0, melee_constructor: (
base_poise_damage: 30, kind: Bash(
knockback: ( strength: 0.0, direction: Away), damage: 50.0,
range: 7.5, poise: 30.0,
damage_effect: None, knockback: 0.0,
energy_regen: 0.0,
),
range: 7.5,
angle: 360.0,
),
energy_cost: 0, energy_cost: 0,
is_infinite: false, is_infinite: false,
movement_behavior: GolemHover, movement_behavior: GolemHover,
@ -14,6 +19,4 @@ SpinMelee(
forward_speed: 0.0, forward_speed: 0.0,
num_spins: 1, num_spins: 1,
specifier: None, specifier: None,
target: Some(OutOfGroup),
damage_kind: Crushing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 12.0, melee_constructor: (
scaled_damage: 16.0, kind: Bash(
base_poise_damage: 0, damage: 12.0,
scaled_poise_damage: 0, poise: 0.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 17.0, energy_regen: 0.0,
range: 4.0, ),
angle: 45.0, scaled: Some(Bash(
damage: 16.0,
poise: 0.0,
knockback: 17.0,
energy_regen: 0.0,
)),
range: 4.0,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 2.0, forward_speed: 2.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.3, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.6, recover_duration: 0.6,
base_damage: 5.0, melee_constructor: (
base_poise_damage: 0.0, kind: Bash(
knockback: ( strength: 50.0, direction: Towards), damage: 5.0,
range: 5.0, poise: 0.0,
max_angle: 60.0, knockback: 50.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 5.0,
angle: 60.0,
),
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 0, energy_cost: 0,
base_damage: 5.0, melee_constructor: (
scaled_damage: 25.0, kind: Bash(
base_poise_damage: 10, damage: 5.0,
scaled_poise_damage: 40, poise: 10.0,
base_knockback: 10.0, knockback: 10.0,
scaled_knockback: 30.0, energy_regen: 0.0,
range: 5.0, ),
angle: 90.0, scaled: Some(Bash(
damage: 25.0,
poise: 40.0,
knockback: 30.0,
energy_regen: 0.0,
)),
range: 5.0,
angle: 90.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 10.0, forward_speed: 10.0,
buildup_duration: 0.4, buildup_duration: 0.4,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: false, is_interruptible: false,
damage_kind: Crushing,
) )

View File

@ -2,16 +2,16 @@ SpinMelee(
buildup_duration: 0.0, buildup_duration: 0.0,
swing_duration: 0.5, swing_duration: 0.5,
recover_duration: 0.0, recover_duration: 0.0,
base_damage: 40.0, melee_constructor: (
base_poise_damage: 0, kind: Slash(
knockback: ( strength: 50.0, direction: Away), damage: 40.0,
range: 3.5, poise: 0.0,
damage_effect: Some(Buff(( knockback: 50.0,
kind: Bleeding, energy_regen: 0.0,
dur_secs: 10.0, ),
strength: DamageFraction(0.1), range: 3.5,
chance: 0.1, angle: 360.0,
))), ),
energy_cost: 0, energy_cost: 0,
is_infinite: true, is_infinite: true,
movement_behavior: ForwardGround, movement_behavior: ForwardGround,
@ -19,6 +19,4 @@ SpinMelee(
forward_speed: 0.0, forward_speed: 0.0,
num_spins: 1, num_spins: 1,
specifier: None, specifier: None,
target: Some(OutOfGroup),
damage_kind: Slashing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.8, buildup_duration: 0.8,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 1.0, recover_duration: 1.0,
base_damage: 10.0, melee_constructor: (
base_poise_damage: 50, kind: Bash(
knockback: ( strength: 50.0, direction: Away), damage: 10.0,
range: 4.0, poise: 50.0,
max_angle: 20.0, knockback: 50.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 4.0,
angle: 20.0,
),
) )

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.1, buildup_duration: 0.1,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.3, recover_duration: 0.3,
base_damage: 5.0, melee_constructor: (
base_poise_damage: 0, kind: Stab(
knockback: ( strength: 0.0, direction: Away), damage: 5.0,
range: 3.5, poise: 0.0,
max_angle: 20.0, knockback: 0.0,
damage_effect: Some(Buff(( energy_regen: 0.0,
kind: Bleeding, ),
dur_secs: 10.0, range: 3.5,
strength: DamageFraction(0.1), angle: 20.0,
chance: 0.1, ),
))),
damage_kind: Piercing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.0, buildup_duration: 0.0,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.9, recover_duration: 0.9,
base_damage: 2.0, melee_constructor: (
base_poise_damage: 0, kind: Bash(
knockback: ( strength: 0.0, direction: Away), damage: 2.0,
range: 3.5, poise: 0.0,
max_angle: 15.0, knockback: 0.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 3.5,
angle: 15.0,
),
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.6, buildup_duration: 0.6,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.15, recover_duration: 0.15,
base_damage: 5.0, melee_constructor: (
base_poise_damage: 0, kind: Bash(
knockback: ( strength: 0.0, direction: Away), damage: 5.0,
range: 3.5, poise: 0.0,
max_angle: 20.0, knockback: 0.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 3.5,
angle: 20.0,
),
) )

View File

@ -1,17 +1,24 @@
ChargedMelee( ChargedMelee(
energy_cost: 1, energy_cost: 1,
energy_drain: 30.0, energy_drain: 30.0,
initial_damage: 0.0, melee_constructor: (
scaled_damage: 20.0, kind: Bash(
initial_poise_damage: 0, damage: 0.0,
scaled_poise_damage: 30, poise: 0.0,
initial_knockback: 5.0, knockback: 5.0,
scaled_knockback: 20.0, energy_regen: 0.0,
range: 3.5, ),
max_angle: 30.0, scaled: Some(Bash(
damage: 20.0,
poise: 30.0,
knockback: 20.0,
energy_regen: 0.0,
)),
range: 3.5,
angle: 30.0,
),
charge_duration: 1.2, charge_duration: 1.2,
swing_duration: 0.12, swing_duration: 0.12,
hit_timing: 0.2, hit_timing: 0.2,
recover_duration: 0.3, recover_duration: 0.3,
damage_kind: Crushing,
) )

View File

@ -4,12 +4,16 @@ LeapMelee(
movement_duration: 0.8, movement_duration: 0.8,
swing_duration: 0.15, swing_duration: 0.15,
recover_duration: 0.2, recover_duration: 0.2,
base_damage: 25.0, melee_constructor: (
base_poise_damage: 40, kind: Bash(
knockback: 25.0, damage: 25.0,
range: 4.5, poise: 40.0,
max_angle: 360.0, knockback: 25.0,
energy_regen: 0.0,
),
range: 4.5,
angle: 360.0,
),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 8.0, vertical_leap_strength: 8.0,
damage_kind: Crushing,
) )

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.25, buildup_duration: 0.25,
swing_duration: 0.05, swing_duration: 0.05,
recover_duration: 0.075, recover_duration: 0.075,
base_damage: 5.0, melee_constructor: (
base_poise_damage: 0, kind: Stab(
knockback: ( strength: 0.0, direction: Away), damage: 5.0,
range: 4.5, poise: 0.0,
max_angle: 20.0, knockback: 0.0,
damage_effect: Some(Buff(( energy_regen: 0.0,
kind: Bleeding, ),
dur_secs: 10.0, range: 4.5,
strength: DamageFraction(0.1), angle: 20.0,
chance: 0.1, ),
))),
damage_kind: Piercing,
) )

View File

@ -3,11 +3,14 @@ BasicMelee(
buildup_duration: 0.1, buildup_duration: 0.1,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.3, recover_duration: 0.3,
base_damage: 4.0, melee_constructor: (
base_poise_damage: 0, kind: Bash(
knockback: ( strength: 0.0, direction: Away), damage: 4.0,
range: 3.0, poise: 0.0,
max_angle: 120.0, knockback: 0.0,
damage_effect: None, energy_regen: 0.0,
damage_kind: Crushing, ),
range: 3.0,
angle: 90.0,
),
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 10.0, energy_cost: 10.0,
base_damage: 1.0, melee_constructor: (
scaled_damage: 8.0, kind: Stab(
base_poise_damage: 0, damage: 1.0,
scaled_poise_damage: 25, poise: 0.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 3.0, ),
angle: 20.0, scaled: Some(Stab(
damage: 9.0,
poise: 25.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 3.0,
angle: 20.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 2.0, forward_speed: 2.0,
buildup_duration: 0.5, buildup_duration: 0.5,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: true, is_interruptible: true,
damage_kind: Piercing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 10.0, energy_cost: 10.0,
base_damage: 8.0, melee_constructor: (
scaled_damage: 16.0, kind: Stab(
base_poise_damage: 0, damage: 8.0,
scaled_poise_damage: 0, poise: 0.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 4.0, ),
angle: 60.0, scaled: Some(Stab(
damage: 16.0,
poise: 0.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 4.0,
angle: 60.0,
),
energy_drain: 30.0, energy_drain: 30.0,
forward_speed: 3.0, forward_speed: 3.0,
buildup_duration: 0.25, buildup_duration: 0.25,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: true, charge_through: true,
is_interruptible: true, is_interruptible: true,
damage_kind: Piercing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -2,16 +2,16 @@ SpinMelee(
buildup_duration: 0.35, buildup_duration: 0.35,
swing_duration: 0.4, swing_duration: 0.4,
recover_duration: 0.5, recover_duration: 0.5,
base_damage: 12.0, melee_constructor: (
base_poise_damage: 10, kind: Slash(
knockback: ( strength: 10.0, direction: Away), damage: 12.0,
range: 3.5, poise: 10.0,
damage_effect: Some(Buff(( knockback: 10.0,
kind: Bleeding, energy_regen: 0.0,
dur_secs: 10.0, ),
strength: DamageFraction(0.1), range: 3.5,
chance: 0.1, angle: 360.0,
))), ),
energy_cost: 20.0, energy_cost: 20.0,
is_infinite: false, is_infinite: false,
movement_behavior: ForwardGround, movement_behavior: ForwardGround,
@ -19,6 +19,4 @@ SpinMelee(
forward_speed: 1.0, forward_speed: 1.0,
num_spins: 3, num_spins: 3,
specifier: None, specifier: None,
target: Some(OutOfGroup),
damage_kind: Slashing,
) )

View File

@ -1,13 +1,21 @@
DashMelee( DashMelee(
energy_cost: 10.0, energy_cost: 10.0,
base_damage: 9.0, melee_constructor: (
scaled_damage: 16.0, kind: Stab(
base_poise_damage: 40, damage: 9.0,
scaled_poise_damage: 0, poise: 40.0,
base_knockback: 8.0, knockback: 8.0,
scaled_knockback: 7.0, energy_regen: 0.0,
range: 5.0, ),
angle: 45.0, scaled: Some(Stab(
damage: 16.0,
poise: 0.0,
knockback: 7.0,
energy_regen: 0.0,
)),
range: 5.0,
angle: 45.0,
),
energy_drain: 0, energy_drain: 0,
forward_speed: 4.0, forward_speed: 4.0,
buildup_duration: 0.6, buildup_duration: 0.6,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3, ori_modifier: 0.3,
charge_through: false, charge_through: false,
is_interruptible: true, is_interruptible: true,
damage_kind: Piercing,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
) )

View File

@ -1,17 +1,24 @@
ChargedMelee( ChargedMelee(
energy_cost: 1, energy_cost: 1,
energy_drain: 1.0, energy_drain: 1.0,
initial_damage: 1.0, melee_constructor: (
scaled_damage: 0.1, kind: Bash(
initial_poise_damage: 1, damage: 1.0,
scaled_poise_damage: 1, poise: 1.0,
initial_knockback: 30.0, knockback: 30.0,
scaled_knockback: 60.0, energy_regen: 0.0,
range: 5.0, ),
max_angle: 30.0, scaled: Some(Bash(
damage: 0.1,
poise: 1.0,
knockback: 60.0,
energy_regen: 0.0,
)),
range: 5.0,
angle: 30.0,
),
charge_duration: 2.0, charge_duration: 2.0,
swing_duration: 0.1, swing_duration: 0.1,
hit_timing: 0.2, hit_timing: 0.2,
recover_duration: 1.5, recover_duration: 1.5,
damage_kind: Crushing,
) )

View File

@ -11,6 +11,7 @@ use crate::{
slot::EquipSlot, slot::EquipSlot,
Inventory, Inventory,
}, },
melee::{MeleeConstructor, MeleeConstructorKind},
projectile::ProjectileConstructor, projectile::ProjectileConstructor,
skillset::{ skillset::{
skills::{self, Skill, SKILL_MODIFIERS}, skills::{self, Skill, SKILL_MODIFIERS},
@ -392,13 +393,7 @@ pub enum CharacterAbility {
buildup_duration: f32, buildup_duration: f32,
swing_duration: f32, swing_duration: f32,
recover_duration: f32, recover_duration: f32,
base_damage: f32, melee_constructor: MeleeConstructor,
base_poise_damage: f32,
knockback: Knockback,
range: f32,
max_angle: f32,
damage_effect: Option<CombatEffect>,
damage_kind: DamageKind,
}, },
BasicRanged { BasicRanged {
energy_cost: f32, energy_cost: f32,
@ -431,25 +426,16 @@ pub enum CharacterAbility {
}, },
DashMelee { DashMelee {
energy_cost: f32, energy_cost: f32,
base_damage: f32,
scaled_damage: f32,
base_poise_damage: f32,
scaled_poise_damage: f32,
base_knockback: f32,
scaled_knockback: f32,
range: f32,
angle: f32,
energy_drain: f32, energy_drain: f32,
forward_speed: f32, forward_speed: f32,
buildup_duration: f32, buildup_duration: f32,
charge_duration: f32, charge_duration: f32,
swing_duration: f32, swing_duration: f32,
recover_duration: f32, recover_duration: f32,
melee_constructor: MeleeConstructor,
ori_modifier: f32, ori_modifier: f32,
charge_through: bool, charge_through: bool,
is_interruptible: bool, is_interruptible: bool,
damage_kind: DamageKind,
damage_effect: Option<CombatEffect>,
}, },
BasicBlock { BasicBlock {
buildup_duration: f32, buildup_duration: f32,
@ -483,25 +469,14 @@ pub enum CharacterAbility {
movement_duration: f32, movement_duration: f32,
swing_duration: f32, swing_duration: f32,
recover_duration: f32, recover_duration: f32,
base_damage: f32, melee_constructor: MeleeConstructor,
base_poise_damage: f32,
range: f32,
max_angle: f32,
knockback: f32,
forward_leap_strength: f32, forward_leap_strength: f32,
vertical_leap_strength: f32, vertical_leap_strength: f32,
damage_kind: DamageKind,
damage_effect: Option<CombatEffect>,
}, },
SpinMelee { SpinMelee {
buildup_duration: f32, buildup_duration: f32,
swing_duration: f32, swing_duration: f32,
recover_duration: f32, recover_duration: f32,
base_damage: f32,
base_poise_damage: f32,
knockback: Knockback,
range: f32,
damage_effect: Option<CombatEffect>,
energy_cost: f32, energy_cost: f32,
is_infinite: bool, is_infinite: bool,
movement_behavior: spin_melee::MovementBehavior, movement_behavior: spin_melee::MovementBehavior,
@ -509,27 +484,17 @@ pub enum CharacterAbility {
forward_speed: f32, forward_speed: f32,
num_spins: u32, num_spins: u32,
specifier: Option<spin_melee::FrontendSpecifier>, specifier: Option<spin_melee::FrontendSpecifier>,
target: Option<combat::GroupTarget>, melee_constructor: MeleeConstructor,
damage_kind: DamageKind,
}, },
ChargedMelee { ChargedMelee {
energy_cost: f32, energy_cost: f32,
energy_drain: f32, energy_drain: f32,
initial_damage: f32,
scaled_damage: f32,
initial_poise_damage: f32,
scaled_poise_damage: f32,
initial_knockback: f32,
scaled_knockback: f32,
range: f32,
max_angle: f32,
charge_duration: f32, charge_duration: f32,
swing_duration: f32, swing_duration: f32,
hit_timing: f32, hit_timing: f32,
recover_duration: f32, recover_duration: f32,
melee_constructor: MeleeConstructor,
specifier: Option<charged_melee::FrontendSpecifier>, specifier: Option<charged_melee::FrontendSpecifier>,
damage_kind: DamageKind,
damage_effect: Option<CombatEffect>,
}, },
ChargedRanged { ChargedRanged {
energy_cost: f32, energy_cost: f32,
@ -633,16 +598,18 @@ impl Default for CharacterAbility {
buildup_duration: 0.25, buildup_duration: 0.25,
swing_duration: 0.25, swing_duration: 0.25,
recover_duration: 0.5, recover_duration: 0.5,
base_damage: 10.0, melee_constructor: MeleeConstructor {
base_poise_damage: 0.0, kind: MeleeConstructorKind::Slash {
knockback: Knockback { damage: 1.0,
strength: 0.0, knockback: 0.0,
direction: combat::KnockbackDir::Away, poise: 0.0,
energy_regen: 0.0,
},
scaled: None,
range: 3.5,
angle: 15.0,
damage_effect: None,
}, },
range: 3.5,
max_angle: 15.0,
damage_effect: None,
damage_kind: DamageKind::Crushing,
} }
} }
} }
@ -728,30 +695,13 @@ impl CharacterAbility {
ref mut buildup_duration, ref mut buildup_duration,
ref mut swing_duration, ref mut swing_duration,
ref mut recover_duration, ref mut recover_duration,
ref mut base_damage, ref mut melee_constructor,
ref mut base_poise_damage,
knockback: _,
ref mut range,
max_angle: _,
ref mut damage_effect,
damage_kind: _,
} => { } => {
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
*recover_duration /= stats.speed; *recover_duration /= stats.speed;
*base_damage *= stats.power;
*base_poise_damage *= stats.effect_power;
*range *= stats.range;
*energy_cost /= stats.energy_efficiency; *energy_cost /= stats.energy_efficiency;
if let Some(CombatEffect::Buff(combat::CombatBuff { *melee_constructor = melee_constructor.adjusted_by_stats(stats, 1.0);
kind: _,
dur_secs: _,
strength,
chance: _,
})) = damage_effect
{
*strength *= stats.buff_strength;
}
}, },
BasicRanged { BasicRanged {
ref mut energy_cost, ref mut energy_cost,
@ -800,45 +750,23 @@ impl CharacterAbility {
}, },
DashMelee { DashMelee {
ref mut energy_cost, ref mut energy_cost,
ref mut base_damage,
ref mut scaled_damage,
ref mut base_poise_damage,
ref mut scaled_poise_damage,
base_knockback: _,
scaled_knockback: _,
ref mut range,
angle: _,
ref mut energy_drain, ref mut energy_drain,
forward_speed: _, forward_speed: _,
ref mut buildup_duration, ref mut buildup_duration,
charge_duration: _, charge_duration: _,
ref mut swing_duration, ref mut swing_duration,
ref mut recover_duration, ref mut recover_duration,
ref mut melee_constructor,
ori_modifier: _, ori_modifier: _,
charge_through: _, charge_through: _,
is_interruptible: _, is_interruptible: _,
damage_kind: _,
ref mut damage_effect,
} => { } => {
*base_damage *= stats.power;
*scaled_damage *= stats.power;
*base_poise_damage *= stats.effect_power;
*scaled_poise_damage *= stats.effect_power;
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
*recover_duration /= stats.speed; *recover_duration /= stats.speed;
*range *= stats.range;
*energy_cost /= stats.energy_efficiency; *energy_cost /= stats.energy_efficiency;
*energy_drain /= stats.energy_efficiency; *energy_drain /= stats.energy_efficiency;
if let Some(CombatEffect::Buff(combat::CombatBuff { *melee_constructor = melee_constructor.adjusted_by_stats(stats, 1.0);
kind: _,
dur_secs: _,
strength,
chance: _,
})) = damage_effect
{
*strength *= stats.buff_strength;
}
}, },
BasicBlock { BasicBlock {
ref mut buildup_duration, ref mut buildup_duration,
@ -888,106 +816,50 @@ impl CharacterAbility {
movement_duration: _, movement_duration: _,
ref mut swing_duration, ref mut swing_duration,
ref mut recover_duration, ref mut recover_duration,
ref mut base_damage, ref mut melee_constructor,
ref mut base_poise_damage,
ref mut range,
max_angle: _,
knockback: _,
forward_leap_strength: _, forward_leap_strength: _,
vertical_leap_strength: _, vertical_leap_strength: _,
damage_kind: _,
ref mut damage_effect,
} => { } => {
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
*recover_duration /= stats.speed; *recover_duration /= stats.speed;
*base_damage *= stats.power;
*base_poise_damage *= stats.effect_power;
*range *= stats.range;
*energy_cost /= stats.energy_efficiency; *energy_cost /= stats.energy_efficiency;
if let Some(CombatEffect::Buff(combat::CombatBuff { *melee_constructor = melee_constructor.adjusted_by_stats(stats, 1.0);
kind: _,
dur_secs: _,
strength,
chance: _,
})) = damage_effect
{
*strength *= stats.buff_strength;
}
}, },
SpinMelee { SpinMelee {
ref mut buildup_duration, ref mut buildup_duration,
ref mut swing_duration, ref mut swing_duration,
ref mut recover_duration, ref mut recover_duration,
ref mut base_damage,
ref mut base_poise_damage,
knockback: _,
ref mut range,
ref mut damage_effect,
ref mut energy_cost, ref mut energy_cost,
ref mut melee_constructor,
is_infinite: _, is_infinite: _,
movement_behavior: _, movement_behavior: _,
is_interruptible: _, is_interruptible: _,
forward_speed: _, forward_speed: _,
num_spins: _, num_spins: _,
specifier: _, specifier: _,
target: _,
damage_kind: _,
} => { } => {
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
*recover_duration /= stats.speed; *recover_duration /= stats.speed;
*base_damage *= stats.power;
*base_poise_damage *= stats.effect_power;
*range *= stats.range;
*energy_cost /= stats.energy_efficiency; *energy_cost /= stats.energy_efficiency;
if let Some(CombatEffect::Buff(combat::CombatBuff { *melee_constructor = melee_constructor.adjusted_by_stats(stats, 1.0);
kind: _,
dur_secs: _,
strength,
chance: _,
})) = damage_effect
{
*strength *= stats.buff_strength;
}
}, },
ChargedMelee { ChargedMelee {
ref mut energy_cost, ref mut energy_cost,
ref mut energy_drain, ref mut energy_drain,
ref mut initial_damage,
ref mut scaled_damage,
ref mut initial_poise_damage,
ref mut scaled_poise_damage,
initial_knockback: _,
scaled_knockback: _,
ref mut range,
max_angle: _,
charge_duration: _, charge_duration: _,
ref mut swing_duration, ref mut swing_duration,
hit_timing: _, hit_timing: _,
ref mut recover_duration, ref mut recover_duration,
ref mut melee_constructor,
specifier: _, specifier: _,
damage_kind: _,
ref mut damage_effect,
} => { } => {
*initial_damage *= stats.power;
*scaled_damage *= stats.power;
*initial_poise_damage *= stats.effect_power;
*scaled_poise_damage *= stats.effect_power;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
*recover_duration /= stats.speed; *recover_duration /= stats.speed;
*range *= stats.range;
*energy_cost /= stats.energy_efficiency; *energy_cost /= stats.energy_efficiency;
*energy_drain /= stats.energy_efficiency; *energy_drain /= stats.energy_efficiency;
if let Some(CombatEffect::Buff(combat::CombatBuff { *melee_constructor = melee_constructor.adjusted_by_stats(stats, 1.0);
kind: _,
dur_secs: _,
strength,
chance: _,
})) = damage_effect
{
*strength *= stats.buff_strength;
}
}, },
ChargedRanged { ChargedRanged {
ref mut energy_cost, ref mut energy_cost,
@ -1266,9 +1138,7 @@ impl CharacterAbility {
} }
} }
#[warn(clippy::pedantic)]
fn adjusted_by_sword_skills(&mut self, skillset: &SkillSet) { fn adjusted_by_sword_skills(&mut self, skillset: &SkillSet) {
#![allow(clippy::enum_glob_use)]
use skills::{Skill::Sword, SwordSkill::*}; use skills::{Skill::Sword, SwordSkill::*};
match self { match self {
@ -1307,10 +1177,9 @@ impl CharacterAbility {
ref mut is_interruptible, ref mut is_interruptible,
ref mut energy_cost, ref mut energy_cost,
ref mut energy_drain, ref mut energy_drain,
ref mut base_damage,
ref mut scaled_damage,
ref mut forward_speed, ref mut forward_speed,
ref mut charge_through, ref mut charge_through,
ref mut melee_constructor,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.sword_tree.dash; let modifiers = SKILL_MODIFIERS.sword_tree.dash;
@ -1321,11 +1190,17 @@ impl CharacterAbility {
if let Ok(level) = skillset.skill_level(Sword(DDrain)) { if let Ok(level) = skillset.skill_level(Sword(DDrain)) {
*energy_drain *= modifiers.energy_drain.powi(level.into()); *energy_drain *= modifiers.energy_drain.powi(level.into());
} }
if let Ok(level) = skillset.skill_level(Sword(DDamage)) { if let MeleeConstructorKind::Slash { ref mut damage, .. } = melee_constructor.kind {
*base_damage *= modifiers.base_damage.powi(level.into()); if let Ok(level) = skillset.skill_level(Sword(DDamage)) {
*damage *= modifiers.base_damage.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Sword(DScaling)) { if let Some(MeleeConstructorKind::Slash { ref mut damage, .. }) =
*scaled_damage *= modifiers.scaled_damage.powi(level.into()); melee_constructor.scaled
{
if let Ok(level) = skillset.skill_level(Sword(DScaling)) {
*damage *= modifiers.scaled_damage.powi(level.into());
}
} }
if skillset.has_skill(Sword(DSpeed)) { if skillset.has_skill(Sword(DSpeed)) {
*forward_speed *= modifiers.forward_speed; *forward_speed *= modifiers.forward_speed;
@ -1334,16 +1209,18 @@ impl CharacterAbility {
}, },
CharacterAbility::SpinMelee { CharacterAbility::SpinMelee {
ref mut is_interruptible, ref mut is_interruptible,
ref mut base_damage,
ref mut swing_duration, ref mut swing_duration,
ref mut energy_cost, ref mut energy_cost,
ref mut num_spins, ref mut num_spins,
ref mut melee_constructor,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.sword_tree.spin; let modifiers = SKILL_MODIFIERS.sword_tree.spin;
*is_interruptible = skillset.has_skill(Sword(InterruptingAttacks)); *is_interruptible = skillset.has_skill(Sword(InterruptingAttacks));
if let Ok(level) = skillset.skill_level(Sword(SDamage)) { if let MeleeConstructorKind::Slash { ref mut damage, .. } = melee_constructor.kind {
*base_damage *= modifiers.base_damage.powi(level.into()); if let Ok(level) = skillset.skill_level(Sword(SDamage)) {
*damage *= modifiers.base_damage.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Sword(SSpeed)) { if let Ok(level) = skillset.skill_level(Sword(SSpeed)) {
*swing_duration *= modifiers.swing_duration.powi(level.into()); *swing_duration *= modifiers.swing_duration.powi(level.into());
@ -1391,11 +1268,11 @@ impl CharacterAbility {
*scales_from_combo = skillset.skill_level(Axe(DsDamage)).unwrap_or(0).into(); *scales_from_combo = skillset.skill_level(Axe(DsDamage)).unwrap_or(0).into();
}, },
CharacterAbility::SpinMelee { CharacterAbility::SpinMelee {
ref mut base_damage,
ref mut swing_duration, ref mut swing_duration,
ref mut energy_cost, ref mut energy_cost,
ref mut is_infinite, ref mut is_infinite,
ref mut movement_behavior, ref mut movement_behavior,
ref mut melee_constructor,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.axe_tree.spin; let modifiers = SKILL_MODIFIERS.axe_tree.spin;
@ -1406,8 +1283,10 @@ impl CharacterAbility {
} else { } else {
spin_melee::MovementBehavior::ForwardGround spin_melee::MovementBehavior::ForwardGround
}; };
if let Ok(level) = skillset.skill_level(Axe(SDamage)) { if let MeleeConstructorKind::Slash { ref mut damage, .. } = melee_constructor.kind {
*base_damage *= modifiers.base_damage.powi(level.into()); if let Ok(level) = skillset.skill_level(Axe(SDamage)) {
*damage *= modifiers.base_damage.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Axe(SSpeed)) { if let Ok(level) = skillset.skill_level(Axe(SSpeed)) {
*swing_duration *= modifiers.swing_duration.powi(level.into()); *swing_duration *= modifiers.swing_duration.powi(level.into());
@ -1417,19 +1296,25 @@ impl CharacterAbility {
} }
}, },
CharacterAbility::LeapMelee { CharacterAbility::LeapMelee {
ref mut base_damage, ref mut melee_constructor,
ref mut knockback,
ref mut energy_cost, ref mut energy_cost,
ref mut forward_leap_strength, ref mut forward_leap_strength,
ref mut vertical_leap_strength, ref mut vertical_leap_strength,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.axe_tree.leap; let modifiers = SKILL_MODIFIERS.axe_tree.leap;
if let Ok(level) = skillset.skill_level(Axe(LDamage)) { if let MeleeConstructorKind::Slash {
*base_damage *= modifiers.base_damage.powi(level.into()); ref mut damage,
} ref mut knockback,
if let Ok(level) = skillset.skill_level(Axe(LKnockback)) { ..
*knockback *= modifiers.knockback.powi(level.into()); } = melee_constructor.kind
{
if let Ok(level) = skillset.skill_level(Axe(LDamage)) {
*damage *= modifiers.base_damage.powi(level.into());
}
if let Ok(level) = skillset.skill_level(Axe(LKnockback)) {
*knockback *= modifiers.knockback.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Axe(LCost)) { if let Ok(level) = skillset.skill_level(Axe(LCost)) {
*energy_cost *= modifiers.energy_cost.powi(level.into()); *energy_cost *= modifiers.energy_cost.powi(level.into());
@ -1482,19 +1367,25 @@ impl CharacterAbility {
*scales_from_combo = skillset.skill_level(Hammer(SsDamage)).unwrap_or(0).into(); *scales_from_combo = skillset.skill_level(Hammer(SsDamage)).unwrap_or(0).into();
}, },
CharacterAbility::ChargedMelee { CharacterAbility::ChargedMelee {
ref mut scaled_damage,
ref mut scaled_knockback,
ref mut energy_drain, ref mut energy_drain,
ref mut charge_duration, ref mut charge_duration,
ref mut melee_constructor,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.hammer_tree.charged; let modifiers = SKILL_MODIFIERS.hammer_tree.charged;
if let Ok(level) = skillset.skill_level(Hammer(CDamage)) { if let Some(MeleeConstructorKind::Bash {
*scaled_damage *= modifiers.scaled_damage.powi(level.into()); ref mut damage,
} ref mut knockback,
if let Ok(level) = skillset.skill_level(Hammer(CKnockback)) { ..
*scaled_knockback *= modifiers.scaled_knockback.powi(level.into()); }) = melee_constructor.scaled
{
if let Ok(level) = skillset.skill_level(Hammer(CDamage)) {
*damage *= modifiers.scaled_damage.powi(level.into());
}
if let Ok(level) = skillset.skill_level(Hammer(CKnockback)) {
*knockback *= modifiers.scaled_knockback.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Hammer(CDrain)) { if let Ok(level) = skillset.skill_level(Hammer(CDrain)) {
*energy_drain *= modifiers.energy_drain.powi(level.into()); *energy_drain *= modifiers.energy_drain.powi(level.into());
@ -1505,20 +1396,25 @@ impl CharacterAbility {
} }
}, },
CharacterAbility::LeapMelee { CharacterAbility::LeapMelee {
ref mut base_damage,
ref mut knockback,
ref mut energy_cost, ref mut energy_cost,
ref mut forward_leap_strength, ref mut forward_leap_strength,
ref mut vertical_leap_strength, ref mut vertical_leap_strength,
ref mut range, ref mut melee_constructor,
.. ..
} => { } => {
let modifiers = SKILL_MODIFIERS.hammer_tree.leap; let modifiers = SKILL_MODIFIERS.hammer_tree.leap;
if let Ok(level) = skillset.skill_level(Hammer(LDamage)) { if let MeleeConstructorKind::Bash {
*base_damage *= modifiers.base_damage.powi(level.into()); ref mut damage,
} ref mut knockback,
if let Ok(level) = skillset.skill_level(Hammer(LKnockback)) { ..
*knockback *= modifiers.knockback.powi(level.into()); } = melee_constructor.kind
{
if let Ok(level) = skillset.skill_level(Hammer(LDamage)) {
*damage *= modifiers.base_damage.powi(level.into());
}
if let Ok(level) = skillset.skill_level(Hammer(LKnockback)) {
*knockback *= modifiers.knockback.powi(level.into());
}
} }
if let Ok(level) = skillset.skill_level(Hammer(LCost)) { if let Ok(level) = skillset.skill_level(Hammer(LCost)) {
*energy_cost *= modifiers.energy_cost.powi(level.into()); *energy_cost *= modifiers.energy_cost.powi(level.into());
@ -1529,7 +1425,7 @@ impl CharacterAbility {
*vertical_leap_strength *= strength.powi(level.into()); *vertical_leap_strength *= strength.powi(level.into());
} }
if let Ok(level) = skillset.skill_level(Hammer(LRange)) { if let Ok(level) = skillset.skill_level(Hammer(LRange)) {
*range += modifiers.range * f32::from(level); melee_constructor.range += modifiers.range * f32::from(level);
} }
}, },
_ => {}, _ => {},
@ -1798,27 +1694,15 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
buildup_duration, buildup_duration,
swing_duration, swing_duration,
recover_duration, recover_duration,
base_damage, melee_constructor,
base_poise_damage,
knockback,
range,
max_angle,
damage_effect,
energy_cost: _, energy_cost: _,
damage_kind,
} => CharacterState::BasicMelee(basic_melee::Data { } => CharacterState::BasicMelee(basic_melee::Data {
static_data: basic_melee::StaticData { static_data: basic_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration), buildup_duration: Duration::from_secs_f32(*buildup_duration),
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
base_damage: *base_damage, melee_constructor: *melee_constructor,
base_poise_damage: *base_poise_damage,
knockback: *knockback,
range: *range,
max_angle: *max_angle,
damage_effect: *damage_effect,
ability_info, ability_info,
damage_kind: *damage_kind,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1867,35 +1751,18 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
}), }),
CharacterAbility::DashMelee { CharacterAbility::DashMelee {
energy_cost: _, energy_cost: _,
base_damage,
scaled_damage,
base_poise_damage,
scaled_poise_damage,
base_knockback,
scaled_knockback,
range,
angle,
energy_drain, energy_drain,
forward_speed, forward_speed,
buildup_duration, buildup_duration,
charge_duration, charge_duration,
swing_duration, swing_duration,
recover_duration, recover_duration,
melee_constructor,
ori_modifier, ori_modifier,
charge_through, charge_through,
is_interruptible, is_interruptible,
damage_kind,
damage_effect,
} => CharacterState::DashMelee(dash_melee::Data { } => CharacterState::DashMelee(dash_melee::Data {
static_data: dash_melee::StaticData { static_data: dash_melee::StaticData {
base_damage: *base_damage,
scaled_damage: *scaled_damage,
base_poise_damage: *base_poise_damage,
scaled_poise_damage: *scaled_poise_damage,
base_knockback: *base_knockback,
scaled_knockback: *scaled_knockback,
range: *range,
angle: *angle,
energy_drain: *energy_drain, energy_drain: *energy_drain,
forward_speed: *forward_speed, forward_speed: *forward_speed,
charge_through: *charge_through, charge_through: *charge_through,
@ -1903,11 +1770,10 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
charge_duration: Duration::from_secs_f32(*charge_duration), charge_duration: Duration::from_secs_f32(*charge_duration),
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
melee_constructor: *melee_constructor,
ori_modifier: *ori_modifier, ori_modifier: *ori_modifier,
is_interruptible: *is_interruptible, is_interruptible: *is_interruptible,
damage_effect: *damage_effect,
ability_info, ability_info,
damage_kind: *damage_kind,
}, },
auto_charge: false, auto_charge: false,
timer: Duration::default(), timer: Duration::default(),
@ -1990,31 +1856,19 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
movement_duration, movement_duration,
swing_duration, swing_duration,
recover_duration, recover_duration,
base_damage, melee_constructor,
base_poise_damage,
knockback,
range,
max_angle,
forward_leap_strength, forward_leap_strength,
vertical_leap_strength, vertical_leap_strength,
damage_kind,
damage_effect,
} => CharacterState::LeapMelee(leap_melee::Data { } => CharacterState::LeapMelee(leap_melee::Data {
static_data: leap_melee::StaticData { static_data: leap_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration), buildup_duration: Duration::from_secs_f32(*buildup_duration),
movement_duration: Duration::from_secs_f32(*movement_duration), movement_duration: Duration::from_secs_f32(*movement_duration),
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
base_damage: *base_damage, melee_constructor: *melee_constructor,
base_poise_damage: *base_poise_damage,
knockback: *knockback,
range: *range,
max_angle: *max_angle,
forward_leap_strength: *forward_leap_strength, forward_leap_strength: *forward_leap_strength,
vertical_leap_strength: *vertical_leap_strength, vertical_leap_strength: *vertical_leap_strength,
damage_effect: *damage_effect,
ability_info, ability_info,
damage_kind: *damage_kind,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -2024,11 +1878,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
buildup_duration, buildup_duration,
swing_duration, swing_duration,
recover_duration, recover_duration,
base_damage, melee_constructor,
base_poise_damage,
knockback,
range,
damage_effect,
energy_cost, energy_cost,
is_infinite, is_infinite,
movement_behavior, movement_behavior,
@ -2036,28 +1886,20 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
forward_speed, forward_speed,
num_spins, num_spins,
specifier, specifier,
target,
damage_kind,
} => CharacterState::SpinMelee(spin_melee::Data { } => CharacterState::SpinMelee(spin_melee::Data {
static_data: spin_melee::StaticData { static_data: spin_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration), buildup_duration: Duration::from_secs_f32(*buildup_duration),
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
base_damage: *base_damage, melee_constructor: *melee_constructor,
base_poise_damage: *base_poise_damage,
knockback: *knockback,
range: *range,
damage_effect: *damage_effect,
energy_cost: *energy_cost, energy_cost: *energy_cost,
is_infinite: *is_infinite, is_infinite: *is_infinite,
movement_behavior: *movement_behavior, movement_behavior: *movement_behavior,
is_interruptible: *is_interruptible, is_interruptible: *is_interruptible,
forward_speed: *forward_speed, forward_speed: *forward_speed,
num_spins: *num_spins, num_spins: *num_spins,
target: *target,
ability_info, ability_info,
specifier: *specifier, specifier: *specifier,
damage_kind: *damage_kind,
}, },
timer: Duration::default(), timer: Duration::default(),
consecutive_spins: 1, consecutive_spins: 1,
@ -2067,41 +1909,23 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
CharacterAbility::ChargedMelee { CharacterAbility::ChargedMelee {
energy_cost, energy_cost,
energy_drain, energy_drain,
initial_damage,
scaled_damage,
initial_poise_damage,
scaled_poise_damage,
initial_knockback,
scaled_knockback,
charge_duration, charge_duration,
swing_duration, swing_duration,
hit_timing, hit_timing,
recover_duration, recover_duration,
range, melee_constructor,
max_angle,
specifier, specifier,
damage_kind,
damage_effect,
} => CharacterState::ChargedMelee(charged_melee::Data { } => CharacterState::ChargedMelee(charged_melee::Data {
static_data: charged_melee::StaticData { static_data: charged_melee::StaticData {
energy_cost: *energy_cost, energy_cost: *energy_cost,
energy_drain: *energy_drain, energy_drain: *energy_drain,
initial_damage: *initial_damage,
scaled_damage: *scaled_damage,
initial_poise_damage: *initial_poise_damage,
scaled_poise_damage: *scaled_poise_damage,
initial_knockback: *initial_knockback,
scaled_knockback: *scaled_knockback,
range: *range,
max_angle: *max_angle,
charge_duration: Duration::from_secs_f32(*charge_duration), charge_duration: Duration::from_secs_f32(*charge_duration),
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
hit_timing: *hit_timing, hit_timing: *hit_timing,
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
damage_effect: *damage_effect, melee_constructor: *melee_constructor,
ability_info, ability_info,
specifier: *specifier, specifier: *specifier,
damage_kind: *damage_kind,
}, },
stage_section: StageSection::Charge, stage_section: StageSection::Charge,
timer: Duration::default(), timer: Duration::default(),

View File

@ -1,8 +1,6 @@
use crate::{ use crate::{
combat::Attack,
comp::{ comp::{
item::ConsumableKind, tool::ToolKind, ControlAction, Density, Energy, InputAttr, InputKind, item::ConsumableKind, ControlAction, Density, Energy, InputAttr, InputKind, Ori, Pos, Vel,
Ori, Pos, Vel,
}, },
event::{LocalEvent, ServerEvent}, event::{LocalEvent, ServerEvent},
states::{ states::{
@ -13,11 +11,10 @@ use crate::{
}, },
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage, VecStorage}; use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use strum_macros::Display; use strum_macros::Display;
use vek::*;
/// Data returned from character behavior fn's to Character Behavior System. /// Data returned from character behavior fn's to Character Behavior System.
pub struct StateUpdate { pub struct StateUpdate {
@ -385,17 +382,3 @@ impl Default for CharacterState {
impl Component for CharacterState { impl Component for CharacterState {
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>; type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
} }
#[derive(Debug, Serialize, Deserialize)]
pub struct Melee {
pub attack: Attack,
pub range: f32,
pub max_angle: f32,
pub applied: bool,
pub hit_count: u32,
pub break_block: Option<(Vec3<i32>, Option<ToolKind>)>,
}
impl Component for Melee {
type Storage = VecStorage<Self>;
}

432
common/src/comp/melee.rs Normal file
View File

@ -0,0 +1,432 @@
use crate::{
combat::{
self, Attack, AttackDamage, AttackEffect, CombatBuff, CombatBuffStrength, CombatEffect,
CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
},
comp::{
buff::BuffKind,
tool::{Stats, ToolKind},
},
};
use common_base::dev_panic;
use serde::{Deserialize, Serialize};
use specs::{Component, VecStorage};
use vek::*;
#[derive(Debug, Serialize, Deserialize)]
pub struct Melee {
pub attack: Attack,
pub range: f32,
pub max_angle: f32,
pub applied: bool,
pub hit_count: u32,
pub break_block: Option<(Vec3<i32>, Option<ToolKind>)>,
}
impl Melee {
#[must_use]
pub fn with_block_breaking(
mut self,
break_block: Option<(Vec3<i32>, Option<ToolKind>)>,
) -> Self {
self.break_block = break_block;
self
}
}
impl Component for Melee {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MeleeConstructor {
pub kind: MeleeConstructorKind,
// This multiplied by a fraction is added to what is specified in kind
pub scaled: Option<MeleeConstructorKind>,
pub range: f32,
pub angle: f32,
pub damage_effect: Option<CombatEffect>,
}
impl MeleeConstructor {
pub fn create_melee(self, (crit_chance, crit_mult): (f32, f32), buff_strength: f32) -> Melee {
use MeleeConstructorKind::*;
if self.scaled.is_some() {
dev_panic!(
"Attempted to create a melee attack that had a provided scaled value without \
scaling the melee attack."
)
}
let attack = match self.kind {
Slash {
damage,
poise,
knockback,
energy_regen,
} => {
let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen))
.with_requirement(CombatRequirement::AnyDamage);
let buff = CombatEffect::Buff(CombatBuff {
kind: BuffKind::Bleeding,
dur_secs: 10.0,
strength: CombatBuffStrength::DamageFraction(0.1 * buff_strength),
chance: 0.1,
});
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: DamageKind::Slashing,
value: damage,
},
Some(GroupTarget::OutOfGroup),
)
.with_effect(buff);
if let Some(damage_effect) = self.damage_effect {
damage = damage.with_effect(damage_effect);
}
let poise =
AttackEffect::new(Some(GroupTarget::OutOfGroup), CombatEffect::Poise(poise))
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(energy)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment()
},
Stab {
damage,
poise,
knockback,
energy_regen,
} => {
let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen))
.with_requirement(CombatRequirement::AnyDamage);
let buff = CombatEffect::Buff(CombatBuff {
kind: BuffKind::Bleeding,
dur_secs: 5.0,
strength: CombatBuffStrength::DamageFraction(0.05 * buff_strength),
chance: 0.1,
});
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: DamageKind::Piercing,
value: damage,
},
Some(GroupTarget::OutOfGroup),
)
.with_effect(buff);
if let Some(damage_effect) = self.damage_effect {
damage = damage.with_effect(damage_effect);
}
let poise =
AttackEffect::new(Some(GroupTarget::OutOfGroup), CombatEffect::Poise(poise))
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(energy)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment()
},
Bash {
damage,
poise,
knockback,
energy_regen,
} => {
let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen))
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: DamageKind::Crushing,
value: damage,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(damage_effect) = self.damage_effect {
damage = damage.with_effect(damage_effect);
}
let poise =
AttackEffect::new(Some(GroupTarget::OutOfGroup), CombatEffect::Poise(poise))
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(energy)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment()
},
NecroticVortex {
damage,
pull,
lifesteal,
} => {
let lifesteal = CombatEffect::Lifesteal(lifesteal);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: DamageKind::Energy,
value: damage,
},
None,
)
.with_effect(lifesteal);
if let Some(damage_effect) = self.damage_effect {
damage = damage.with_effect(damage_effect);
}
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: pull,
direction: KnockbackDir::Towards,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(knockback)
.with_combo_increment()
},
};
Melee {
attack,
range: self.range,
max_angle: self.angle.to_radians(),
applied: false,
hit_count: 0,
break_block: None,
}
}
#[must_use]
pub fn handle_scaling(mut self, scaling: f32) -> Self {
let scale_values = |a, b| a + b * scaling;
if let Some(max_scale) = self.scaled {
use MeleeConstructorKind::*;
let scaled = match (self.kind, max_scale) {
(
Slash {
damage: a_damage,
poise: a_poise,
knockback: a_knockback,
energy_regen: a_energy_regen,
},
Slash {
damage: b_damage,
poise: b_poise,
knockback: b_knockback,
energy_regen: b_energy_regen,
},
) => Slash {
damage: scale_values(a_damage, b_damage),
poise: scale_values(a_poise, b_poise),
knockback: scale_values(a_knockback, b_knockback),
energy_regen: scale_values(a_energy_regen, b_energy_regen),
},
(
Stab {
damage: a_damage,
poise: a_poise,
knockback: a_knockback,
energy_regen: a_energy_regen,
},
Stab {
damage: b_damage,
poise: b_poise,
knockback: b_knockback,
energy_regen: b_energy_regen,
},
) => Stab {
damage: scale_values(a_damage, b_damage),
poise: scale_values(a_poise, b_poise),
knockback: scale_values(a_knockback, b_knockback),
energy_regen: scale_values(a_energy_regen, b_energy_regen),
},
(
Bash {
damage: a_damage,
poise: a_poise,
knockback: a_knockback,
energy_regen: a_energy_regen,
},
Bash {
damage: b_damage,
poise: b_poise,
knockback: b_knockback,
energy_regen: b_energy_regen,
},
) => Bash {
damage: scale_values(a_damage, b_damage),
poise: scale_values(a_poise, b_poise),
knockback: scale_values(a_knockback, b_knockback),
energy_regen: scale_values(a_energy_regen, b_energy_regen),
},
(
NecroticVortex {
damage: a_damage,
pull: a_pull,
lifesteal: a_lifesteal,
},
NecroticVortex {
damage: b_damage,
pull: b_pull,
lifesteal: b_lifesteal,
},
) => NecroticVortex {
damage: scale_values(a_damage, b_damage),
pull: scale_values(a_pull, b_pull),
lifesteal: scale_values(a_lifesteal, b_lifesteal),
},
_ => {
dev_panic!(
"Attempted to scale on a melee attack between two different kinds of \
melee constructors."
);
self.kind
},
};
self.kind = scaled;
self.scaled = None;
} else {
dev_panic!("Attempted to scale on a melee attack that had no provided scaling value.")
}
self
}
#[must_use]
pub fn adjusted_by_stats(mut self, stats: Stats, regen: f32) -> Self {
self.range *= stats.range;
self.kind = self.kind.adjusted_by_stats(stats, regen);
if let Some(ref mut scaled) = &mut self.scaled {
*scaled = scaled.adjusted_by_stats(stats, regen);
}
if let Some(CombatEffect::Buff(combat::CombatBuff { strength, .. })) =
&mut self.damage_effect
{
*strength *= stats.buff_strength;
}
self
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
// TODO: Get someone not me to name these variants
pub enum MeleeConstructorKind {
Slash {
damage: f32,
poise: f32,
knockback: f32,
energy_regen: f32,
},
Stab {
damage: f32,
poise: f32,
knockback: f32,
energy_regen: f32,
},
Bash {
damage: f32,
poise: f32,
knockback: f32,
energy_regen: f32,
},
NecroticVortex {
damage: f32,
pull: f32,
lifesteal: f32,
},
}
impl MeleeConstructorKind {
#[must_use]
pub fn adjusted_by_stats(mut self, stats: Stats, regen: f32) -> Self {
use MeleeConstructorKind::*;
match self {
Slash {
ref mut damage,
ref mut poise,
knockback: _,
ref mut energy_regen,
} => {
*damage *= stats.power;
*poise *= stats.effect_power;
*energy_regen *= regen;
},
Stab {
ref mut damage,
ref mut poise,
knockback: _,
ref mut energy_regen,
} => {
*damage *= stats.power;
*poise *= stats.effect_power;
*energy_regen *= regen;
},
Bash {
ref mut damage,
ref mut poise,
knockback: _,
ref mut energy_regen,
} => {
*damage *= stats.power;
*poise *= stats.effect_power;
*energy_regen *= regen;
},
NecroticVortex {
ref mut damage,
pull: _,
lifesteal: _,
} => {
*damage *= stats.power;
},
}
self
}
}

View File

@ -29,6 +29,7 @@ pub mod inventory;
pub mod invite; pub mod invite;
#[cfg(not(target_arch = "wasm32"))] mod last; #[cfg(not(target_arch = "wasm32"))] mod last;
#[cfg(not(target_arch = "wasm32"))] mod location; #[cfg(not(target_arch = "wasm32"))] mod location;
#[cfg(not(target_arch = "wasm32"))] pub mod melee;
#[cfg(not(target_arch = "wasm32"))] mod misc; #[cfg(not(target_arch = "wasm32"))] mod misc;
#[cfg(not(target_arch = "wasm32"))] pub mod ori; #[cfg(not(target_arch = "wasm32"))] pub mod ori;
#[cfg(not(target_arch = "wasm32"))] pub mod pet; #[cfg(not(target_arch = "wasm32"))] pub mod pet;
@ -66,7 +67,7 @@ pub use self::{
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs, Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,
ModifierKind, ModifierKind,
}, },
character_state::{CharacterState, Melee, StateUpdate}, character_state::{CharacterState, StateUpdate},
chat::{ chat::{
ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg, ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,
}, },
@ -89,6 +90,7 @@ pub use self::{
}, },
last::Last, last::Last,
location::{Waypoint, WaypointArea}, location::{Waypoint, WaypointArea},
melee::{Melee, MeleeConstructor},
misc::Object, misc::Object,
ori::Ori, ori::Ori,
pet::Pet, pet::Pet,

View File

@ -1,9 +1,8 @@
use crate::{ use crate::{
combat::{ comp::{
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, MeleeConstructor,
DamageSource, GroupTarget, Knockback, StateUpdate,
}, },
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
states::{ states::{
behavior::{CharacterBehavior, JoinData}, behavior::{CharacterBehavior, JoinData},
utils::*, utils::*,
@ -22,22 +21,10 @@ pub struct StaticData {
pub swing_duration: Duration, pub swing_duration: Duration,
/// How long the state has until exiting /// How long the state has until exiting
pub recover_duration: Duration, pub recover_duration: Duration,
/// Base damage /// Used to construct the Melee attack
pub base_damage: f32, pub melee_constructor: MeleeConstructor,
/// Base poise reduction
pub base_poise_damage: f32,
/// Knockback
pub knockback: Knockback,
/// Max range
pub range: f32,
/// Max angle (45.0 will give you a 90.0 angle window)
pub max_angle: f32,
/// Adds an effect onto the main damage of the attack
pub damage_effect: Option<CombatEffect>,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// Which kind of damage does this attack deal
pub damage_kind: DamageKind,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -86,57 +73,26 @@ impl CharacterBehavior for Data {
..*self ..*self
}); });
let poise = AttackEffect::new( let crit_data = get_crit_data(data, self.static_data.ability_info);
Some(GroupTarget::OutOfGroup), let buff_strength = get_buff_strength(data, self.static_data.ability_info);
CombatEffect::Poise(self.static_data.base_poise_damage as f32),
)
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(self.static_data.knockback),
)
.with_requirement(CombatRequirement::AnyDamage);
let energy = AttackEffect::new(None, CombatEffect::EnergyReward(50.0))
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.base_damage as f32,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(energy)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
// Hit attempt data.updater.insert(
data.updater.insert(data.entity, Melee { data.entity,
attack, self.static_data
range: self.static_data.range, .melee_constructor
max_angle: self.static_data.max_angle, .create_melee(crit_data, buff_strength)
applied: false, .with_block_breaking(
hit_count: 0, data.inputs
break_block: data .break_block_pos
.inputs .map(|p| {
.break_block_pos (
.map(|p| { p.map(|e| e.floor() as i32),
( self.static_data.ability_info.tool,
p.map(|e| e.floor() as i32), )
self.static_data.ability_info.tool, })
) .filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
}) ),
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)), );
});
} else if self.timer < self.static_data.swing_duration { } else if self.timer < self.static_data.swing_duration {
// Swings // Swings
update.character = CharacterState::BasicMelee(Data { update.character = CharacterState::BasicMelee(Data {

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
event::LocalEvent, event::LocalEvent,
outcome::Outcome, outcome::Outcome,
states::{ states::{
@ -8,7 +7,6 @@ use crate::{
utils::{StageSection, *}, utils::{StageSection, *},
wielding, wielding,
}, },
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
@ -20,22 +18,6 @@ pub struct StaticData {
pub energy_drain: f32, pub energy_drain: f32,
/// Energy cost per attack /// Energy cost per attack
pub energy_cost: f32, pub energy_cost: f32,
/// How much damage is dealt with no charge
pub initial_damage: f32,
/// How much the damage is scaled by
pub scaled_damage: f32,
/// How much poise damage is dealt with no charge
pub initial_poise_damage: f32,
/// How much poise damage is scaled by
pub scaled_poise_damage: f32,
/// How much knockback there is with no charge
pub initial_knockback: f32,
/// How much the knockback is scaled by
pub scaled_knockback: f32,
/// Max range
pub range: f32,
/// Max angle (45.0 will give you a 90.0 angle window)
pub max_angle: f32,
/// How long it takes to charge the weapon to max damage and knockback /// How long it takes to charge the weapon to max damage and knockback
pub charge_duration: Duration, pub charge_duration: Duration,
/// How long the weapon is swinging for /// How long the weapon is swinging for
@ -44,14 +26,12 @@ pub struct StaticData {
pub hit_timing: f32, pub hit_timing: f32,
/// How long the state has until exiting /// How long the state has until exiting
pub recover_duration: Duration, pub recover_duration: Duration,
/// Adds an effect onto the main damage of the attack /// Used to construct the Melee attack
pub damage_effect: Option<CombatEffect>, pub melee_constructor: MeleeConstructor,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// Used to specify the melee attack to the frontend /// Used to specify the melee attack to the frontend
pub specifier: Option<FrontendSpecifier>, pub specifier: Option<FrontendSpecifier>,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -132,69 +112,25 @@ impl CharacterBehavior for Data {
exhausted: true, exhausted: true,
..*self ..*self
}); });
let poise = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Poise(
self.static_data.initial_poise_damage as f32
+ self.charge_amount * self.static_data.scaled_poise_damage as f32,
),
)
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: self.static_data.initial_knockback
+ self.charge_amount * self.static_data.scaled_knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.initial_damage as f32
+ self.charge_amount * self.static_data.scaled_damage as f32,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
// Hit attempt let crit_data = get_crit_data(data, self.static_data.ability_info);
data.updater.insert(data.entity, Melee { let buff_strength = get_buff_strength(data, self.static_data.ability_info);
attack,
range: self.static_data.range, data.updater.insert(
max_angle: self.static_data.max_angle.to_radians(), data.entity,
applied: false, self.static_data
hit_count: 0, .melee_constructor
break_block: data .handle_scaling(self.charge_amount)
.inputs .create_melee(crit_data, buff_strength),
.break_block_pos );
.map(|p| {
(
p.map(|e| e.floor() as i32),
self.static_data.ability_info.tool,
)
})
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
});
if let Some(FrontendSpecifier::GroundCleave) = self.static_data.specifier { if let Some(FrontendSpecifier::GroundCleave) = self.static_data.specifier {
// Send local event used for frontend shenanigans // Send local event used for frontend shenanigans
output_events.emit_local(LocalEvent::CreateOutcome(Outcome::GroundSlam { output_events.emit_local(LocalEvent::CreateOutcome(Outcome::GroundSlam {
pos: data.pos.0 pos: data.pos.0
+ *data.ori.look_dir() + *data.ori.look_dir()
* (data.body.max_radius() + self.static_data.range), * (data.body.max_radius()
+ self.static_data.melee_constructor.range),
})); }));
} }
} else if self.timer < self.static_data.swing_duration { } else if self.timer < self.static_data.swing_duration {

View File

@ -109,6 +109,8 @@ impl Stage<f32> {
} }
} }
// TODO: Completely rewrite this with skill tree rework. Don't bother converting
// to melee constructor.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
/// Separated out to condense update portions of character state /// Separated out to condense update portions of character state
pub struct StaticData { pub struct StaticData {

View File

@ -1,12 +1,10 @@
use crate::{ use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
states::{ states::{
behavior::{CharacterBehavior, JoinData}, behavior::{CharacterBehavior, JoinData},
utils::*, utils::*,
wielding, wielding,
}, },
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
@ -14,22 +12,6 @@ use std::time::Duration;
/// Separated out to condense update portions of character state /// Separated out to condense update portions of character state
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StaticData { pub struct StaticData {
/// How much damage the attack initially does
pub base_damage: f32,
/// How much the attack scales in damage
pub scaled_damage: f32,
/// Initial poise damage
pub base_poise_damage: f32,
/// How much the attac scales in poise damage
pub scaled_poise_damage: f32,
/// How much the attack knocks the target back initially
pub base_knockback: f32,
/// How much the attack scales in knockback
pub scaled_knockback: f32,
/// Range of the attack
pub range: f32,
/// Angle of the attack
pub angle: f32,
/// Rate of energy drain /// Rate of energy drain
pub energy_drain: f32, pub energy_drain: f32,
/// How quickly dasher moves forward /// How quickly dasher moves forward
@ -44,16 +26,14 @@ pub struct StaticData {
pub swing_duration: Duration, pub swing_duration: Duration,
/// How long the state has until exiting /// How long the state has until exiting
pub recover_duration: Duration, pub recover_duration: Duration,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// How fast can you turn during charge /// How fast can you turn during charge
pub ori_modifier: f32, pub ori_modifier: f32,
/// Whether the state can be interrupted by other abilities /// Whether the state can be interrupted by other abilities
pub is_interruptible: bool, pub is_interruptible: bool,
/// Adds an effect onto the main damage of the attack
pub damage_effect: Option<CombatEffect>,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -120,61 +100,17 @@ impl CharacterBehavior for Data {
// while checking if it has hit something. // while checking if it has hit something.
if !self.exhausted { if !self.exhausted {
// Hit attempt // Hit attempt
let poise = AttackEffect::new( let crit_data = get_crit_data(data, self.static_data.ability_info);
Some(GroupTarget::OutOfGroup), let buff_strength = get_buff_strength(data, self.static_data.ability_info);
CombatEffect::Poise(
self.static_data.base_poise_damage as f32 data.updater.insert(
+ charge_frac * self.static_data.scaled_poise_damage as f32, data.entity,
), self.static_data
) .melee_constructor
.with_requirement(CombatRequirement::AnyDamage); .handle_scaling(charge_frac)
let knockback = AttackEffect::new( .create_melee(crit_data, buff_strength),
Some(GroupTarget::OutOfGroup), );
CombatEffect::Knockback(Knockback {
strength: self.static_data.base_knockback
+ charge_frac * self.static_data.scaled_knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.base_damage as f32
+ charge_frac * self.static_data.scaled_damage as f32,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: self.static_data.angle.to_radians(),
applied: false,
hit_count: 0,
break_block: data
.inputs
.break_block_pos
.map(|p| {
(
p.map(|e| e.floor() as i32),
self.static_data.ability_info.tool,
)
})
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
});
update.character = CharacterState::DashMelee(Data { update.character = CharacterState::DashMelee(Data {
timer: tick_attack_or_default(data, self.timer, None), timer: tick_attack_or_default(data, self.timer, None),
exhausted: true, exhausted: true,
@ -204,7 +140,7 @@ impl CharacterBehavior for Data {
} else { } else {
self.timer self.timer
.checked_add(Duration::from_secs_f32( .checked_add(Duration::from_secs_f32(
0.2 * self.static_data.range 0.2 * self.static_data.melee_constructor.range
/ self.static_data.forward_speed, / self.static_data.forward_speed,
)) ))
.unwrap_or(self.static_data.charge_duration) .unwrap_or(self.static_data.charge_duration)
@ -256,61 +192,17 @@ impl CharacterBehavior for Data {
/ self.static_data.charge_duration.as_secs_f32()) / self.static_data.charge_duration.as_secs_f32())
.min(1.0); .min(1.0);
let poise = AttackEffect::new( let crit_data = get_crit_data(data, self.static_data.ability_info);
Some(GroupTarget::OutOfGroup), let buff_strength = get_buff_strength(data, self.static_data.ability_info);
CombatEffect::Poise(
self.static_data.base_poise_damage as f32 data.updater.insert(
+ charge_frac * self.static_data.scaled_poise_damage as f32, data.entity,
), self.static_data
) .melee_constructor
.with_requirement(CombatRequirement::AnyDamage); .handle_scaling(charge_frac)
let knockback = AttackEffect::new( .create_melee(crit_data, buff_strength),
Some(GroupTarget::OutOfGroup), );
CombatEffect::Knockback(Knockback {
strength: self.static_data.base_knockback
+ charge_frac * self.static_data.scaled_knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.base_damage as f32
+ charge_frac * self.static_data.scaled_damage as f32,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: self.static_data.angle.to_radians(),
applied: false,
hit_count: 0,
break_block: data
.inputs
.break_block_pos
.map(|p| {
(
p.map(|e| e.floor() as i32),
self.static_data.ability_info.tool,
)
})
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
});
update.character = CharacterState::DashMelee(Data { update.character = CharacterState::DashMelee(Data {
timer: tick_attack_or_default(data, self.timer, None), timer: tick_attack_or_default(data, self.timer, None),
exhausted: true, exhausted: true,

View File

@ -1,12 +1,10 @@
use crate::{ use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
states::{ states::{
behavior::{CharacterBehavior, JoinData}, behavior::{CharacterBehavior, JoinData},
utils::{StageSection, *}, utils::{StageSection, *},
wielding, wielding,
}, },
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
@ -22,26 +20,14 @@ pub struct StaticData {
pub swing_duration: Duration, pub swing_duration: Duration,
/// How long the state has until exiting /// How long the state has until exiting
pub recover_duration: Duration, pub recover_duration: Duration,
/// Base damage /// Used to construct the Melee attack
pub base_damage: f32, pub melee_constructor: MeleeConstructor,
/// Base poise damage
pub base_poise_damage: f32,
/// Knockback
pub knockback: f32,
/// Max range
pub range: f32,
/// Max angle (45.0 will give you a 90.0 angle window)
pub max_angle: f32,
/// Affects how far forward the player leaps /// Affects how far forward the player leaps
pub forward_leap_strength: f32, pub forward_leap_strength: f32,
/// Affects how high the player leaps /// Affects how high the player leaps
pub vertical_leap_strength: f32, pub vertical_leap_strength: f32,
/// Adds an effect onto the main damage of the attack
pub damage_effect: Option<CombatEffect>,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -131,57 +117,15 @@ impl CharacterBehavior for Data {
}, },
StageSection::Recover => { StageSection::Recover => {
if !self.exhausted { if !self.exhausted {
let poise = AttackEffect::new( let crit_data = get_crit_data(data, self.static_data.ability_info);
Some(GroupTarget::OutOfGroup), let buff_strength = get_buff_strength(data, self.static_data.ability_info);
CombatEffect::Poise(self.static_data.base_poise_damage as f32),
)
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: self.static_data.knockback,
direction: KnockbackDir::Away,
}),
)
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.base_damage as f32,
},
Some(GroupTarget::OutOfGroup),
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
// Hit attempt, when animation plays data.updater.insert(
data.updater.insert(data.entity, Melee { data.entity,
attack, self.static_data
range: self.static_data.range, .melee_constructor
max_angle: self.static_data.max_angle.to_radians(), .create_melee(crit_data, buff_strength),
applied: false, );
hit_count: 0,
break_block: data
.inputs
.break_block_pos
.map(|p| {
(
p.map(|e| e.floor() as i32),
self.static_data.ability_info.tool,
)
})
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
});
update.character = CharacterState::LeapMelee(Data { update.character = CharacterState::LeapMelee(Data {
timer: tick_attack_or_default(data, self.timer, None), timer: tick_attack_or_default(data, self.timer, None),

View File

@ -1,9 +1,5 @@
use crate::{ use crate::{
combat::{ comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind,
DamageSource, GroupTarget, Knockback,
},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
consts::GRAVITY, consts::GRAVITY,
states::{ states::{
behavior::{CharacterBehavior, JoinData}, behavior::{CharacterBehavior, JoinData},
@ -24,16 +20,8 @@ pub struct StaticData {
pub swing_duration: Duration, pub swing_duration: Duration,
/// How long until state ends /// How long until state ends
pub recover_duration: Duration, pub recover_duration: Duration,
/// Base damage /// Used to construct the Melee attack
pub base_damage: f32, pub melee_constructor: MeleeConstructor,
/// Base poise damage
pub base_poise_damage: f32,
/// Knockback
pub knockback: Knockback,
/// Range
pub range: f32,
/// Adds an effect onto the main damage of the attack
pub damage_effect: Option<CombatEffect>,
/// Energy cost per attack /// Energy cost per attack
pub energy_cost: f32, pub energy_cost: f32,
/// Whether spin state is infinite /// Whether spin state is infinite
@ -46,14 +34,10 @@ pub struct StaticData {
pub forward_speed: f32, pub forward_speed: f32,
/// Number of spins /// Number of spins
pub num_spins: u32, pub num_spins: u32,
/// Used to determine targeting of attack
pub target: Option<GroupTarget>,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// Used to specify the melee attack to the frontend /// Used to specify the melee attack to the frontend
pub specifier: Option<FrontendSpecifier>, pub specifier: Option<FrontendSpecifier>,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -111,54 +95,15 @@ impl CharacterBehavior for Data {
..*self ..*self
}); });
let poise = AttackEffect::new( let crit_data = get_crit_data(data, self.static_data.ability_info);
self.static_data.target, let buff_strength = get_buff_strength(data, self.static_data.ability_info);
CombatEffect::Poise(self.static_data.base_poise_damage as f32),
)
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
self.static_data.target,
CombatEffect::Knockback(self.static_data.knockback),
)
.with_requirement(CombatRequirement::AnyDamage);
let mut damage = AttackDamage::new(
Damage {
source: DamageSource::Melee,
kind: self.static_data.damage_kind,
value: self.static_data.base_damage as f32,
},
self.static_data.target,
);
if let Some(effect) = self.static_data.damage_effect {
damage = damage.with_effect(effect);
}
let (crit_chance, crit_mult) =
get_crit_data(data, self.static_data.ability_info);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_effect(poise)
.with_effect(knockback)
.with_combo_increment();
// Hit attempt data.updater.insert(
data.updater.insert(data.entity, Melee { data.entity,
attack, self.static_data
range: self.static_data.range, .melee_constructor
max_angle: 180_f32.to_radians(), .create_melee(crit_data, buff_strength),
applied: false, );
hit_count: 0,
break_block: data
.inputs
.break_block_pos
.map(|p| {
(
p.map(|e| e.floor() as i32),
self.static_data.ability_info.tool,
)
})
.filter(|(_, tool)| tool == &Some(ToolKind::Pick)),
});
} else if self.timer < self.static_data.swing_duration { } else if self.timer < self.static_data.swing_duration {
if matches!( if matches!(
self.static_data.movement_behavior, self.static_data.movement_behavior,

View File

@ -1,10 +1,10 @@
use super::*; use super::*;
use crate::audio::sfx::SfxEvent; use crate::audio::sfx::SfxEvent;
use common::{ use common::{
combat::{self, DamageKind}, combat::DamageKind,
comp::{ comp::{
inventory::loadout_builder::LoadoutBuilder, item::tool::ToolKind, CharacterAbilityType, inventory::loadout_builder::LoadoutBuilder, item::tool::ToolKind, melee,
CharacterState, InputKind, Item, CharacterAbilityType, CharacterState, InputKind, Item,
}, },
states, states,
}; };
@ -75,17 +75,19 @@ fn maps_basic_melee() {
buildup_duration: Duration::default(), buildup_duration: Duration::default(),
swing_duration: Duration::default(), swing_duration: Duration::default(),
recover_duration: Duration::default(), recover_duration: Duration::default(),
base_damage: 10.0, melee_constructor: melee::MeleeConstructor {
base_poise_damage: 10.0, kind: melee::MeleeConstructorKind::Slash {
knockback: combat::Knockback { damage: 1.0,
strength: 0.0, knockback: 0.0,
direction: combat::KnockbackDir::Away, poise: 0.0,
energy_regen: 0.0,
},
scaled: None,
range: 3.5,
angle: 15.0,
damage_effect: None,
}, },
range: 1.0,
max_angle: 1.0,
ability_info: empty_ability_info(), ability_info: empty_ability_info(),
damage_effect: None,
damage_kind: DamageKind::Slashing,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: states::utils::StageSection::Buildup, stage_section: states::utils::StageSection::Buildup,

View File

@ -603,7 +603,7 @@ impl ParticleMgr {
match specifier { match specifier {
states::spin_melee::FrontendSpecifier::CultistVortex => { states::spin_melee::FrontendSpecifier::CultistVortex => {
if matches!(spin.stage_section, StageSection::Action) { if matches!(spin.stage_section, StageSection::Action) {
let range = spin.static_data.range; let range = spin.static_data.melee_constructor.range;
// Particles for vortex // Particles for vortex
let heartbeats = let heartbeats =
self.scheduler.heartbeats(Duration::from_millis(3)); self.scheduler.heartbeats(Duration::from_millis(3));