Merge branch 'snowram/bird-large' into 'master'

Large bird skeleton

See merge request veloren/veloren!2121
This commit is contained in:
Justin Shipsey 2021-04-25 03:34:12 +00:00
commit 79cb7a5826
86 changed files with 3109 additions and 517 deletions

View File

@ -45,6 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Drag is now calculated based on physical properties
- Terrain chunks are now deflate-compressed when sent over the network.
- Missing translations can be displayed in English.
- New large birds npcs
- Day period dependant wildlife spawns
### Changed

View File

@ -0,0 +1,17 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.5,
recover_duration: 0.35,
projectile: Fireball(
damage: 100.0,
radius: 5.0,
energy_regen: 50,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_gravity: Some(Gravity(0.15)),
projectile_speed: 60.0,
)

View File

@ -0,0 +1,14 @@
BasicBeam(
buildup_duration: 0.4,
recover_duration: 0.25,
beam_duration: 0.5,
damage: 50,
tick_rate: 3.0,
range: 15.0,
max_angle: 22.5,
damage_effect: None,
energy_regen: 0,
energy_drain: 0,
orientation_behavior: Normal,
specifier: Flamethrower,
)

View File

@ -0,0 +1,53 @@
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,
),
(
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,
),
(
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,
),
],
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,
)

View File

@ -0,0 +1,17 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.5,
recover_duration: 0.35,
projectile: Fireball(
damage: 100.0,
radius: 5.0,
energy_regen: 50,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_gravity: Some(Gravity(0.15)),
projectile_speed: 60.0,
)

View File

@ -0,0 +1,15 @@
Shockwave(
energy_cost: 600,
buildup_duration: 0.7,
swing_duration: 0.1,
recover_duration: 0.2,
damage: 200,
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,
)

View File

@ -0,0 +1,14 @@
BasicBeam(
buildup_duration: 0.4,
recover_duration: 0.25,
beam_duration: 0.5,
damage: 50,
tick_rate: 3.0,
range: 15.0,
max_angle: 22.5,
damage_effect: None,
energy_regen: 0,
energy_drain: 0,
orientation_behavior: Normal,
specifier: Flamethrower,
)

View File

@ -0,0 +1,53 @@
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,
),
(
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,
),
(
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,
),
],
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,
)

View File

