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,
swing_duration: 0.2,
recover_duration: 0.2,
base_damage: 30.0,
base_poise_damage: 0,
knockback: 12.0,
range: 4.5,
max_angle: 30.0,
melee_constructor: (
kind: Slash(
damage: 30.0,
poise: 0.0,
knockback: 12.0,
energy_regen: 0.0,
),
range: 4.5,
angle: 30.0,
),
forward_leap_strength: 20.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,
swing_duration: 0.6,
recover_duration: 0.2,
base_damage: 8.0,
base_poise_damage: 10,
knockback: ( strength: 0.0, direction: Away),
range: 3.5,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
melee_constructor: (
kind: Slash(
damage: 8.0,
poise: 10.0,
knockback: 0.0,
energy_regen: 0.0,
),
range: 3.5,
angle: 360.0,
),
energy_cost: 10.0,
is_infinite: true,
movement_behavior: AxeHover,
@ -19,6 +19,4 @@ SpinMelee(
forward_speed: 0.0,
num_spins: 1,
specifier: None,
target: Some(OutOfGroup),
damage_kind: Slashing,
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,24 @@
ChargedMelee(
energy_cost: 0,
energy_drain: 0,
initial_damage: 5.0,
scaled_damage: 45.0,
initial_poise_damage: 50,
scaled_poise_damage: 150,
initial_knockback: 0.0,
scaled_knockback: 0.0,
range: 3.5,
max_angle: 45.0,
melee_constructor: (
kind: Bash(
damage: 5.0,
poise: 50.0,
knockback: 0.0,
energy_regen: 0.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,
swing_duration: 0.1,
hit_timing: 0.8,
recover_duration: 0.5,
damage_kind: Crushing,
)

View File

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

View File

@ -1,13 +1,27 @@
DashMelee(
energy_cost: 0,
base_damage: 15.0,
scaled_damage: 60.0,
base_poise_damage: 25,
scaled_poise_damage: 100,
base_knockback: 10.0,
scaled_knockback: 30.0,
range: 5.0,
angle: 90.0,
melee_constructor: (
kind: Stab(
damage: 15.0,
poise: 25.0,
knockback: 10.0,
energy_regen: 0.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,
forward_speed: 5.0,
buildup_duration: 0.4,
@ -17,11 +31,4 @@ DashMelee(
ori_modifier: 0.1,
charge_through: 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(
energy_cost: 0,
energy_drain: 0,
initial_damage: 5.0,
scaled_damage: 45.0,
initial_poise_damage: 50,
scaled_poise_damage: 150,
initial_knockback: 0.0,
scaled_knockback: 0.0,
range: 5.0,
max_angle: 45.0,
melee_constructor: (
kind: Slash(
damage: 5.0,
poise: 50.0,
knockback: 0.0,
energy_regen: 0.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,
swing_duration: 0.1,
hit_timing: 0.8,
recover_duration: 0.5,
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,
swing_duration: 0.1,
recover_duration: 0.6,
base_damage: 15.0,
base_poise_damage: 60.0,
knockback: ( strength: 15.0, direction: Away),
range: 5.0,
max_angle: 60.0,
damage_effect: Some(Buff((
kind: Crippled,
dur_secs: 10.0,
strength: Value(0.5),
chance: 1.0,
))),
damage_kind: Slashing,
melee_constructor: (
kind: Slash(
damage: 15.0,
poise: 60.0,
knockback: 15.0,
energy_regen: 0.0,
),
range: 5.0,
angle: 60.0,
),
)

View File

@ -1,13 +1,21 @@
DashMelee(
energy_cost: 0,
base_damage: 8.0,
scaled_damage: 16.0,
base_poise_damage: 0,
scaled_poise_damage: 0,
base_knockback: 8.0,
scaled_knockback: 7.0,
range: 2.0,
angle: 15.0,
melee_constructor: (
kind: Slash(
damage: 8.0,
poise: 0.0,
knockback: 8.0,
energy_regen: 0.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,
forward_speed: 3.0,
buildup_duration: 0.5,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
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(
energy_cost: 0,
base_damage: 8.0,
scaled_damage: 15.0,
base_poise_damage: 25,
scaled_poise_damage: 0,
base_knockback: 4.0,
scaled_knockback: 17.0,
range: 2.5,
angle: 45.0,
melee_constructor: (
kind: Bash(
damage: 8.0,
poise: 25.0,
knockback: 4.0,
energy_regen: 0.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,
forward_speed: 4.0,
buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
is_interruptible: false,
damage_kind: Crushing,
)

View File

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

View File

@ -1,17 +1,24 @@
ChargedMelee(
energy_cost: 0,
energy_drain: 0,
initial_damage: 4.0,
scaled_damage: 20.0,
initial_poise_damage: 30,
scaled_poise_damage: 80,
initial_knockback: 10.0,
scaled_knockback: 20.0,
range: 6.0,
max_angle: 90.0,
melee_constructor: (
kind: Bash(
damage: 4.0,
poise: 30.0,
knockback: 10.0,
energy_regen: 0.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,
swing_duration: 0.7,
hit_timing: 0.9,
recover_duration: 0.7,
damage_kind: Crushing,
)

View File

@ -1,13 +1,21 @@
DashMelee(
energy_cost: 0,
base_damage: 7.0,
scaled_damage: 28.0,
base_poise_damage: 28,
scaled_poise_damage: 40,
base_knockback: 8.0,
scaled_knockback: 17.0,
range: 2.5,
angle: 45.0,
melee_constructor: (
kind: Bash(
damage: 7.0,
poise: 28.0,
knockback: 8.0,
energy_regen: 0.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,
forward_speed: 2.0,
buildup_duration: 0.5,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
is_interruptible: false,
damage_kind: Crushing,
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,21 @@
DashMelee(
energy_cost: 0,
base_damage: 5.0,
scaled_damage: 25.0,
base_poise_damage: 10,
scaled_poise_damage: 40,
base_knockback: 10.0,
scaled_knockback: 30.0,
range: 5.0,
angle: 90.0,
melee_constructor: (
kind: Bash(
damage: 5.0,
poise: 10.0,
knockback: 10.0,
energy_regen: 0.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,
forward_speed: 10.0,
buildup_duration: 0.4,
@ -17,5 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
is_interruptible: false,
damage_kind: Crushing,
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,24 @@
ChargedMelee(
energy_cost: 1,
energy_drain: 30.0,
initial_damage: 0.0,
scaled_damage: 20.0,
initial_poise_damage: 0,
scaled_poise_damage: 30,
initial_knockback: 5.0,
scaled_knockback: 20.0,
range: 3.5,
max_angle: 30.0,
melee_constructor: (
kind: Bash(
damage: 0.0,
poise: 0.0,
knockback: 5.0,
energy_regen: 0.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,
swing_duration: 0.12,
hit_timing: 0.2,
recover_duration: 0.3,
damage_kind: Crushing,
)

View File

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

View File

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

View File

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

View File

@ -1,13 +1,21 @@
DashMelee(
energy_cost: 10.0,
base_damage: 1.0,
scaled_damage: 8.0,
base_poise_damage: 0,
scaled_poise_damage: 25,
base_knockback: 8.0,
scaled_knockback: 7.0,
range: 3.0,
angle: 20.0,
melee_constructor: (
kind: Stab(
damage: 1.0,
poise: 0.0,
knockback: 8.0,
energy_regen: 0.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,
forward_speed: 2.0,
buildup_duration: 0.5,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
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(
energy_cost: 10.0,
base_damage: 8.0,
scaled_damage: 16.0,
base_poise_damage: 0,
scaled_poise_damage: 0,
base_knockback: 8.0,
scaled_knockback: 7.0,
range: 4.0,
angle: 60.0,
melee_constructor: (
kind: Stab(
damage: 8.0,
poise: 0.0,
knockback: 8.0,
energy_regen: 0.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,
forward_speed: 3.0,
buildup_duration: 0.25,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: 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,
swing_duration: 0.4,
recover_duration: 0.5,
base_damage: 12.0,
base_poise_damage: 10,
knockback: ( strength: 10.0, direction: Away),
range: 3.5,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
melee_constructor: (
kind: Slash(
damage: 12.0,
poise: 10.0,
knockback: 10.0,
energy_regen: 0.0,
),
range: 3.5,
angle: 360.0,
),
energy_cost: 20.0,
is_infinite: false,
movement_behavior: ForwardGround,
@ -19,6 +19,4 @@ SpinMelee(
forward_speed: 1.0,
num_spins: 3,
specifier: None,
target: Some(OutOfGroup),
damage_kind: Slashing,
)

View File

@ -1,13 +1,21 @@
DashMelee(
energy_cost: 10.0,
base_damage: 9.0,
scaled_damage: 16.0,
base_poise_damage: 40,
scaled_poise_damage: 0,
base_knockback: 8.0,
scaled_knockback: 7.0,
range: 5.0,
angle: 45.0,
melee_constructor: (
kind: Stab(
damage: 9.0,
poise: 40.0,
knockback: 8.0,
energy_regen: 0.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,
forward_speed: 4.0,
buildup_duration: 0.6,
@ -17,11 +25,4 @@ DashMelee(
ori_modifier: 0.3,
charge_through: false,
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(
energy_cost: 1,
energy_drain: 1.0,
initial_damage: 1.0,
scaled_damage: 0.1,
initial_poise_damage: 1,
scaled_poise_damage: 1,
initial_knockback: 30.0,
scaled_knockback: 60.0,
range: 5.0,
max_angle: 30.0,
melee_constructor: (
kind: Bash(
damage: 1.0,
poise: 1.0,
knockback: 30.0,
energy_regen: 0.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,
swing_duration: 0.1,
hit_timing: 0.2,
recover_duration: 1.5,
damage_kind: Crushing,
)

View File

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

View File

@ -1,8 +1,6 @@
use crate::{
combat::Attack,
comp::{
item::ConsumableKind, tool::ToolKind, ControlAction, Density, Energy, InputAttr, InputKind,
Ori, Pos, Vel,
item::ConsumableKind, ControlAction, Density, Energy, InputAttr, InputKind, Ori, Pos, Vel,
},
event::{LocalEvent, ServerEvent},
states::{
@ -13,11 +11,10 @@ use crate::{
},
};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage, VecStorage};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
use std::collections::BTreeMap;
use strum_macros::Display;
use vek::*;
/// Data returned from character behavior fn's to Character Behavior System.
pub struct StateUpdate {
@ -385,17 +382,3 @@ impl Default for CharacterState {
impl Component for CharacterState {
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;
#[cfg(not(target_arch = "wasm32"))] mod last;
#[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"))] pub mod ori;
#[cfg(not(target_arch = "wasm32"))] pub mod pet;
@ -66,7 +67,7 @@ pub use self::{
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,
ModifierKind,
},
character_state::{CharacterState, Melee, StateUpdate},
character_state::{CharacterState, StateUpdate},
chat::{
ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,
},
@ -89,6 +90,7 @@ pub use self::{
},
last::Last,
location::{Waypoint, WaypointArea},
melee::{Melee, MeleeConstructor},
misc::Object,
ori::Ori,
pet::Pet,

View File

@ -1,9 +1,8 @@
use crate::{
combat::{
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind,
DamageSource, GroupTarget, Knockback,
comp::{
character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, MeleeConstructor,
StateUpdate,
},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -22,22 +21,10 @@ pub struct StaticData {
pub swing_duration: Duration,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Base damage
pub base_damage: f32,
/// 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>,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// What key is used to press ability
pub ability_info: AbilityInfo,
/// Which kind of damage does this attack deal
pub damage_kind: DamageKind,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -86,57 +73,26 @@ impl CharacterBehavior for Data {
..*self
});
let poise = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
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();
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
// Hit attempt
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: self.static_data.max_angle,
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)),
});
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.create_melee(crit_data, buff_strength)
.with_block_breaking(
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 {
// Swings
update.character = CharacterState::BasicMelee(Data {

View File

@ -1,6 +1,5 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
event::LocalEvent,
outcome::Outcome,
states::{
@ -8,7 +7,6 @@ use crate::{
utils::{StageSection, *},
wielding,
},
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -20,22 +18,6 @@ pub struct StaticData {
pub energy_drain: f32,
/// Energy cost per attack
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
pub charge_duration: Duration,
/// How long the weapon is swinging for
@ -44,14 +26,12 @@ pub struct StaticData {
pub hit_timing: f32,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Adds an effect onto the main damage of the attack
pub damage_effect: Option<CombatEffect>,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// What key is used to press ability
pub ability_info: AbilityInfo,
/// Used to specify the melee attack to the frontend
pub specifier: Option<FrontendSpecifier>,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -132,69 +112,25 @@ impl CharacterBehavior for Data {
exhausted: true,
..*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
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: self.static_data.max_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)),
});
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.handle_scaling(self.charge_amount)
.create_melee(crit_data, buff_strength),
);
if let Some(FrontendSpecifier::GroundCleave) = self.static_data.specifier {
// Send local event used for frontend shenanigans
output_events.emit_local(LocalEvent::CreateOutcome(Outcome::GroundSlam {
pos: data.pos.0
+ *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 {

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)]
/// Separated out to condense update portions of character state
pub struct StaticData {

View File

@ -1,12 +1,10 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
wielding,
},
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -14,22 +12,6 @@ use std::time::Duration;
/// Separated out to condense update portions of character state
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
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
pub energy_drain: f32,
/// How quickly dasher moves forward
@ -44,16 +26,14 @@ pub struct StaticData {
pub swing_duration: Duration,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// How fast can you turn during charge
pub ori_modifier: f32,
/// Whether the state can be interrupted by other abilities
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
pub ability_info: AbilityInfo,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -120,61 +100,17 @@ impl CharacterBehavior for Data {
// while checking if it has hit something.
if !self.exhausted {
// Hit attempt
let poise = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Poise(
self.static_data.base_poise_damage as f32
+ charge_frac * 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.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();
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.handle_scaling(charge_frac)
.create_melee(crit_data, buff_strength),
);
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 {
timer: tick_attack_or_default(data, self.timer, None),
exhausted: true,
@ -204,7 +140,7 @@ impl CharacterBehavior for Data {
} else {
self.timer
.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,
))
.unwrap_or(self.static_data.charge_duration)
@ -256,61 +192,17 @@ impl CharacterBehavior for Data {
/ self.static_data.charge_duration.as_secs_f32())
.min(1.0);
let poise = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Poise(
self.static_data.base_poise_damage as f32
+ charge_frac * 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.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();
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.handle_scaling(charge_frac)
.create_melee(crit_data, buff_strength),
);
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 {
timer: tick_attack_or_default(data, self.timer, None),
exhausted: true,

View File

@ -1,12 +1,10 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::{StageSection, *},
wielding,
},
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -22,26 +20,14 @@ pub struct StaticData {
pub swing_duration: Duration,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Base damage
pub base_damage: f32,
/// 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,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// Affects how far forward the player leaps
pub forward_leap_strength: f32,
/// Affects how high the player leaps
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
pub ability_info: AbilityInfo,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -131,57 +117,15 @@ impl CharacterBehavior for Data {
},
StageSection::Recover => {
if !self.exhausted {
let poise = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
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();
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
// Hit attempt, when animation plays
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: self.static_data.max_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)),
});
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.create_melee(crit_data, buff_strength),
);
update.character = CharacterState::LeapMelee(Data {
timer: tick_attack_or_default(data, self.timer, None),

View File

@ -1,9 +1,5 @@
use crate::{
combat::{
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind,
DamageSource, GroupTarget, Knockback,
},
comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate},
comp::{character_state::OutputEvents, CharacterState, Melee, MeleeConstructor, StateUpdate},
consts::GRAVITY,
states::{
behavior::{CharacterBehavior, JoinData},
@ -24,16 +20,8 @@ pub struct StaticData {
pub swing_duration: Duration,
/// How long until state ends
pub recover_duration: Duration,
/// Base damage
pub base_damage: f32,
/// 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>,
/// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor,
/// Energy cost per attack
pub energy_cost: f32,
/// Whether spin state is infinite
@ -46,14 +34,10 @@ pub struct StaticData {
pub forward_speed: f32,
/// Number of spins
pub num_spins: u32,
/// Used to determine targeting of attack
pub target: Option<GroupTarget>,
/// What key is used to press ability
pub ability_info: AbilityInfo,
/// Used to specify the melee attack to the frontend
pub specifier: Option<FrontendSpecifier>,
/// What kind of damage the attack does
pub damage_kind: DamageKind,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -111,54 +95,15 @@ impl CharacterBehavior for Data {
..*self
});
let poise = AttackEffect::new(
self.static_data.target,
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();
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
// Hit attempt
data.updater.insert(data.entity, Melee {
attack,
range: self.static_data.range,
max_angle: 180_f32.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)),
});
data.updater.insert(
data.entity,
self.static_data
.melee_constructor
.create_melee(crit_data, buff_strength),
);
} else if self.timer < self.static_data.swing_duration {
if matches!(
self.static_data.movement_behavior,

View File

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

View File

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