spawn wyverns

This commit is contained in:
flo 2023-08-02 07:55:10 +00:00 committed by Isse
parent 690385df96
commit 57fe2c4adb
78 changed files with 1505 additions and 1066 deletions

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- First version of multisalvage that allows to obtain more than one piece of material from salvage - First version of multisalvage that allows to obtain more than one piece of material from salvage
- Axe - Axe
- Combat music toggle - Combat music toggle
- Spawn rtsim wyverns that travel the world, providing dragon scale loot drops
### Changed ### Changed

View File

@ -724,42 +724,42 @@
), ),
Custom("Flame Wyvern"): ( Custom("Flame Wyvern"): (
primary: Simple(None, "common.abilities.custom.flamewyvern.firebomb"), primary: Simple(None, "common.abilities.custom.flamewyvern.firebomb"),
secondary: Simple(None, "common.abilities.custom.flamewyvern.fireshockwave"), secondary: Simple(None, "common.abilities.custom.flamewyvern.triplestrike"),
abilities: [ abilities: [
Simple(None, "common.abilities.custom.flamewyvern.triplestrike"), Simple(None, "common.abilities.custom.flamewyvern.fireshockwave"),
Simple(None, "common.abilities.custom.flamewyvern.flamethrower"), Simple(None, "common.abilities.custom.flamewyvern.flamethrower"),
], ],
), ),
Custom("Frost Wyvern"): ( Custom("Frost Wyvern"): (
primary: Simple(None, "common.abilities.custom.frostwyvern.frostbomb"), primary: Simple(None, "common.abilities.custom.frostwyvern.frostbomb"),
secondary: Simple(None, "common.abilities.custom.frostwyvern.iceshockwave"), secondary: Simple(None, "common.abilities.custom.frostwyvern.triplestrike"),
abilities: [ abilities: [
Simple(None, "common.abilities.custom.frostwyvern.triplestrike"), Simple(None, "common.abilities.custom.frostwyvern.iceshockwave"),
Simple(None, "common.abilities.custom.frostwyvern.frostthrower"), Simple(None, "common.abilities.custom.frostwyvern.frostthrower"),
], ],
), ),
Custom("Cloud Wyvern"): ( Custom("Cloud Wyvern"): (
primary: Simple(None, "common.abilities.custom.cloudwyvern.windbomb"), primary: Simple(None, "common.abilities.custom.cloudwyvern.lightningbomb"),
secondary: Simple(None, "common.abilities.custom.cloudwyvern.windshockwave"), secondary: Simple(None, "common.abilities.custom.cloudwyvern.triplestrike"),
abilities: [ abilities: [
Simple(None, "common.abilities.custom.cloudwyvern.triplestrike"), Simple(None, "common.abilities.custom.cloudwyvern.lightningshockwave"),
Simple(None, "common.abilities.custom.cloudwyvern.windthrower"), Simple(None, "common.abilities.custom.cloudwyvern.lightningthrower"),
], ],
), ),
Custom("Sea Wyvern"): ( Custom("Sea Wyvern"): (
primary: Simple(None, "common.abilities.custom.seawyvern.seabomb"), primary: Simple(None, "common.abilities.custom.seawyvern.inkbomb"),
secondary: Simple(None, "common.abilities.custom.seawyvern.seashockwave"), secondary: Simple(None, "common.abilities.custom.seawyvern.triplestrike"),
abilities: [ abilities: [
Simple(None, "common.abilities.custom.seawyvern.triplestrike"), Simple(None, "common.abilities.custom.seawyvern.inkshockwave"),
Simple(None, "common.abilities.custom.seawyvern.bubblethrower"), Simple(None, "common.abilities.custom.seawyvern.inkthrower"),
], ],
), ),
Custom("Weald Wyvern"): ( Custom("Weald Wyvern"): (
primary: Simple(None, "common.abilities.custom.wealdwyvern.firebomb"), primary: Simple(None, "common.abilities.custom.wealdwyvern.poisonbomb"),
secondary: Simple(None, "common.abilities.custom.wealdwyvern.fireshockwave"), secondary: Simple(None, "common.abilities.custom.wealdwyvern.triplestrike"),
abilities: [ abilities: [
Simple(None, "common.abilities.custom.wealdwyvern.triplestrike"), Simple(None, "common.abilities.custom.wealdwyvern.poisonshockwave"),
Simple(None, "common.abilities.custom.wealdwyvern.flamethrower"), Simple(None, "common.abilities.custom.wealdwyvern.poisonthrower"),
], ],
), ),
Custom("Bird Large Basic"): ( Custom("Bird Large Basic"): (

View File

@ -13,7 +13,7 @@ BasicRanged(
col: (1.0, 0.75, 0.11).into(), col: (1.0, 0.75, 0.11).into(),
..Default::default() ..Default::default()
}),*/ }),*/
projectile_speed: 260.0, projectile_speed: 25.0,
num_projectiles: 1, num_projectiles: 1,
projectile_spread: 0.3, projectile_spread: 0.3,
move_efficiency: 0.3, move_efficiency: 0.3,

View File

@ -1,59 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 22.0, kind: Slash(
damage_increase: 0, damage: 22,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 3.0, movement: (
damage_kind: Crushing, swing: Some(Forward(3.0)),
),
ori_modifier: 0.7,
), ),
( (
stage: 2, melee_constructor: (
base_damage: 18.0, kind: Slash(
damage_increase: 0, damage: 18,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 3.0, movement: (
damage_kind: Crushing, swing: Some(Forward(3.0)),
),
ori_modifier: 0.7,
), ),
( (
stage: 3, melee_constructor: (
base_damage: 28.0, kind: Slash(
damage_increase: 0, damage: 28,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 1.3, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 1.3,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 3.5, movement: (
damage_kind: Crushing, swing: Some(Forward(3.5)),
),
ori_modifier: 0.7,
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 1.3, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -0,0 +1,18 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.5,
recover_duration: 1.5,
projectile: LaserBeam(
damage: 20.0,
radius: 5.0,
knockback: 5.0,
energy_regen: 20.0,
min_falloff: 0.1,
),
projectile_body: Object(LightningBolt),
projectile_light: None,
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -0,0 +1,24 @@
Shockwave(
energy_cost: 0,
buildup_duration: 0.3,
swing_duration: 0.3,
recover_duration: 2.0,
damage: 20.0,
poise_damage: 10,
knockback: (strength: 18.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 15.0,
shockwave_duration: 2.0,
requires_ground: true,
move_efficiency: 0.0,
damage_kind: Crushing,
specifier: Lightning,
ori_rate: 1.0,
damage_effect: Some(Buff((
kind: Crippled,
dur_secs: 2.0,
strength: Value(0.3),
chance: 1.0,
))),
)

View File

@ -0,0 +1,19 @@
BasicBeam(
buildup_duration: 0.3,
recover_duration: 1.5,
beam_duration: 2.0,
damage: 22.5,
tick_rate: 3.0,
range: 22.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Crippled,
dur_secs: 3.0,
strength: Value(0.5),
chance: 1.0,
))),
energy_regen: 2,
energy_drain: 0,
ori_rate: 0.5,
specifier: Lightning,
)

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,20 +0,0 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 1.0,
recover_duration: 0.7,
projectile: WindBomb(
damage: 20.0,
radius: 5.0,
energy_regen: 5.0,
min_falloff: 0.5,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -1,18 +0,0 @@
Shockwave(
energy_cost: 60.0,
buildup_duration: 1.4,
swing_duration: 0.1,
recover_duration: 0.4,
damage: 40.0,
poise_damage: 0,
knockback: ( strength: 25.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 20.0,
shockwave_duration: 0.5,
requires_ground: false,
move_efficiency: 0.1,
damage_kind: Energy,
specifier: Water,
ori_rate: 1.0,
)

View File

@ -1,19 +0,0 @@
BasicBeam(
buildup_duration: 0.8,
recover_duration: 0.5,
beam_duration: 0.5,
damage: 10.0,
tick_rate: 3.0,
range: 15.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 10.0,
strength: DamageFraction(0.5),
chance: 0.25,
))),
energy_regen: 0,
energy_drain: 0,
ori_rate: 0.3,
specifier: Bubbles,
)

View File

@ -1,19 +1,16 @@
BasicRanged( BasicRanged(
energy_cost: 0, energy_cost: 0,
buildup_duration: 1.0, buildup_duration: 0.5,
recover_duration: 0.7, recover_duration: 1.5,
projectile: Fireball( projectile: Fireball(
damage: 20.0, damage: 32.0,
radius: 5.0, radius: 5.0,
energy_regen: 5.0, energy_regen: 5.0,
min_falloff: 0.5, min_falloff: 0.1,
), ),
projectile_body: Object(BoltFire), projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter { projectile_light: None,
col: (1.0, 0.75, 0.11).into(), projectile_speed: 100.0,
..Default::default()
}),*/
projectile_speed: 60.0,
num_projectiles: 1, num_projectiles: 1,
projectile_spread: 0.0, projectile_spread: 0.0,
move_efficiency: 0.3, move_efficiency: 0.3,

View File

@ -1,18 +1,24 @@
Shockwave( Shockwave(
energy_cost: 60.0, energy_cost: 0,
buildup_duration: 1.4, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.3,
recover_duration: 0.4, recover_duration: 2.0,
damage: 40.0, damage: 20.0,
poise_damage: 0, poise_damage: 10,
knockback: ( strength: 25.0, direction: Away), knockback: (strength: 18.0, direction: Away),
shockwave_angle: 360.0, shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0, shockwave_vertical_angle: 90.0,
shockwave_speed: 20.0, shockwave_speed: 15.0,
shockwave_duration: 0.5, shockwave_duration: 2.0,
requires_ground: false, requires_ground: true,
move_efficiency: 0.1, move_efficiency: 0.0,
damage_kind: Energy, damage_kind: Crushing,
specifier: Fire, specifier: Fire,
ori_rate: 1.0, ori_rate: 1.0,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 2.0,
strength: DamageFraction(0.3),
chance: 1.0,
))),
) )

View File

@ -1,19 +1,19 @@
BasicBeam( BasicBeam(
buildup_duration: 0.8, buildup_duration: 0.3,
recover_duration: 0.5, recover_duration: 1.5,
beam_duration: 0.5, beam_duration: 2.0,
damage: 10.0, damage: 22.5,
tick_rate: 3.0, tick_rate: 3.0,
range: 15.0, range: 22.0,
max_angle: 22.5, max_angle: 22.5,
damage_effect: Some(Buff(( damage_effect: Some(Buff((
kind: Burning, kind: Burning,
dur_secs: 10.0, dur_secs: 3.0,
strength: DamageFraction(0.5), strength: DamageFraction(0.5),
chance: 0.25, chance: 1.0,
))), ))),
energy_regen: 0, energy_regen: 2,
energy_drain: 0, energy_drain: 0,
ori_rate: 0.3, ori_rate: 0.5,
specifier: Flamethrower, specifier: Flamethrower,
) )

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,19 +1,16 @@
BasicRanged( BasicRanged(
energy_cost: 0, energy_cost: 0,
buildup_duration: 1.0, buildup_duration: 0.5,
recover_duration: 0.7, recover_duration: 1.5,
projectile: Frostball( projectile: Frostball(
damage: 20.0, damage: 32.0,
radius: 5.0, radius: 5.0,
energy_regen: 5.0, energy_regen: 5.0,
min_falloff: 0.5, min_falloff: 0.1,
), ),
projectile_body: Object(BoltNature), projectile_body: Object(SpearIcicle),
/*projectile_light: Some(LightEmitter { projectile_light: None,
col: (1.0, 0.75, 0.11).into(), projectile_speed: 100.0,
..Default::default()
}),*/
projectile_speed: 60.0,
num_projectiles: 1, num_projectiles: 1,
projectile_spread: 0.0, projectile_spread: 0.0,
move_efficiency: 0.3, move_efficiency: 0.3,

View File

@ -1,19 +1,19 @@
BasicBeam( BasicBeam(
buildup_duration: 0.8, buildup_duration: 0.3,
recover_duration: 0.5, recover_duration: 1.5,
beam_duration: 0.5, beam_duration: 2.0,
damage: 10.0, damage: 22.5,
tick_rate: 3.0, tick_rate: 3.0,
range: 15.0, range: 22.0,
max_angle: 22.5, max_angle: 22.5,
damage_effect: Some(Buff(( damage_effect: Some(Buff((
kind: Burning, kind: Frigid,
dur_secs: 10.0, dur_secs: 3.0,
strength: DamageFraction(0.5), strength: Value(0.5),
chance: 0.25, chance: 1.0,
))), ))),
energy_regen: 0, energy_regen: 2,
energy_drain: 0, energy_drain: 0,
ori_rate: 0.3, ori_rate: 0.5,
specifier: Frost, specifier: Frost,
) )

View File

@ -1,18 +1,24 @@
Shockwave( Shockwave(
energy_cost: 60.0, energy_cost: 0,
buildup_duration: 1.4, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.3,
recover_duration: 0.4, recover_duration: 2.0,
damage: 40.0, damage: 20.0,
poise_damage: 0, poise_damage: 10,
knockback: ( strength: 25.0, direction: Away), knockback: (strength: 18.0, direction: Away),
shockwave_angle: 360.0, shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0, shockwave_vertical_angle: 90.0,
shockwave_speed: 20.0, shockwave_speed: 15.0,
shockwave_duration: 0.5, shockwave_duration: 2.0,
requires_ground: false, requires_ground: true,
move_efficiency: 0.1, move_efficiency: 0.0,
damage_kind: Energy, damage_kind: Crushing,
specifier: IceSpikes, specifier: Ice,
ori_rate: 1.0, ori_rate: 1.0,
damage_effect: Some(Buff((
kind: Frozen,
dur_secs: 2.0,
strength: Value(0.3),
chance: 1.0,
))),
) )

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,19 +0,0 @@
BasicBeam(
buildup_duration: 0.8,
recover_duration: 0.5,
beam_duration: 0.5,
damage: 10.0,
tick_rate: 3.0,
range: 15.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 10.0,
strength: DamageFraction(0.5),
chance: 0.25,
))),
energy_regen: 0,
energy_drain: 0,
ori_rate: 0.3,
specifier: Bubbles,
)