@ -207,6 +207,20 @@
(None, "common.abilities.unique.mindflayer.summonminions"),
],
),
Unique(BirdLargeBreathe): (
primary: "common.abilities.unique.birdlargebreathe.firebomb",
secondary: "common.abilities.unique.birdlargebreathe.triplestrike",
abilities: [
(None, "common.abilities.unique.birdlargebreathe.flamethrower"),
],
),
Unique(BirdLargeFire): (
primary: "common.abilities.unique.birdlargefire.firebomb",
secondary: "common.abilities.unique.birdlargefire.triplestrike",
abilities: [
(None, "common.abilities.unique.birdlargefire.fireshockwave"),
],
),
Debug: (
primary: "common.abilities.debug.forwardboost",
secondary: "common.abilities.debug.upboost",

View File

@ -0,0 +1,18 @@
ItemDef(
name: "Bird Large Breathe",
description: "testing123",
kind: Tool((
kind: Unique(BirdLargeBreathe),
hands: Two,
stats: Direct((
equip_time_secs: 0.01,
power: 1.0,
poise_strength: 1.0,
speed: 1.0,
crit_chance: 0.0625,
crit_mult: 1.9142857,
)),
)),
quality: Low,
tags: [],
)

View File

@ -0,0 +1,18 @@
ItemDef(
name: "Bird Large Fire",
description: "testing123",
kind: Tool((
kind: Unique(BirdLargeFire),
hands: Two,
stats: Direct((
equip_time_secs: 0.01,
power: 1.0,
poise_strength: 1.0,
speed: 1.0,
crit_chance: 0.0625,
crit_mult: 1.9142857,
)),
)),
quality: Low,
tags: [],
)

View File

@ -804,10 +804,6 @@
keyword: "parrot",
generic: "Parrot"
),
cockatrice: (
keyword: "cockatrice",
generic: "Cockatrice"
)
)
),
biped_large: (
@ -1068,12 +1064,23 @@
)
)
),
bird_small: (
bird_large: (
body: (
keyword: "bird_small",
names_0: []
keyword: "bird_large",
names_0: [
"Aitvaras"
]
),
species: ()
species: (
phoenix: (
keyword: "phoenix",
generic: "Phoenix"
),
cockatrice: (
keyword: "cockatrice",
generic: "Cockatrice"
),
)
),
quadruped_low: (
body: (

View File

@ -0,0 +1,106 @@
({
(Phoenix, Male): (
head: (
offset: (-4.0, -4.0, 0.0),
central: ("npc.phoenix.male.head"),
),
beak: (
offset: (-2.0, 0.0, -3.0),
central: ("npc.phoenix.male.beak"),
),
neck: (
offset: (-4.0, 0.0, 0.0),
central: ("npc.phoenix.male.neck"),
),
chest: (
offset: (-6.0, -9.5, -7.5),
central: ("npc.phoenix.male.chest"),
),
tail_front: (
offset: (-10.0, -14.0, -3.0),
central: ("npc.phoenix.male.tail_front"),
),
tail_rear: (
offset: (-9.0, -30.0, -2.0),
central: ("npc.phoenix.male.tail_rear"),
)
),
(Phoenix, Female): (
head: (
offset: (-4.0, -4.0, 0.0),
central: ("npc.phoenix.male.head"),
),
beak: (
offset: (-2.0, 0.0, -3.0),
central: ("npc.phoenix.male.beak"),
),
neck: (
offset: (-4.0, 0.0, 0.0),
central: ("npc.phoenix.male.neck"),
),
chest: (
offset: (-6.0, -9.5, -7.5),
central: ("npc.phoenix.male.chest"),
),
tail_front: (
offset: (-10.0, -14.0, -3.0),
central: ("npc.phoenix.male.tail_front"),
),
tail_rear: (
offset: (-9.0, -30.0, -2.0),
central: ("npc.phoenix.male.tail_rear"),
)
),
(Cockatrice, Male): (
head: (
offset: (-4.5, -6.0, -3.5),
central: ("npc.cockatrice.male.head"),
),
beak: (
offset: (-1.5, 0.0, -1.5),
central: ("npc.cockatrice.male.beak"),
),
neck: (
offset: (-3.5, 0.0, -6.0),
central: ("npc.cockatrice.male.neck"),
),
chest: (
offset: (-5.5, -10.0, -9.5),
central: ("npc.cockatrice.male.chest"),
),
tail_front: (
offset: (-2.5, -9.0, -6.0),
central: ("npc.cockatrice.male.tail_front"),
),
tail_rear: (
offset: (-2.5, -13.0, -3.0),
central: ("npc.cockatrice.male.tail_rear"),
)
),
(Cockatrice, Female): (
head: (
offset: (-4.5, -6.0, -3.5),
central: ("npc.cockatrice.male.head"),
),
beak: (
offset: (-1.5, 0.0, -1.5),
central: ("npc.cockatrice.male.beak"),
),
neck: (
offset: (-3.5, 0.0, -6.0),
central: ("npc.cockatrice.male.neck"),
),
chest: (
offset: (-5.5, -10.0, -9.5),
central: ("npc.cockatrice.male.chest"),
),
tail_front: (
offset: (-2.5, -9.0, -6.0),
central: ("npc.cockatrice.male.tail_front"),
),
tail_rear: (
offset: (-2.5, -13.0, -3.0),
central: ("npc.cockatrice.male.tail_rear"),
)
),
})

View File

@ -0,0 +1,170 @@
({
(Phoenix, Male): (
wing_in_l: (
offset: (-10.0, -12.0, -1.5),
lateral: ("npc.phoenix.male.wing_in_r"),
),
wing_in_r: (
offset: (0.0, -12.0, -1.5),
lateral: ("npc.phoenix.male.wing_in_r"),
),
wing_mid_l: (
offset: (-7.0, -15.0, -0.5),
lateral: ("npc.phoenix.male.wing_mid_r"),
),
wing_mid_r: (
offset: (0.0, -15.0, -0.5),
lateral: ("npc.phoenix.male.wing_mid_r"),
),
wing_out_l: (
offset: (-18.0, -18.0, -2.0),
lateral: ("npc.phoenix.male.wing_out_r"),
),
wing_out_r: (
offset: (0.0, -18.0, -2.0),
lateral: ("npc.phoenix.male.wing_out_r"),
),
leg_l: (
offset: (-4.0, -5.0, -4.5),
lateral: ("npc.phoenix.male.leg_r"),
),
leg_r: (
offset: (-4.0, -5.0, -4.5),
lateral: ("npc.phoenix.male.leg_r"),
),
foot_l: (
offset: (-3.5, -4.5, -9.0),
lateral: ("npc.phoenix.male.foot_r"),
),
foot_r: (
offset: (-3.5, -4.5, -9.0),
lateral: ("npc.phoenix.male.foot_r"),
)
),
(Phoenix, Female): (
wing_in_l: (
offset: (-10.0, -12.0, -1.5),
lateral: ("npc.phoenix.male.wing_in_r"),
),
wing_in_r: (
offset: (0.0, -12.0, -1.5),
lateral: ("npc.phoenix.male.wing_in_r"),
),
wing_mid_l: (
offset: (-7.0, -15.0, -0.5),
lateral: ("npc.phoenix.male.wing_mid_r"),
),
wing_mid_r: (
offset: (0.0, -15.0, -0.5),
lateral: ("npc.phoenix.male.wing_mid_r"),
),
wing_out_l: (
offset: (-18.0, -18.0, -2.0),
lateral: ("npc.phoenix.male.wing_out_r"),
),
wing_out_r: (
offset: (0.0, -18.0, -2.0),
lateral: ("npc.phoenix.male.wing_out_r"),
),
leg_l: (
offset: (-4.0, -5.0, -4.5),
lateral: ("npc.phoenix.male.leg_r"),
),
leg_r: (
offset: (-4.0, -5.0, -4.5),
lateral: ("npc.phoenix.male.leg_r"),
),
foot_l: (
offset: (-3.5, -4.5, -9.0),
lateral: ("npc.phoenix.male.foot_r"),
),
foot_r: (
offset: (-3.5, -4.5, -9.0),
lateral: ("npc.phoenix.male.foot_r"),
)
),
(Cockatrice, Male): (
wing_in_l: (
offset: (-7.0, -8.0, -2.0),
lateral: ("npc.cockatrice.male.wing_in_r"),
),
wing_in_r: (
offset: (0.0, -8.0, -2.0),
lateral: ("npc.cockatrice.male.wing_in_r"),
),
wing_mid_l: (
offset: (-5.0, -9.0, -2.0),
lateral: ("npc.cockatrice.male.wing_mid_r"),
),
wing_mid_r: (
offset: (0.0, -9.0, -2.0),
lateral: ("npc.cockatrice.male.wing_mid_r"),
),
wing_out_l: (
offset: (-10.0, -11.0, -2.0),
lateral: ("npc.cockatrice.male.wing_out_r"),
),
wing_out_r: (
offset: (0.0, -11.0, -2.0),
lateral: ("npc.cockatrice.male.wing_out_r"),
),
leg_l: (
offset: (-3.0, -4.5, -4.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
leg_r: (
offset: (-3.0, -4.5, -4.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
foot_l: (
offset: (-3.5, -5.5, -10.0),
lateral: ("npc.cockatrice.male.foot_r"),
),
foot_r: (
offset: (-3.5, -5.5, -10.0),
lateral: ("npc.cockatrice.male.foot_r"),
)
),
(Cockatrice, Female): (
wing_in_l: (
offset: (-7.0, -8.0, -2.0),
lateral: ("npc.cockatrice.male.wing_in_r"),
),
wing_in_r: (
offset: (0.0, -8.0, -2.0),
lateral: ("npc.cockatrice.male.wing_in_r"),
),
wing_mid_l: (
offset: (-5.0, -9.0, -2.0),
lateral: ("npc.cockatrice.male.wing_mid_r"),
),
wing_mid_r: (
offset: (0.0, -9.0, -2.0),
lateral: ("npc.cockatrice.male.wing_mid_r"),
),
wing_out_l: (
offset: (-10.0, -11.0, -2.0),
lateral: ("npc.cockatrice.male.wing_out_r"),
),
wing_out_r: (
offset: (0.0, -11.0, -2.0),
lateral: ("npc.cockatrice.male.wing_out_r"),
),
leg_l: (
offset: (-3.0, -4.5, -4.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
leg_r: (
offset: (-3.0, -4.5, -4.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
foot_l: (
offset: (-3.5, -5.5, -10.0),
lateral: ("npc.cockatrice.male.foot_r"),
),
foot_r: (
offset: (-3.5, -5.5, -10.0),
lateral: ("npc.cockatrice.male.foot_r"),
)
),
})

View File

@ -195,32 +195,4 @@
central: ("npc.parrot.male.tail"),
)
),
(Cockatrice, Male): (
head: (
offset: (-2.5, 0.0, -8.0),
central: ("npc.cockatrice.male.head"),
),
torso: (
offset: (-3.5, -6.5, -7.5),
central: ("npc.cockatrice.male.torso"),
),
tail: (
offset: (-1.5, -3.5, -4.0),
central: ("npc.cockatrice.male.tail"),
)
),
(Cockatrice, Female): (
head: (
offset: (-2.5, 0.0, -8.0),
central: ("npc.cockatrice.male.head"),
),
torso: (
offset: (-3.5, -6.5, -7.5),
central: ("npc.cockatrice.male.torso"),
),
tail: (
offset: (-1.5, -3.5, -4.0),
central: ("npc.cockatrice.male.tail"),
)
),
})

View File

@ -251,40 +251,4 @@
lateral: ("npc.parrot.male.leg_r"),
)
),
(Cockatrice, Male): (
wing_l: (
offset: (-2.0, -3.0, -9.0),
lateral: ("npc.cockatrice.male.wing_r"),
),
wing_r: (
offset: (-2.0, -3.0, -9.0),
lateral: ("npc.cockatrice.male.wing_r"),
),
foot_l: (
offset: (-2.5, 0.0, -12.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
foot_r: (
offset: (-2.5, 0.0, -12.0),
lateral: ("npc.cockatrice.male.leg_r"),
)
),
(Cockatrice, Female): (
wing_l: (
offset: (-2.0, -3.0, -9.0),
lateral: ("npc.cockatrice.male.wing_r"),
),
wing_r: (
offset: (-2.0, -3.0, -9.0),
lateral: ("npc.cockatrice.male.wing_r"),
),
foot_l: (
offset: (-2.5, 0.0, -12.0),
lateral: ("npc.cockatrice.male.leg_r"),
),
foot_r: (
offset: (-2.5, 0.0, -12.0),
lateral: ("npc.cockatrice.male.leg_r"),
)
),
})

BIN
assets/voxygen/voxel/npc/cockatrice/male/beak.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/chest.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/foot_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/neck.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/tail_front.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/tail_rear.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/wing_in_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/wing_mid_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/cockatrice/male/wing_out_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/beak.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/chest.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/foot_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/head.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/leg_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/neck.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/tail_front.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/tail_rear.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/wing_in_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/wing_mid_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/phoenix/male/wing_out_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -38,6 +38,8 @@ pub enum Tactic {
FixedTurret,
RotatingTurret,
Mindflayer,
BirdLargeBreathe,
BirdLargeFire,
}
#[derive(Copy, Clone, Debug, PartialEq)]
@ -247,7 +249,7 @@ impl<'a> From<&'a Body> for Psyche {
},
Body::BipedSmall(_) => 0.5,
Body::BirdMedium(_) => 0.5,
Body::BirdSmall(_) => 0.4,
Body::BirdLarge(_) => 0.9,
Body::FishMedium(_) => 0.15,
Body::FishSmall(_) => 0.0,
Body::BipedLarge(_) => 1.0,

View File

@ -1,7 +1,7 @@
pub mod biped_large;
pub mod biped_small;
pub mod bird_large;
pub mod bird_medium;
pub mod bird_small;
pub mod dragon;
pub mod fish_medium;
pub mod fish_small;
@ -38,7 +38,7 @@ make_case_elim!(
BirdMedium(body: bird_medium::Body) = 3,
FishMedium(body: fish_medium::Body) = 4,
Dragon(body: dragon::Body) = 5,
BirdSmall(body: bird_small::Body) = 6,
BirdLarge(body: bird_large::Body) = 6,
FishSmall(body: fish_small::Body) = 7,
BipedLarge(body: biped_large::Body)= 8,
BipedSmall(body: biped_small::Body)= 9,
@ -73,7 +73,7 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
pub bird_medium: BodyData<BodyMeta, bird_medium::AllSpecies<SpeciesMeta>>,
pub fish_medium: BodyData<BodyMeta, fish_medium::AllSpecies<SpeciesMeta>>,
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
pub bird_small: BodyData<BodyMeta, ()>,
pub bird_large: BodyData<BodyMeta, bird_large::AllSpecies<SpeciesMeta>>,
pub fish_small: BodyData<BodyMeta, fish_small::AllSpecies<SpeciesMeta>>,
pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
pub biped_small: BodyData<BodyMeta, biped_small::AllSpecies<SpeciesMeta>>,
@ -95,6 +95,7 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
NpcKind::Pig => &self.quadruped_small.body,
NpcKind::Wolf => &self.quadruped_medium.body,
NpcKind::Duck => &self.bird_medium.body,
NpcKind::Phoenix => &self.bird_large.body,
NpcKind::Marlin => &self.fish_medium.body,
NpcKind::Clownfish => &self.fish_small.body,
NpcKind::Ogre => &self.biped_large.body,
@ -118,9 +119,9 @@ impl<'a, BodyMeta, SpeciesMeta> core::ops::Index<&'a Body> for AllBodies<BodyMet
Body::QuadrupedSmall(_) => &self.quadruped_small.body,
Body::QuadrupedMedium(_) => &self.quadruped_medium.body,
Body::BirdMedium(_) => &self.bird_medium.body,
Body::BirdLarge(_) => &self.bird_large.body,
Body::FishMedium(_) => &self.fish_medium.body,
Body::Dragon(_) => &self.dragon.body,
Body::BirdSmall(_) => &self.bird_small.body,
Body::FishSmall(_) => &self.fish_small.body,
Body::BipedLarge(_) => &self.biped_large.body,
Body::BipedSmall(_) => &self.biped_small.body,
@ -152,7 +153,7 @@ impl Body {
let d = match self {
// based on a house sparrow (Passer domesticus)
Body::BirdMedium(_) => 700.0,
Body::BirdSmall(_) => 700.0,
Body::BirdLarge(_) => 2_200.0,
// based on its mass divided by the volume of a bird scaled up to the size of the dragon
Body::Dragon(_) => 3_700.0,
@ -183,8 +184,7 @@ impl Body {
// ravens are 0.69-2 kg, crows are 0.51 kg on average
Body::BirdMedium(_) => 1.0,
// australian magpies are around 0.22-0.35 kg
Body::BirdSmall(_) => 0.3,
Body::BirdLarge(_) => 200.0,
Body::Dragon(_) => 20_000.0,
Body::FishMedium(_) => 2.5,
@ -281,11 +281,8 @@ impl Body {
_ => Vec3::new(4.6, 3.0, 6.0),
},
Body::BipedSmall(_) => Vec3::new(1.0, 0.75, 1.4),
Body::BirdMedium(body) => match body.species {
bird_medium::Species::Cockatrice => Vec3::new(2.0, 1.0, 1.8),
_ => Vec3::new(2.0, 1.0, 1.1),
},
Body::BirdSmall(_) => Vec3::new(1.2, 0.6, 1.1),
Body::BirdMedium(_) => Vec3::new(2.0, 1.0, 1.1),
Body::BirdLarge(_) => Vec3::new(2.0, 5.0, 2.4),
Body::Dragon(_) => Vec3::new(16.0, 10.0, 16.0),
Body::FishMedium(_) => Vec3::new(0.5, 2.0, 0.8),
Body::FishSmall(_) => Vec3::new(0.3, 1.2, 0.6),
@ -374,6 +371,10 @@ impl Body {
biped_large::Species::Dullahan => 4000,
_ => 3000,
},
Body::BirdLarge(body) => match body.species {
bird_large::Species::Cockatrice => 4000,
bird_large::Species::Phoenix => 6000,
},
Body::Humanoid(_) => 750,
_ => 1000,
}
@ -429,13 +430,12 @@ impl Body {
bird_medium::Species::Goose => 60,
bird_medium::Species::Parrot => 60,
bird_medium::Species::Peacock => 60,
bird_medium::Species::Cockatrice => 400,
bird_medium::Species::Eagle => 400,
_ => 100,
},
Body::FishMedium(_) => 50,
Body::Dragon(_) => 5000,
Body::BirdSmall(_) => 50,
Body::BirdLarge(_) => 3000,
Body::FishSmall(_) => 20,
Body::BipedLarge(biped_large) => match biped_large.species {
biped_large::Species::Ogre => 2500,
@ -542,13 +542,12 @@ impl Body {
bird_medium::Species::Goose => 10,
bird_medium::Species::Parrot => 10,
bird_medium::Species::Peacock => 10,
bird_medium::Species::Cockatrice => 10,
bird_medium::Species::Eagle => 10,
_ => 20,
},
Body::FishMedium(_) => 10,
Body::Dragon(_) => 500,
Body::BirdSmall(_) => 10,
Body::BirdLarge(_) => 120,
Body::FishSmall(_) => 10,
Body::BipedLarge(biped_large) => match biped_large.species {
biped_large::Species::Ogre => 70,
@ -587,7 +586,7 @@ impl Body {
pub fn flying_height(&self) -> f32 {
match self {
Body::BirdSmall(_) => 30.0,
Body::BirdLarge(_) => 50.0,
Body::BirdMedium(_) => 40.0,
Body::Dragon(_) => 60.0,
Body::Ship(ship::Body::DefaultAirship) => 60.0,

View File

@ -0,0 +1,82 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
make_proj_elim!(
body,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub species: Species,
pub body_type: BodyType,
}
);
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
let species = *(&ALL_SPECIES).choose(&mut rng).unwrap();
Self::random_with(&mut rng, &species)
}
#[inline]
pub fn random_with(rng: &mut impl rand::Rng, &species: &Species) -> Self {
let body_type = *(&ALL_BODY_TYPES).choose(rng).unwrap();
Self { species, body_type }
}
}
impl From<Body> for super::Body {
fn from(body: Body) -> Self { super::Body::BirdLarge(body) }
}
make_case_elim!(
species,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Species {
Phoenix = 0,
Cockatrice = 1,
}
);
/// Data representing per-species generic data.
///
/// NOTE: Deliberately don't (yet?) implement serialize.
#[derive(Clone, Debug, Deserialize)]
pub struct AllSpecies<SpeciesMeta> {
pub phoenix: SpeciesMeta,
pub cockatrice: SpeciesMeta,
}
impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
type Output = SpeciesMeta;
#[inline]
fn index(&self, &index: &'a Species) -> &Self::Output {
match index {
Species::Phoenix => &self.phoenix,
Species::Cockatrice => &self.cockatrice,
}
}
}
pub const ALL_SPECIES: [Species; 2] = [Species::Phoenix, Species::Cockatrice];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}
make_case_elim!(
body_type,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum BodyType {
Female = 0,
Male = 1,
}
);
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];

View File

@ -41,7 +41,6 @@ make_case_elim!(
Eagle = 4,
Owl = 5,
Parrot = 6,
Cockatrice = 7,
}
);
@ -57,7 +56,6 @@ pub struct AllSpecies<SpeciesMeta> {
pub eagle: SpeciesMeta,
pub owl: SpeciesMeta,
pub parrot: SpeciesMeta,
pub cockatrice: SpeciesMeta,
}
impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
@ -73,12 +71,11 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
Species::Eagle => &self.eagle,
Species::Owl => &self.owl,
Species::Parrot => &self.parrot,
Species::Cockatrice => &self.cockatrice,
}
}
}
pub const ALL_SPECIES: [Species; 8] = [
pub const ALL_SPECIES: [Species; 7] = [
Species::Duck,
Species::Chicken,
Species::Goose,
@ -86,7 +83,6 @@ pub const ALL_SPECIES: [Species; 8] = [
Species::Eagle,
Species::Owl,
Species::Parrot,
Species::Cockatrice,
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {

View File

@ -1,66 +0,0 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
make_proj_elim!(
body,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub head: Head,
pub torso: Torso,
pub wing_l: WingL,
pub wing_r: WingR,
}
);
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
Self {
head: *(&ALL_HEADS).choose(&mut rng).unwrap(),
torso: *(&ALL_TORSOS).choose(&mut rng).unwrap(),
wing_l: *(&ALL_WING_LS).choose(&mut rng).unwrap(),
wing_r: *(&ALL_WING_RS).choose(&mut rng).unwrap(),
}
}
}
make_case_elim!(
head,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Head {
Default = 0,
}
);
const ALL_HEADS: [Head; 1] = [Head::Default];
make_case_elim!(
torso,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Torso {
Default = 0,
}
);
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
make_case_elim!(
wing_l,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum WingL {
Default = 0,
}
);
const ALL_WING_LS: [WingL; 1] = [WingL::Default];
make_case_elim!(
wing_r,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum WingR {
Default = 0,
}
);
const ALL_WING_RS: [WingR; 1] = [WingR::Default];

View File

@ -129,11 +129,11 @@ impl Body {
},
// Cross-section, zero-lift angle; exclude the wings (width * 0.2)
Body::BirdMedium(_) | Body::BirdSmall(_) | Body::Dragon(_) => {
Body::BirdMedium(_) | Body::BirdLarge(_) | Body::Dragon(_) => {
let dim = self.dimensions().map(|a| a * 0.5);
let cd = match self {
Body::BirdMedium(_) => 0.2,
Body::BirdSmall(_) => 0.4,
Body::BirdLarge(_) => 0.4,
_ => 0.7,
};
cd * std::f32::consts::PI * dim.x * 0.2 * dim.z

View File

@ -441,4 +441,6 @@ pub enum UniqueKind {
ObjectTurret,
WoodenSpear,
MindflayerStaff,
BirdLargeBreathe,
BirdLargeFire,
}

View File

@ -1,6 +1,6 @@
use crate::{
comp::{
biped_large, biped_small, golem,
biped_large, biped_small, bird_large, golem,
inventory::{
loadout::Loadout,
slot::{ArmorSlot, EquipSlot},
@ -333,6 +333,18 @@ impl LoadoutBuilder {
));
},
},
Body::BirdLarge(bird_large) => match (bird_large.species, bird_large.body_type) {
(bird_large::Species::Cockatrice, _) => {
main_tool = Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.birdlargebreathe",
));
},
(bird_large::Species::Phoenix, _) => {
main_tool = Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.birdlargefire",
));
},
},
_ => {},
};
}

