Make tornado (and empty models in general) work on WGPU.

This commit is contained in:
Avi Weinstock 2021-06-03 21:25:42 -04:00 committed by Robin Gilh
parent 3ba0500b90
commit cb0566299a
18 changed files with 544 additions and 54 deletions

View File

@ -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"),
],

View 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,
)

View File

@ -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,
)),
)

View File

@ -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,
)

View File

@ -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,

View File

@ -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,

View File

@ -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),
}
}

View File

@ -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(

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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),

View 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
}
}

View File

@ -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};

View 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
}
}

View File

@ -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. */
}

View File

@ -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!(

View File

@ -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);

View File

@ -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,
)