diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb1304efb..b0aa14db29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/assets/common/abilities/unique/birdlargebreathe/firebomb.ron b/assets/common/abilities/unique/birdlargebreathe/firebomb.ron new file mode 100644 index 0000000000..def79061ea --- /dev/null +++ b/assets/common/abilities/unique/birdlargebreathe/firebomb.ron @@ -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, +) diff --git a/assets/common/abilities/unique/birdlargebreathe/flamethrower.ron b/assets/common/abilities/unique/birdlargebreathe/flamethrower.ron new file mode 100644 index 0000000000..4bf507fa86 --- /dev/null +++ b/assets/common/abilities/unique/birdlargebreathe/flamethrower.ron @@ -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, +) \ No newline at end of file diff --git a/assets/common/abilities/unique/birdlargebreathe/triplestrike.ron b/assets/common/abilities/unique/birdlargebreathe/triplestrike.ron new file mode 100644 index 0000000000..2eaa09c043 --- /dev/null +++ b/assets/common/abilities/unique/birdlargebreathe/triplestrike.ron @@ -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, +) diff --git a/assets/common/abilities/unique/birdlargefire/firebomb.ron b/assets/common/abilities/unique/birdlargefire/firebomb.ron new file mode 100644 index 0000000000..def79061ea --- /dev/null +++ b/assets/common/abilities/unique/birdlargefire/firebomb.ron @@ -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, +) diff --git a/assets/common/abilities/unique/birdlargefire/fireshockwave.ron b/assets/common/abilities/unique/birdlargefire/fireshockwave.ron new file mode 100644 index 0000000000..e7e1f67a0f --- /dev/null +++ b/assets/common/abilities/unique/birdlargefire/fireshockwave.ron @@ -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, +) diff --git a/assets/common/abilities/unique/birdlargefire/flamethrower.ron b/assets/common/abilities/unique/birdlargefire/flamethrower.ron new file mode 100644 index 0000000000..4bf507fa86 --- /dev/null +++ b/assets/common/abilities/unique/birdlargefire/flamethrower.ron @@ -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, +) \ No newline at end of file diff --git a/assets/common/abilities/unique/birdlargefire/triplestrike.ron b/assets/common/abilities/unique/birdlargefire/triplestrike.ron new file mode 100644 index 0000000000..2eaa09c043 --- /dev/null +++ b/assets/common/abilities/unique/birdlargefire/triplestrike.ron @@ -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, +) diff --git a/assets/common/abilities/weapon_ability_manifest.ron b/assets/common/abilities/weapon_ability_manifest.ron index 21a39831a8..e36d47685c 100644 --- a/assets/common/abilities/weapon_ability_manifest.ron +++ b/assets/common/abilities/weapon_ability_manifest.ron @@ -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", diff --git a/assets/common/items/npc_weapons/unique/birdlargebreathe.ron b/assets/common/items/npc_weapons/unique/birdlargebreathe.ron new file mode 100644 index 0000000000..15b41aa6ed --- /dev/null +++ b/assets/common/items/npc_weapons/unique/birdlargebreathe.ron @@ -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: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/birdlargefire.ron b/assets/common/items/npc_weapons/unique/birdlargefire.ron new file mode 100644 index 0000000000..b092a15f0f --- /dev/null +++ b/assets/common/items/npc_weapons/unique/birdlargefire.ron @@ -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: [], +) \ No newline at end of file diff --git a/assets/common/npc_names.ron b/assets/common/npc_names.ron index 5f273b5593..2729cacb40 100644 --- a/assets/common/npc_names.ron +++ b/assets/common/npc_names.ron @@ -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: ( diff --git a/assets/voxygen/voxel/bird_large_central_manifest.ron b/assets/voxygen/voxel/bird_large_central_manifest.ron new file mode 100644 index 0000000000..f8a0999986 --- /dev/null +++ b/assets/voxygen/voxel/bird_large_central_manifest.ron @@ -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"), + ) + ), +}) diff --git a/assets/voxygen/voxel/bird_large_lateral_manifest.ron b/assets/voxygen/voxel/bird_large_lateral_manifest.ron new file mode 100644 index 0000000000..3eca741462 --- /dev/null +++ b/assets/voxygen/voxel/bird_large_lateral_manifest.ron @@ -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"), + ) + ), +}) \ No newline at end of file diff --git a/assets/voxygen/voxel/bird_medium_central_manifest.ron b/assets/voxygen/voxel/bird_medium_central_manifest.ron index 57d03ecfe1..d24a0be621 100644 --- a/assets/voxygen/voxel/bird_medium_central_manifest.ron +++ b/assets/voxygen/voxel/bird_medium_central_manifest.ron @@ -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"), - ) - ), }) \ No newline at end of file diff --git a/assets/voxygen/voxel/bird_medium_lateral_manifest.ron b/assets/voxygen/voxel/bird_medium_lateral_manifest.ron index 2bcb349b14..95c4027cc7 100644 --- a/assets/voxygen/voxel/bird_medium_lateral_manifest.ron +++ b/assets/voxygen/voxel/bird_medium_lateral_manifest.ron @@ -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"), - ) - ), }) \ No newline at end of file diff --git a/assets/voxygen/voxel/npc/cockatrice/male/beak.vox b/assets/voxygen/voxel/npc/cockatrice/male/beak.vox new file mode 100644 index 0000000000..9146caa0b2 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/beak.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cce54e7acf7b0a9551c816abff099a2cf1f6ae8676fd0b016d1359a4c1f3b320 +size 1232 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/chest.vox b/assets/voxygen/voxel/npc/cockatrice/male/chest.vox new file mode 100644 index 0000000000..9921765588 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01ec0fb420e315408a9b82df79adedc05abd081bf54659bc4a53cb500604a141 +size 6840 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/foot_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/foot_r.vox new file mode 100644 index 0000000000..ef46bed01d --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/foot_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6917f73529fa1631e248ef46665bcdc2811e8690678919149201b1655c57a493 +size 1588 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/head.vox b/assets/voxygen/voxel/npc/cockatrice/male/head.vox index 4df45a0d07..edd8c20ca6 100644 --- a/assets/voxygen/voxel/npc/cockatrice/male/head.vox +++ b/assets/voxygen/voxel/npc/cockatrice/male/head.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5103831b0b9c38ba8d8464266aa55da2b765cc5843a083cb8ce70f4cd9242c56 -size 1952 +oid sha256:835c2e4647b95ff4b583e50932522243bc6d5ac990d0e9fd4a09bbe69f53a395 +size 3112 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/leg_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/leg_r.vox index e68e4781a1..23aca80aa3 100644 --- a/assets/voxygen/voxel/npc/cockatrice/male/leg_r.vox +++ b/assets/voxygen/voxel/npc/cockatrice/male/leg_r.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b95667bdfa3818583fa968a101f4bf39219f0488d4f7cf05f05374b7251ef3f6 -size 1364 +oid sha256:a11d94b3930ae2f50ba23f6d4c75e4d0fb590d7181e7df246c4e690babea366a +size 2224 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/neck.vox b/assets/voxygen/voxel/npc/cockatrice/male/neck.vox new file mode 100644 index 0000000000..be2fc102c5 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/neck.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd52c35cb0670f77be4ed7a8a0a23968f12db49b7487abd6a6aea78d7162d50b +size 3424 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/tail.vox b/assets/voxygen/voxel/npc/cockatrice/male/tail.vox deleted file mode 100644 index dad94dedf5..0000000000 --- a/assets/voxygen/voxel/npc/cockatrice/male/tail.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0267a7da9724b1c8c6c7c2b7657d828897205af3c0c7b6d9a98861abf8f0baf8 -size 1216 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/tail_front.vox b/assets/voxygen/voxel/npc/cockatrice/male/tail_front.vox new file mode 100644 index 0000000000..f045ffb594 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/tail_front.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bb5859c43e04522008a3961dbd804852fdd0a6d446a000d7b74934b3523ff9b +size 2056 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/tail_rear.vox b/assets/voxygen/voxel/npc/cockatrice/male/tail_rear.vox new file mode 100644 index 0000000000..ddb1b2f182 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/tail_rear.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f251fa3447de8ba97da74c703c0ad8b5892167a4ec65ae5a4ad46fa946654aab +size 1772 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/torso.vox b/assets/voxygen/voxel/npc/cockatrice/male/torso.vox deleted file mode 100644 index a4c118f9b3..0000000000 --- a/assets/voxygen/voxel/npc/cockatrice/male/torso.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8fb4738f22d69176aea93efd95993f47e6a32cdd45c14435ef29bfd3f795fa46 -size 3048 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/wing_in_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/wing_in_r.vox new file mode 100644 index 0000000000..95e2e1c4ce --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/wing_in_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bb7d1f8a8cb4108bb1787777a59fb8cd4bfb6e21ded2707515204dadd441f91 +size 1412 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/wing_mid_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/wing_mid_r.vox new file mode 100644 index 0000000000..6daf0777bb --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/wing_mid_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1f1f5cb35b7026bdba42cfdc77f6cc8f505116550611e84ed41922c7a342166 +size 1408 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/wing_out_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/wing_out_r.vox new file mode 100644 index 0000000000..37c70de238 --- /dev/null +++ b/assets/voxygen/voxel/npc/cockatrice/male/wing_out_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:074c1ced666ad7fcf6135d0424c12fb183aca5c022ba0e739be0bba422d5ada9 +size 1624 diff --git a/assets/voxygen/voxel/npc/cockatrice/male/wing_r.vox b/assets/voxygen/voxel/npc/cockatrice/male/wing_r.vox deleted file mode 100644 index 8ea51d1c13..0000000000 --- a/assets/voxygen/voxel/npc/cockatrice/male/wing_r.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bc0aed5d4195504288f7be8063bbb1e1058d7ae65bbd570ae97276b009c54318 -size 1212 diff --git a/assets/voxygen/voxel/npc/phoenix/male/beak.vox b/assets/voxygen/voxel/npc/phoenix/male/beak.vox new file mode 100644 index 0000000000..50b2c09489 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/beak.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d9f547cf2cb789ca4a8daa442657a41db25a91fe08594c8970083bf8e7ce7bc +size 1248 diff --git a/assets/voxygen/voxel/npc/phoenix/male/chest.vox b/assets/voxygen/voxel/npc/phoenix/male/chest.vox new file mode 100644 index 0000000000..0dd5d6650a --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a985f025e429ca63f6570365addd8a128258119fe7eeef22c5f9c0bae0b3cada +size 8448 diff --git a/assets/voxygen/voxel/npc/phoenix/male/foot_r.vox b/assets/voxygen/voxel/npc/phoenix/male/foot_r.vox new file mode 100644 index 0000000000..076bc736c0 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/foot_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8df02041d931946f0a053c24faebcacaccb5de301c42b4a32df06e798bad5d5b +size 1628 diff --git a/assets/voxygen/voxel/npc/phoenix/male/head.vox b/assets/voxygen/voxel/npc/phoenix/male/head.vox new file mode 100644 index 0000000000..6db2f6d043 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:022ea7752438f738ebd2bb47f68ff827cb6c8f85fab05dc4286e01f31102e482 +size 3392 diff --git a/assets/voxygen/voxel/npc/phoenix/male/leg_r.vox b/assets/voxygen/voxel/npc/phoenix/male/leg_r.vox new file mode 100644 index 0000000000..e2f83fba5e --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/leg_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59bec4734dd00e6fed8320b68e7f9a33be3956105ef78994d6ed689512e200e5 +size 2644 diff --git a/assets/voxygen/voxel/npc/phoenix/male/neck.vox b/assets/voxygen/voxel/npc/phoenix/male/neck.vox new file mode 100644 index 0000000000..3c47ead3e8 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/neck.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:091faef09b43d101a523ef5b46a74c4754057ecbf20d7ed3d9f8c609b7b4a7f1 +size 4536 diff --git a/assets/voxygen/voxel/npc/phoenix/male/tail_front.vox b/assets/voxygen/voxel/npc/phoenix/male/tail_front.vox new file mode 100644 index 0000000000..62436cadc9 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/tail_front.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:234c8e396b9cace8165d9118793817df5a8ff78140b700cb5b655ef5df326ac8 +size 2768 diff --git a/assets/voxygen/voxel/npc/phoenix/male/tail_rear.vox b/assets/voxygen/voxel/npc/phoenix/male/tail_rear.vox new file mode 100644 index 0000000000..3da4400bf0 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/tail_rear.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77ea457f336df7c1321c89279d061c2e278455743810027dbea19064f59b7c53 +size 3032 diff --git a/assets/voxygen/voxel/npc/phoenix/male/wing_in_r.vox b/assets/voxygen/voxel/npc/phoenix/male/wing_in_r.vox new file mode 100644 index 0000000000..33ac105cb6 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/wing_in_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f0fc4eaebdd0dfbdceecd73f4bbef61df1ad41a4f02e74466fe38e4d73ef81a +size 1840 diff --git a/assets/voxygen/voxel/npc/phoenix/male/wing_mid_r.vox b/assets/voxygen/voxel/npc/phoenix/male/wing_mid_r.vox new file mode 100644 index 0000000000..eaf3532512 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/wing_mid_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:476c07d679d1fe9ca356390ea16da02f843ed94637e767bff4fa2e875bc09ad4 +size 1748 diff --git a/assets/voxygen/voxel/npc/phoenix/male/wing_out_r.vox b/assets/voxygen/voxel/npc/phoenix/male/wing_out_r.vox new file mode 100644 index 0000000000..7d4af77900 --- /dev/null +++ b/assets/voxygen/voxel/npc/phoenix/male/wing_out_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:085ca80b33c9b0962a4b8614fa17211abae68c0b13b9e7f0044e6109b3d8c429 +size 2648 diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index a777055891..237a480119 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -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, diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 4da8d22f83..1fe48767b6 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -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 { pub bird_medium: BodyData>, pub fish_medium: BodyData>, pub dragon: BodyData>, - pub bird_small: BodyData, + pub bird_large: BodyData>, pub fish_small: BodyData>, pub biped_large: BodyData>, pub biped_small: BodyData>, @@ -95,6 +95,7 @@ impl core::ops::Index for AllBodies &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 &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, diff --git a/common/src/comp/body/bird_large.rs b/common/src/comp/body/bird_large.rs new file mode 100644 index 0000000000..629317082a --- /dev/null +++ b/common/src/comp/body/bird_large.rs @@ -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 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 { + pub phoenix: SpeciesMeta, + pub cockatrice: SpeciesMeta, +} + +impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { + 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 { + type IntoIter = std::iter::Copied>; + 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]; diff --git a/common/src/comp/body/bird_medium.rs b/common/src/comp/body/bird_medium.rs index 264e6abf05..5eb7dbee65 100644 --- a/common/src/comp/body/bird_medium.rs +++ b/common/src/comp/body/bird_medium.rs @@ -41,7 +41,6 @@ make_case_elim!( Eagle = 4, Owl = 5, Parrot = 6, - Cockatrice = 7, } ); @@ -57,7 +56,6 @@ pub struct AllSpecies { pub eagle: SpeciesMeta, pub owl: SpeciesMeta, pub parrot: SpeciesMeta, - pub cockatrice: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -73,12 +71,11 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies 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 { diff --git a/common/src/comp/body/bird_small.rs b/common/src/comp/body/bird_small.rs deleted file mode 100644 index a3be8c3087..0000000000 --- a/common/src/comp/body/bird_small.rs +++ /dev/null @@ -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]; diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 79b60eaf2e..6508160168 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -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 diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index f9c0701742..9bf489e6e8 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -441,4 +441,6 @@ pub enum UniqueKind { ObjectTurret, WoodenSpear, MindflayerStaff, + BirdLargeBreathe, + BirdLargeFire, } diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 6e7668d62c..e1fb785727 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -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", + )); + }, + }, _ => {}, }; } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 2c3664a2c7..5f563a3836 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -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, }, diff --git a/common/src/generation.rs b/common/src/generation.rs index 9b187ecc05..e922f604c7 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -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)), diff --git a/common/src/npc.rs b/common/src/npc.rs index d7eebe5f17..5712c33696 100644 --- a/common/src/npc.rs +++ b/common/src/npc.rs @@ -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, diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 766959470f..ca700bf91b 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -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 diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 654fa44ade..245169fc3b 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -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 { 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)); }, diff --git a/common/src/time.rs b/common/src/time.rs index 023c2f5089..a13ba253f4 100644 --- a/common/src/time.rs +++ b/common/src/time.rs @@ -1,4 +1,4 @@ -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DayPeriod { Night, Morning, diff --git a/server/src/chunk_generator.rs b/server/src/chunk_generator.rs index 06f27de086..0559b4a460 100644 --- a/server/src/chunk_generator.rs +++ b/server/src/chunk_generator.rs @@ -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, 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)); }); diff --git a/server/src/lib.rs b/server/src/lib.rs index acc5d9c254..692ae02c0e 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -725,6 +725,7 @@ impl Server { &slow_jobs, Arc::clone(&world), index.clone(), + *ecs.read_resource::(), ); }); } @@ -930,6 +931,7 @@ impl Server { &slow_jobs, Arc::clone(&self.world), self.index.clone(), + *ecs.read_resource::(), ); } diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs index 8d265b929d..04e59de0cf 100644 --- a/server/src/rtsim/entity.rs +++ b/server/src/rtsim/entity.rs @@ -38,12 +38,18 @@ impl Entity { match self.rng(PERM_GENUS).gen::() { // 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(), diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 93dd7cdc77..89a037d95b 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -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::()); } }); } diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 68ba3e23a1..2afa0d5ebd 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -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; + } + }, } } diff --git a/voxygen/anim/src/bird_large/alpha.rs b/voxygen/anim/src/bird_large/alpha.rs new file mode 100644 index 0000000000..99f5c56566 --- /dev/null +++ b/voxygen/anim/src/bird_large/alpha.rs @@ -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, Vec3, Vec3, 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 = 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 + } +} diff --git a/voxygen/anim/src/bird_large/breathe.rs b/voxygen/anim/src/bird_large/breathe.rs new file mode 100644 index 0000000000..9d9c632619 --- /dev/null +++ b/voxygen/anim/src/bird_large/breathe.rs @@ -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, + Vec3, + Option, + 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 = 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 + } +} diff --git a/voxygen/anim/src/bird_large/feed.rs b/voxygen/anim/src/bird_large/feed.rs new file mode 100644 index 0000000000..59daa60311 --- /dev/null +++ b/voxygen/anim/src/bird_large/feed.rs @@ -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 + } +} diff --git a/voxygen/anim/src/bird_large/fly.rs b/voxygen/anim/src/bird_large/fly.rs new file mode 100644 index 0000000000..227be64ae0 --- /dev/null +++ b/voxygen/anim/src/bird_large/fly.rs @@ -0,0 +1,177 @@ +use super::{ + super::{vek::*, Animation}, + BirdLargeSkeleton, SkeletonAttr, +}; + +pub struct FlyAnimation; + +impl Animation for FlyAnimation { + type Dependency = (Vec3, Vec3, Vec3); + 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 = 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 + } +} diff --git a/voxygen/anim/src/bird_large/idle.rs b/voxygen/anim/src/bird_large/idle.rs new file mode 100644 index 0000000000..ced671cb26 --- /dev/null +++ b/voxygen/anim/src/bird_large/idle.rs @@ -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 + } +} diff --git a/voxygen/anim/src/bird_large/mod.rs b/voxygen/anim/src/bird_large/mod.rs new file mode 100644 index 0000000000..55ac715d38 --- /dev/null +++ b/voxygen/anim/src/bird_large/mod.rs @@ -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, + buf: &mut [FigureBoneData; super::MAX_BONE_COUNT], + ) -> Vec3 { + let chest_mat = base_mat * Mat4::::from(self.chest); + let neck_mat = chest_mat * Mat4::::from(self.neck); + let head_mat = neck_mat * Mat4::::from(self.head); + let beak_mat = head_mat * Mat4::::from(self.beak); + let tail_front_mat = chest_mat * Mat4::::from(self.tail_front); + let tail_rear_mat = tail_front_mat * Mat4::::from(self.tail_rear); + let wing_in_l_mat = chest_mat * Mat4::::from(self.wing_in_l); + let wing_in_r_mat = chest_mat * Mat4::::from(self.wing_in_r); + let wing_mid_l_mat = wing_in_l_mat * Mat4::::from(self.wing_mid_l); + let wing_mid_r_mat = wing_in_r_mat * Mat4::::from(self.wing_mid_r); + let wing_out_l_mat = wing_mid_l_mat * Mat4::::from(self.wing_out_l); + let wing_out_r_mat = wing_mid_r_mat * Mat4::::from(self.wing_out_r); + let leg_l_mat = base_mat * Mat4::::from(self.leg_l); + let leg_r_mat = base_mat * Mat4::::from(self.leg_r); + let foot_l_mat = leg_l_mat * Mat4::::from(self.foot_l); + let foot_r_mat = leg_r_mat * Mat4::::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 { + 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), + }, + } + } +} diff --git a/voxygen/anim/src/bird_large/run.rs b/voxygen/anim/src/bird_large/run.rs new file mode 100644 index 0000000000..cde5f7aba5 --- /dev/null +++ b/voxygen/anim/src/bird_large/run.rs @@ -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, Vec3, Vec3, 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::::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 = 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 + } +} diff --git a/voxygen/anim/src/bird_large/shockwave.rs b/voxygen/anim/src/bird_large/shockwave.rs new file mode 100644 index 0000000000..c6dd88dd57 --- /dev/null +++ b/voxygen/anim/src/bird_large/shockwave.rs @@ -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, 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 + } +} diff --git a/voxygen/anim/src/bird_large/shoot.rs b/voxygen/anim/src/bird_large/shoot.rs new file mode 100644 index 0000000000..23cd8c3f08 --- /dev/null +++ b/voxygen/anim/src/bird_large/shoot.rs @@ -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, 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 + } +} diff --git a/voxygen/anim/src/bird_large/stunned.rs b/voxygen/anim/src/bird_large/stunned.rs new file mode 100644 index 0000000000..5377b3cdbb --- /dev/null +++ b/voxygen/anim/src/bird_large/stunned.rs @@ -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, 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 + } +} diff --git a/voxygen/anim/src/bird_large/swim.rs b/voxygen/anim/src/bird_large/swim.rs new file mode 100644 index 0000000000..f914cc20e6 --- /dev/null +++ b/voxygen/anim/src/bird_large/swim.rs @@ -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 + } +} diff --git a/voxygen/anim/src/bird_medium/mod.rs b/voxygen/anim/src/bird_medium/mod.rs index 8bffda2e5a..ab72ea8173 100644 --- a/voxygen/anim/src/bird_medium/mod.rs +++ b/voxygen/anim/src/bird_medium/mod.rs @@ -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, }, } diff --git a/voxygen/anim/src/bird_small/idle.rs b/voxygen/anim/src/bird_small/idle.rs deleted file mode 100644 index c87c59a1a8..0000000000 --- a/voxygen/anim/src/bird_small/idle.rs +++ /dev/null @@ -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 - } -} diff --git a/voxygen/anim/src/bird_small/jump.rs b/voxygen/anim/src/bird_small/jump.rs deleted file mode 100644 index 5a940935ce..0000000000 --- a/voxygen/anim/src/bird_small/jump.rs +++ /dev/null @@ -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 - } -} diff --git a/voxygen/anim/src/bird_small/mod.rs b/voxygen/anim/src/bird_small/mod.rs deleted file mode 100644 index b5ffa053a5..0000000000 --- a/voxygen/anim/src/bird_small/mod.rs +++ /dev/null @@ -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, - buf: &mut [FigureBoneData; super::MAX_BONE_COUNT], - ) -> Vec3 { - let torso_mat = base_mat * Mat4::::from(self.torso); - - *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ - make_bone(torso_mat * Mat4::::from(self.head)), - make_bone(torso_mat), - make_bone(torso_mat * Mat4::::from(self.wing_l)), - make_bone(torso_mat * Mat4::::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 { - 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 } -} diff --git a/voxygen/anim/src/bird_small/run.rs b/voxygen/anim/src/bird_small/run.rs deleted file mode 100644 index 67b01ad7af..0000000000 --- a/voxygen/anim/src/bird_small/run.rs +++ /dev/null @@ -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 - } -} diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index 8895e92841..45d7e65e87 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -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; diff --git a/voxygen/benches/meshing_benchmark.rs b/voxygen/benches/meshing_benchmark.rs index 31f12a9215..a203913312 100644 --- a/voxygen/benches/meshing_benchmark.rs +++ b/voxygen/benches/meshing_benchmark.rs @@ -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)); }); diff --git a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs index 1816f057c8..d4300e1610 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs @@ -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, } diff --git a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs index 0fa422308a..0c89e29f2e 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs @@ -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 { diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index ae677b6127..1a0dde31f7 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -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)) + } } //// diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index e583942cfa..ff3845c199 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -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>, theropod_states: HashMap>, dragon_states: HashMap>, - bird_small_states: HashMap>, + bird_large_states: HashMap>, fish_small_states: HashMap>, biped_large_states: HashMap>, biped_small_states: HashMap>, @@ -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, quadruped_low_model_cache: FigureModelCache, bird_medium_model_cache: FigureModelCache, - bird_small_model_cache: FigureModelCache, + bird_large_model_cache: FigureModelCache, dragon_model_cache: FigureModelCache, fish_medium_model_cache: FigureModelCache, fish_small_model_cache: FigureModelCache, @@ -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::::unit_y(), + state.last_ori * anim::vek::Vec3::::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::::unit_y(), + state.last_ori * anim::vek::Vec3::::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::::unit_y(), + state.last_ori * anim::vek::Vec3::::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::::unit_y(), + state.last_ori * anim::vek::Vec3::::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, diff --git a/voxygen/src/ui/widgets/item_tooltip.rs b/voxygen/src/ui/widgets/item_tooltip.rs index 62b106643a..7d66c154d9 100644 --- a/voxygen/src/ui/widgets/item_tooltip.rs +++ b/voxygen/src/ui/widgets/item_tooltip.rs @@ -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 }; diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 854eb18072..9785b7b01a 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -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, diff --git a/world/src/layer/wildlife.rs b/world/src/layer/wildlife.rs index abd7cda7d6..8e2c007608 100644 --- a/world/src/layer/wildlife.rs +++ b/world/src/layer/wildlife.rs @@ -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, ) { struct Entry { make_entity: fn(Vec3, &mut R) -> EntityInfo, // Entity group_size: Range, // Group size range is_underwater: bool, // Underwater? + day_period: Vec, // 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::() < density * col_sample.spawn_rate && underwater == *is_underwater + && day_period.contains(¤t_day_period) && col_sample.gradient < Some(1.3) { Some((make_entity, group_size.clone())) diff --git a/world/src/lib.rs b/world/src/lib.rs index 87eae3c622..a349e5bf7a 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -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, // TODO: misleading name mut should_continue: impl FnMut() -> bool, + time: Option, ) -> 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