View File

@ -50,7 +50,7 @@ pub use self::{
aura::{Aura, AuraChange, AuraKind, Auras},
beam::{Beam, BeamSegment},
body::{
biped_large, biped_small, bird_medium, bird_small, dragon, fish_medium, fish_small, golem,
biped_large, biped_small, bird_large, bird_medium, dragon, fish_medium, fish_small, golem,
humanoid, object, quadruped_low, quadruped_medium, quadruped_small, ship, theropod,
AllBodies, Body, BodyData,
},

View File

@ -135,6 +135,7 @@ impl EntityInfo {
Some(get_npc_name(&npc_names.quadruped_medium, body.species))
},
Body::BirdMedium(body) => Some(get_npc_name(&npc_names.bird_medium, body.species)),
Body::BirdLarge(body) => Some(get_npc_name(&npc_names.bird_large, body.species)),
Body::FishSmall(body) => Some(get_npc_name(&npc_names.fish_small, body.species)),
Body::FishMedium(body) => Some(get_npc_name(&npc_names.fish_medium, body.species)),
Body::Theropod(body) => Some(get_npc_name(&npc_names.theropod, body.species)),

View File

@ -13,6 +13,7 @@ pub enum NpcKind {
Wolf,
Pig,
Duck,
Phoenix,
Clownfish,
Marlin,
Ogre,
@ -23,11 +24,12 @@ pub enum NpcKind {
Crocodile,
}
pub const ALL_NPCS: [NpcKind; 12] = [
pub const ALL_NPCS: [NpcKind; 13] = [
NpcKind::Humanoid,
NpcKind::Wolf,
NpcKind::Pig,
NpcKind::Duck,
NpcKind::Phoenix,
NpcKind::Clownfish,
NpcKind::Marlin,
NpcKind::Ogre,
@ -122,6 +124,7 @@ pub fn kind_to_body(kind: NpcKind) -> Body {
NpcKind::Pig => comp::quadruped_small::Body::random().into(),
NpcKind::Wolf => comp::quadruped_medium::Body::random().into(),
NpcKind::Duck => comp::bird_medium::Body::random().into(),
NpcKind::Phoenix => comp::bird_large::Body::random().into(),
NpcKind::Clownfish => comp::fish_small::Body::random().into(),
NpcKind::Marlin => comp::fish_medium::Body::random().into(),
NpcKind::Ogre => comp::biped_large::Body::random().into(),
@ -228,6 +231,14 @@ impl NpcBody {
comp::bird_medium::Body::random_with,
)
})
.or_else(|| {
parse(
s,
NpcKind::Phoenix,
&npc_names.bird_large,
comp::bird_large::Body::random_with,
)
})
.or_else(|| {
parse(
s,

View File

@ -3,7 +3,7 @@ use crate::{
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageSource,
GroupTarget,
},
comp::{beam, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate},
comp::{beam, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -136,11 +136,15 @@ impl CharacterBehavior for Data {
owner: Some(*data.uid),
specifier: self.static_data.specifier,
};
let body_offsets_z = match data.body {
Body::BirdLarge(_) => data.body.height() * 0.9,
_ => data.body.height() * 0.5,
};
// Gets offsets
let body_offsets = Vec3::new(
(data.body.radius() + 0.2) * data.inputs.look_dir.x,
(data.body.radius() + 0.2) * data.inputs.look_dir.y,
data.body.eye_height() * 0.6,
(data.body.radius() + 1.0) * data.inputs.look_dir.x,
(data.body.radius() + 1.0) * data.inputs.look_dir.y,
body_offsets_z,
);
let pos = Pos(data.pos.0 + body_offsets);
// Create beam segment

View File

@ -77,7 +77,7 @@ impl Body {
Body::BirdMedium(_) => 80.0,
Body::FishMedium(_) => 80.0,
Body::Dragon(_) => 250.0,
Body::BirdSmall(_) => 75.0,
Body::BirdLarge(_) => 110.0,
Body::FishSmall(_) => 60.0,
Body::BipedSmall(biped_small) => match biped_small.species {
biped_small::Species::Haniwa => 65.0,
@ -133,7 +133,7 @@ impl Body {
Body::BirdMedium(_) => 6.0,
Body::FishMedium(_) => 6.0,
Body::Dragon(_) => 1.0,
Body::BirdSmall(_) => 7.0,
Body::BirdLarge(_) => 7.0,
Body::FishSmall(_) => 7.0,
Body::BipedLarge(_) => 1.6,
Body::BipedSmall(_) => 2.4,
@ -165,7 +165,7 @@ impl Body {
Body::BipedLarge(_) | Body::Golem(_) => Some(200.0 * self.mass().0),
Body::BipedSmall(_) => Some(100.0 * self.mass().0),
Body::BirdMedium(_) => Some(50.0 * self.mass().0),
Body::BirdSmall(_) => Some(50.0 * self.mass().0),
Body::BirdLarge(_) => Some(50.0 * self.mass().0),
Body::FishMedium(_) => Some(50.0 * self.mass().0),
Body::FishSmall(_) => Some(50.0 * self.mass().0),
Body::Dragon(_) => Some(200.0 * self.mass().0),
@ -188,7 +188,7 @@ impl Body {
pub fn fly_thrust(&self) -> Option<f32> {
match self {
Body::BirdMedium(_) => Some(GRAVITY * self.mass().0 * 2.0),
Body::BirdSmall(_) => Some(GRAVITY * self.mass().0 * 2.0),
Body::BirdLarge(_) => Some(GRAVITY * self.mass().0 * 0.5),
Body::Dragon(_) => Some(200_000.0),
Body::Ship(ship::Body::DefaultAirship) => Some(300_000.0),
_ => None,
@ -377,7 +377,7 @@ pub fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) -> b
// Elevation control
match data.body {
// flappy flappy
Body::Dragon(_) | Body::BirdMedium(_) | Body::BirdSmall(_) => {
Body::Dragon(_) | Body::BirdMedium(_) | Body::BirdLarge(_) => {
let anti_grav = GRAVITY * (1.0 + data.inputs.move_z.min(0.0));
update.vel.0.z += data.dt.0 * (anti_grav + accel * data.inputs.move_z.max(0.0));
},

View File

@ -1,4 +1,4 @@
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DayPeriod {
Night,
Morning,

View File

@ -1,7 +1,9 @@
use crate::metrics::ChunkGenMetrics;
#[cfg(not(feature = "worldgen"))]
use crate::test_world::{IndexOwned, World};
use common::{generation::ChunkSupplement, slowjob::SlowJobPool, terrain::TerrainChunk};
use common::{
generation::ChunkSupplement, resources::TimeOfDay, slowjob::SlowJobPool, terrain::TerrainChunk,
};
use hashbrown::{hash_map::Entry, HashMap};
use specs::Entity as EcsEntity;
use std::sync::{
@ -42,6 +44,7 @@ impl ChunkGenerator {
slowjob_pool: &SlowJobPool,
world: Arc<World>,
index: IndexOwned,
time: TimeOfDay,
) {
let v = if let Entry::Vacant(v) = self.pending_chunks.entry(key) {
v
@ -55,7 +58,7 @@ impl ChunkGenerator {
slowjob_pool.spawn("CHUNK_GENERATOR", move || {
let index = index.as_index_ref();
let payload = world
.generate_chunk(index, key, || cancel.load(Ordering::Relaxed))
.generate_chunk(index, key, || cancel.load(Ordering::Relaxed), Some(time))
.map_err(|_| entity);
let _ = chunk_tx.send((key, payload));
});

View File

@ -725,6 +725,7 @@ impl Server {
&slow_jobs,
Arc::clone(&world),
index.clone(),
*ecs.read_resource::<TimeOfDay>(),
);
});
}
@ -930,6 +931,7 @@ impl Server {
&slow_jobs,
Arc::clone(&self.world),
self.index.clone(),
*ecs.read_resource::<TimeOfDay>(),
);
}

View File

@ -38,12 +38,18 @@ impl Entity {
match self.rng(PERM_GENUS).gen::<f32>() {
// we want 5% airships, 45% birds, 50% humans
x if x < 0.05 => comp::Body::Ship(comp::ship::Body::DefaultAirship),
x if x < 0.50 => {
x if x < 0.45 => {
let species = *(&comp::bird_medium::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
.unwrap();
comp::bird_medium::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
},
x if x < 0.50 => {
let species = *(&comp::bird_large::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
.unwrap();
comp::bird_large::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
},
_ => {
let species = *(&comp::humanoid::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
@ -60,7 +66,7 @@ impl Entity {
comp::Body::BirdMedium(b) => {
get_npc_name(&npc_names.bird_medium, b.species).to_string()
},
comp::Body::BirdSmall(_) => "Warbler".to_string(),
comp::Body::BirdLarge(b) => get_npc_name(&npc_names.bird_large, b.species).to_string(),
comp::Body::Dragon(b) => get_npc_name(&npc_names.dragon, b.species).to_string(),
comp::Body::Humanoid(b) => get_npc_name(&npc_names.humanoid, b.species).to_string(),
comp::Body::Ship(_) => "Veloren Air".to_string(),

View File

@ -11,6 +11,7 @@ use common::{
Group, Inventory,
},
effect::Effect,
resources::TimeOfDay,
slowjob::SlowJobPool,
uid::{Uid, UidAllocator},
};
@ -382,7 +383,7 @@ impl StateExt for State {
.for_each(|chunk_key| {
#[cfg(feature = "worldgen")]
{
chunk_generator.generate_chunk(None, chunk_key, &slow_jobs, Arc::clone(world), index.clone());
chunk_generator.generate_chunk(None, chunk_key, &slow_jobs, Arc::clone(world), index.clone(), *ecs.read_resource::<TimeOfDay>());
}
});
}

View File

@ -1538,6 +1538,8 @@ impl<'a> AgentData<'a> {
Some(ToolKind::Unique(UniqueKind::TheropodBird)) => Tactic::Theropod,
Some(ToolKind::Unique(UniqueKind::ObjectTurret)) => Tactic::Turret,
Some(ToolKind::Unique(UniqueKind::MindflayerStaff)) => Tactic::Mindflayer,
Some(ToolKind::Unique(UniqueKind::BirdLargeBreathe)) => Tactic::BirdLargeBreathe,
Some(ToolKind::Unique(UniqueKind::BirdLargeFire)) => Tactic::BirdLargeFire,
_ => Tactic::Melee,
};
@ -2587,6 +2589,244 @@ impl<'a> AgentData<'a> {
controller.inputs.move_z = bearing.z;
}
},
Tactic::BirdLargeFire => {
// Set fly to false
controller
.actions
.push(ControlAction::CancelInput(InputKind::Fly));
// If further than 30 blocks
if dist_sqrd > 30.0_f32.powi(2) {
// If random chance and can see target
if thread_rng().gen_bool(0.05)
&& can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd)
{
// Fireball
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
// If some target
if let Some((bearing, speed)) = agent.chaser.chase(
&*terrain,
self.pos.0,
self.vel.0,
tgt_pos.0,
TraversalConfig {
min_tgt_dist: 1.25,
..self.traversal_config
},
) {
// Walk to target
controller.inputs.move_dir =
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
// If less than 20 blocks higher than target
if (self.pos.0.z - tgt_pos.0.z) < 20.0 {
// Fly upward
controller
.actions
.push(ControlAction::basic_input(InputKind::Fly));
controller
.actions
.push(ControlAction::basic_input(InputKind::Jump));
controller.inputs.move_z = 1.0;
} else {
// Jump
self.jump_if(controller, bearing.z > 1.5);
controller.inputs.move_z = bearing.z;
}
}
}
// If higher than 2 blocks
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
// Fly to target
controller
.actions
.push(ControlAction::basic_input(InputKind::Fly));
let move_dir = tgt_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 further than 4 blocks and random chance
if thread_rng().gen_bool(0.05) && dist_sqrd > (4.0 * min_attack_dist).powi(2) {
// Fireball
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
}
// If further than 4 blocks and random chance
else if thread_rng().gen_bool(0.05) && dist_sqrd > (4.0 * min_attack_dist).powi(2)
{
// Fireball
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
// If random chance and less than 20 blocks higher than target and further than 4
// blocks
else if thread_rng().gen_bool(0.5)
&& (self.pos.0.z - tgt_pos.0.z) < 15.0
&& dist_sqrd > (4.0 * min_attack_dist).powi(2)
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Fly));
controller
.actions
.push(ControlAction::basic_input(InputKind::Jump));
controller.inputs.move_z = 1.0;
}
// If further than 2.5 blocks and random chance
else if dist_sqrd > (2.5 * min_attack_dist).powi(2) {
// If some target
if let Some((bearing, speed)) = agent.chaser.chase(
&*terrain,
self.pos.0,
self.vel.0,
tgt_pos.0,
TraversalConfig {
min_tgt_dist: 1.25,
..self.traversal_config
},
) {
// Walk to target
controller.inputs.move_dir =
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
self.jump_if(controller, bearing.z > 1.5);
controller.inputs.move_z = bearing.z;
}
}
// If energy higher than 600 and random chance
else if self.energy.current() > 600 && thread_rng().gen_bool(0.4) {
// Shockwave
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
} else {
// Triple strike
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
}
},
// Mostly identical to BirdLargeFire but tweaked for flamethrower instead of shockwave
Tactic::BirdLargeBreathe => {
// Set fly to false
controller
.actions
.push(ControlAction::CancelInput(InputKind::Fly));
if dist_sqrd > 30.0_f32.powi(2) {
if thread_rng().gen_bool(0.05)
&& can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd)
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
if let Some((bearing, speed)) = agent.chaser.chase(
&*terrain,
self.pos.0,
self.vel.0,
tgt_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_pos.0.z) < 20.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Fly));
controller
.actions
.push(ControlAction::basic_input(InputKind::Jump));
controller.inputs.move_z = 1.0;
} else {
self.jump_if(controller, bearing.z > 1.5);
controller.inputs.move_z = bearing.z;
}
}
} 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
.actions
.push(ControlAction::basic_input(InputKind::Fly));
let move_dir = tgt_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 thread_rng().gen_bool(0.05) && dist_sqrd > (4.0 * min_attack_dist).powi(2) {
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
} else if thread_rng().gen_bool(0.05) && dist_sqrd > (4.0 * min_attack_dist).powi(2)
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
} else if thread_rng().gen_bool(0.5)
&& (self.pos.0.z - tgt_pos.0.z) < 15.0
&& dist_sqrd > (4.0 * min_attack_dist).powi(2)
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Fly));
controller
.actions
.push(ControlAction::basic_input(InputKind::Jump));
controller.inputs.move_z = 1.0;
} else if dist_sqrd > (3.0 * min_attack_dist).powi(2) {
if let Some((bearing, speed)) = agent.chaser.chase(
&*terrain,
self.pos.0,
self.vel.0,
tgt_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;
self.jump_if(controller, bearing.z > 1.5);
controller.inputs.move_z = bearing.z;
}
} else if self.energy.current() > 600 && agent.action_timer < 3.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
agent.action_timer += dt.0;
} else if agent.action_timer < 6.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
agent.action_timer += dt.0;
} else {
agent.action_timer = 0.0;
}
},
}
}

View File

@ -0,0 +1,108 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::states::utils::StageSection;
pub struct AlphaAnimation;
impl Animation for AlphaAnimation {
type Dependency = (Option<StageSection>, Vec3<f32>, Vec3<f32>, bool);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_alpha\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_alpha")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(stage_section, orientation, last_ori, on_ground): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let (move1base, move2base, move3) = match stage_section {
Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0),
Some(StageSection::Swing) => (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 pullback = 1.0 - move3;
let move1 = move1base * pullback;
let move2 = move2base * pullback;
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.chest.position =
Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + wave_slow_cos * 0.06) * s_a.scaler / 8.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.8)
* Quaternion::rotation_z(move1 * tilt * 1.5);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_x(move1 * 0.5 - move2 * 0.8);
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 - 0.02);
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) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation =
Quaternion::rotation_y(1.0 - wave_slow_cos * 0.06) * 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) * 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) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation =
Quaternion::rotation_y(0.2) * Quaternion::rotation_z(-0.2);
} else {
}
next
}
}