View File

@ -0,0 +1,17 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.5,
recover_duration: 1.5,
projectile: InkBomb(
damage: 32.0,
radius: 5.0,
energy_regen: 5.0,
min_falloff: 0.1,
),
projectile_body: Object(SpitPoison),
projectile_light: None,
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -0,0 +1,25 @@
Shockwave(
energy_cost: 0,
buildup_duration: 0.3,
swing_duration: 0.3,
recover_duration: 2.0,
damage: 20.0,
poise_damage: 10,
knockback: (strength: 18.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 15.0,
shockwave_duration: 2.0,
requires_ground: true,
move_efficiency: 0.0,
damage_kind: Crushing,
specifier: Ink,
ori_rate: 1.0,
damage_effect: Some(Buff((
kind: Wet,
dur_secs: 8.0,
strength: Value(0.3),
chance: 1.0,
))),
)

View File

@ -0,0 +1,19 @@
BasicBeam(
buildup_duration: 0.3,
recover_duration: 1.5,
beam_duration: 2.0,
damage: 22.5,
tick_rate: 3.0,
range: 22.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Wet,
dur_secs: 8.0,
strength: Value(1.5),
chance: 1.0,
))),
energy_regen: 2,
energy_drain: 0,
ori_rate: 0.5,
specifier: Ink,
)

View File

