mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make tornado (and empty models in general) work on WGPU.
This commit is contained in:
parent
3ba0500b90
commit
cb0566299a
@ -265,8 +265,8 @@
|
||||
],
|
||||
),
|
||||
Custom("Bird Large Basic"): (
|
||||
primary: "common.abilities.custom.birdlargebreathe.firebomb",
|
||||
secondary: "common.abilities.custom.birdlargebreathe.triplestrike",
|
||||
primary: "common.abilities.custom.birdlargebasic.dash",
|
||||
secondary: "common.abilities.custom.birdlargebasic.triplestrike",
|
||||
abilities: [
|
||||
(None, "common.abilities.custom.birdlargebasic.summontornadoes"),
|
||||
],
|
||||
|
20
assets/common/abilities/custom/birdlargebasic/dash.ron
Normal file
20
assets/common/abilities/custom/birdlargebasic/dash.ron
Normal file
@ -0,0 +1,20 @@
|
||||
DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 70,
|
||||
scaled_damage: 150,
|
||||
base_poise_damage: 50,
|
||||
scaled_poise_damage: 100,
|
||||
base_knockback: 12.0,
|
||||
scaled_knockback: 17.0,
|
||||
range: 6.0,
|
||||
angle: 20.0,
|
||||
energy_drain: 0,
|
||||
forward_speed: 1.5,
|
||||
buildup_duration: 0.5,
|
||||
charge_duration: 1.2,
|
||||
swing_duration: 0.1,
|
||||
recover_duration: 1.1,
|
||||
charge_through: true,
|
||||
is_interruptible: false,
|
||||
damage_kind: Crushing,
|
||||
)
|
@ -1,9 +1,9 @@
|
||||
BasicSummon(
|
||||
buildup_duration: 0.5,
|
||||
cast_duration: 1.0,
|
||||
recover_duration: 0.5,
|
||||
cast_duration: 0.2,
|
||||
recover_duration: 0.2,
|
||||
summon_amount: 6,
|
||||
summon_distance: (1, 5),
|
||||
summon_distance: (1, 3),
|
||||
summon_info: (
|
||||
body: Object(Tornado),
|
||||
scale: None,
|
||||
@ -12,7 +12,7 @@ BasicSummon(
|
||||
skillset_config: None,
|
||||
),
|
||||
duration: Some((
|
||||
secs: 5,
|
||||
secs: 10,
|
||||
nanos: 0,
|
||||
)),
|
||||
)
|
@ -0,0 +1,57 @@
|
||||
ComboMelee(
|
||||
stage_data: [
|
||||
(
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 0,
|
||||
poise_damage_increase: 0,
|
||||
knockback: 5.0,
|
||||
range: 4.5,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: 0.4,
|
||||
base_swing_duration: 0.1,
|
||||
base_recover_duration: 0.3,
|
||||
forward_movement: 2.0,
|
||||
damage_kind: Slashing,
|
||||
),
|
||||
(
|
||||
stage: 2,
|
||||
base_damage: 80,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 0,
|
||||
poise_damage_increase: 0,
|
||||
knockback: 5.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: 0.4,
|
||||
base_swing_duration: 0.1,
|
||||
base_recover_duration: 0.3,
|
||||
forward_movement: 1.5,
|
||||
damage_kind: Slashing,
|
||||
),
|
||||
(
|
||||
stage: 3,
|
||||
base_damage: 130,
|
||||
damage_increase: 0,
|
||||
base_poise_damage: 0,
|
||||
poise_damage_increase: 0,
|
||||
knockback: 10.0,
|
||||
range: 3.5,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: 0.65,
|
||||
base_swing_duration: 0.1,
|
||||
base_recover_duration: 0.3,
|
||||
forward_movement: 1.5,
|
||||
damage_kind: Slashing,
|
||||
),
|
||||
],
|
||||
initial_energy_gain: 0,
|
||||
max_energy_gain: 0,
|
||||
energy_increase: 0,
|
||||
speed_increase: 0.0,
|
||||
max_speed_increase: 0.0,
|
||||
scales_from_combo: 0,
|
||||
is_interruptible: false,
|
||||
ori_modifier: 0.7,
|
||||
)
|
@ -2,9 +2,9 @@ SpinMelee(
|
||||
buildup_duration: 0.0,
|
||||
swing_duration: 0.5,
|
||||
recover_duration: 0.0,
|
||||
base_damage: 15000,
|
||||
base_poise_damage: 200,
|
||||
knockback: ( strength: 200.0, direction: Away),
|
||||
base_damage: 50,
|
||||
base_poise_damage: 100,
|
||||
knockback: ( strength: 50.0, direction: Away),
|
||||
range: 3.5,
|
||||
damage_effect: None,
|
||||
energy_cost: 0,
|
||||
|
@ -472,7 +472,10 @@ impl Body {
|
||||
},
|
||||
Body::FishMedium(_) => 250,
|
||||
Body::Dragon(_) => 5000,
|
||||
Body::BirdLarge(_) => 3000,
|
||||
Body::BirdLarge(bird_large) => match bird_large.species {
|
||||
bird_large::Species::Roc => 2400,
|
||||
_ => 3000,
|
||||
},
|
||||
Body::FishSmall(_) => 20,
|
||||
Body::BipedLarge(biped_large) => match biped_large.species {
|
||||
biped_large::Species::Ogre => 3200,
|
||||
@ -591,7 +594,10 @@ impl Body {
|
||||
},
|
||||
Body::FishMedium(_) => 10,
|
||||
Body::Dragon(_) => 500,
|
||||
Body::BirdLarge(_) => 120,
|
||||
Body::BirdLarge(bird_large) => match bird_large.species {
|
||||
bird_large::Species::Roc => 100,
|
||||
_ => 120,
|
||||
},
|
||||
Body::FishSmall(_) => 10,
|
||||
Body::BipedLarge(biped_large) => match biped_large.species {
|
||||
biped_large::Species::Ogre => 70,
|
||||
|
@ -376,6 +376,7 @@ impl Body {
|
||||
Body::HaniwaSentry => Vec3::new(0.8, 0.8, 1.4),
|
||||
Body::SeaLantern => Vec3::new(0.5, 0.5, 1.0),
|
||||
Body::Snowball => Vec3::broadcast(2.5),
|
||||
Body::Tornado => Vec3::new(2.0, 2.0, 3.4),
|
||||
_ => Vec3::broadcast(0.5),
|
||||
}
|
||||
}
|
||||
|
@ -253,13 +253,12 @@ fn default_main_tool(body: &Body) -> Item {
|
||||
(biped_large::Species::Ogre, biped_large::BodyType::Female) => Some(
|
||||
Item::new_from_asset_expect("common.items.npc_weapons.staff.ogre_staff"),
|
||||
),
|
||||
(biped_large::Species::Cavetroll, _) => Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.hammer.troll_hammer",
|
||||
)),
|
||||
(biped_large::Species::Mountaintroll, _) => Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.hammer.troll_hammer",
|
||||
)),
|
||||
(biped_large::Species::Swamptroll, _) => Some(Item::new_from_asset_expect(
|
||||
(
|
||||
biped_large::Species::Mountaintroll
|
||||
| biped_large::Species::Swamptroll
|
||||
| biped_large::Species::Cavetroll,
|
||||
_,
|
||||
) => Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.hammer.troll_hammer",
|
||||
)),
|
||||
(biped_large::Species::Wendigo, _) => Some(Item::new_from_asset_expect(
|
||||
|
@ -137,6 +137,11 @@ impl<'a> System<'a> for Sys {
|
||||
agent,
|
||||
alignment: match body {
|
||||
comp::Body::Humanoid(_) => comp::Alignment::Npc,
|
||||
comp::Body::BirdLarge(bird_large) => match bird_large.species {
|
||||
comp::bird_large::Species::Roc => comp::Alignment::Enemy,
|
||||
comp::bird_large::Species::Cockatrice => comp::Alignment::Enemy,
|
||||
_ => comp::Alignment::Wild,
|
||||
},
|
||||
_ => comp::Alignment::Wild,
|
||||
},
|
||||
scale: match body {
|
||||
|
@ -3286,18 +3286,57 @@ impl<'a> AgentData<'a> {
|
||||
tgt_data: &TargetData,
|
||||
read_data: &ReadData,
|
||||
) {
|
||||
if can_see_tgt(
|
||||
&*read_data.terrain,
|
||||
self.pos,
|
||||
tgt_data.pos,
|
||||
attack_data.dist_sqrd,
|
||||
) && attack_data.angle < 15.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
|
||||
controller
|
||||
.actions
|
||||
.push(ControlAction::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.timer > 7.0 {
|
||||
controller
|
||||
.actions
|
||||
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
||||
// Reset timer
|
||||
agent.action_state.timer = 0.0;
|
||||
} else if attack_data.angle < 90.0
|
||||
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
|
||||
&& agent.action_state.timer < 6.0
|
||||
{
|
||||
controller.inputs.move_dir = Vec2::zero();
|
||||
controller
|
||||
.actions
|
||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||
agent.action_state.timer += read_data.dt.0;
|
||||
} else if attack_data.dist_sqrd < (3.0 * attack_data.min_attack_dist).powi(2)
|
||||
&& attack_data.dist_sqrd > (2.0 * attack_data.min_attack_dist).powi(2)
|
||||
&& attack_data.angle < 90.0
|
||||
&& agent.action_state.timer < 6.0
|
||||
{
|
||||
controller
|
||||
.actions
|
||||
.push(ControlAction::basic_input(InputKind::Primary));
|
||||
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
|
||||
.xy()
|
||||
.rotated_z(-0.47 * PI)
|
||||
.try_normalized()
|
||||
.unwrap_or_else(Vec2::unit_y);
|
||||
agent.action_state.timer += read_data.dt.0;
|
||||
} else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
|
||||
self.path_toward_target(agent, controller, tgt_data, read_data, true, None);
|
||||
agent.action_state.timer += read_data.dt.0;
|
||||
} else {
|
||||
agent.target = None;
|
||||
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
|
||||
agent.action_state.timer += read_data.dt.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +419,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
||||
(Wendigo, _) => (15.0, 0.0),
|
||||
(Cavetroll, _) => (13.0, 1.5),
|
||||
(Mountaintroll, _) => (13.0, 1.5),
|
||||
(Swamptroll, _) => (13.0, 1.5),
|
||||
(Swamptroll, _) => (15.0, 0.5),
|
||||
(Dullahan, _) => (15.0, 0.0),
|
||||
(Werewolf, _) => (13.0, 0.0),
|
||||
(Occultsaurok, _) => (10.0, 0.0),
|
||||
|
177
voxygen/anim/src/bird_large/dash.rs
Normal file
177
voxygen/anim/src/bird_large/dash.rs
Normal file
@ -0,0 +1,177 @@
|
||||
use super::{
|
||||
super::{vek::*, Animation},
|
||||
BirdLargeSkeleton, SkeletonAttr,
|
||||
};
|
||||
use common::states::utils::StageSection;
|
||||
use std::f32::consts::PI;
|
||||
|
||||
pub struct DashAnimation;
|
||||
type DashAnimationDependency<'a> = (
|
||||
Vec3<f32>,
|
||||
Vec3<f32>,
|
||||
Vec3<f32>,
|
||||
f32,
|
||||
Option<StageSection>,
|
||||
f32,
|
||||
f32,
|
||||
);
|
||||
|
||||
impl Animation for DashAnimation {
|
||||
type Dependency<'a> = DashAnimationDependency<'a>;
|
||||
type Skeleton = BirdLargeSkeleton;
|
||||
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"bird_large_dash\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_dash")]
|
||||
fn update_skeleton_inner<'a>(
|
||||
skeleton: &Self::Skeleton,
|
||||
(velocity, orientation, last_ori, acc_vel, stage_section, global_time, timer): Self::Dependency<'a>,
|
||||
anim_time: f32,
|
||||
rate: &mut f32,
|
||||
s_a: &SkeletonAttr,
|
||||
) -> Self::Skeleton {
|
||||
let mut next = (*skeleton).clone();
|
||||
let speed = (Vec2::<f32>::from(velocity).magnitude()).min(22.0);
|
||||
*rate = 1.0;
|
||||
|
||||
let (movement1base, chargemovementbase, movement2base, movement3, legtell) =
|
||||
match stage_section {
|
||||
Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0, 0.0, anim_time),
|
||||
Some(StageSection::Charge) => (1.0, 1.0, 0.0, 0.0, 0.0),
|
||||
Some(StageSection::Swing) => (1.0, 0.0, anim_time.powi(4), 0.0, 1.0),
|
||||
Some(StageSection::Recover) => (1.0, 0.0, 1.0, anim_time, 1.0),
|
||||
_ => (0.0, 0.0, 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 movement1abs = movement1base * pullback;
|
||||
let movement2abs = movement2base * pullback;
|
||||
let legtwitch = (legtell * 6.0).sin() * pullback;
|
||||
let legswing = legtell * pullback;
|
||||
let chargeanim = (chargemovementbase * anim_time * 15.0).sin();
|
||||
|
||||
//let speednorm = speed / 13.0;
|
||||
let speednorm = (speed / 13.0).powf(0.25);
|
||||
|
||||
let speedmult = 0.8;
|
||||
let lab: f32 = 0.6; //6
|
||||
|
||||
// acc_vel and anim_time mix to make sure phase lenght isn't starting at
|
||||
// +infinite
|
||||
let mixed_vel = acc_vel + anim_time * 5.0; //sets run frequency using speed, with anim_time setting a floor
|
||||
|
||||
let short = ((1.0
|
||||
/ (0.72
|
||||
+ 0.28 * ((mixed_vel * 1.0 * lab * speedmult + PI * -0.15 - 0.5).sin()).powi(2)))
|
||||
.sqrt())
|
||||
* ((mixed_vel * 1.0 * lab * speedmult + PI * -0.15 - 0.5).sin())
|
||||
* speednorm;
|
||||
|
||||
//
|
||||
let shortalt = (mixed_vel * 1.0 * lab * speedmult + PI * 3.0 / 8.0 - 0.5).sin() * speednorm;
|
||||
|
||||
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;
|
||||
|
||||
next.head.scale = Vec3::one() * 0.98;
|
||||
next.neck.scale = Vec3::one() * 1.02;
|
||||
next.leg_l.scale = Vec3::one() / 8.0 * 0.98;
|
||||
next.leg_r.scale = Vec3::one() / 8.0 * 0.98;
|
||||
next.foot_l.scale = Vec3::one() * 1.02;
|
||||
next.foot_r.scale = Vec3::one() * 1.02;
|
||||
next.chest.scale = Vec3::one() * s_a.scaler / 8.0;
|
||||
|
||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
||||
next.head.orientation = Quaternion::rotation_x(
|
||||
-0.1 * speednorm + short * -0.05 + movement1abs * -0.8 + movement2abs * 0.2,
|
||||
) * Quaternion::rotation_y(tilt * 0.2)
|
||||
* Quaternion::rotation_z(shortalt * -0.05 - tilt * 1.5);
|
||||
|
||||
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
|
||||
next.beak.orientation =
|
||||
Quaternion::rotation_x(short * -0.02 - 0.02 + movement1abs * -0.4 + movement2abs * 0.4);
|
||||
|
||||
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
|
||||
next.neck.orientation = Quaternion::rotation_x(-0.1 * speednorm + short * -0.04)
|
||||
* Quaternion::rotation_y(tilt * 0.1)
|
||||
* Quaternion::rotation_z(shortalt * -0.1 - tilt * 0.5);
|
||||
|
||||
next.chest.position = Vec3::new(
|
||||
0.0,
|
||||
s_a.chest.0,
|
||||
s_a.chest.1 + short * 0.5 + 0.5 * speednorm,
|
||||
) * s_a.scaler
|
||||
/ 8.0;
|
||||
next.chest.orientation =
|
||||
Quaternion::rotation_x(short * 0.07 + movement1abs * 0.8 + movement2abs * -1.2)
|
||||
* Quaternion::rotation_y(tilt * 0.8)
|
||||
* Quaternion::rotation_z(shortalt * 0.10);
|
||||
|
||||
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(0.6 + short * -0.02 + movement1abs * -0.8 + movement2abs * 0.8);
|
||||
|
||||
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.2 + short * -0.1);
|
||||
|
||||
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(
|
||||
-0.8 + movement1abs * 1.0 + chargeanim * 0.2 - movement2abs * 0.6,
|
||||
) * Quaternion::rotation_z(0.2 - movement1abs * 0.6 - movement2abs * 0.6);
|
||||
next.wing_in_r.orientation =
|
||||
Quaternion::rotation_y(
|
||||
0.8 - movement1abs * 1.0 - chargeanim * 0.2 + movement2abs * 0.6,
|
||||
) * Quaternion::rotation_z(-0.2 + movement1abs * 0.6 + movement2abs * 0.6);
|
||||
|
||||
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) * Quaternion::rotation_z(0.7);
|
||||
next.wing_mid_r.orientation = Quaternion::rotation_y(0.1) * Quaternion::rotation_z(-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 + short * 0.05) * Quaternion::rotation_z(0.2);
|
||||
next.wing_out_r.orientation =
|
||||
Quaternion::rotation_y(0.2 + short * -0.05) * Quaternion::rotation_z(-0.2);
|
||||
|
||||
if legtell > 0.0 {
|
||||
if mirror.is_sign_positive() {
|
||||
next.leg_l.orientation = Quaternion::rotation_x(legswing * 1.1);
|
||||
|
||||
next.foot_l.orientation = Quaternion::rotation_x(legswing * -1.1 + legtwitch * 0.5);
|
||||
|
||||
next.leg_r.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.foot_r.orientation = Quaternion::rotation_x(0.0);
|
||||
} else {
|
||||
next.leg_l.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.foot_l.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.leg_r.orientation = Quaternion::rotation_x(legswing * 1.1);
|
||||
|
||||
next.foot_r.orientation = Quaternion::rotation_x(legswing * -1.1 + legtwitch * 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
pub mod alpha;
|
||||
pub mod breathe;
|
||||
pub mod dash;
|
||||
pub mod feed;
|
||||
pub mod fly;
|
||||
pub mod idle;
|
||||
@ -7,13 +8,14 @@ pub mod run;
|
||||
pub mod shockwave;
|
||||
pub mod shoot;
|
||||
pub mod stunned;
|
||||
pub mod summon;
|
||||
pub mod swim;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
alpha::AlphaAnimation, breathe::BreatheAnimation, feed::FeedAnimation, fly::FlyAnimation,
|
||||
idle::IdleAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, shoot::ShootAnimation,
|
||||
stunned::StunnedAnimation, swim::SwimAnimation,
|
||||
alpha::AlphaAnimation, breathe::BreatheAnimation, dash::DashAnimation, feed::FeedAnimation,
|
||||
fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation, shockwave::ShockwaveAnimation,
|
||||
shoot::ShootAnimation, stunned::StunnedAnimation, summon::SummonAnimation, swim::SwimAnimation,
|
||||
};
|
||||
|
||||
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
||||
|
114
voxygen/anim/src/bird_large/summon.rs
Normal file
114
voxygen/anim/src/bird_large/summon.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use super::{
|
||||
super::{vek::*, Animation},
|
||||
BirdLargeSkeleton, SkeletonAttr,
|
||||
};
|
||||
use common::{states::utils::StageSection, util::Dir};
|
||||
|
||||
pub struct SummonAnimation;
|
||||
|
||||
type SummonAnimationDependency = (f32, Option<StageSection>, f32, Dir, bool);
|
||||
|
||||
impl Animation for SummonAnimation {
|
||||
type Dependency<'a> = SummonAnimationDependency;
|
||||
type Skeleton = BirdLargeSkeleton;
|
||||
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"bird_large_summon\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_summon")]
|
||||
#[allow(clippy::approx_constant)] // TODO: Pending review in #587
|
||||
fn update_skeleton_inner<'a>(
|
||||
skeleton: &Self::Skeleton,
|
||||
(global_time, stage_section, timer, look_dir, on_ground): Self::Dependency<'a>,
|
||||
anim_time: f32,
|
||||
rate: &mut f32,
|
||||
s_a: &SkeletonAttr,
|
||||
) -> Self::Skeleton {
|
||||
*rate = 1.0;
|
||||
let mut next = (*skeleton).clone();
|
||||
|
||||
let (movement1base, movement2base, movement3, twitch) = match stage_section {
|
||||
Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0, 0.0),
|
||||
Some(StageSection::Cast) => (1.0, anim_time.min(1.0).powf(0.1), 0.0, anim_time),
|
||||
Some(StageSection::Recover) => (1.0, 1.0, anim_time.min(1.0).powi(2), 1.0),
|
||||
_ => (0.0, 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 twitch2 = mirror * (twitch * 20.0).sin() * pullback;
|
||||
|
||||
let movement1abs = movement1base * pullback;
|
||||
let movement2abs = movement2base * pullback;
|
||||
|
||||
let wave_slow_cos = (anim_time * 4.5).cos();
|
||||
|
||||
next.head.scale = Vec3::one() * 0.98;
|
||||
next.neck.scale = Vec3::one() * 1.02;
|
||||
next.leg_l.scale = Vec3::one() / 8.0 * 0.98;
|
||||
next.leg_r.scale = Vec3::one() / 8.0 * 0.98;
|
||||
next.foot_l.scale = Vec3::one() * 1.02;
|
||||
next.foot_r.scale = Vec3::one() * 1.02;
|
||||
next.chest.scale = Vec3::one() * s_a.scaler / 8.0;
|
||||
|
||||
next.chest.position = Vec3::new(
|
||||
0.0,
|
||||
s_a.chest.0,
|
||||
s_a.chest.1 + wave_slow_cos * 0.06 + twitch2 * 0.1,
|
||||
) * s_a.scaler
|
||||
/ 8.0;
|
||||
|
||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
||||
next.head.orientation =
|
||||
Quaternion::rotation_x(movement1abs * -1.0 - movement2abs * 0.1 + look_dir.z * 0.4);
|
||||
|
||||
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
|
||||
next.beak.orientation = Quaternion::rotation_x(movement1abs * -0.7 + twitch2 * 0.1);
|
||||
|
||||
if on_ground {
|
||||
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
|
||||
next.neck.orientation = Quaternion::rotation_x(movement1abs * 0.5 - movement2abs * 0.5);
|
||||
|
||||
next.chest.orientation =
|
||||
Quaternion::rotation_x(movement1abs * 1.1 - movement2abs * 0.1);
|
||||
|
||||
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_x(movement1abs * 0.4 - movement2abs * 0.4)
|
||||
* Quaternion::rotation_y(-1.0 + movement1abs * 1.6 - movement2abs * 1.8)
|
||||
* Quaternion::rotation_z(0.2 - movement1abs * 1.8 + movement2abs * 0.4);
|
||||
next.wing_in_r.orientation =
|
||||
Quaternion::rotation_x(movement1abs * 0.4 - movement2abs * 0.4)
|
||||
* Quaternion::rotation_y(1.0 - movement1abs * 1.6 + movement2abs * 1.8)
|
||||
* Quaternion::rotation_z(-0.2 + movement1abs * 1.8 - movement2abs * 0.4);
|
||||
|
||||
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 - movement2abs * 0.4) * Quaternion::rotation_z(0.7);
|
||||
next.wing_mid_r.orientation =
|
||||
Quaternion::rotation_y(0.1 + movement2abs * 0.4) * Quaternion::rotation_z(-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 - movement2abs * 0.4) * Quaternion::rotation_z(0.2);
|
||||
next.wing_out_r.orientation =
|
||||
Quaternion::rotation_y(0.2 + movement2abs * 0.4) * Quaternion::rotation_z(-0.2);
|
||||
|
||||
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(-movement1abs * 0.1 + movement2abs * 0.1 + twitch2 * 0.02);
|
||||
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(-movement1abs * 0.1 + movement2abs * 0.1 + twitch2 * 0.02);
|
||||
} else {
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
}
|
@ -80,7 +80,7 @@ impl Default for BoneData {
|
||||
}
|
||||
|
||||
pub struct FigureModel {
|
||||
pub opaque: Model<Vertex>,
|
||||
pub opaque: Option<Model<Vertex>>,
|
||||
/* TODO: Consider using mipmaps instead of storing multiple texture atlases for different
|
||||
* LOD levels. */
|
||||
}
|
||||
|
@ -88,11 +88,12 @@ pub struct FigureModelEntry<const N: usize> {
|
||||
}
|
||||
|
||||
impl<const N: usize> FigureModelEntry<N> {
|
||||
pub fn lod_model(&self, lod: usize) -> SubModel<TerrainVertex> {
|
||||
pub fn lod_model(&self, lod: usize) -> Option<SubModel<TerrainVertex>> {
|
||||
// Note: Range doesn't impl Copy even for trivially Cloneable things
|
||||
self.model
|
||||
.opaque
|
||||
.submodel(self.lod_vertex_ranges[lod].clone())
|
||||
.as_ref()
|
||||
.map(|m| m.submodel(self.lod_vertex_ranges[lod].clone()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -3480,6 +3481,70 @@ impl FigureMgr {
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
CharacterState::BasicSummon(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::Cast => {
|
||||
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::bird_large::SummonAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(
|
||||
time,
|
||||
Some(s.stage_section),
|
||||
state.state_time,
|
||||
look_dir,
|
||||
physics.on_ground,
|
||||
),
|
||||
stage_progress,
|
||||
&mut state_animation_rate,
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
CharacterState::DashMelee(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::Charge => {
|
||||
stage_time / s.static_data.charge_duration.as_secs_f32()
|
||||
},
|
||||
StageSection::Swing => {
|
||||
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::bird_large::DashAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(
|
||||
rel_vel,
|
||||
// TODO: Update to use the quaternion.
|
||||
ori * anim::vek::Vec3::<f32>::unit_y(),
|
||||
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
|
||||
state.acc_vel,
|
||||
Some(s.stage_section),
|
||||
time,
|
||||
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 {
|
||||
@ -5163,7 +5228,7 @@ impl FigureMgr {
|
||||
model_entry.lod_model(0)
|
||||
};
|
||||
|
||||
Some((bound, model, col_lights_.texture(model_entry)))
|
||||
Some((bound, model?, col_lights_.texture(model_entry)))
|
||||
} else {
|
||||
// trace!("Body has no saved figure");
|
||||
None
|
||||
@ -5221,9 +5286,7 @@ impl FigureColLights {
|
||||
let col_lights = renderer.figure_bind_col_light(col_lights);
|
||||
let model_len = u32::try_from(opaque.vertices().len())
|
||||
.expect("The model size for this figure does not fit in a u32!");
|
||||
let model = renderer
|
||||
.create_model(&opaque)
|
||||
.expect("The model contains no vertices!");
|
||||
let model = renderer.create_model(&opaque);
|
||||
|
||||
vertex_ranges.iter().for_each(|range| {
|
||||
assert!(
|
||||
|
@ -366,20 +366,20 @@ impl Scene {
|
||||
);
|
||||
|
||||
if let Some(model) = model {
|
||||
figure_drawer.draw(
|
||||
model.lod_model(0),
|
||||
self.figure_state.bound(),
|
||||
&self.col_lights.texture(model),
|
||||
);
|
||||
if let Some(lod) = model.lod_model(0) {
|
||||
figure_drawer.draw(
|
||||
lod,
|
||||
self.figure_state.bound(),
|
||||
&self.col_lights.texture(model),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((model, state)) = &self.backdrop {
|
||||
figure_drawer.draw(
|
||||
model.lod_model(0),
|
||||
state.bound(),
|
||||
&self.col_lights.texture(model),
|
||||
);
|
||||
if let Some(lod) = model.lod_model(0) {
|
||||
figure_drawer.draw(lod, state.bound(), &self.col_lights.texture(model));
|
||||
}
|
||||
}
|
||||
drop(figure_drawer);
|
||||
|
||||
|
@ -119,9 +119,15 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(
|
||||
biped_large::Body::random_with(rng, &biped_large::Species::Wendigo).into(),
|
||||
)
|
||||
.with_body(match rng.gen_range(0..2) {
|
||||
0 => biped_large::Body::random_with(rng, &biped_large::Species::Wendigo)
|
||||
.into(),
|
||||
_ => biped_large::Body::random_with(
|
||||
rng,
|
||||
&biped_large::Species::Mountaintroll,
|
||||
)
|
||||
.into(),
|
||||
})
|
||||
.with_alignment(Alignment::Enemy)
|
||||
},
|
||||
group_size: 1..2,
|
||||
@ -623,7 +629,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..4) {
|
||||
.with_body(match rng.gen_range(0..5) {
|
||||
0 => theropod::Body::random_with(rng, &theropod::Species::Odonto).into(),
|
||||
1 => {
|
||||
biped_large::Body::random_with(rng, &biped_large::Species::Mightysaurok)
|
||||
@ -633,6 +639,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
biped_large::Body::random_with(rng, &biped_large::Species::Occultsaurok)
|
||||
.into()
|
||||
},
|
||||
3 => bird_large::Body::random_with(rng, &bird_large::Species::Cockatrice)
|
||||
.into(),
|
||||
_ => biped_large::Body::random_with(rng, &biped_large::Species::Slysaurok)
|
||||
.into(),
|
||||
})
|
||||
@ -652,12 +660,11 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..4) {
|
||||
.with_body(match rng.gen_range(0..3) {
|
||||
0 => bird_medium::Body::random_with(rng, &bird_medium::Species::Parrot)
|
||||
.into(),
|
||||
1 => bird_large::Body::random_with(rng, &bird_large::Species::Cockatrice)
|
||||
.into(),
|
||||
2 => quadruped_small::Body::random_with(
|
||||
|
||||
1 => quadruped_small::Body::random_with(
|
||||
rng,
|
||||
&quadruped_small::Species::Quokka,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user