View File

@ -0,0 +1,135 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::{states::utils::StageSection, util::Dir};
pub struct BreatheAnimation;
type BreatheAnimationDependency = (
f32,
Vec3<f32>,
Vec3<f32>,
Option<StageSection>,
f32,
Dir,
bool,
);
impl Animation for BreatheAnimation {
type Dependency = BreatheAnimationDependency;
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_breathe\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_breathe")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(global_time, orientation, last_ori, stage_section, timer, look_dir, on_ground): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
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, 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.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.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation =
Quaternion::rotation_x(movement1abs * 0.5 - movement2abs * 0.5 + 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.chest.orientation =
Quaternion::rotation_x(movement1abs * 0.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_y(-1.0 + movement1abs * 0.8 - movement2abs * 0.4)
* Quaternion::rotation_z(0.2 - movement1abs * 0.8 + movement2abs * 0.4);
next.wing_in_r.orientation =
Quaternion::rotation_y(1.0 - movement1abs * 0.8 + movement2abs * 0.4)
* Quaternion::rotation_z(-0.2 + movement1abs * 0.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) * 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) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation =
Quaternion::rotation_y(0.2) * 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 {
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.chest.orientation =
Quaternion::rotation_x(movement1abs * 0.1 - movement2abs * 0.1)
* Quaternion::rotation_y(tilt * 1.8);
}
next
}
}

View File

@ -0,0 +1,100 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use std::ops::Mul;
pub struct FeedAnimation;
impl Animation for FeedAnimation {
type Dependency = f32;
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_feed\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_feed")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
global_time: Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let duck_head_look = Vec2::new(
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(7331.0)
.sin()
* 0.5,
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(1337.0)
.sin()
* 0.25,
);
let wave_slow_cos = (anim_time * 4.5).cos();
let wave_fast = (anim_time * 9.0).cos();
let beak = (anim_time * 16.0).sin();
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 - 1.8)
* s_a.scaler
/ 8.0;
next.chest.orientation = Quaternion::rotation_x(s_a.feed);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation = Quaternion::rotation_x(-0.2);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_z(duck_head_look.x)
* Quaternion::rotation_x(-0.2 - duck_head_look.y.abs() + wave_slow_cos * 0.01);
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
next.beak.orientation = Quaternion::rotation_x(beak * -0.1 - 0.1);
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.0);
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(-0.7 + wave_fast * 0.08) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation =
Quaternion::rotation_y(0.7 - wave_fast * 0.08) * 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) * 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) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation = Quaternion::rotation_y(0.2) * Quaternion::rotation_z(-0.2);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(0.0);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(0.0);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(0.0);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(0.0);
next
}
}

View File

@ -0,0 +1,177 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
pub struct FlyAnimation;
impl Animation for FlyAnimation {
type Dependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_fly\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_fly")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let slow = (anim_time * 2.0).sin();
let fast = (anim_time * 4.0).sin();
// Harmonic series hack to get a sine/saw mix
let freq = 8.0;
let off1 = 0.0;
let off2 = -1.7;
let off3 = -2.0;
let off4 = -2.4;
let flap1 = 7.0 / 16.0 * (freq * anim_time + off1).sin()
+ 7.0 / 64.0 * (freq * 2.0 * anim_time + off1).sin()
+ 1.0 / 48.0 * (freq * 3.0 * anim_time + off1).sin();
let flap2 = 7.0 / 16.0 * (freq * anim_time + off2).sin()
+ 7.0 / 64.0 * (freq * 2.0 * anim_time + off2).sin()
+ 1.0 / 48.0 * (freq * 3.0 * anim_time + off2).sin();
let flap3 = 7.0 / 16.0 * (freq * anim_time + off3).sin()
+ 7.0 / 64.0 * (freq * 2.0 * anim_time + off3).sin()
+ 1.0 / 48.0 * (freq * 3.0 * anim_time + off3).sin();
let flap4 = 7.0 / 16.0 * (freq * anim_time + off4).sin()
+ 7.0 / 64.0 * (freq * 2.0 * anim_time + off4).sin()
+ 1.0 / 48.0 * (freq * 3.0 * anim_time + off4).sin();
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.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation =
Quaternion::rotation_x((-0.4 + 0.2 * velocity.xy().magnitude() / 5.0).min(0.15));
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_x(
(-0.5 + 0.2 * velocity.xy().magnitude() / 5.0).min(-0.3) + fast * 0.05,
);
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
if velocity.z > 2.0 || velocity.xy().magnitude() < 12.0 {
next.chest.position =
Vec3::new(0.0, s_a.chest.0, s_a.chest.1 - flap4 * 1.5) * s_a.scaler / 8.0;
next.chest.orientation = Quaternion::rotation_x(
(0.8 - 0.8 * velocity.xy().magnitude() / 5.0).max(-0.2) - flap1 * 0.2,
) * Quaternion::rotation_y(tilt * 1.8 + fast * 0.01);
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(-flap1 * 1.9 + 0.2) * Quaternion::rotation_x(0.4);
next.wing_in_r.orientation =
Quaternion::rotation_y(flap1 * 1.9 - 0.2) * Quaternion::rotation_x(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(-flap2 * 1.4 - 0.2);
next.wing_mid_r.orientation = Quaternion::rotation_y(flap2 * 1.4 + 0.2);
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(-flap3 * 1.2 - 0.3);
next.wing_out_r.orientation = Quaternion::rotation_y(flap3 * 1.2 + 0.3);
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(-flap2 * 0.2 + 0.1) * Quaternion::rotation_z(-tilt * 1.0);
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(-flap3 * 0.3 + 0.15) * Quaternion::rotation_z(-tilt * 0.8);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2 - flap4 * 1.5) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(
(-1.0 * velocity.xy().magnitude() / 5.0).max(-1.2) + flap1 * -0.1,
) * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2 - flap4 * 1.5) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(
(-1.0 * velocity.xy().magnitude() / 5.0).max(-1.2) + flap1 * -0.1,
) * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(flap1 * -0.1);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(flap1 * -0.1);
} else {
next.chest.position =
Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + slow * 0.05) * s_a.scaler / 8.0;
next.chest.orientation =
Quaternion::rotation_x(-0.2 + slow * 0.05 + (0.8 * velocity.z / 80.0).min(0.8))
* Quaternion::rotation_y(tilt * 1.8 + fast * 0.01);
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.1 + slow * 0.04 + (0.8 * velocity.z / 80.0).min(0.8))
* Quaternion::rotation_x(0.4);
next.wing_in_r.orientation =
Quaternion::rotation_y(-0.1 + slow * -0.04 - (0.8 * velocity.z / 80.0).min(0.8))
* Quaternion::rotation_x(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 + slow * 0.04);
next.wing_mid_r.orientation = Quaternion::rotation_y(-0.1 + slow * -0.04);
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.1 + slow * 0.04 + (0.4 * velocity.z / 80.0).min(0.2));
next.wing_out_r.orientation =
Quaternion::rotation_y(-0.1 + slow * -0.04 - (0.4 * velocity.z / 80.0).min(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(0.04 - slow * 0.04) * Quaternion::rotation_z(-tilt * 1.0);
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(slow * 0.08) * Quaternion::rotation_z(-tilt * 0.8);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2 + slow * 0.05) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(-1.2 + slow * -0.05)
* Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2 + slow * 0.05) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(-1.2 + slow * -0.05)
* Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(slow * -0.05);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(slow * -0.05);
}
next
}
}