@ -1,20 +0,0 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 1.0,
recover_duration: 0.7,
projectile: SeaBomb(
damage: 20.0,
radius: 5.0,
energy_regen: 5.0,
min_falloff: 0.5,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -1,18 +0,0 @@
Shockwave(
energy_cost: 60.0,
buildup_duration: 1.4,
swing_duration: 0.1,
recover_duration: 0.4,
damage: 40.0,
poise_damage: 0,
knockback: ( strength: 25.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 20.0,
shockwave_duration: 0.5,
requires_ground: false,
move_efficiency: 0.1,
damage_kind: Energy,
specifier: Water,
ori_rate: 1.0,
)

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -1,20 +0,0 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 1.0,
recover_duration: 0.7,
projectile: Fireball(
damage: 20.0,
radius: 5.0,
energy_regen: 5.0,
min_falloff: 0.5,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -1,18 +0,0 @@
Shockwave(
energy_cost: 60.0,
buildup_duration: 1.4,
swing_duration: 0.1,
recover_duration: 0.4,
damage: 40.0,
poise_damage: 0,
knockback: ( strength: 25.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 20.0,
shockwave_duration: 0.5,
requires_ground: false,
move_efficiency: 0.1,
damage_kind: Energy,
specifier: Fire,
ori_rate: 1.0,
)

View File

@ -1,19 +0,0 @@
BasicBeam(
buildup_duration: 0.8,
recover_duration: 0.5,
beam_duration: 0.5,
damage: 10.0,
tick_rate: 3.0,
range: 15.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 10.0,
strength: DamageFraction(0.5),
chance: 0.25,
))),
energy_regen: 0,
energy_drain: 0,
ori_rate: 0.3,
specifier: Flamethrower,
)

View File

@ -0,0 +1,17 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.5,
recover_duration: 1.5,
projectile: Poisonball(
damage: 32.0,
radius: 5.0,
energy_regen: 5.0,
min_falloff: 0.1,
),
projectile_body: Object(SpitPoison),
projectile_light: None,
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -0,0 +1,25 @@
Shockwave(
energy_cost: 0,
buildup_duration: 0.3,
swing_duration: 0.3,
recover_duration: 2.0,
damage: 20.0,
poise_damage: 10,
knockback: (strength: 18.0, direction: Away),
shockwave_angle: 360.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 15.0,
shockwave_duration: 2.0,
requires_ground: true,
move_efficiency: 0.0,
damage_kind: Crushing,
specifier: Poison,
ori_rate: 1.0,
damage_effect: Some(Buff((
kind: Poisoned,
dur_secs: 8.0,
strength: DamageFraction(0.3),
chance: 1.0,
))),
)

View File

@ -0,0 +1,19 @@
BasicBeam(
buildup_duration: 0.3,
recover_duration: 1.5,
beam_duration: 2.0,
damage: 22.5,
tick_rate: 3.0,
range: 22.0,
max_angle: 22.5,
damage_effect: Some(Buff((
kind: Poisoned,
dur_secs: 3.0,
strength: DamageFraction(0.5),
chance: 1.0,
))),
energy_regen: 2,
energy_drain: 0,
ori_rate: 0.5,
specifier: Poison,
)

View File

@ -1,77 +1,66 @@
ComboMelee( ComboMelee2(
stage_data: [ strikes: [
( (
stage: 1, melee_constructor: (
base_damage: 20.0, kind: Slash(
damage_increase: 0, damage: 20,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 4.5, ),
angle: 30.0, range: 4.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 2.0, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 2, melee_constructor: (
base_damage: 16.0, kind: Slash(
damage_increase: 0, damage: 16,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 5,
knockback: 5.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.8, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.8,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(2.0)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
( (
stage: 3, melee_constructor: (
base_damage: 26.0, kind: Slash(
damage_increase: 0, damage: 26,
base_poise_damage: 0, poise: 0,
poise_damage_increase: 0, knockback: 10,
knockback: 10.0, energy_regen: 0,
range: 3.5, ),
angle: 30.0, range: 3.5,
base_buildup_duration: 0.375, angle: 30.0,
base_swing_duration: 0.1, ),
buildup_duration: 0.4,
swing_duration: 0.1,
hit_timing: 0.5, hit_timing: 0.5,
base_recover_duration: 0.6, recover_duration: 0.6,
forward_movement: 1.5, movement: (
damage_kind: Slashing, swing: Some(Forward(1.5)),
damage_effect: Some(Buff(( ),
kind: Bleeding, ori_modifier: 0.7,
dur_secs: 10.0,
strength: DamageFraction(0.1),
chance: 0.1,
))),
), ),
], ],
initial_energy_gain: 0, energy_cost_per_strike: 0,
max_energy_gain: 0, auto_progress: true,
energy_increase: 0,
speed_increase: 0.0,
max_speed_increase: 0.0,
scales_from_combo: 0,
ori_modifier: 0.7,
) )

View File

@ -3,7 +3,7 @@
name: Automatic, name: Automatic,
body: RandomWith("wyvern_cloud"), body: RandomWith("wyvern_cloud"),
alignment: Alignment(Enemy), alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.creature.bird_large.wyvern"), loot: LootTable("common.loot_tables.creature.bird_large.cloudwyvern"),
inventory: ( inventory: (
loadout: FromBody, loadout: FromBody,
), ),

View File

@ -3,7 +3,7 @@
name: Automatic, name: Automatic,
body: RandomWith("wyvern_flame"), body: RandomWith("wyvern_flame"),
alignment: Alignment(Enemy), alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.creature.bird_large.wyvern"), loot: LootTable("common.loot_tables.creature.bird_large.flamewyvern"),
inventory: ( inventory: (
loadout: FromBody, loadout: FromBody,
), ),

View File

@ -3,7 +3,7 @@
name: Automatic, name: Automatic,
body: RandomWith("wyvern_frost"), body: RandomWith("wyvern_frost"),
alignment: Alignment(Enemy), alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.creature.bird_large.wyvern"), loot: LootTable("common.loot_tables.creature.bird_large.frostwyvern"),
inventory: ( inventory: (
loadout: FromBody, loadout: FromBody,
), ),

View File

@ -3,7 +3,7 @@
name: Automatic, name: Automatic,
body: RandomWith("wyvern_sea"), body: RandomWith("wyvern_sea"),
alignment: Alignment(Enemy), alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.creature.bird_large.wyvern"), loot: LootTable("common.loot_tables.creature.bird_large.seawyvern"),
inventory: ( inventory: (
loadout: FromBody, loadout: FromBody,
), ),

View File

@ -3,7 +3,7 @@
name: Automatic, name: Automatic,
body: RandomWith("wyvern_weald"), body: RandomWith("wyvern_weald"),
alignment: Alignment(Enemy), alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.creature.bird_large.wyvern"), loot: LootTable("common.loot_tables.creature.bird_large.wealdwyvern"),
inventory: ( inventory: (
loadout: FromBody, loadout: FromBody,
), ),

View File

@ -0,0 +1,7 @@
[
(1.0, MultiDrop(Item("common.items.mineral.gem.topaz"), 1, 3)),
(5.0, MultiDrop(Item("common.items.mineral.gem.amethyst"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.elegant_crest"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.claw"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 2, 6)),
]

View File

@ -0,0 +1,7 @@
[
(1.0, MultiDrop(Item("common.items.mineral.gem.topaz"), 1, 3)),
(5.0, MultiDrop(Item("common.items.mineral.gem.ruby"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.large_horn"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.sharp_fang"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 2, 6)),
]

View File

@ -0,0 +1,7 @@
[
(1.0, MultiDrop(Item("common.items.mineral.gem.topaz"), 1, 3)),
(5.0, MultiDrop(Item("common.items.mineral.gem.diamond"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.large_horn"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.claw"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 2, 6)),
]

View File

@ -0,0 +1,7 @@
[
(1.0, MultiDrop(Item("common.items.mineral.gem.topaz"), 1, 3)),
(5.0, MultiDrop(Item("common.items.mineral.gem.sapphire"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.sharp_fang"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.claw"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 2, 6)),
]

View File

@ -0,0 +1,7 @@
[
(1.0, MultiDrop(Item("common.items.mineral.gem.topaz"), 1, 3)),
(5.0, MultiDrop(Item("common.items.mineral.gem.emerald"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.elegant_crest"), 1, 3)),
(1.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.large_horn"), 1, 3)),
(5.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 2, 6)),
]

View File

@ -1,6 +0,0 @@
[
(1.0, MultiDrop(Item("common.items.food.meat.bird_large_raw"), 1, 2)),
(1.0, MultiDrop(Item("common.items.food.meat.beast_large_raw"), 2, 2)),
(2.0, MultiDrop(Item("common.items.crafting_ing.animal_misc.elegant_crest"), 1, 3)),
(1.0, MultiDrop(Item("common.items.crafting_ing.hide.scales"), 2, 6)),
]

View File

@ -1,6 +1,5 @@
[ [
(1.0, MultiDrop(Item("common.items.crafting_ing.cloth.sunsilk"), 1, 3)), (1.0, MultiDrop(Item("common.items.crafting_ing.cloth.sunsilk"), 1, 3)),
(1.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 3, 8)),
(1.0, MultiDrop(Item("common.items.mineral.ingot.orichalcum"), 1, 3)), (1.0, MultiDrop(Item("common.items.mineral.ingot.orichalcum"), 1, 3)),
(1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)), (1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)),
] ]

View File

@ -8,6 +8,5 @@
(1.0, LootTable("common.loot_tables.weapons.legendary_melee")), (1.0, LootTable("common.loot_tables.weapons.legendary_melee")),
// Crafting material // Crafting material
// Allow for DS and Eldwood to drop till entity droppers are implemented // Allow for DS and Eldwood to drop till entity droppers are implemented
(1.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 3, 8)),
(1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)), (1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)),
] ]

View File

@ -13,6 +13,5 @@
// Crafting material // Crafting material
// Allow for DS and Eldwood to drop till entity droppers are implemented // Allow for DS and Eldwood to drop till entity droppers are implemented
(1.0, Item("common.items.crafting_ing.mindflayer_bag_damaged")), (1.0, Item("common.items.crafting_ing.mindflayer_bag_damaged")),
(1.0, MultiDrop(Item("common.items.crafting_ing.hide.dragon_scale"), 3, 8)),
(1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)), (1.0, MultiDrop(Item("common.items.log.eldwood"), 2, 6)),
] ]

View File

@ -1430,12 +1430,18 @@
threshold: 1.25, threshold: 1.25,
subtitle: "subtitle-attack-laser_beam", subtitle: "subtitle-attack-laser_beam",
), ),
Woosh: ( Whoosh: (
files: [ files: [
"voxygen.audio.sfx.abilities.woosh", "voxygen.audio.sfx.abilities.whoosh",
], ],
threshold: 0.4, threshold: 0.4,
), ),
Swoosh: (
files: [
"voxygen.audio.sfx.abilities.swoosh",
],
threshold: 1.3,
),
CyclopsCharge: ( CyclopsCharge: (
files: [ files: [
"voxygen.audio.sfx.abilities.cyclops_charge", "voxygen.audio.sfx.abilities.cyclops_charge",
@ -1518,6 +1524,13 @@
threshold: 1.0, threshold: 1.0,
subtitle: "subtitle-utterance-bird-angry", subtitle: "subtitle-utterance-bird-angry",
), ),
Utterance(Angry, Wyvern): (
files: [
"voxygen.audio.sfx.utterance.wyvern_angry",
],
threshold: 1.3,
subtitle: "subtitle-utterance-wyvern-angry",
),
Utterance(Angry, Adlet): ( Utterance(Angry, Adlet): (
files: [ files: [
"voxygen.audio.sfx.utterance.adlet_angry1", "voxygen.audio.sfx.utterance.adlet_angry1",
@ -1719,6 +1732,13 @@
threshold: 1.0, threshold: 1.0,
subtitle: "subtitle-utterance-asp-hurt", subtitle: "subtitle-utterance-asp-hurt",
), ),
Utterance(Hurt, Wyvern): (
files: [
"voxygen.audio.sfx.utterance.wyvern_hurt",
],
threshold: 1.2,
subtitle: "subtitle-utterance-wyvern-hurt",
),
Utterance(Angry, Wendigo): ( Utterance(Angry, Wendigo): (
files: [ files: [
"voxygen.audio.sfx.utterance.wendigo_angry1", "voxygen.audio.sfx.utterance.wendigo_angry1",

BIN
assets/voxygen/audio/sfx/abilities/swoosh.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/utterance/wyvern_angry.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/utterance/wyvern_hurt.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -149,3 +149,5 @@ subtitle-utterance-wendigo-angry = Wendigo screaming
subtitle-utterance-wendigo-calm = Wendigo mumbling subtitle-utterance-wendigo-calm = Wendigo mumbling
subtitle-utterance-wolf-angry = Wolf growling subtitle-utterance-wolf-angry = Wolf growling
subtitle-utterance-wolf-hurt = Wolf whining subtitle-utterance-wolf-hurt = Wolf whining
subtitle-utterance-wyvern-angry = Wyvern roaring
subtitle-utterance-wyvern-hurt = Wyvern hurting

View File

@ -82,6 +82,7 @@ const int POTION_SICKNESS = 41;
const int GIGA_SNOW = 42; const int GIGA_SNOW = 42;
const int CYCLOPS_CHARGE = 43; const int CYCLOPS_CHARGE = 43;
const int PORTAL_FIZZ = 45; const int PORTAL_FIZZ = 45;
const int INK = 46;
// meters per second squared (acceleration) // meters per second squared (acceleration)
const float earth_gravity = 9.807; const float earth_gravity = 9.807;
@ -691,6 +692,17 @@ void main() {
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
); );
break; break;
case INK:
f_reflect = 0.0; // Magic water doesn't reflect light, it emits it
float black_color = 0.3 + 0.2 * rand3 + 0.3 * max(floor(rand4 + 0.3), 0.0);
float ink_size = 8.0 * (1 - slow_start(0.1)) * slow_end(0.15);
attr = Attr(
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
vec3(ink_size),
vec4(0.5 * black_color, 0.75 * black_color, black_color, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
);
break;
default: default:
attr = Attr( attr = Attr(
linear_motion( linear_motion(

View File

@ -939,6 +939,26 @@
central: ("armor.empty"), central: ("armor.empty"),
) )
), ),
LightningBolt: (
bone0: (
offset: (-4.5, -80.0, -3.0),
central: ("weapon.projectile.lightning_bolt"),
),
bone1: (
offset: (0.0, 0.0, 0.0),
central: ("armor.empty"),
)
),
SpearIcicle: (
bone0: (
offset: (-2.5, -30.0, -2.5),
central: ("weapon.projectile.icicle-spear"),
),
bone1: (
offset: (0.0, 0.0, 0.0),
central: ("armor.empty"),
)
),
AdletSpear: ( AdletSpear: (
bone0: ( bone0: (
offset: (5.0, -22.0, -2.0), offset: (5.0, -22.0, -2.0),

BIN
assets/voxygen/voxel/weapon/projectile/icicle-spear.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/weapon/projectile/lightning_bolt.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -354,7 +354,7 @@ impl<'a> From<&'a Body> for Psyche {
bird_medium::Species::Puffin => 0.8, bird_medium::Species::Puffin => 0.8,
bird_medium::Species::Toucan => 0.4, bird_medium::Species::Toucan => 0.4,
}, },
Body::BirdLarge(_) => 0.1, Body::BirdLarge(_) => 0.0,
Body::FishSmall(_) => 1.0, Body::FishSmall(_) => 1.0,
Body::FishMedium(_) => 0.75, Body::FishMedium(_) => 0.75,
Body::BipedLarge(_) => 0.0, Body::BipedLarge(_) => 0.0,
@ -380,7 +380,10 @@ impl<'a> From<&'a Body> for Psyche {
arthropod::Species::Emberfly => 0.1, arthropod::Species::Emberfly => 0.1,
}, },
}, },
sight_dist: 40.0, sight_dist: match body {
Body::BirdLarge(_) => 80.0,
_ => 40.0,
},
listen_dist: 30.0, listen_dist: 30.0,
aggro_dist: match body { aggro_dist: match body {
Body::Humanoid(_) => Some(20.0), Body::Humanoid(_) => Some(20.0),

View File

@ -55,4 +55,7 @@ pub enum FrontendSpecifier {
Steam, Steam,
Frost, Frost,
WebStrand, WebStrand,
Poison,
Ink,
Lightning,
} }

View File

@ -108,6 +108,8 @@ make_case_elim!(
AdletTrap = 93, AdletTrap = 93,
Flamethrower = 94, Flamethrower = 94,
Mine = 95, Mine = 95,
LightningBolt = 96,
SpearIcicle = 97,
} }
); );
@ -118,7 +120,7 @@ impl Body {
} }
} }
pub const ALL_OBJECTS: [Body; 96] = [ pub const ALL_OBJECTS: [Body; 98] = [
Body::Arrow, Body::Arrow,
Body::Bomb, Body::Bomb,
Body::Scarecrow, Body::Scarecrow,
@ -215,6 +217,8 @@ pub const ALL_OBJECTS: [Body; 96] = [
Body::AdletTrap, Body::AdletTrap,
Body::Flamethrower, Body::Flamethrower,
Body::Mine, Body::Mine,
Body::LightningBolt,
Body::SpearIcicle,
]; ];
impl From<Body> for super::Body { impl From<Body> for super::Body {
@ -320,6 +324,8 @@ impl Body {
Body::AdletTrap => "adlet_trap", Body::AdletTrap => "adlet_trap",
Body::Flamethrower => "flamethrower", Body::Flamethrower => "flamethrower",
Body::Mine => "mine", Body::Mine => "mine",
Body::LightningBolt => "lightning_bolt",
Body::SpearIcicle => "spear_icicle",
} }
} }
@ -372,11 +378,8 @@ impl Body {
Body::BedBlue => 50.0, Body::BedBlue => 50.0,
Body::Bedroll => 3.0, Body::Bedroll => 3.0,
Body::Bench => 100.0, Body::Bench => 100.0,
Body::BoltFire Body::BoltFire | Body::BoltFireBig | Body::BoltNature | Body::BoltIcicle => 1.0,
| Body::BoltFireBig Body::SpitPoison => 100.0,
| Body::BoltNature
| Body::BoltIcicle
| Body::SpitPoison => 1.0,
Body::Bomb | Body::DagonBomb => { Body::Bomb | Body::DagonBomb => {
0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3) 0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
}, },
@ -446,6 +449,7 @@ impl Body {
Body::AdletSpear => 1.5, Body::AdletSpear => 1.5,
Body::AdletTrap => 10.0, Body::AdletTrap => 10.0,
Body::Mine => 100.0, Body::Mine => 100.0,
Body::LightningBolt | Body::SpearIcicle => 20000.0,
}; };
Mass(m) Mass(m)
@ -477,6 +481,7 @@ impl Body {
Body::IceBomb => Vec3::broadcast(2.5), Body::IceBomb => Vec3::broadcast(2.5),
Body::LaserBeam => Vec3::new(8.0, 8.0, 8.0), Body::LaserBeam => Vec3::new(8.0, 8.0, 8.0),
Body::Mine => Vec3::new(0.8, 0.8, 0.5), Body::Mine => Vec3::new(0.8, 0.8, 0.5),
Body::LightningBolt | Body::SpearIcicle => Vec3::new(1.0, 1.0, 1.0),
// FIXME: this *must* be exhaustive match // FIXME: this *must* be exhaustive match
_ => Vec3::broadcast(0.5), _ => Vec3::broadcast(0.5),
} }

View File

@ -91,12 +91,7 @@ pub enum ProjectileConstructor {
knockback: f32, knockback: f32,
min_falloff: f32, min_falloff: f32,
}, },
SeaBomb { InkBomb {
damage: f32,
radius: f32,
min_falloff: f32,
},
WindBomb {
damage: f32, damage: f32,
radius: f32, radius: f32,
min_falloff: f32, min_falloff: f32,
@ -527,7 +522,7 @@ impl ProjectileConstructor {
is_point: true, is_point: true,
} }
}, },
SeaBomb { InkBomb {
damage, damage,
radius, radius,
min_falloff, min_falloff,
@ -541,12 +536,27 @@ impl ProjectileConstructor {
Some(GroupTarget::OutOfGroup), Some(GroupTarget::OutOfGroup),
instance, instance,
); );
let buff = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Buff(CombatBuff {
kind: BuffKind::Wet,
dur_secs: 8.0,
strength: CombatBuffStrength::Value(0.5),
chance: 1.0,
})
.adjusted_by_stats(tool_stats),
)
.with_requirement(CombatRequirement::AnyDamage);
let attack = Attack::default() let attack = Attack::default()
.with_damage(damage) .with_damage(damage)
.with_crit(crit_chance, crit_mult) .with_crit(crit_chance, crit_mult)
.with_effect(buff)
.with_combo_increment(); .with_combo_increment();
let explosion = Explosion { let explosion = Explosion {
effects: vec![RadiusEffect::Attack(attack)], effects: vec![
RadiusEffect::Attack(attack),
RadiusEffect::TerrainDestruction(18.0, Rgb::new(4.0, 7.0, 32.0)),
],
radius, radius,
reagent: Some(Reagent::Blue), reagent: Some(Reagent::Blue),
min_falloff, min_falloff,
@ -561,40 +571,6 @@ impl ProjectileConstructor {
is_point: true, is_point: true,
} }
}, },
WindBomb {
damage,
radius,
min_falloff,
} => {
let damage = AttackDamage::new(
Damage {
source: DamageSource::Explosion,
kind: DamageKind::Energy,
value: damage,
},
Some(GroupTarget::OutOfGroup),
instance,
);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_combo_increment();
let explosion = Explosion {
effects: vec![RadiusEffect::Attack(attack)],
radius,
reagent: Some(Reagent::White),
min_falloff,
};
Projectile {
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
hit_entity: vec![Effect::Explode(explosion), Effect::Vanish],
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
is_sticky: true,
is_point: true,
}
},
Snowball { Snowball {
damage, damage,
radius, radius,
@ -982,15 +958,7 @@ impl ProjectileConstructor {
*damage *= power; *damage *= power;
*radius *= range; *radius *= range;
}, },
SeaBomb { InkBomb {
ref mut damage,
ref mut radius,
..
} => {
*damage *= power;
*radius *= range;
},
WindBomb {
ref mut damage, ref mut damage,
ref mut radius, ref mut radius,
.. ..
@ -1068,8 +1036,7 @@ impl ProjectileConstructor {
Snowball { .. } => true, Snowball { .. } => true,
ExplodingPumpkin { .. } => true, ExplodingPumpkin { .. } => true,
DagonBomb { .. } => true, DagonBomb { .. } => true,
SeaBomb { .. } => true, InkBomb { .. } => true,
WindBomb { .. } => true,
IceBomb { .. } => true, IceBomb { .. } => true,
LaserBeam { .. } => true, LaserBeam { .. } => true,
Trap { .. } => false, Trap { .. } => false,

View File

@ -49,6 +49,10 @@ pub enum FrontendSpecifier {
Ground, Ground,
Fire, Fire,
Water, Water,
Ice,
IceSpikes, IceSpikes,
Steam, Steam,
Poison,
Ink,
Lightning,
} }

View File

@ -128,7 +128,10 @@ pub enum Outcome {
FailedSpriteUnlock { FailedSpriteUnlock {
pos: Vec3<i32>, pos: Vec3<i32>,
}, },
Woosh { Whoosh {
pos: Vec3<f32>,
},
Swoosh {
pos: Vec3<f32>, pos: Vec3<f32>,
}, },
FireShockwave { FireShockwave {
@ -152,7 +155,8 @@ impl Outcome {
| Outcome::PoiseChange { pos, .. } | Outcome::PoiseChange { pos, .. }
| Outcome::GroundSlam { pos } | Outcome::GroundSlam { pos }
| Outcome::FlashFreeze { pos } | Outcome::FlashFreeze { pos }
| Outcome::Woosh { pos } | Outcome::Whoosh { pos }
| Outcome::Swoosh { pos }
| Outcome::IceSpikes { pos } | Outcome::IceSpikes { pos }
| Outcome::Steam { pos } | Outcome::Steam { pos }
| Outcome::FireShockwave { pos } | Outcome::FireShockwave { pos }

View File

@ -75,7 +75,7 @@ impl CharacterBehavior for Data {
}); });
if let Some(FrontendSpecifier::ElderLeap) = self.static_data.specifier { if let Some(FrontendSpecifier::ElderLeap) = 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::Woosh { output_events.emit_local(LocalEvent::CreateOutcome(Outcome::Whoosh {
pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()), pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()),
})); }));
} }

