diff --git a/assets/common/abilities/custom/dagon/steamwave.ron b/assets/common/abilities/custom/dagon/steamwave.ron index ded3515f73..fbccb65a38 100644 --- a/assets/common/abilities/custom/dagon/steamwave.ron +++ b/assets/common/abilities/custom/dagon/steamwave.ron @@ -2,7 +2,7 @@ Shockwave( energy_cost: 0, buildup_duration: 0.3, swing_duration: 0.3, - recover_duration: 0.0, + recover_duration: 0.5, damage: 20.0, poise_damage: 10, knockback: (strength: 18.0, direction: Away), diff --git a/assets/common/loot_tables/dungeon/sea_chapel/dagon.ron b/assets/common/loot_tables/dungeon/sea_chapel/dagon.ron index e45ac3e322..8901187705 100644 --- a/assets/common/loot_tables/dungeon/sea_chapel/dagon.ron +++ b/assets/common/loot_tables/dungeon/sea_chapel/dagon.ron @@ -1,4 +1,5 @@ [ (0.5, Item("common.items.crafting_ing.abyssal_heart")), (5.0, LootTable("common.loot_tables.creature.quad_low.fanged")), + (5.0, Item("common.items.food.meat.tough_raw")), ] \ No newline at end of file diff --git a/assets/voxygen/voxel/quadruped_low_central_manifest.ron b/assets/voxygen/voxel/quadruped_low_central_manifest.ron index a0e0ea82d6..1ad74735fb 100644 --- a/assets/voxygen/voxel/quadruped_low_central_manifest.ron +++ b/assets/voxygen/voxel/quadruped_low_central_manifest.ron @@ -730,15 +730,15 @@ ), (Dagon, Male): ( upper: ( - offset: (-4.5, 2.5, -13.0), + offset: (-3.5, 2.5, -8.0), central: ("npc.dagon.male.head_upper"), ), lower: ( - offset: (-4.5, -10.0, -10.5), + offset: (-4.5, -10.0, -3.5), central: ("npc.dagon.male.head_lower"), ), jaw: ( - offset: (-3.5, 11.5, -13.0), + offset: (-2.5, 2.5, -10.0), central: ("npc.dagon.male.jaw"), ), chest: ( @@ -756,15 +756,15 @@ ), (Dagon, Female): ( upper: ( - offset: (-4.5, 2.5, -13.0), + offset: (-3.5, 2.5, -8.0), central: ("npc.dagon.male.head_upper"), ), lower: ( - offset: (-4.5, -10.0, -10.5), + offset: (-4.5, -10.0, -3.5), central: ("npc.dagon.male.head_lower"), ), jaw: ( - offset: (-3.5, 11.5, -13.0), + offset: (-2.5, 2.5, -10.0), central: ("npc.dagon.male.jaw"), ), chest: ( diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 9e9b81ce63..2a1df08862 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -3809,23 +3809,28 @@ impl<'a> AgentData<'a> { enum ActionStateTimers { TimerDagon = 0, } - if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 2.5 { agent.action_state.timers[ActionStateTimers::TimerDagon as usize] = 0.0; } - // if close to target lay out sea urchins, use steambeam and shoot dagon bombs - if attack_data.dist_sqrd < (1.3 * attack_data.min_attack_dist).powi(2) { - controller.inputs.move_dir = Vec2::zero(); - if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 2.0 { + // if target gets very close, shoot dagon bombs and lay out sea urchins + if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) { + if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 1.0 { controller.push_basic_input(InputKind::Primary); agent.action_state.timers[ActionStateTimers::TimerDagon as usize] += read_data.dt.0; - } else if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 1.0 { - controller.push_basic_input(InputKind::Ability(1)); } else { controller.push_basic_input(InputKind::Secondary); agent.action_state.timers[ActionStateTimers::TimerDagon as usize] += read_data.dt.0; } - } else if attack_data.dist_sqrd > (3.0 * attack_data.min_attack_dist).powi(2) { + // if target in close range use steambeam and shoot dagon bombs + } else if attack_data.dist_sqrd < (3.0 * attack_data.min_attack_dist).powi(2) { + controller.inputs.move_dir = Vec2::zero(); + if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 2.0 { + controller.push_basic_input(InputKind::Primary); + agent.action_state.timers[ActionStateTimers::TimerDagon as usize] += read_data.dt.0; + } else { + controller.push_basic_input(InputKind::Ability(1)); + } + } else if attack_data.dist_sqrd > (4.0 * attack_data.min_attack_dist).powi(2) { // if enemy is far, heal controller.push_basic_input(InputKind::Ability(2)); agent.action_state.timers[ActionStateTimers::TimerDagon as usize] += read_data.dt.0; @@ -3836,7 +3841,7 @@ impl<'a> AgentData<'a> { tgt_data.body, read_data, ) { - // if in range shoot dagon bombs and steamwave + // if enemy in mid range shoot dagon bombs and steamwave if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 1.0 { controller.push_basic_input(InputKind::Primary); agent.action_state.timers[ActionStateTimers::TimerDagon as usize] += read_data.dt.0; diff --git a/voxygen/anim/src/quadruped_low/mod.rs b/voxygen/anim/src/quadruped_low/mod.rs index 6eb80830b2..7e13941213 100644 --- a/voxygen/anim/src/quadruped_low/mod.rs +++ b/voxygen/anim/src/quadruped_low/mod.rs @@ -5,15 +5,18 @@ pub mod dash; pub mod idle; pub mod jump; pub mod run; +pub mod shockwave; pub mod shoot; +pub mod spritesummon; pub mod stunned; pub mod tailwhip; // Reexports pub use self::{ alpha::AlphaAnimation, beta::BetaAnimation, breathe::BreatheAnimation, dash::DashAnimation, - idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation, shoot::ShootAnimation, - stunned::StunnedAnimation, tailwhip::TailwhipAnimation, + idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, + shoot::ShootAnimation, spritesummon::SpriteSummonAnimation, stunned::StunnedAnimation, + tailwhip::TailwhipAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton}; @@ -189,7 +192,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Maneater, _) => (1.0, 4.5), (Sandshark, _) => (13.5, -10.5), (Hakulaq, _) => (10.5, 1.0), - (Dagon, _) => (10.5, 1.0), + (Dagon, _) => (12.0, -6.0), (Lavadrake, _) => (9.0, -6.0), (Icedrake, _) => (11.5, -6.0), (Basilisk, _) => (12.5, -5.5), @@ -212,7 +215,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Maneater, _) => (-1.0, 4.0), (Sandshark, _) => (-8.0, -5.5), (Hakulaq, _) => (-6.5, -4.0), - (Dagon, _) => (-6.5, -4.0), + (Dagon, _) => (2.0, -2.0), (Lavadrake, _) => (3.0, -5.0), (Icedrake, _) => (-0.5, -8.0), (Basilisk, _) => (0.5, -3.0), diff --git a/voxygen/anim/src/quadruped_low/shockwave.rs b/voxygen/anim/src/quadruped_low/shockwave.rs new file mode 100644 index 0000000000..1e56162353 --- /dev/null +++ b/voxygen/anim/src/quadruped_low/shockwave.rs @@ -0,0 +1,65 @@ +use super::{ + super::{vek::*, Animation}, + QuadrupedLowSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; +//use std::ops::Rem; + +pub struct ShockwaveAnimation; + +impl Animation for ShockwaveAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = QuadrupedLowSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"quadruped_low_shockwave\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "quadruped_low_shockwave")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, timer): Self::Dependency<'_>, + anim_time: f32, + _rate: &mut f32, + _s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1base, movement2base, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = -1.0 - movement3; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let twitch3 = (mirror * movement3 * 9.0).sin(); + let movement1 = mirror * movement1base * pullback; + let movement2 = mirror * movement2base * pullback; + let movement1abs = movement1base * pullback; + let movement2abs = movement2base * pullback; + + next.head_upper.orientation = Quaternion::rotation_z(twitch3 * 1.0); + + next.head_lower.orientation = + Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1 * -0.1 + movement2 * 0.5); + + next.jaw.orientation = Quaternion::rotation_x(movement1abs * 0.0 + movement2abs * 0.3) + * Quaternion::rotation_z(twitch3 * 0.2); + next.chest.orientation = Quaternion::rotation_y(movement1 * 0.08 + movement2 * -0.15) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * -0.3); + + next.tail_front.orientation = Quaternion::rotation_x(0.15) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * 0.2) + * twitch3 + * 0.8; + + next.tail_rear.orientation = Quaternion::rotation_x(-0.12) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * 0.2) + * twitch3 + * 0.8; + next + } +} diff --git a/voxygen/anim/src/quadruped_low/spritesummon.rs b/voxygen/anim/src/quadruped_low/spritesummon.rs new file mode 100644 index 0000000000..9f10a01cc1 --- /dev/null +++ b/voxygen/anim/src/quadruped_low/spritesummon.rs @@ -0,0 +1,65 @@ +use super::{ + super::{vek::*, Animation}, + QuadrupedLowSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; +//use std::ops::Rem; + +pub struct SpriteSummonAnimation; + +impl Animation for SpriteSummonAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = QuadrupedLowSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"quadruped_low_sprite_summon\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "quadruped_low_sprite_summon")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, timer): Self::Dependency<'_>, + anim_time: f32, + _rate: &mut f32, + _s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1base, movement2base, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = -1.0 - movement3; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let twitch3 = (mirror * movement3 * 9.0).sin(); + let movement1 = mirror * movement1base * pullback; + let movement2 = mirror * movement2base * pullback; + let movement1abs = movement1base * pullback; + let movement2abs = movement2base * pullback; + + next.head_upper.orientation = Quaternion::rotation_z(twitch3 * 0.2); + + next.head_lower.orientation = + Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1 * -0.1 + movement2 * 0.5); + + next.jaw.orientation = Quaternion::rotation_x(movement1abs * 0.0 + movement2abs * 0.3) + * Quaternion::rotation_z(twitch3 * 0.2); + next.chest.orientation = Quaternion::rotation_y(movement1 * 0.08 + movement2 * -0.15) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * -0.3); + + next.tail_front.orientation = Quaternion::rotation_x(0.15) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * 0.2) + * twitch3 + * 1.8; + + next.tail_rear.orientation = Quaternion::rotation_x(-0.12) + * Quaternion::rotation_z(movement1 * 0.2 + movement2 * 0.2) + * twitch3 + * 1.8; + next + } +} diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 321eac0e62..7b3980223c 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -2813,7 +2813,6 @@ impl FigureMgr { skeleton_attr, ) }, - CharacterState::ChargedMelee(s) => { let stage_time = s.timer.as_secs_f32(); @@ -2843,6 +2842,64 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::Shockwave(s) => { + let stage_time = s.timer.as_secs_f32(); + + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + stage_time / s.static_data.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + + _ => 0.0, + }; + anim::quadruped_low::ShockwaveAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::SpriteSummon(s) => { + let stage_time = s.timer.as_secs_f32(); + + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + stage_time / s.static_data.cast_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + + _ => 0.0, + }; + anim::quadruped_low::SpriteSummonAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::Stunned(s) => { let stage_time = s.timer.as_secs_f32(); let stage_progress = match s.stage_section {