View File

@ -0,0 +1,98 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use std::ops::Mul;
pub struct IdleAnimation;
impl Animation for IdleAnimation {
type Dependency = f32;
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_idle")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
global_time: Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let duck_head_look = Vec2::new(
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(7331.0)
.sin()
* 0.5,
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(1337.0)
.sin()
* 0.25,
);
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 + 1.5)
* s_a.scaler
/ 8.0;
next.chest.orientation = Quaternion::rotation_x(0.0);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation = Quaternion::rotation_x(0.0);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_z(duck_head_look.x)
* Quaternion::rotation_x(-duck_head_look.y.abs() + wave_slow_cos * 0.01);
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 - 0.02);
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);
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);
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 + wave_slow_cos * 0.06) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation =
Quaternion::rotation_y(0.8 - wave_slow_cos * 0.06) * 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) * 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.4) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation = Quaternion::rotation_y(0.4) * Quaternion::rotation_z(-0.2);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(0.0);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(0.0);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(0.0);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(0.0);
next
}
}

View File

@ -0,0 +1,203 @@
pub mod alpha;
pub mod breathe;
pub mod feed;
pub mod fly;
pub mod idle;
pub mod run;
pub mod shockwave;
pub mod shoot;
pub mod stunned;
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,
};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::bird_large::Body;
skeleton_impls!(struct BirdLargeSkeleton {
+ head,
+ beak,
+ neck,
+ chest,
+ tail_front,
+ tail_rear,
+ wing_in_l,
+ wing_in_r,
+ wing_mid_l,
+ wing_mid_r,
+ wing_out_l,
+ wing_out_r,
+ leg_l,
+ leg_r,
+ foot_l,
+ foot_r,
});
impl Skeleton for BirdLargeSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 16;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"bird_large_compute_mats\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_compute_mats")]
fn compute_matrices_inner(
&self,
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Vec3<f32> {
let chest_mat = base_mat * Mat4::<f32>::from(self.chest);
let neck_mat = chest_mat * Mat4::<f32>::from(self.neck);
let head_mat = neck_mat * Mat4::<f32>::from(self.head);
let beak_mat = head_mat * Mat4::<f32>::from(self.beak);
let tail_front_mat = chest_mat * Mat4::<f32>::from(self.tail_front);
let tail_rear_mat = tail_front_mat * Mat4::<f32>::from(self.tail_rear);
let wing_in_l_mat = chest_mat * Mat4::<f32>::from(self.wing_in_l);
let wing_in_r_mat = chest_mat * Mat4::<f32>::from(self.wing_in_r);
let wing_mid_l_mat = wing_in_l_mat * Mat4::<f32>::from(self.wing_mid_l);
let wing_mid_r_mat = wing_in_r_mat * Mat4::<f32>::from(self.wing_mid_r);
let wing_out_l_mat = wing_mid_l_mat * Mat4::<f32>::from(self.wing_out_l);
let wing_out_r_mat = wing_mid_r_mat * Mat4::<f32>::from(self.wing_out_r);
let leg_l_mat = base_mat * Mat4::<f32>::from(self.leg_l);
let leg_r_mat = base_mat * Mat4::<f32>::from(self.leg_r);
let foot_l_mat = leg_l_mat * Mat4::<f32>::from(self.foot_l);
let foot_r_mat = leg_r_mat * Mat4::<f32>::from(self.foot_r);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(head_mat),
make_bone(beak_mat),
make_bone(neck_mat),
make_bone(chest_mat),
make_bone(tail_front_mat),
make_bone(tail_rear_mat),
make_bone(wing_in_l_mat),
make_bone(wing_in_r_mat),
make_bone(wing_mid_l_mat),
make_bone(wing_mid_r_mat),
make_bone(wing_out_l_mat),
make_bone(wing_out_r_mat),
make_bone(leg_l_mat),
make_bone(leg_r_mat),
make_bone(foot_l_mat),
make_bone(foot_r_mat),
];
Vec3::default()
}
}
pub struct SkeletonAttr {
chest: (f32, f32),
neck: (f32, f32),
head: (f32, f32),
beak: (f32, f32),
tail_front: (f32, f32),
tail_rear: (f32, f32),
wing_in: (f32, f32, f32),
wing_mid: (f32, f32, f32),
wing_out: (f32, f32, f32),
leg: (f32, f32, f32),
foot: (f32, f32, f32),
scaler: f32,
feed: f32,
}
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
type Error = ();
fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
match body {
comp::Body::BirdLarge(body) => Ok(SkeletonAttr::from(body)),
_ => Err(()),
}
}
}
impl Default for SkeletonAttr {
fn default() -> Self {
Self {
chest: (0.0, 0.0),
neck: (0.0, 0.0),
head: (0.0, 0.0),
beak: (0.0, 0.0),
tail_front: (0.0, 0.0),
tail_rear: (0.0, 0.0),
wing_in: (0.0, 0.0, 0.0),
wing_mid: (0.0, 0.0, 0.0),
wing_out: (0.0, 0.0, 0.0),
leg: (0.0, 0.0, 0.0),
foot: (0.0, 0.0, 0.0),
scaler: 0.0,
feed: 0.0,
}
}
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::bird_large::Species::*;
Self {
chest: match (body.species, body.body_type) {
(Phoenix, _) => (2.5, 16.0),
(Cockatrice, _) => (2.5, 16.0),
},
neck: match (body.species, body.body_type) {
(Phoenix, _) => (2.5, -5.5),
(Cockatrice, _) => (5.0, -1.5),
},
head: match (body.species, body.body_type) {
(Phoenix, _) => (6.0, 12.0),
(Cockatrice, _) => (8.0, 4.5),
},
beak: match (body.species, body.body_type) {
(Phoenix, _) => (5.0, 3.0),
(Cockatrice, _) => (2.0, -3.0),
},
tail_front: match (body.species, body.body_type) {
(Phoenix, _) => (-9.5, -1.0),
(Cockatrice, _) => (-5.0, -2.5),
},
tail_rear: match (body.species, body.body_type) {
(Phoenix, _) => (-11.0, 0.0),
(Cockatrice, _) => (-8.0, -3.0),
},
wing_in: match (body.species, body.body_type) {
(Phoenix, _) => (3.0, 2.5, 2.0),
(Cockatrice, _) => (3.5, 7.0, 3.5),
},
wing_mid: match (body.species, body.body_type) {
(Phoenix, _) => (10.0, 1.0, 0.0),
(Cockatrice, _) => (6.0, 0.0, 0.0),
},
wing_out: match (body.species, body.body_type) {
(Phoenix, _) => (7.0, 2.0, 1.5),
(Cockatrice, _) => (4.0, -1.0, 1.0),
},
leg: match (body.species, body.body_type) {
(Phoenix, _) => (4.0, 1.5, 12.0),
(Cockatrice, _) => (3.5, 2.5, 13.0),
},
foot: match (body.species, body.body_type) {
(Phoenix, _) => (0.5, -0.5, -2.5),
(Cockatrice, _) => (0.5, -3.0, -3.0),
},
scaler: match (body.species, body.body_type) {
(Phoenix, _) => (1.0),
(Cockatrice, _) => (1.0),
},
feed: match (body.species, body.body_type) {
(Phoenix, _) => (-0.65),
(Cockatrice, _) => (-0.5),
},
}
}
}

View File

@ -0,0 +1,159 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use std::f32::consts::PI;
pub struct RunAnimation;
impl Animation for RunAnimation {
type Dependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f32);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_run")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori, acc_vel): Self::Dependency,
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 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;
//FL
let foot1a = (mixed_vel * 1.0 * lab * speedmult + 0.0 + PI).sin() * speednorm; //1.5
let foot1b = (mixed_vel * 1.0 * lab * speedmult + 1.57 + PI).sin() * speednorm; //1.9
//FR
let foot2a = (mixed_vel * 1.0 * lab * speedmult).sin() * speednorm; //1.2
let foot2b = (mixed_vel * 1.0 * lab * speedmult + 1.57).sin() * speednorm; //1.6
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)
* 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);
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)
* 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);
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) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation = Quaternion::rotation_y(0.8) * 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) * 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);
next.leg_l.position = Vec3::new(
-s_a.leg.0 + speednorm * 1.5,
s_a.leg.1 + foot1b * -2.3,
s_a.leg.2,
) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(-0.2 * speednorm + foot1a * 0.15)
* Quaternion::rotation_y(tilt * 0.5);
next.leg_r.position = Vec3::new(
s_a.leg.0 + speednorm * -1.5,
s_a.leg.1 + foot2b * -2.3,
s_a.leg.2,
) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(-0.2 * speednorm + foot2a * 0.15)
* Quaternion::rotation_y(tilt * 0.5);
next.foot_l.position = Vec3::new(
-s_a.foot.0,
s_a.foot.1 + foot1b * -1.0,
s_a.foot.2 + (foot1a * 1.5).max(0.0),
);
next.foot_l.orientation = Quaternion::rotation_x(0.2 * speednorm + foot1b * -0.5 + 0.1)
* Quaternion::rotation_y(tilt * -1.0)
* Quaternion::rotation_z(tilt * -0.5);
next.foot_r.position = Vec3::new(
s_a.foot.0,
s_a.foot.1 + foot2b * -1.0,
s_a.foot.2 + (foot2a * 1.5).max(0.0),
);
next.foot_r.orientation = Quaternion::rotation_x(0.2 * speednorm + foot2b * -0.5 + 0.1)
* Quaternion::rotation_y(tilt * -1.0)
* Quaternion::rotation_z(tilt * -0.5);
next
}
}

View File

@ -0,0 +1,106 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::states::utils::StageSection;
pub struct ShockwaveAnimation;
impl Animation for ShockwaveAnimation {
#[allow(clippy::type_complexity)]
type Dependency = (Option<StageSection>, bool);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_shockwave\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_shockwave")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(stage_section, on_ground): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let (movement1base, movement2base, movement3, _twitch) = match stage_section {
Some(StageSection::Buildup) => (anim_time.powf(0.5), 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, 1.0),
_ => (0.0, 0.0, 0.0, 0.0),
};
let pullback = 1.0 - movement3;
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 + movement1abs * 1.5) * s_a.scaler / 8.0;
next.chest.orientation = Quaternion::rotation_x(movement1abs * 1.0 + movement2abs * -1.0);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation = Quaternion::rotation_x(-0.2);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_x(wave_slow_cos * 0.01);
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 - 0.02);
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);
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);
if on_ground {
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.6 + movement2abs * -1.6)
* Quaternion::rotation_z(0.2 + movement1abs * -0.8);
next.wing_in_r.orientation =
Quaternion::rotation_y(0.8 + movement1abs * -1.6 + movement2abs * 1.6)
* Quaternion::rotation_z(-0.2 + movement1abs * 0.8);
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.4) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation =
Quaternion::rotation_y(0.4) * Quaternion::rotation_z(-0.2);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(0.0);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(0.0);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(0.0);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(0.0);
} else {
}
next
}
}

View File

@ -0,0 +1,110 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::{states::utils::StageSection, util::Dir};
pub struct ShootAnimation;
type ShootAnimationDependency = (f32, Option<StageSection>, f32, Dir, bool);
impl Animation for ShootAnimation {
type Dependency = ShootAnimationDependency;
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_shoot\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_shoot")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(global_time, stage_section, timer, look_dir, on_ground): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
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, 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 * 0.5 - movement2abs * 0.5 + 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 * 0.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_y(-1.0 + movement1abs * 0.8 - movement2abs * 0.4)
* Quaternion::rotation_z(0.2 - movement1abs * 0.8 + movement2abs * 0.4);
next.wing_in_r.orientation =
Quaternion::rotation_y(1.0 - movement1abs * 0.8 + movement2abs * 0.4)
* Quaternion::rotation_z(-0.2 + movement1abs * 0.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) * 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) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation =
Quaternion::rotation_y(0.2) * 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