View File

@ -173,7 +173,11 @@ impl CharacterBehavior for Data {
}, },
)); ));
}, },
_ => {}, _ => {
output_events.emit_local(LocalEvent::CreateOutcome(Outcome::Swoosh {
pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()),
}));
},
} }
} else { } else {
// Transitions to recover // Transitions to recover

View File

@ -29,7 +29,7 @@ use std::{
/// Note that this number does *not* need incrementing on every change: most /// Note that this number does *not* need incrementing on every change: most
/// field removals/additions are fine. This number should only be incremented /// field removals/additions are fine. This number should only be incremented
/// when we wish to perform a *hard purge* of rtsim data. /// when we wish to perform a *hard purge* of rtsim data.
pub const CURRENT_VERSION: u32 = 3; pub const CURRENT_VERSION: u32 = 4;
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
pub struct Data { pub struct Data {

View File

@ -218,6 +218,11 @@ impl Data {
comp::body::bird_large::Species::Phoenix, comp::body::bird_large::Species::Phoenix,
comp::body::bird_large::Species::Cockatrice, comp::body::bird_large::Species::Cockatrice,
comp::body::bird_large::Species::Roc, comp::body::bird_large::Species::Roc,
comp::body::bird_large::Species::FlameWyvern,
comp::body::bird_large::Species::CloudWyvern,
comp::body::bird_large::Species::FrostWyvern,
comp::body::bird_large::Species::SeaWyvern,
comp::body::bird_large::Species::WealdWyvern,
] ]
.choose(&mut rng) .choose(&mut rng)
.unwrap(); .unwrap();

View File

@ -1147,45 +1147,74 @@ fn humanoid() -> impl Action<DefaultState> {
} }
fn bird_large() -> impl Action<DefaultState> { fn bird_large() -> impl Action<DefaultState> {
choose(|ctx, _| { now(|ctx, bearing: &mut Vec2<f32>| {
let data = ctx.state.data(); *bearing = bearing
if let Some(home) = ctx.npc.home { .map(|e| e + ctx.rng.gen_range(-0.1..0.1))
let is_home = ctx.npc.current_site.map_or(false, |site| home == site); .try_normalized()
let goto = |wpos| { .unwrap_or_default();
casual(goto_2d_flying( let bearing_dist = 24.0;
wpos, let mut pos = ctx.npc.wpos.xy() + *bearing * bearing_dist;
1.0, let is_deep_water = ctx
20.0, .world
32.0, .sim()
22.0, .get_interpolated(pos.as_(), |c| c.alt - c.water_alt)
ctx.npc.body.flying_height(), .unwrap_or(f32::NEG_INFINITY)
)) < -120.0
}; && ctx
if is_home { .world
if let Some((_, site)) = data .sim()
.sites .get(pos.as_().wpos_to_cpos())
.iter() .map_or(false, |c| c.river.is_ocean() || c.river.is_lake());
.filter(|(id, site)| { // when high tree_density fly high, otherwise fly low-mid
*id != home let npc_pos = ctx.npc.wpos.xy();
&& site.world_site.map_or(false, |site| { let tree_density = ctx
matches!(ctx.index.sites.get(site).kind, SiteKind::Dungeon(_)) .world
}) .sim()
}) .get_interpolated(npc_pos.as_(), |c| c.tree_density)
.choose(&mut ctx.rng) .unwrap_or(1.0);
{ let height_factor = if tree_density > 0.1 {
goto(site.wpos.as_::<f32>()) 2.0
} else {
casual(idle())
}
} else if let Some(site) = data.sites.get(home) {
goto(site.wpos.as_::<f32>())
} else {
casual(idle())
}
} else { } else {
casual(idle()) ctx.rng.gen_range(0.1..0.5)
};
if !is_deep_water {
goto_2d_flying(
pos,
0.2,
bearing_dist,
8.0,
8.0,
ctx.npc.body.flying_height() * height_factor,
)
} else {
*bearing *= -1.0;
pos = ctx.npc.wpos.xy() + *bearing * 24.0;
goto_2d_flying(
pos,
0.2,
bearing_dist,
8.0,
8.0,
ctx.npc.body.flying_height() * height_factor,
)
} }
// If we are too far away from our goal position we can stop since we aren't going to a specific place.
.stop_if(move |ctx: &mut NpcCtx| {
ctx.npc.wpos.xy().distance_squared(pos) > (bearing_dist + 5.0).powi(2)
})
// If goal position wasn't reached within 20 seconds we're probably stuck and need to find a new goal position.
.stop_if(timeout(10.0))
.debug({
let bearing = *bearing;
move || format!("Moving with a bearing of {:?}", bearing)
})
}) })
.repeat()
.with_state(Vec2::<f32>::zero())
.map(|_, _| ())
} }
fn monster() -> impl Action<DefaultState> { fn monster() -> impl Action<DefaultState> {

View File

@ -106,68 +106,6 @@ impl<'a> AgentData<'a> {
} }
} }
pub fn handle_wyvern_attack(
&self,
_agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
_rng: &mut impl Rng,
) {
// Fly to target
let dir_to_target = ((tgt_data.pos.0 + Vec3::unit_z() * 1.5) - self.pos.0)
.try_normalized()
.unwrap_or_else(Vec3::zero);
let speed = 1.0;
controller.inputs.move_dir = dir_to_target.xy() * speed;
// Always fly! If the floor can't touch you, it can't hurt you...
controller.push_basic_input(InputKind::Fly);
// Flee from the ground! The internet told me it was lava!
// If on the ground, jump with every last ounce of energy, holding onto all that
// is dear in life and straining for the wide open skies.
if self.physics_state.on_ground.is_some() {
controller.push_basic_input(InputKind::Jump);
} else {
// Only fly down if close enough to target in the xy plane
// Otherwise fly towards the target bouncing around a 5 block altitude
let mut maintain_altitude = |altitude| {
if read_data
.terrain
.ray(self.pos.0, self.pos.0 - (Vec3::unit_z() * altitude))
.until(Block::is_solid)
.cast()
.1
.map_or(true, |b| b.is_some())
{
// Fly up
controller.inputs.move_z = 1.0;
} else {
// Fly down
controller.inputs.move_z = -1.0;
}
};
if (tgt_data.pos.0 - self.pos.0).xy().magnitude_squared() > (30.0_f32).powi(2) {
// If above 30 blocks, fly down and attack
maintain_altitude(30.0);
// Shoot bombs
controller.push_basic_input(InputKind::Primary);
} else {
maintain_altitude(2.0);
// Attack if in range
if attack_data.dist_sqrd < 6.0_f32.powi(2) && attack_data.angle < 150.0 {
controller.push_basic_input(InputKind::Ability(0));
} else if attack_data.dist_sqrd < 8.0_f32.powi(2) && attack_data.angle < 150.0 {
controller.push_basic_input(InputKind::Ability(1));
} else if attack_data.dist_sqrd < 12.0_f32.powi(2) && attack_data.angle < 150.0 {
controller.push_basic_input(InputKind::Secondary);
}
}
}
}
// Intended for any agent that has one attack, that attack is a melee attack, // Intended for any agent that has one attack, that attack is a melee attack,
// the agent is able to freely walk around, and the agent is trying to attack // the agent is able to freely walk around, and the agent is trying to attack
// from behind its target // from behind its target
@ -3034,27 +2972,26 @@ impl<'a> AgentData<'a> {
attack_data: &AttackData, attack_data: &AttackData,
tgt_data: &TargetData, tgt_data: &TargetData,
read_data: &ReadData, read_data: &ReadData,
rng: &mut impl Rng, _rng: &mut impl Rng,
) { ) {
enum ActionStateTimers {
AttackTimer = 0,
}
// Set fly to false
controller.push_cancel_input(InputKind::Fly);
if attack_data.dist_sqrd > 30.0_f32.powi(2) { if attack_data.dist_sqrd > 30.0_f32.powi(2) {
let small_chance = rng.gen_bool(0.05); if entities_have_line_of_sight(
self.pos,
if small_chance self.body,
&& entities_have_line_of_sight( self.scale,
self.pos, tgt_data.pos,
self.body, tgt_data.body,
self.scale, tgt_data.scale,
tgt_data.pos, read_data,
tgt_data.body, ) && attack_data.angle < 15.0
tgt_data.scale,
read_data,
)
&& attack_data.angle < 15.0
{ {
// Fireball
controller.push_basic_input(InputKind::Primary); controller.push_basic_input(InputKind::Primary);
} }
// If some target
if let Some((bearing, speed)) = agent.chaser.chase( if let Some((bearing, speed)) = agent.chaser.chase(
&*read_data.terrain, &*read_data.terrain,
self.pos.0, self.pos.0,
@ -3065,23 +3002,14 @@ impl<'a> AgentData<'a> {
..self.traversal_config ..self.traversal_config
}, },
) { ) {
// Walk to target
controller.inputs.move_dir = controller.inputs.move_dir =
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
// If less than 20 blocks higher than target
if (self.pos.0.z - tgt_data.pos.0.z) < 20.0 { if (self.pos.0.z - tgt_data.pos.0.z) < 20.0 {
// Fly upward
controller.push_basic_input(InputKind::Fly); controller.push_basic_input(InputKind::Fly);
controller.inputs.move_z = 1.0; controller.inputs.move_z = 1.0;
} else {
// Jump
self.jump_if(bearing.z > 1.5, controller);
controller.inputs.move_z = bearing.z;
} }
} }
} } else if !read_data
// If higher than 2 blocks
else if !read_data
.terrain .terrain
.ray(self.pos.0, self.pos.0 - (Vec3::unit_z() * 2.0)) .ray(self.pos.0, self.pos.0 - (Vec3::unit_z() * 2.0))
.until(Block::is_solid) .until(Block::is_solid)
@ -3092,41 +3020,52 @@ impl<'a> AgentData<'a> {
// Do not increment the timer during this movement // Do not increment the timer during this movement
// The next stage shouldn't trigger until the entity // The next stage shouldn't trigger until the entity
// is on the ground // is on the ground
// Fly to target
controller.push_basic_input(InputKind::Fly); controller.push_basic_input(InputKind::Fly);
let move_dir = tgt_data.pos.0 - self.pos.0; let move_dir = tgt_data.pos.0 - self.pos.0;
controller.inputs.move_dir = controller.inputs.move_dir =
move_dir.xy().try_normalized().unwrap_or_else(Vec2::zero) * 2.0; move_dir.xy().try_normalized().unwrap_or_else(Vec2::zero) * 2.0;
controller.inputs.move_z = move_dir.z - 0.5; controller.inputs.move_z = move_dir.z - 0.5;
// If further than 4 blocks and random chance if attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2)
if rng.gen_bool(0.05)
&& attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2)
&& attack_data.angle < 15.0 && attack_data.angle < 15.0
{ {
// Fireball
controller.push_basic_input(InputKind::Primary); controller.push_basic_input(InputKind::Primary);
} }
} } else if attack_data.dist_sqrd > (3.0 * attack_data.min_attack_dist).powi(2) {
// If further than 4 blocks and random chance self.path_toward_target(
else if rng.gen_bool(0.05) agent,
&& attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2) controller,
tgt_data.pos.0,
read_data,
Path::Separate,
None,
);
} else if self.energy.current() > 60.0
&& agent.action_state.timers[ActionStateTimers::AttackTimer as usize] < 3.0
&& attack_data.angle < 15.0 && attack_data.angle < 15.0
{ {
// Fireball // Shockwave
controller.push_basic_input(InputKind::Primary); controller.push_basic_input(InputKind::Ability(0));
} // Move towards the target slowly
// If random chance and less than 20 blocks higher than target and further than 4 self.path_toward_target(
// blocks agent,
else if rng.gen_bool(0.5) controller,
&& (self.pos.0.z - tgt_data.pos.0.z) < 15.0 tgt_data.pos.0,
&& attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2) read_data,
Path::Separate,
Some(0.5),
);
agent.action_state.timers[ActionStateTimers::AttackTimer as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::AttackTimer as usize] < 6.0
&& attack_data.angle < 90.0
&& attack_data.in_min_range()
{ {
controller.push_basic_input(InputKind::Fly); // Triple strike
controller.inputs.move_z = 1.0; controller.push_basic_input(InputKind::Secondary);
} agent.action_state.timers[ActionStateTimers::AttackTimer as usize] += read_data.dt.0;
// If further than 2.5 blocks and random chance } else {
else if attack_data.dist_sqrd > (2.5 * attack_data.min_attack_dist).powi(2) { // Reset timer
// Walk to target agent.action_state.timers[ActionStateTimers::AttackTimer as usize] = 0.0;
// Target is behind us or the timer needs to be reset. Chase target
self.path_toward_target( self.path_toward_target(
agent, agent,
controller, controller,
@ -3136,15 +3075,113 @@ impl<'a> AgentData<'a> {
None, None,
); );
} }
// If energy higher than 600 and random chance }
else if self.energy.current() > 60.0 && rng.gen_bool(0.4) {
// Shockwave pub fn handle_wyvern_attack(
controller.push_basic_input(InputKind::Ability(0)); &self,
} else if attack_data.angle < 90.0 { agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
_rng: &mut impl Rng,
) {
enum ActionStateTimers {
AttackTimer = 0,
}
// Set fly to false
controller.push_cancel_input(InputKind::Fly);
if attack_data.dist_sqrd > 30.0_f32.powi(2) {
if entities_have_line_of_sight(
self.pos,
self.body,
self.scale,
tgt_data.pos,
tgt_data.body,
tgt_data.scale,
read_data,
) && attack_data.angle < 15.0
{
controller.push_basic_input(InputKind::Primary);
}
if let Some((bearing, speed)) = agent.chaser.chase(
&*read_data.terrain,
self.pos.0,
self.vel.0,
tgt_data.pos.0,
TraversalConfig {
min_tgt_dist: 1.25,
..self.traversal_config
},
) {
controller.inputs.move_dir =
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
if (self.pos.0.z - tgt_data.pos.0.z) < 35.0 {
controller.push_basic_input(InputKind::Fly);
controller.inputs.move_z = 1.0;
}
}
} else if !read_data
.terrain
.ray(self.pos.0, self.pos.0 - (Vec3::unit_z() * 2.0))
.until(Block::is_solid)
.cast()
.1
.map_or(true, |b| b.is_some())
{
// Do not increment the timer during this movement
// The next stage shouldn't trigger until the entity
// is on the ground
controller.push_basic_input(InputKind::Fly);
let move_dir = tgt_data.pos.0 - self.pos.0;
controller.inputs.move_dir =
move_dir.xy().try_normalized().unwrap_or_else(Vec2::zero) * 2.0;
controller.inputs.move_z = move_dir.z - 0.5;
if attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2)
&& attack_data.angle < 15.0
{
controller.push_basic_input(InputKind::Primary);
}
} else if attack_data.dist_sqrd > (3.0 * attack_data.min_attack_dist).powi(2) {
self.path_toward_target(
agent,
controller,
tgt_data.pos.0,
read_data,
Path::Separate,
None,
);
} else if attack_data.angle < 15.0 {
if agent.action_state.timers[ActionStateTimers::AttackTimer as usize] < 5.0 {
// beam
controller.push_basic_input(InputKind::Ability(1));
} else if agent.action_state.timers[ActionStateTimers::AttackTimer as usize] < 9.0 {
// shockwave
controller.push_basic_input(InputKind::Ability(0));
} else {
agent.action_state.timers[ActionStateTimers::AttackTimer as usize] = 0.0;
}
// Move towards the target slowly
self.path_toward_target(
agent,
controller,
tgt_data.pos.0,
read_data,
Path::Separate,
Some(0.5),
);
agent.action_state.timers[ActionStateTimers::AttackTimer as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::AttackTimer as usize] < 9.0
&& attack_data.angle < 90.0
&& attack_data.in_min_range()
{
// Triple strike // Triple strike
controller.push_basic_input(InputKind::Secondary); controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::AttackTimer as usize] += read_data.dt.0;
} else { } else {
// Target is behind us. Turn around and chase target // Reset timer
agent.action_state.timers[ActionStateTimers::AttackTimer as usize] = 0.0;
// Target is behind us or the timer needs to be reset. Chase target
self.path_toward_target( self.path_toward_target(
agent, agent,
controller, controller,
@ -3201,9 +3238,6 @@ impl<'a> AgentData<'a> {
if (self.pos.0.z - tgt_data.pos.0.z) < 20.0 { if (self.pos.0.z - tgt_data.pos.0.z) < 20.0 {
controller.push_basic_input(InputKind::Fly); controller.push_basic_input(InputKind::Fly);
controller.inputs.move_z = 1.0; controller.inputs.move_z = 1.0;
} else {
self.jump_if(bearing.z > 1.5, controller);
controller.inputs.move_z = bearing.z;
} }
} }
} else if !read_data } else if !read_data
@ -3311,22 +3345,7 @@ impl<'a> AgentData<'a> {
// Increase action timer // Increase action timer
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] += agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] +=
read_data.dt.0; read_data.dt.0;
// If higher than 2 blocks if agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] > 8.0 {
if !read_data
.terrain
.ray(self.pos.0, self.pos.0 - (Vec3::unit_z() * 2.0))
.until(Block::is_solid)
.cast()
.1
.map_or(true, |b| b.is_some())
{
// Fly to target and land
controller.push_basic_input(InputKind::Fly);
let move_dir = tgt_data.pos.0 - self.pos.0;
controller.inputs.move_dir =
move_dir.xy().try_normalized().unwrap_or_else(Vec2::zero) * 2.0;
controller.inputs.move_z = move_dir.z - 0.5;
} else if agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] > 8.0 {
// If action timer higher than 8, make bird summon tornadoes // If action timer higher than 8, make bird summon tornadoes
controller.push_basic_input(InputKind::Secondary); controller.push_basic_input(InputKind::Secondary);
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover)) if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))