@ -0,0 +1,91 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use common::states::utils::StageSection;
pub struct StunnedAnimation;
impl Animation for StunnedAnimation {
type Dependency = (f32, Option<StageSection>, f32);
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_stunned\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_stunned")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(global_time, stage_section, timer): Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave_slow_cos = (anim_time * 4.5).cos();
let (movement1base, movement2, twitch) = match stage_section {
Some(StageSection::Buildup) => (anim_time.powf(0.1), 0.0, anim_time),
Some(StageSection::Recover) => (1.0, anim_time.powf(4.0), 1.0),
_ => (0.0, 0.0, 0.0),
};
let pullback = 1.0 - movement2;
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;
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) * s_a.scaler / 8.0;
next.chest.orientation = Quaternion::rotation_x(movement1base * 0.5);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation =
Quaternion::rotation_z(twitch2 * 0.8) * Quaternion::rotation_x(wave_slow_cos * 0.01);
next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
next.beak.orientation = Quaternion::rotation_x(-movement1abs * 0.8);
next.tail_front.position = Vec3::new(0.0, s_a.tail_front.0, s_a.tail_front.1);
next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.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(wave_slow_cos * 0.06 + twitch2 * 0.8)
* Quaternion::rotation_z(0.2 - movement1abs);
next.wing_in_r.orientation = Quaternion::rotation_y(wave_slow_cos * 0.06 - twitch2 * 0.8)
* Quaternion::rotation_z(-0.2 + movement1abs);
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) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation = Quaternion::rotation_y(0.2) * Quaternion::rotation_z(-0.2);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(movement1abs * 0.8);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next
}
}

View File

@ -0,0 +1,102 @@
use super::{
super::{vek::*, Animation},
BirdLargeSkeleton, SkeletonAttr,
};
use std::ops::Mul;
pub struct SwimAnimation;
impl Animation for SwimAnimation {
#[allow(clippy::type_complexity)]
type Dependency = f32;
type Skeleton = BirdLargeSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_large_swim\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_swim")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
global_time: Self::Dependency,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let duck_head_look = Vec2::new(
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(7331.0)
.sin()
* 0.5,
(global_time / 2.0 + anim_time / 8.0)
.floor()
.mul(1337.0)
.sin()
* 0.25,
);
let wave_slow_cos = (anim_time * 4.5).cos();
let wave_fast = (anim_time * 6.0).sin();
let wave_fast_cos = (anim_time * 6.0).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 + 1.5)
* s_a.scaler
/ 8.0;
next.chest.orientation = Quaternion::rotation_x(0.0);
next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
next.neck.orientation = Quaternion::rotation_x(0.0);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_z(duck_head_look.x)
* Quaternion::rotation_x(-duck_head_look.y.abs() + wave_slow_cos * 0.01);
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 - 0.02);
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);
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);
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 + wave_slow_cos * 0.06) * Quaternion::rotation_z(0.2);
next.wing_in_r.orientation =
Quaternion::rotation_y(0.8 - wave_slow_cos * 0.06) * 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) * 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.4) * Quaternion::rotation_z(0.2);
next.wing_out_r.orientation = Quaternion::rotation_y(0.4) * Quaternion::rotation_z(-0.2);
next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_l.orientation = Quaternion::rotation_x(-0.8 + wave_fast * 0.5);
next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2) / 8.0;
next.leg_r.orientation = Quaternion::rotation_x(-0.8 + wave_fast_cos * 0.5);
next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_l.orientation = Quaternion::rotation_x(0.0);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.orientation = Quaternion::rotation_x(0.0);
next
}
}

View File

@ -99,7 +99,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Owl, Male) => (2.5, 5.0),
(Owl, Female) => (2.5, 7.0),
(Parrot, _) => (0.5, 4.5),
(Cockatrice, _) => (0.0, 4.0),
},
chest: match (body.species, body.body_type) {
(Duck, _) => (0.0, 5.0),
@ -111,7 +110,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Owl, Male) => (0.0, 4.5),
(Owl, Female) => (0.0, 4.5),
(Parrot, _) => (0.0, 5.0),
(Cockatrice, _) => (0.0, 12.5),
},
tail: match (body.species, body.body_type) {
(Duck, _) => (-3.0, 1.5),
@ -123,7 +121,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Owl, Male) => (-6.0, -2.0),
(Owl, Female) => (-6.0, -2.5),
(Parrot, _) => (-8.0, -2.0),
(Cockatrice, _) => (-10.0, -2.5),
},
wing: match (body.species, body.body_type) {
(Duck, _) => (2.75, 0.0, 1.0),
@ -135,7 +132,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Owl, Male) => (3.5, -5.5, 4.0),
(Owl, Female) => (3.5, -6.0, 3.5),
(Parrot, _) => (2.0, -4.5, 3.0),
(Cockatrice, _) => (4.5, -2.5, 1.5),
},
foot: match (body.species, body.body_type) {
(Duck, _) => (2.0, -1.5, 4.0),
@ -147,7 +143,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Owl, Male) => (1.5, -2.5, 7.0),
(Owl, Female) => (1.5, -3.0, 6.5),
(Parrot, _) => (1.5, -3.0, 3.0),
(Cockatrice, _) => (4.0, -3.5, 12.0),
},
feed: match (body.species, body.body_type) {
(Chicken, _) => 1.2,
@ -155,7 +150,6 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Peacock, _) => 1.6,
(Eagle, _) => 1.2,
(Parrot, _) => 1.2,
(Cockatrice, _) => 1.3,
_ => 1.0,
},
}

View File

@ -1,42 +0,0 @@
use super::{super::Animation, BirdSmallSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
pub struct IdleAnimation;
impl Animation for IdleAnimation {
type Dependency = f32;
type Skeleton = BirdSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_small_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_small_idle")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f32,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.head.scale = Vec3::one() / 10.88;
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
next.wing_l.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_l.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_l.scale = Vec3::one() / 10.88;
next.wing_r.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_r.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_r.scale = Vec3::one() / 10.88;
next
}
}

View File

@ -1,42 +0,0 @@
use super::{super::Animation, BirdSmallSkeleton, SkeletonAttr};
//use std::f32::consts::PI;
use super::super::vek::*;
pub struct JumpAnimation;
impl Animation for JumpAnimation {
type Dependency = (f32, f32);
type Skeleton = BirdSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_small_jump\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_small_jump")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f32,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.head.scale = Vec3::one() / 10.88;
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
next.wing_l.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_l.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_l.scale = Vec3::one() / 10.88;
next.wing_r.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_r.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_r.scale = Vec3::one() / 10.88;
next
}
}

View File

@ -1,67 +0,0 @@
pub mod idle;
pub mod jump;
pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::bird_small::Body;
skeleton_impls!(struct BirdSmallSkeleton {
+ head,
+ torso,
+ wing_l,
+ wing_r,
});
impl Skeleton for BirdSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 4;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"bird_small_compute_mats\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_small_compute_mats")]
fn compute_matrices_inner(
&self,
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Vec3<f32> {
let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(torso_mat * Mat4::<f32>::from(self.head)),
make_bone(torso_mat),
make_bone(torso_mat * Mat4::<f32>::from(self.wing_l)),
make_bone(torso_mat * Mat4::<f32>::from(self.wing_r)),
];
Vec3::default()
}
}
pub struct SkeletonAttr;
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
type Error = ();
fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
match body {
comp::Body::BirdSmall(body) => Ok(SkeletonAttr::from(body)),
_ => Err(()),
}
}
}
impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -1,42 +0,0 @@
use super::{super::Animation, BirdSmallSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
pub struct RunAnimation;
impl Animation for RunAnimation {
type Dependency = (f32, f32);
type Skeleton = BirdSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"bird_small_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "bird_small_run")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(_velocity, _global_time): Self::Dependency,
_anim_time: f32,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.head.scale = Vec3::one() / 10.88;
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
next.wing_l.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_l.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_l.scale = Vec3::one() / 10.88;
next.wing_r.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.wing_r.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.wing_r.scale = Vec3::one() / 10.88;
next
}
}

View File

@ -50,8 +50,8 @@ macro_rules! skeleton_impls {
pub mod biped_large;
pub mod biped_small;
pub mod bird_large;
pub mod bird_medium;
pub mod bird_small;
pub mod character;
pub mod dragon;
#[cfg(feature = "use-dyn-lib")] pub mod dyn_lib;

View File

@ -27,7 +27,12 @@ pub fn criterion_benchmark(c: &mut Criterion) {
(0..GEN_SIZE)
.flat_map(|x| (0..GEN_SIZE).map(move |y| Vec2::new(x, y)))
.map(|offset| offset + CENTER)
.map(|pos| (pos, world.generate_chunk(index, pos, || false).unwrap()))
.map(|pos| {
(
pos,
world.generate_chunk(index, pos, || false, None).unwrap(),
)
})
.for_each(|(key, chunk)| {
terrain.insert(key, Arc::new(chunk.0));
});

View File

@ -93,7 +93,7 @@ impl EventMapper for MovementEventMapper {
Body::QuadrupedMedium(_) | Body::QuadrupedSmall(_) | Body::QuadrupedLow(_) => {
Self::map_quadruped_movement_event(physics, vel.0, underfoot_block_kind)
},
Body::BirdMedium(_) | Body::BirdSmall(_) | Body::BipedLarge(_) => {
Body::BirdMedium(_) | Body::BirdLarge(_) | Body::BipedLarge(_) => {
Self::map_non_humanoid_movement_event(physics, vel.0, underfoot_block_kind)
},
_ => SfxEvent::Idle, // Ignore fish, etc...
@ -281,7 +281,7 @@ impl MovementEventMapper {
Body::QuadrupedMedium(_) => 0.7,
Body::QuadrupedLow(_) => 0.7,
Body::BirdMedium(_) => 0.3,
Body::BirdSmall(_) => 0.2,
Body::BirdLarge(_) => 0.2,
Body::BipedLarge(_) => 1.0,
_ => 0.9,
}

View File

@ -2,7 +2,7 @@ use super::*;
use crate::audio::sfx::SfxEvent;
use common::{
comp::{
bird_small, humanoid, quadruped_medium, quadruped_small, Body, CharacterState, InputKind,
bird_large, humanoid, quadruped_medium, quadruped_small, Body, CharacterState, InputKind,
PhysicsState,
},
states,
@ -340,12 +340,12 @@ fn determines_relative_volumes() {
quadruped_small::Body::random(),
));
let bird_small =
MovementEventMapper::get_volume_for_body_type(&Body::BirdSmall(bird_small::Body::random()));
let bird_large =
MovementEventMapper::get_volume_for_body_type(&Body::BirdLarge(bird_large::Body::random()));
assert!(quadruped_medium < human);
assert!(quadruped_small < quadruped_medium);
assert!(bird_small < quadruped_small);
assert!(bird_large < quadruped_small);
}
fn empty_ability_info() -> states::utils::AbilityInfo {

View File

@ -4,8 +4,8 @@ use common::{
comp::{
biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
biped_small,
bird_large::{self, BodyType as BLABodyType, Species as BLASpecies},
bird_medium::{self, BodyType as BMBodyType, Species as BMSpecies},
bird_small,
dragon::{self, BodyType as DBodyType, Species as DSpecies},
fish_medium::{self, BodyType as FMBodyType, Species as FMSpecies},
fish_small::{self, BodyType as FSBodyType, Species as FSSpecies},
@ -3109,65 +3109,379 @@ impl DragonLateralSpec {
}
////
#[derive(Deserialize)]
struct BirdLargeCentralSpec(HashMap<(BLASpecies, BLABodyType), SidedBLACentralVoxSpec>);
#[derive(Deserialize)]
struct SidedBLACentralVoxSpec {
head: BirdLargeCentralSubSpec,
beak: BirdLargeCentralSubSpec,
neck: BirdLargeCentralSubSpec,
chest: BirdLargeCentralSubSpec,
tail_front: BirdLargeCentralSubSpec,
tail_rear: BirdLargeCentralSubSpec,
}
#[derive(Deserialize)]
struct BirdLargeCentralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
central: VoxSimple,
}
#[derive(Deserialize)]
struct BirdLargeLateralSpec(HashMap<(BLASpecies, BLABodyType), SidedBLALateralVoxSpec>);
#[derive(Deserialize)]
struct SidedBLALateralVoxSpec {
wing_in_l: BirdLargeLateralSubSpec,
wing_in_r: BirdLargeLateralSubSpec,
wing_mid_l: BirdLargeLateralSubSpec,
wing_mid_r: BirdLargeLateralSubSpec,
wing_out_l: BirdLargeLateralSubSpec,
wing_out_r: BirdLargeLateralSubSpec,
leg_l: BirdLargeLateralSubSpec,
leg_r: BirdLargeLateralSubSpec,
foot_l: BirdLargeLateralSubSpec,
foot_r: BirdLargeLateralSubSpec,
}
#[derive(Deserialize)]
struct BirdLargeLateralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
lateral: VoxSimple,
}
make_vox_spec!(
bird_small::Body,
struct BirdSmallSpec {},
|FigureKey { body, .. }, _spec| {
bird_large::Body,
struct BirdLargeSpec {
central: BirdLargeCentralSpec = "voxygen.voxel.bird_large_central_manifest",
lateral: BirdLargeLateralSpec = "voxygen.voxel.bird_large_lateral_manifest",
},
|FigureKey { body, .. }, spec| {
[
Some(mesh_bird_small_head(body.head)),
Some(mesh_bird_small_torso(body.torso)),
Some(mesh_bird_small_wing_l(body.wing_l)),
Some(mesh_bird_small_wing_r(body.wing_r)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some(spec.central.read().0.mesh_head(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_beak(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_neck(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_chest(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_tail_front(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_tail_rear(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_in_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_in_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_mid_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_mid_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_out_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_out_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_foot_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_foot_r(
body.species,
body.body_type,
)),
]
},
);
fn mesh_bird_small_head(head: bird_small::Head) -> BoneMeshes {
load_mesh(
match head {
bird_small::Head::Default => "npc.crow.head",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
impl BirdLargeCentralSpec {
fn mesh_head(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No head specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.head.central.0);
fn mesh_bird_small_torso(torso: bird_small::Torso) -> BoneMeshes {
load_mesh(
match torso {
bird_small::Torso::Default => "npc.crow.torso",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
(central, Vec3::from(spec.head.offset))
}
fn mesh_bird_small_wing_l(wing_l: bird_small::WingL) -> BoneMeshes {
load_mesh(
match wing_l {
bird_small::WingL::Default => "npc.crow.wing_l",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
fn mesh_beak(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No beak specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.beak.central.0);
fn mesh_bird_small_wing_r(wing_r: bird_small::WingR) -> BoneMeshes {
load_mesh(
match wing_r {
bird_small::WingR::Default => "npc.crow.wing_r",
},
Vec3::new(-7.0, -6.0, -6.0),
)
(central, Vec3::from(spec.beak.offset))
}
fn mesh_neck(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No neck specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.neck.central.0);
(central, Vec3::from(spec.neck.offset))
}
fn mesh_chest(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No chest specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.chest.central.0);
(central, Vec3::from(spec.chest.offset))
}
fn mesh_tail_front(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No tail front specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.tail_front.central.0);
(central, Vec3::from(spec.tail_front.offset))
}
fn mesh_tail_rear(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No tail rear specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.tail_rear.central.0);
(central, Vec3::from(spec.tail_rear.offset))
}
}
impl BirdLargeLateralSpec {
fn mesh_wing_in_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing in in left specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment_flipped(&spec.wing_in_l.lateral.0, true);
(lateral, Vec3::from(spec.wing_in_l.offset))
}
fn mesh_wing_in_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing in right specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.wing_in_r.lateral.0);
(lateral, Vec3::from(spec.wing_in_r.offset))
}
fn mesh_wing_mid_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing mid specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment_flipped(&spec.wing_mid_l.lateral.0, true);
(lateral, Vec3::from(spec.wing_mid_l.offset))
}
fn mesh_wing_mid_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing mid specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.wing_mid_r.lateral.0);
(lateral, Vec3::from(spec.wing_mid_r.offset))
}
fn mesh_wing_out_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing out specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment_flipped(&spec.wing_out_l.lateral.0, true);
(lateral, Vec3::from(spec.wing_out_l.offset))
}
fn mesh_wing_out_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No wing out specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.wing_out_r.lateral.0);
(lateral, Vec3::from(spec.wing_out_r.offset))
}
fn mesh_leg_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No leg specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment_flipped(&spec.leg_l.lateral.0, true);
(lateral, Vec3::from(spec.leg_l.offset))
}
fn mesh_leg_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No leg specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.leg_r.lateral.0);
(lateral, Vec3::from(spec.leg_r.offset))
}
fn mesh_foot_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No foot specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment_flipped(&spec.foot_l.lateral.0, true);
(lateral, Vec3::from(spec.foot_l.offset))
}
fn mesh_foot_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No foot specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.foot_r.lateral.0);
(lateral, Vec3::from(spec.foot_r.offset))
}
}
////

View File

@ -19,7 +19,7 @@ use crate::{
};
use anim::{
biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton,
bird_medium::BirdMediumSkeleton, bird_small::BirdSmallSkeleton, character::CharacterSkeleton,
bird_large::BirdLargeSkeleton, bird_medium::BirdMediumSkeleton, character::CharacterSkeleton,
dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton,
golem::GolemSkeleton, object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton,
quadruped_medium::QuadrupedMediumSkeleton, quadruped_small::QuadrupedSmallSkeleton,
@ -95,7 +95,7 @@ struct FigureMgrStates {
fish_medium_states: HashMap<EcsEntity, FigureState<FishMediumSkeleton>>,
theropod_states: HashMap<EcsEntity, FigureState<TheropodSkeleton>>,
dragon_states: HashMap<EcsEntity, FigureState<DragonSkeleton>>,
bird_small_states: HashMap<EcsEntity, FigureState<BirdSmallSkeleton>>,
bird_large_states: HashMap<EcsEntity, FigureState<BirdLargeSkeleton>>,
fish_small_states: HashMap<EcsEntity, FigureState<FishSmallSkeleton>>,
biped_large_states: HashMap<EcsEntity, FigureState<BipedLargeSkeleton>>,
biped_small_states: HashMap<EcsEntity, FigureState<BipedSmallSkeleton>>,
@ -115,7 +115,7 @@ impl FigureMgrStates {
fish_medium_states: HashMap::new(),
theropod_states: HashMap::new(),
dragon_states: HashMap::new(),
bird_small_states: HashMap::new(),
bird_large_states: HashMap::new(),
fish_small_states: HashMap::new(),
biped_large_states: HashMap::new(),
biped_small_states: HashMap::new(),
@ -164,8 +164,8 @@ impl FigureMgrStates {
.get_mut(&entity)
.map(DerefMut::deref_mut),
Body::Dragon(_) => self.dragon_states.get_mut(&entity).map(DerefMut::deref_mut),
Body::BirdSmall(_) => self
.bird_small_states
Body::BirdLarge(_) => self
.bird_large_states
.get_mut(&entity)
.map(DerefMut::deref_mut),
Body::FishSmall(_) => self
@ -202,7 +202,7 @@ impl FigureMgrStates {
Body::FishMedium(_) => self.fish_medium_states.remove(&entity).map(|e| e.meta),
Body::Theropod(_) => self.theropod_states.remove(&entity).map(|e| e.meta),
Body::Dragon(_) => self.dragon_states.remove(&entity).map(|e| e.meta),
Body::BirdSmall(_) => self.bird_small_states.remove(&entity).map(|e| e.meta),
Body::BirdLarge(_) => self.bird_large_states.remove(&entity).map(|e| e.meta),
Body::FishSmall(_) => self.fish_small_states.remove(&entity).map(|e| e.meta),
Body::BipedLarge(_) => self.biped_large_states.remove(&entity).map(|e| e.meta),
Body::BipedSmall(_) => self.biped_small_states.remove(&entity).map(|e| e.meta),
@ -222,7 +222,7 @@ impl FigureMgrStates {
self.fish_medium_states.retain(|k, v| f(k, &mut *v));
self.theropod_states.retain(|k, v| f(k, &mut *v));
self.dragon_states.retain(|k, v| f(k, &mut *v));
self.bird_small_states.retain(|k, v| f(k, &mut *v));
self.bird_large_states.retain(|k, v| f(k, &mut *v));
self.fish_small_states.retain(|k, v| f(k, &mut *v));
self.biped_large_states.retain(|k, v| f(k, &mut *v));
self.biped_small_states.retain(|k, v| f(k, &mut *v));
@ -241,7 +241,7 @@ impl FigureMgrStates {
+ self.fish_medium_states.len()
+ self.theropod_states.len()
+ self.dragon_states.len()
+ self.bird_small_states.len()
+ self.bird_large_states.len()
+ self.fish_small_states.len()
+ self.biped_large_states.len()
+ self.biped_small_states.len()
@ -291,7 +291,7 @@ impl FigureMgrStates {
.filter(|(_, c)| c.visible())
.count()
+ self
.bird_small_states
.bird_large_states
.iter()
.filter(|(_, c)| c.visible())
.count()
@ -332,7 +332,7 @@ pub struct FigureMgr {
quadruped_medium_model_cache: FigureModelCache<QuadrupedMediumSkeleton>,
quadruped_low_model_cache: FigureModelCache<QuadrupedLowSkeleton>,
bird_medium_model_cache: FigureModelCache<BirdMediumSkeleton>,
bird_small_model_cache: FigureModelCache<BirdSmallSkeleton>,
bird_large_model_cache: FigureModelCache<BirdLargeSkeleton>,
dragon_model_cache: FigureModelCache<DragonSkeleton>,
fish_medium_model_cache: FigureModelCache<FishMediumSkeleton>,
fish_small_model_cache: FigureModelCache<FishSmallSkeleton>,
@ -354,7 +354,7 @@ impl FigureMgr {
quadruped_medium_model_cache: FigureModelCache::new(),
quadruped_low_model_cache: FigureModelCache::new(),
bird_medium_model_cache: FigureModelCache::new(),
bird_small_model_cache: FigureModelCache::new(),
bird_large_model_cache: FigureModelCache::new(),
dragon_model_cache: FigureModelCache::new(),
fish_medium_model_cache: FigureModelCache::new(),
fish_small_model_cache: FigureModelCache::new(),
@ -381,7 +381,7 @@ impl FigureMgr {
.clean(&mut self.col_lights, tick);
self.bird_medium_model_cache
.clean(&mut self.col_lights, tick);
self.bird_small_model_cache
self.bird_large_model_cache
.clean(&mut self.col_lights, tick);
self.dragon_model_cache.clean(&mut self.col_lights, tick);
self.fish_medium_model_cache
@ -3263,8 +3263,8 @@ impl FigureMgr {
physics.ground_vel,
);
},
Body::BirdSmall(body) => {
let (model, skeleton_attr) = self.bird_small_model_cache.get_or_create_model(
Body::BirdLarge(body) => {
let (model, skeleton_attr) = self.bird_large_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
*body,
@ -3277,15 +3277,12 @@ impl FigureMgr {
let state = self
.states
.bird_small_states
.bird_large_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(renderer, BirdSmallSkeleton::default())
FigureState::new(renderer, BirdLargeSkeleton::default())
});
// Average velocity relative to the current ground
let _rel_avg_vel = state.avg_vel - physics.ground_vel;
let (character, last_character) = match (character, last_character) {
(Some(c), Some(l)) => (c, l),
_ => continue,
@ -3301,41 +3298,214 @@ impl FigureMgr {
physics.in_liquid().is_some(), // In water
) {
// Standing
(true, false, false) => anim::bird_small::IdleAnimation::update_skeleton(
&BirdSmallSkeleton::default(),
(true, false, false) => anim::bird_large::IdleAnimation::update_skeleton(
&BirdLargeSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Running
(true, true, false) => anim::bird_small::RunAnimation::update_skeleton(
&BirdSmallSkeleton::default(),
(rel_vel.magnitude(), time),
(true, true, false) => anim::bird_large::RunAnimation::update_skeleton(
&BirdLargeSkeleton::default(),
(
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,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// In air
(false, _, false) => anim::bird_small::JumpAnimation::update_skeleton(
&BirdSmallSkeleton::default(),
(rel_vel.magnitude(), time),
(false, _, false) => anim::bird_large::FlyAnimation::update_skeleton(
&BirdLargeSkeleton::default(),
(
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.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Swim
(_, true, _) => anim::bird_large::SwimAnimation::update_skeleton(
&BirdLargeSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// TODO!
_ => anim::bird_small::IdleAnimation::update_skeleton(
&BirdSmallSkeleton::default(),
_ => anim::bird_large::IdleAnimation::update_skeleton(
&BirdLargeSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
};
let target_bones = match &character {
CharacterState::Sit { .. } => {
anim::bird_large::FeedAnimation::update_skeleton(
&target_base,
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
)
},
CharacterState::BasicBeam(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 => s.timer.as_secs_f32(),
StageSection::Recover => {
stage_time / s.static_data.recover_duration.as_secs_f32()
},
_ => 0.0,
};
anim::bird_large::BreatheAnimation::update_skeleton(
&target_base,
(
time,
ori * anim::vek::Vec3::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
Some(s.stage_section),
state.state_time,
look_dir,
physics.on_ground,
),
stage_progress,
&mut state_animation_rate,
skeleton_attr,
)
},
CharacterState::ComboMelee(s) => {
let stage_index = (s.stage - 1) as usize;
let stage_time = s.timer.as_secs_f32();
let stage_progress = match s.stage_section {
StageSection::Buildup => {
stage_time
/ s.static_data.stage_data[stage_index]
.base_buildup_duration
.as_secs_f32()
},
StageSection::Swing => {
stage_time
/ s.static_data.stage_data[stage_index]
.base_swing_duration
.as_secs_f32()
},
StageSection::Recover => {
stage_time
/ s.static_data.stage_data[stage_index]
.base_recover_duration
.as_secs_f32()
},
_ => 0.0,
};
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp);
anim::bird_large::AlphaAnimation::update_skeleton(
&target_base,
(
Some(s.stage_section),
ori * anim::vek::Vec3::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
physics.on_ground,
),
stage_progress,
&mut state_animation_rate,
skeleton_attr,
)
},
CharacterState::BasicRanged(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::Recover => {
stage_time / s.static_data.recover_duration.as_secs_f32()
},
_ => 0.0,
};
anim::bird_large::ShootAnimation::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::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::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::ShockwaveAnimation::update_skeleton(
&target_base,
(Some(s.stage_section), physics.on_ground),
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 {
StageSection::Buildup => {
stage_time / s.static_data.buildup_duration.as_secs_f32()
},
StageSection::Recover => {
stage_time / s.static_data.recover_duration.as_secs_f32()
},
_ => 0.0,
};
match s.static_data.poise_state {
PoiseState::Normal
| PoiseState::Interrupted
| PoiseState::Stunned
| PoiseState::Dazed
| PoiseState::KnockedDown => {
anim::bird_large::StunnedAnimation::update_skeleton(
&target_base,
(time, Some(s.stage_section), state.state_time),
stage_progress,
&mut state_animation_rate,
skeleton_attr,
)
},
}
},
// TODO!
_ => target_base,
};
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
@ -4572,7 +4742,7 @@ impl FigureMgr {
quadruped_medium_model_cache,
quadruped_low_model_cache,
bird_medium_model_cache,
bird_small_model_cache,
bird_large_model_cache,
dragon_model_cache,
fish_medium_model_cache,
fish_small_model_cache,
@ -4591,7 +4761,7 @@ impl FigureMgr {
fish_medium_states,
theropod_states,
dragon_states,
bird_small_states,
bird_large_states,
fish_small_states,
biped_large_states,
biped_small_states,
@ -4738,14 +4908,14 @@ impl FigureMgr {
),
)
}),
Body::BirdSmall(body) => bird_small_states
Body::BirdLarge(body) => bird_large_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
bird_small_model_cache.get_model(
bird_large_model_cache.get_model(
col_lights,
*body,
inventory,

View File

@ -1058,7 +1058,7 @@ impl<'a> Widget for ItemTooltip<'a> {
.w(text_w)
.get_h(ui)
.unwrap_or(0.0)
+ V_PAD
+ V_PAD * 2.0
} else {
0.0
};

View File

@ -282,7 +282,7 @@ pub fn apply_caves_supplement<'a>(
},
_ => {
is_hostile = true;
let species = match dynamic_rng.gen_range(0..4) {
let species = match dynamic_rng.gen_range(0..5) {
0 => comp::biped_large::Species::Ogre,
1 => comp::biped_large::Species::Cyclops,
2 => comp::biped_large::Species::Wendigo,

View File

@ -1,11 +1,13 @@
use crate::{column::ColumnSample, sim::SimChunk, IndexRef, CONFIG};
use common::{
comp::{
biped_large, bird_medium, fish_medium, fish_small, quadruped_low, quadruped_medium,
quadruped_small, theropod, Alignment,
biped_large, bird_large, bird_medium, fish_medium, fish_small, quadruped_low,
quadruped_medium, quadruped_small, theropod, Alignment,
},
generation::{ChunkSupplement, EntityInfo},
resources::TimeOfDay,
terrain::Block,
time::DayPeriod::{self, Evening, Morning, Night, Noon},
vol::{BaseVol, ReadVol, RectSizedVol, WriteVol},
};
use rand::prelude::*;
@ -28,11 +30,13 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
_index: IndexRef,
chunk: &SimChunk,
supplement: &mut ChunkSupplement,
time: Option<TimeOfDay>,
) {
struct Entry<R> {
make_entity: fn(Vec3<f32>, &mut R) -> EntityInfo, // Entity
group_size: Range<usize>, // Group size range
is_underwater: bool, // Underwater?
day_period: Vec<DayPeriod>, // Period of the day
get_density: fn(&SimChunk, &ColumnSample) -> f32, // Density
}
@ -60,6 +64,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..4,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp, 0.3)
* BASE_DENSITY
@ -91,6 +96,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4
},
@ -106,6 +112,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5,
},
// Tundra rarer solitary ennemies
@ -119,6 +126,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.1,
},
// Tundra rock solitary ennemies
@ -133,6 +141,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * col.rock * 1.0
},
@ -154,6 +163,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4
},
@ -170,6 +180,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 3..8,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp + 0.2, 0.6) * col.tree_density * BASE_DENSITY * 0.9
},
@ -199,6 +210,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..4,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * BASE_DENSITY * 1.0,
},
// Taiga solitary wild
@ -237,6 +249,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| close(c.temp, CONFIG.snow_temp + 0.2, 0.6) * BASE_DENSITY * 5.0,
},
// Temperate solitary ennemies
@ -271,6 +284,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.temperate_temp + 0.1, 0.5)
* col.tree_density
@ -341,6 +355,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..8,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
* close(c.humidity, CONFIG.forest_hum, 0.6)
@ -352,7 +367,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(match rng.gen_range(0..11) {
.with_body(match rng.gen_range(0..10) {
0 => quadruped_small::Body {
species: quadruped_small::Species::Fox,
body_type: quadruped_small::BodyType::Male,
@ -393,14 +408,9 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
&quadruped_medium::Species::Hirdrasil,
)
.into(),
9 => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Truffler,
)
.into(),
_ => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Batfox,
&quadruped_small::Species::Truffler,
)
.into(),
})
@ -408,6 +418,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
* BASE_DENSITY
@ -415,6 +426,26 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
* 8.0
},
},
// Temperate solitary wild night
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(
quadruped_small::Body::random_with(rng, &quadruped_small::Species::Batfox)
.into(),
)
.with_alignment(Alignment::Enemy)
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night],
get_density: |c, _col| {
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
* BASE_DENSITY
* close(c.humidity, CONFIG.forest_hum, 0.6)
* 0.8
},
},
// Rare temperate solitary enemies
Entry {
make_entity: |pos, rng| {
@ -433,6 +464,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| close(c.temp, CONFIG.temperate_temp, 0.8) * BASE_DENSITY * 0.08,
},
// Temperate river wildlife
@ -463,6 +495,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.temperate_temp, 0.6)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -487,6 +520,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.temperate_temp, 0.6)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -508,6 +542,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.temperate_temp, 0.6)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -532,6 +567,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.tropical_temp + 0.1, 0.5) * col.rock * BASE_DENSITY * 5.0
},
@ -557,14 +593,34 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.2)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
* BASE_DENSITY
* 3.0
* 2.8
},
},
// Jungle rare solitary wild
// Jungle solitary ennemies day
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(
theropod::Body::random_with(rng, &theropod::Species::Sunlizard).into(),
)
.with_alignment(Alignment::Enemy)
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.2)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
* BASE_DENSITY
* 0.5
},
},
// Jungle rare solitary wild day
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
@ -585,6 +641,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.2)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
@ -596,16 +653,12 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(match rng.gen_range(0..5) {
.with_body(match rng.gen_range(0..4) {
0 => bird_medium::Body::random_with(rng, &bird_medium::Species::Parrot)
.into(),
1 => {
quadruped_low::Body::random_with(rng, &quadruped_low::Species::Monitor)
.into()
},
2 => bird_medium::Body::random_with(rng, &bird_medium::Species::Cockatrice)
1 => bird_large::Body::random_with(rng, &bird_large::Species::Cockatrice)
.into(),
3 => quadruped_small::Body::random_with(
2 => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Quokka,
)
@ -619,6 +672,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
@ -626,6 +680,26 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
* 8.0
},
},
// Jungle solitary wild day
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(
quadruped_low::Body::random_with(rng, &quadruped_low::Species::Monitor)
.into(),
)
.with_alignment(Alignment::Enemy)
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
* BASE_DENSITY
* 2.0
},
},
// Tropical rare river enemy
Entry {
make_entity: |pos, rng| {
@ -638,6 +712,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.tropical_temp + 0.2, 0.5)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -671,6 +746,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.tropical_temp, 0.5)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -700,6 +776,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.1, 0.4)
* close(c.humidity, CONFIG.desert_hum, 0.4)
@ -727,6 +804,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 3..7,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.1, 0.4)
* close(c.humidity, CONFIG.desert_hum, 0.4)
@ -757,6 +835,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.desert_hum, 0.5)
@ -781,6 +860,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.desert_hum, 0.5)
@ -800,6 +880,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |_c, col| {
close(col.temp, CONFIG.desert_temp + 0.2, 0.3)
* if col.water_dist.map(|d| d < 10.0).unwrap_or(false) {
@ -824,6 +905,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.desert_hum, 0.5)
@ -835,7 +917,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(match rng.gen_range(0..7) {
.with_body(match rng.gen_range(0..4) {
0 => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Holladon,
@ -850,21 +932,36 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
&quadruped_medium::Species::Camel,
)
.into(),
3 => quadruped_low::Body {
species: quadruped_low::Species::Salamander,
body_type: quadruped_low::BodyType::Male,
}
.into(),
4 => quadruped_small::Body::random_with(
3 => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Porcupine,
)
.into(),
5 => quadruped_small::Body {
_ => quadruped_small::Body {
species: quadruped_small::Species::Hare,
body_type: quadruped_small::BodyType::Male,
}
.into(),
})
.with_alignment(Alignment::Wild)
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3) * BASE_DENSITY * 3.8
},
},
// Desert solitary wild day
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(match rng.gen_range(0..3) {
1 => quadruped_low::Body {
species: quadruped_low::Species::Salamander,
body_type: quadruped_low::BodyType::Male,
}
.into(),
_ => quadruped_small::Body::random_with(
rng,
&quadruped_small::Species::Gecko,
@ -875,8 +972,9 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..2,
is_underwater: false,
day_period: vec![Morning, Noon, Evening],
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3) * BASE_DENSITY * 5.0
close(c.temp, CONFIG.desert_temp + 0.2, 0.3) * BASE_DENSITY * 1.0
},
},
// Underwater temperate
@ -896,6 +994,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 3..5,
is_underwater: true,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.temperate_temp, 1.0) * col.tree_density * BASE_DENSITY * 5.0
},
@ -911,6 +1010,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
},
group_size: 1..3,
is_underwater: true,
day_period: vec![Night, Morning, Noon, Evening],
get_density: |c, col| {
close(c.temp, CONFIG.snow_temp, 0.15) * col.tree_density * BASE_DENSITY * 5.0
},
@ -931,6 +1031,12 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
};
let underwater = col_sample.water_level > col_sample.alt;
let current_day_period;
if let Some(time) = time {
current_day_period = DayPeriod::from(time.0)
} else {
current_day_period = Noon
}
let entity_group = scatter.iter().enumerate().find_map(
|(
@ -939,6 +1045,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
make_entity,
group_size,
is_underwater,
day_period,
get_density,
},
)| {
@ -946,6 +1053,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
if density > 0.0
&& dynamic_rng.gen::<f32>() < density * col_sample.spawn_rate
&& underwater == *is_underwater
&& day_period.contains(&current_day_period)
&& col_sample.gradient < Some(1.3)
{
Some((make_entity, group_size.clone()))

View File

@ -50,6 +50,7 @@ use crate::{
use common::{
assets,
generation::{ChunkSupplement, EntityInfo},
resources::TimeOfDay,
terrain::{Block, BlockKind, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
vol::{ReadVol, RectVolSize, WriteVol},
};
@ -171,7 +172,9 @@ impl World {
// Unwrapping because generate_chunk only returns err when should_continue evals
// to true
let (tc, _cs) = self.generate_chunk(index, chunk_pos, || false).unwrap();
let (tc, _cs) = self
.generate_chunk(index, chunk_pos, || false, None)
.unwrap();
let min_z = tc.get_min_z();
let max_z = tc.get_max_z();
@ -209,6 +212,7 @@ impl World {
chunk_pos: Vec2<i32>,
// TODO: misleading name
mut should_continue: impl FnMut() -> bool,
time: Option<TimeOfDay>,
) -> Result<(TerrainChunk, ChunkSupplement), ()> {
let mut sampler = self.sample_blocks();
@ -390,6 +394,7 @@ impl World {
index,
sim_chunk,
&mut supplement,
time,
);
// Apply site supplementary information