View File

@ -165,9 +165,19 @@ fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef) -> EntityInfo
comp::bird_large::Species::Phoenix => "common.entity.wild.peaceful.phoenix", comp::bird_large::Species::Phoenix => "common.entity.wild.peaceful.phoenix",
comp::bird_large::Species::Cockatrice => "common.entity.wild.aggressive.cockatrice", comp::bird_large::Species::Cockatrice => "common.entity.wild.aggressive.cockatrice",
comp::bird_large::Species::Roc => "common.entity.wild.aggressive.roc", comp::bird_large::Species::Roc => "common.entity.wild.aggressive.roc",
// Wildcard match used here as there is an array above comp::bird_large::Species::CloudWyvern => {
// which limits what species are used "common.entity.wild.aggressive.cloudwyvern"
_ => unimplemented!(), },
comp::bird_large::Species::FlameWyvern => {
"common.entity.wild.aggressive.flamewyvern"
},
comp::bird_large::Species::FrostWyvern => {
"common.entity.wild.aggressive.frostwyvern"
},
comp::bird_large::Species::SeaWyvern => "common.entity.wild.aggressive.seawyvern",
comp::bird_large::Species::WealdWyvern => {
"common.entity.wild.aggressive.wealdwyvern"
},
}, },
Body::BipedLarge(body) => match body.species { Body::BipedLarge(body) => match body.species {
comp::biped_large::Species::Ogre => "common.entity.wild.aggressive.ogre", comp::biped_large::Species::Ogre => "common.entity.wild.aggressive.ogre",

View File

@ -0,0 +1,149 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::states::utils::StageSection;
pub struct ComboAnimation;
impl Animation for ComboAnimation {
type Dependency<'a> = (
Option<&'a str>,
Option<StageSection>,
usize,
f32,
f32,
Vec3<f32>,
Vec3<f32>,
bool,
);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_combo\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_combo")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(
_ability_id,
stage_section,
current_strike,
global_time,
timer,
orientation,
last_ori,
on_ground,
): Self::Dependency<'_>,
anim_time: f32,
rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
*rate = 1.0;
let mut next = (*skeleton).clone();
let multi_strike_pullback = 1.0
- if matches!(stage_section, Some(StageSection::Recover)) {
anim_time.powi(4)
} else {
0.0
};
let (move1base, move2base, _move3) = match stage_section {
Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0),
Some(StageSection::Action) => (1.0, anim_time, 0.0),
Some(StageSection::Recover) => (1.0, 1.0, anim_time.powf(4.0)),
_ => (0.0, 0.0, 0.0),
};
let wave_slow_cos = (anim_time * 4.5).cos();
let subtract = global_time - timer;
let check = subtract - subtract.trunc();
let mirror = (check - 0.5).signum();
let move1 = move1base * multi_strike_pullback;
let move2 = move2base * multi_strike_pullback;
let move1mirror = move1base * multi_strike_pullback * mirror;
let ori: Vec2<f32> = Vec2::from(orientation);
let last_ori = Vec2::from(last_ori);
let tilt = if vek::Vec2::new(ori, last_ori)
.map(|o| o.magnitude_squared())
.map(|m| m > 0.001 && m.is_finite())
.reduce_and()
&& ori.angle_between(last_ori).is_finite()
{
ori.angle_between(last_ori).min(0.2)
* last_ori.determine_side(Vec2::zero(), ori).signum()
} else {
0.0
} * 1.3;
for strike in 0..=current_strike {
match strike {
0..=2 => {
next.chest.position = Vec3::new(
0.0,
s_a.chest.0,
s_a.chest.1 + wave_slow_cos * 0.06 + move2 * -6.0,
);
next.chest.orientation = Quaternion::rotation_x(move1 * 0.5 - move2 * 0.8);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation = Quaternion::rotation_x(move1 * 0.5 - move2 * 0.4)
* Quaternion::rotation_z(move1 * tilt * 1.5)
* Quaternion::rotation_y(move1mirror * 0.3);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_x(move1 * -0.2 - move2 * 0.2)
* Quaternion::rotation_y(move1mirror * 0.5);
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
next.beak.orientation =
Quaternion::rotation_x(wave_slow_cos * -0.02 + move1 * -0.5 + move2 * 0.5);
if on_ground {
next.tail_front.position =
Vec3::new(0.0, s_a.tail_front.0, s_a.tail_front.1);
next.tail_front.orientation = Quaternion::rotation_x(-move1 * 0.2);
next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.1);
next.tail_rear.orientation = Quaternion::rotation_x(0.0);
next.wing_in_l.position =
Vec3::new(-s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
next.wing_in_r.position =
Vec3::new(s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
next.wing_in_l.orientation = Quaternion::rotation_y(
-1.0 + wave_slow_cos * 0.06 + move1 * 1.0 + move2 * 0.5,
) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation = Quaternion::rotation_y(
1.0 - wave_slow_cos * 0.06 + move1 * -1.0 + move2 * -0.5,
) * Quaternion::rotation_z(-0.2);
next.wing_mid_l.position =
Vec3::new(-s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
next.wing_mid_r.position =
Vec3::new(s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
next.wing_mid_l.orientation = Quaternion::rotation_y(-0.1 + move1 * -0.5)
* Quaternion::rotation_z(0.7 + move1 * -0.7);
next.wing_mid_r.orientation = Quaternion::rotation_y(0.1 + move1 * 0.5)
* Quaternion::rotation_z(-0.7 + move1 * 0.7);
next.wing_out_l.position =
Vec3::new(-s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
next.wing_out_r.position =
Vec3::new(s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
next.wing_out_l.orientation = Quaternion::rotation_y(-0.2 + move1 * -0.3)
* Quaternion::rotation_z(0.2);
next.wing_out_r.orientation = Quaternion::rotation_y(0.2 + move1 * 0.3)
* Quaternion::rotation_z(-0.2);
} else {
}
},
_ => {},
}
}
next
}
}

View File

@ -1,5 +1,6 @@
pub mod alpha; pub mod alpha;
pub mod breathe; pub mod breathe;
pub mod combomelee;
pub mod dash; pub mod dash;
pub mod feed; pub mod feed;
pub mod fly; pub mod fly;
@ -13,9 +14,10 @@ pub mod swim;
// Reexports // Reexports
pub use self::{ pub use self::{
alpha::AlphaAnimation, breathe::BreatheAnimation, dash::DashAnimation, feed::FeedAnimation, alpha::AlphaAnimation, breathe::BreatheAnimation, combomelee::ComboAnimation,
fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, dash::DashAnimation, feed::FeedAnimation, fly::FlyAnimation, idle::IdleAnimation,
shoot::ShootAnimation, stunned::StunnedAnimation, summon::SummonAnimation, swim::SwimAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, shoot::ShootAnimation,
stunned::StunnedAnimation, summon::SummonAnimation, swim::SwimAnimation,
}; };
use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton}; use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton};

View File

@ -93,7 +93,7 @@ use client::Client;
use common::{ use common::{
assets::{self, AssetExt, AssetHandle}, assets::{self, AssetExt, AssetHandle},
comp::{ comp::{
beam, biped_large, biped_small, humanoid, beam, biped_large, biped_small, bird_large, humanoid,
item::{AbilitySpec, ItemDefinitionId, ItemKind, ToolKind}, item::{AbilitySpec, ItemDefinitionId, ItemKind, ToolKind},
object, object,
poise::PoiseState, poise::PoiseState,
@ -178,9 +178,10 @@ pub enum SfxEvent {
Yeet, Yeet,
Klonk, Klonk,
SmashKlonk, SmashKlonk,
Woosh,
FireShockwave, FireShockwave,
DeepLaugh, DeepLaugh,
Whoosh,
Swoosh,
} }
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]
@ -213,6 +214,7 @@ pub enum VoiceKind {
Fungome, Fungome,
Truffler, Truffler,
Wolf, Wolf,
Wyvern,
} }
fn body_to_voice(body: &Body) -> Option<VoiceKind> { fn body_to_voice(body: &Body) -> Option<VoiceKind> {
@ -261,7 +263,15 @@ fn body_to_voice(body: &Body) -> Option<VoiceKind> {
quadruped_medium::Species::Antelope => VoiceKind::Antelope, quadruped_medium::Species::Antelope => VoiceKind::Antelope,
_ => return None, _ => return None,
}, },
Body::BirdMedium(_) | Body::BirdLarge(_) => VoiceKind::Bird, Body::BirdMedium(_) => VoiceKind::Bird,
Body::BirdLarge(body) => match body.species {
bird_large::Species::CloudWyvern
| bird_large::Species::FlameWyvern
| bird_large::Species::FrostWyvern
| bird_large::Species::SeaWyvern
| bird_large::Species::WealdWyvern => VoiceKind::Wyvern,
_ => VoiceKind::Bird,
},
Body::BipedSmall(body) => match body.species { Body::BipedSmall(body) => match body.species {
biped_small::Species::Adlet => VoiceKind::Adlet, biped_small::Species::Adlet => VoiceKind::Adlet,
biped_small::Species::Mandragora => VoiceKind::Mandragora, biped_small::Species::Mandragora => VoiceKind::Mandragora,
@ -510,12 +520,16 @@ impl SfxMgr {
Body::Object( Body::Object(
object::Body::BoltFire object::Body::BoltFire
| object::Body::BoltFireBig | object::Body::BoltFireBig
| object::Body::BoltNature, | object::Body::BoltNature
| object::Body::BoltIcicle
| object::Body::SpearIcicle
| object::Body::SpitPoison,
) => { ) => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FireShot); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FireShot);
audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); audio.emit_sfx(sfx_trigger_item, *pos, None, underwater);
}, },
Body::Object(object::Body::LaserBeam) => { Body::Object(object::Body::LaserBeam)
| Body::Object(object::Body::LightningBolt) => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::LaserBeam); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::LaserBeam);
audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); audio.emit_sfx(sfx_trigger_item, *pos, None, underwater);
}, },
@ -589,6 +603,10 @@ impl SfxMgr {
Outcome::Beam { pos, specifier } => match specifier { Outcome::Beam { pos, specifier } => match specifier {
beam::FrontendSpecifier::LifestealBeam beam::FrontendSpecifier::LifestealBeam
| beam::FrontendSpecifier::Steam | beam::FrontendSpecifier::Steam
| beam::FrontendSpecifier::Poison
| beam::FrontendSpecifier::Ink
| beam::FrontendSpecifier::Lightning
| beam::FrontendSpecifier::Frost
| beam::FrontendSpecifier::Bubbles => { | beam::FrontendSpecifier::Bubbles => {
if thread_rng().gen_bool(0.5) { if thread_rng().gen_bool(0.5) {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::SceptreBeam); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::SceptreBeam);
@ -601,9 +619,7 @@ impl SfxMgr {
audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); audio.emit_sfx(sfx_trigger_item, *pos, None, underwater);
} }
}, },
beam::FrontendSpecifier::ClayGolem beam::FrontendSpecifier::ClayGolem | beam::FrontendSpecifier::WebStrand => {},
| beam::FrontendSpecifier::Frost
| beam::FrontendSpecifier::WebStrand => {},
}, },
Outcome::SpriteUnlocked { pos } => { Outcome::SpriteUnlocked { pos } => {
// TODO: Dedicated sound effect! // TODO: Dedicated sound effect!
@ -719,8 +735,17 @@ impl SfxMgr {
_ => {}, _ => {},
}; };
}, },
Outcome::Woosh { pos, .. } => { Outcome::Whoosh { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Woosh); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Whoosh);
audio.emit_sfx(
sfx_trigger_item,
pos.map(|e| e + 0.5),
Some(3.0),
underwater,
);
},
Outcome::Swoosh { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Swoosh);
audio.emit_sfx( audio.emit_sfx(
sfx_trigger_item, sfx_trigger_item,
pos.map(|e| e + 0.5), pos.map(|e| e + 0.5),

View File

@ -97,6 +97,7 @@ pub enum ParticleMode {
CyclopsCharge = 43, CyclopsCharge = 43,
SnowStorm = 44, SnowStorm = 44,
PortalFizz = 45, PortalFizz = 45,
Ink = 46,
} }
impl ParticleMode { impl ParticleMode {

View File

@ -4944,38 +4944,36 @@ impl FigureMgr {
skeleton_attr, skeleton_attr,
) )
}, },
CharacterState::ComboMelee(s) => { CharacterState::ComboMelee2(s) => {
let stage_index = (s.stage - 1) as usize; let timer = s.timer.as_secs_f32();
let stage_time = s.timer.as_secs_f32(); let current_strike = s.completed_strikes % s.static_data.strikes.len();
let stage_progress = let strike_data = s.static_data.strikes[current_strike];
if let Some(stage) = s.static_data.stage_data.get(stage_index) { let progress = match s.stage_section {
match s.stage_section { StageSection::Buildup => {
StageSection::Buildup => { timer / strike_data.buildup_duration.as_secs_f32()
stage_time / stage.base_buildup_duration.as_secs_f32() },
}, StageSection::Action => {
StageSection::Action => { timer / strike_data.swing_duration.as_secs_f32()
stage_time / stage.base_swing_duration.as_secs_f32() },
}, StageSection::Recover => {
StageSection::Recover => { timer / strike_data.recover_duration.as_secs_f32()
stage_time / stage.base_recover_duration.as_secs_f32() },
}, _ => 0.0,
_ => 0.0, };
}
} else {
0.0
};
anim::bird_large::AlphaAnimation::update_skeleton( anim::bird_large::ComboAnimation::update_skeleton(
&target_base, &target_base,
( (
ability_id,
Some(s.stage_section), Some(s.stage_section),
current_strike,
time, time,
state.state_time, state.state_time,
ori * anim::vek::Vec3::<f32>::unit_y(), ori * anim::vek::Vec3::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(), state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
physics.on_ground.is_some(), physics.on_ground.is_some(),
), ),
stage_progress, progress,
&mut state_animation_rate, &mut state_animation_rate,
skeleton_attr, skeleton_attr,
) )

View File

@ -397,7 +397,8 @@ impl ParticleMgr {
| Outcome::IceSpikes { .. } | Outcome::IceSpikes { .. }
| Outcome::IceCrack { .. } | Outcome::IceCrack { .. }
| Outcome::Glider { .. } | Outcome::Glider { .. }
| Outcome::Woosh { .. } | Outcome::Whoosh { .. }
| Outcome::Swoosh { .. }
| Outcome::Steam { .. } | Outcome::Steam { .. }
| Outcome::FireShockwave { .. } | Outcome::FireShockwave { .. }
| Outcome::LaserBeam { .. } => {}, | Outcome::LaserBeam { .. } => {},
@ -1071,6 +1072,56 @@ impl ParticleMgr {
}, },
); );
}, },
beam::FrontendSpecifier::Poison => {
let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
self.particles.resize_with(
self.particles.len() + usize::from(beam_tick_count) / 15,
|| {
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
let theta: f32 = rng.gen_range(0.0..2.0 * PI);
let offset_z = Vec3::new(
phi.sin() * theta.cos(),
phi.sin() * theta.sin(),
phi.cos(),
);
let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0);
Particle::new_directed(
beam.properties.duration,
time,
ParticleMode::CultistFlame,
pos,
pos + random_ori * range,
)
},
);
},
beam::FrontendSpecifier::Ink => {
let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
self.particles.resize_with(
self.particles.len() + usize::from(beam_tick_count) / 15,
|| {
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
let theta: f32 = rng.gen_range(0.0..2.0 * PI);
let offset_z = Vec3::new(
phi.sin() * theta.cos(),
phi.sin() * theta.sin(),
phi.cos(),
);
let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0);
Particle::new_directed(
beam.properties.duration,
time,
ParticleMode::Ink,
pos,
pos + random_ori * range,
)
},
);
},
beam::FrontendSpecifier::Steam => { beam::FrontendSpecifier::Steam => {
let mut rng = thread_rng(); let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir()); let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
@ -1096,6 +1147,17 @@ impl ParticleMgr {
}, },
); );
}, },
beam::FrontendSpecifier::Lightning => {
self.particles.resize_with(self.particles.len() + 2, || {
Particle::new_directed(
beam.properties.duration,
time,
ParticleMode::Lightning,
pos,
pos + *ori.look_dir() * range,
)
})
},
beam::FrontendSpecifier::Frost => { beam::FrontendSpecifier::Frost => {
let mut rng = thread_rng(); let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir()); let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
@ -1943,6 +2005,41 @@ impl ParticleMgr {
} }
} }
}, },
FrontendSpecifier::Lightning => {
// 1 particle per unit length of arc
let particles_per_length = arc_length as usize;
let dtheta = radians / particles_per_length as f32;
// Scales number of desired heartbeats from speed - thicker arc = higher speed =
// lower duration = more particles
let heartbeats = self
.scheduler
.heartbeats(Duration::from_secs_f32(1.0 / speed));
// Reserves capacity for new particles
let new_particle_count = particles_per_length * heartbeats as usize;
self.particles.reserve(new_particle_count);
for i in 0..particles_per_length {
let angle = dtheta * i as f32;
let direction = Vec3::new(angle.cos(), angle.sin(), 0.0);
for j in 0..heartbeats {
// Sub tick dt
let dt = (j as f32 / heartbeats as f32) * dt;
let distance = distance + speed * dt;
let pos1 = pos + distance * direction - Vec3::unit_z();
let pos2 = pos1 + (Vec3::unit_z() + direction) * 3.0;
let time = time + dt as f64;
self.particles.push(Particle::new_directed(
Duration::from_secs_f32(0.5),
time,
ParticleMode::Lightning,
pos1,
pos2,
));
}
}
},
FrontendSpecifier::Steam => { FrontendSpecifier::Steam => {
// 1 particle per unit length of arc // 1 particle per unit length of arc
let particles_per_length = arc_length as usize; let particles_per_length = arc_length as usize;
@ -1978,7 +2075,77 @@ impl ParticleMgr {
} }
} }
}, },
FrontendSpecifier::IceSpikes => { FrontendSpecifier::Poison => {
// 1 particle per unit length of arc
let particles_per_length = arc_length as usize;
let dtheta = radians / particles_per_length as f32;
// Scales number of desired heartbeats from speed - thicker arc = higher speed =
// lower duration = more particles
let heartbeats = self
.scheduler
.heartbeats(Duration::from_secs_f32(1.0 / speed));
// Reserves capacity for new particles
let new_particle_count = particles_per_length * heartbeats as usize;
self.particles.reserve(new_particle_count);
for i in 0..particles_per_length {
let angle = dtheta * i as f32;
let direction = Vec3::new(angle.cos(), angle.sin(), 0.0);
for j in 0..heartbeats {
// Sub tick dt
let dt = (j as f32 / heartbeats as f32) * dt;
let distance = distance + speed * dt;
let pos1 = pos + distance * direction - Vec3::unit_z();
let pos2 = pos1 + (Vec3::unit_z() + direction) * 3.0;
let time = time + dt as f64;
self.particles.push(Particle::new_directed(
Duration::from_secs_f32(0.5),
time,
ParticleMode::CultistFlame,
pos1,
pos2,
));
}
}
},
FrontendSpecifier::Ink => {
// 1 particle per unit length of arc
let particles_per_length = arc_length as usize;
let dtheta = radians / particles_per_length as f32;
// Scales number of desired heartbeats from speed - thicker arc = higher speed =
// lower duration = more particles
let heartbeats = self
.scheduler
.heartbeats(Duration::from_secs_f32(1.0 / speed));
// Reserves capacity for new particles
let new_particle_count = particles_per_length * heartbeats as usize;
self.particles.reserve(new_particle_count);
for i in 0..particles_per_length {
let angle = dtheta * i as f32;
let direction = Vec3::new(angle.cos(), angle.sin(), 0.0);
for j in 0..heartbeats {
// Sub tick dt
let dt = (j as f32 / heartbeats as f32) * dt;
let distance = distance + speed * dt;
let pos1 = pos + distance * direction - Vec3::unit_z();
let pos2 = pos1 + (Vec3::unit_z() + direction) * 3.0;
let time = time + dt as f64;
self.particles.push(Particle::new_directed(
Duration::from_secs_f32(0.5),
time,
ParticleMode::Ink,
pos1,
pos2,
));
}
}
},
FrontendSpecifier::IceSpikes | FrontendSpecifier::Ice => {
// 1 / 3 the size of terrain voxel // 1 / 3 the size of terrain voxel
let scale = 1.0 / 3.0; let scale = 1.0 / 3.0;
let scaled_distance = distance / scale; let scaled_distance = distance / scale;