Merge branch 'pets' into 'master'

Pets

See merge request veloren/veloren!177

Former-commit-id: 06a160658c2d2688543e65e502f3419016c9a277
This commit is contained in:
Forest Anderson 2019-05-26 15:19:56 +00:00
commit 3ad8f49f7f
20 changed files with 755 additions and 12 deletions

BIN
assets/voxygen/voxel/npc/wolf/wolf_ears.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_jaw.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_lb_foot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_lf_foot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_lower_head.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_rb_foot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_rf_foot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_tail.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_torso_back.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_torso_mid.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/wolf/wolf_upper_head.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -101,6 +101,57 @@ pub enum PigLegL {
pub enum PigLegR {
Default,
}
/////
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfUpperHead {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfJaw {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfLowerHead {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfTail {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfTorsoBack {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfTorsoMid {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfEars {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfLFFoot {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfRFFoot {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfLBFoot {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WolfRBFoot {
Default,
}
pub const ALL_RACES: [Race; 6] = [
Race::Danari,
@ -178,6 +229,7 @@ impl HumanoidBody {
}
}
}
///////////
const ALL_QRACES: [Race; 6] = [
Race::Danari,
Race::Dwarf,
@ -214,11 +266,70 @@ impl QuadrupedBody {
}
}
}
/////////////
const ALL_QMRACES: [Race; 6] = [
Race::Danari,
Race::Dwarf,
Race::Elf,
Race::Human,
Race::Orc,
Race::Undead,
];
const ALL_QMBODY_TYPES: [BodyType; 3] = [BodyType::Female, BodyType::Male, BodyType::Unspecified];
const ALL_QMWOLF_UPPERHEADS: [WolfUpperHead; 1] = [WolfUpperHead::Default];
const ALL_QMWOLF_JAWS: [WolfJaw; 1] = [WolfJaw::Default];
const ALL_QMWOLF_LOWERHEADS: [WolfLowerHead; 1] = [WolfLowerHead::Default];
const ALL_QMWOLF_TAILS: [WolfTail; 1] = [WolfTail::Default];
const ALL_QMWOLF_TORSOBACKS: [WolfTorsoBack; 1] = [WolfTorsoBack::Default];
const ALL_QMWOLF_TORSOMIDS: [WolfTorsoMid; 1] = [WolfTorsoMid::Default];
const ALL_QMWOLF_EARS: [WolfEars; 1] = [WolfEars::Default];
const ALL_QMWOLF_LFFEET: [WolfLFFoot; 1] = [WolfLFFoot::Default];
const ALL_QMWOLF_RFFEET: [WolfRFFoot; 1] = [WolfRFFoot::Default];
const ALL_QMWOLF_LBFEET: [WolfLBFoot; 1] = [WolfLBFoot::Default];
const ALL_QMWOLF_RBFEET: [WolfRBFoot; 1] = [WolfRBFoot::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct QuadrupedMediumBody {
pub race: Race,
pub body_type: BodyType,
pub wolf_upperhead: WolfUpperHead,
pub wolf_jaw: WolfJaw,
pub wolf_lowerhead: WolfLowerHead,
pub wolf_tail: WolfTail,
pub wolf_torsoback: WolfTorsoBack,
pub wolf_torsomid: WolfTorsoMid,
pub wolf_ears: WolfEars,
pub wolf_lffoot: WolfLFFoot,
pub wolf_rffoot: WolfRFFoot,
pub wolf_lbfoot: WolfLBFoot,
pub wolf_rbfoot: WolfRBFoot,
}
impl QuadrupedMediumBody {
pub fn random() -> Self {
Self {
race: *thread_rng().choose(&ALL_QMRACES).unwrap(),
body_type: *thread_rng().choose(&ALL_QMBODY_TYPES).unwrap(),
wolf_upperhead: *thread_rng().choose(&ALL_QMWOLF_UPPERHEADS).unwrap(),
wolf_jaw: *thread_rng().choose(&ALL_QMWOLF_JAWS).unwrap(),
wolf_lowerhead: *thread_rng().choose(&ALL_QMWOLF_LOWERHEADS).unwrap(),
wolf_tail: *thread_rng().choose(&ALL_QMWOLF_TAILS).unwrap(),
wolf_torsoback: *thread_rng().choose(&ALL_QMWOLF_TORSOBACKS).unwrap(),
wolf_torsomid: *thread_rng().choose(&ALL_QMWOLF_TORSOMIDS).unwrap(),
wolf_ears: *thread_rng().choose(&ALL_QMWOLF_EARS).unwrap(),
wolf_lffoot: *thread_rng().choose(&ALL_QMWOLF_LFFEET).unwrap(),
wolf_rffoot: *thread_rng().choose(&ALL_QMWOLF_RFFEET).unwrap(),
wolf_lbfoot: *thread_rng().choose(&ALL_QMWOLF_LBFEET).unwrap(),
wolf_rbfoot: *thread_rng().choose(&ALL_QMWOLF_RBFEET).unwrap(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Body {
Humanoid(HumanoidBody),
Quadruped(QuadrupedBody),
QuadrupedMedium(QuadrupedMediumBody),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]

View File

@ -11,6 +11,7 @@ pub use actor::Actor;
pub use actor::Body;
pub use actor::HumanoidBody;
pub use actor::QuadrupedBody;
pub use actor::QuadrupedMediumBody;
pub use agent::Agent;
pub use animation::Animation;
pub use animation::AnimationInfo;

View File

@ -82,10 +82,16 @@ lazy_static! {
handle_kill
),
ChatCommand::new(
"pet",
"pig",
"{}",
"/pet : Spawn a test pet NPC",
handle_pet
"/pig : Spawn a test pig NPC",
handle_petpig
),
ChatCommand::new(
"wolf",
"{}",
"/wolf : Spawn a test wolf NPC",
handle_petwolf
),
ChatCommand::new(
"help", "", "/help: Display this message", handle_help)
@ -206,7 +212,7 @@ fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &Chat
}
}
fn handle_pet(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
fn handle_petpig(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
match server
.state
.read_component_cloned::<comp::phys::Pos>(entity)
@ -233,7 +239,33 @@ fn handle_pet(server: &mut Server, entity: EcsEntity, args: String, action: &Cha
.notify(entity, ServerMsg::Chat("You have no position!".to_owned())),
}
}
fn handle_petwolf(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
match server
.state
.read_component_cloned::<comp::phys::Pos>(entity)
{
Some(mut pos) => {
pos.0.x += 1.0; // Temp fix TODO: Solve NaN issue with positions of pets
server
.create_npc(
pos,
"Tobermory".to_owned(),
comp::Body::QuadrupedMedium(comp::QuadrupedMediumBody::random()),
)
.with(comp::Agent::Pet {
target: entity,
offset: Vec2::zero(),
})
.build();
server
.clients
.notify(entity, ServerMsg::Chat("Spawned pet!".to_owned()));
}
None => server
.clients
.notify(entity, ServerMsg::Chat("You have no position!".to_owned())),
}
}
fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) {
for cmd in CHAT_COMMANDS.iter() {
server

View File

@ -1,6 +1,7 @@
pub mod character;
pub mod fixture;
pub mod quadruped;
pub mod quadrupedmedium;
// Library
use vek::*;

View File

@ -0,0 +1,105 @@
// Standard
use std::{f32::consts::PI, ops::Mul};
// Library
use vek::*;
// Local
use super::{super::Animation, QuadrupedMediumSkeleton, SCALE};
pub struct IdleAnimation;
impl Animation for IdleAnimation {
type Skeleton = QuadrupedMediumSkeleton;
type Dependency = (f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
global_time: Self::Dependency,
anim_time: f64,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 3.5 + PI).sin();
let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
let wolf_look = Vec2::new(
((global_time + anim_time) as f32 / 8.0)
.floor()
.mul(7331.0)
.sin()
* 0.5,
((global_time + anim_time) as f32 / 8.0)
.floor()
.mul(1337.0)
.sin()
* 0.25,
);
let wolf_tail = Vec2::new(
((global_time + anim_time) as f32 / 2.0)
.floor()
.mul(7331.0)
.sin()
* 0.25,
((global_time + anim_time) as f32 / 2.0)
.floor()
.mul(1337.0)
.sin()
* 0.125,
);
next.wolf_upperhead.offset = Vec3::new(0.0, 7.5, 15.0 + wave_ultra_slow * 0.4) / 11.0;
next.wolf_upperhead.ori =
Quaternion::rotation_z(wolf_look.x) * Quaternion::rotation_x(wolf_look.y);
next.wolf_upperhead.scale = Vec3::one() / 10.88;
next.wolf_jaw.offset =
Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0 + wave_slow * 0.2);
next.wolf_jaw.ori = Quaternion::rotation_x(wave_slow * 0.05);
next.wolf_jaw.scale = Vec3::one() * 1.01;
next.wolf_lowerhead.offset = Vec3::new(0.0, 3.1, -4.5 + wave_ultra_slow * 0.20);
next.wolf_lowerhead.ori = Quaternion::rotation_z(0.0);
next.wolf_lowerhead.scale = Vec3::one() * 0.98;
next.wolf_tail.offset = Vec3::new(0.0, -13.0, 8.0 + wave_ultra_slow * 1.2) / 11.0;
next.wolf_tail.ori = Quaternion::rotation_z(0.0 + wave_slow * 0.2 + wolf_tail.x)
* Quaternion::rotation_x(wolf_tail.y);
next.wolf_tail.scale = Vec3::one() / 11.0;
next.wolf_torsoback.offset = Vec3::new(0.0, -9.5, 11.0 + wave_ultra_slow * 1.2) / 11.0;
next.wolf_torsoback.ori = Quaternion::rotation_y(wave_slow_cos * 0.015);
next.wolf_torsoback.scale = Vec3::one() / 11.0;
next.wolf_torsomid.offset = Vec3::new(0.0, 0.0, 12.0 + wave_ultra_slow * 0.7) / 11.0;
next.wolf_torsomid.ori = Quaternion::rotation_y(wave_slow * 0.015);
next.wolf_torsomid.scale = Vec3::one() / 10.9;
next.wolf_ears.offset = Vec3::new(0.0, 0.75, 6.25);
next.wolf_ears.ori = Quaternion::rotation_x(0.0 + wave_slow * 0.1);
next.wolf_ears.scale = Vec3::one() * 1.05;
next.wolf_LFFoot.offset = Vec3::new(-5.0, 5.0, 2.5) / 11.0;
next.wolf_LFFoot.ori = Quaternion::rotation_x(0.0);
next.wolf_LFFoot.scale = Vec3::one() / 11.0;
next.wolf_RFFoot.offset = Vec3::new(5.0, 5.0, 2.5) / 11.0;
next.wolf_RFFoot.ori = Quaternion::rotation_x(0.0);
next.wolf_RFFoot.scale = Vec3::one() / 11.0;
next.wolf_LBFoot.offset = Vec3::new(-5.0, -10.0, 2.5) / 11.0;
next.wolf_LBFoot.ori = Quaternion::rotation_x(0.0);
next.wolf_LBFoot.scale = Vec3::one() / 11.0;
next.wolf_RBFoot.offset = Vec3::new(5.0, -10.0, 2.5) / 11.0;
next.wolf_RBFoot.ori = Quaternion::rotation_x(0.0);
next.wolf_RBFoot.scale = Vec3::one() / 11.0;
next
}
}

View File

@ -0,0 +1,84 @@
// Standard
use std::f32::consts::PI;
// Library
use vek::*;
// Local
use super::{super::Animation, QuadrupedMediumSkeleton, SCALE};
pub struct JumpAnimation;
impl Animation for JumpAnimation {
type Skeleton = QuadrupedMediumSkeleton;
type Dependency = (f32, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
global_time: Self::Dependency,
anim_time: f64,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 3.5 + PI).sin();
let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos();
let wave_stop = (anim_time as f32 * 5.0).min(PI / 2.0).sin();
next.wolf_upperhead.offset = Vec3::new(0.0, 7.5, 15.0 + wave_stop * 4.8) / 11.0;
next.wolf_upperhead.ori =
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(wave_slow * -0.25);
next.wolf_upperhead.scale = Vec3::one() / 10.88;
next.wolf_jaw.offset = Vec3::new(0.0, 4.5, 2.0);
next.wolf_jaw.ori = Quaternion::rotation_x(0.0);
next.wolf_jaw.scale = Vec3::one() * 1.01;
next.wolf_lowerhead.offset = Vec3::new(0.0, 3.1, -4.5);
next.wolf_lowerhead.ori = Quaternion::rotation_x(wave_stop * -0.1);
next.wolf_lowerhead.scale = Vec3::one() * 0.98;
next.wolf_tail.offset = Vec3::new(0.0, -12.0, 8.0) / 11.0;
next.wolf_tail.ori =
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(wave_slow * -0.25);
next.wolf_tail.scale = Vec3::one() / 11.0;
next.wolf_torsoback.offset =
Vec3::new(0.0, -9.5 + wave_stop * 1.0, 11.0 + wave_stop * 2.2) / 11.0;
next.wolf_torsoback.ori = Quaternion::rotation_x(wave_slow * -0.25);
next.wolf_torsoback.scale = Vec3::one() / 11.0;
next.wolf_torsomid.offset = Vec3::new(0.0, 0.0, 12.0 + wave_stop * 3.6) / 11.0;
next.wolf_torsomid.ori = Quaternion::rotation_x(wave_slow * -0.25);
next.wolf_torsomid.scale = Vec3::one() / 10.9;
next.wolf_ears.offset = Vec3::new(0.0, 0.75, 6.25);
next.wolf_ears.ori = Quaternion::rotation_x(0.0);
next.wolf_ears.scale = Vec3::one() * 1.05;
next.wolf_LFFoot.offset =
Vec3::new(-5.0, 5.0 + wave_stop * 3.0, 5.0 + wave_stop * 7.0) / 11.0;
next.wolf_LFFoot.ori = Quaternion::rotation_x(wave_stop * 1.0 + wave * 0.15);
next.wolf_LFFoot.scale = Vec3::one() / 11.0;
next.wolf_RFFoot.offset =
Vec3::new(5.0, 5.0 - wave_stop * 3.0, 5.0 + wave_stop * 5.0) / 11.0;
next.wolf_RFFoot.ori = Quaternion::rotation_x(wave_stop * -1.0 + wave * 0.15);
next.wolf_RFFoot.scale = Vec3::one() / 11.0;
next.wolf_LBFoot.offset =
Vec3::new(-5.0, -10.0 - wave_stop * 2.0, 5.0 + wave_stop * 0.0) / 11.0;
next.wolf_LBFoot.ori = Quaternion::rotation_x(wave_stop * -1.0 + wave * 0.15);
next.wolf_LBFoot.scale = Vec3::one() / 11.0;
next.wolf_RBFoot.offset =
Vec3::new(5.0, -10.0 + wave_stop * 2.0, 5.0 + wave_stop * 2.0) / 11.0;
next.wolf_RBFoot.ori = Quaternion::rotation_x(wave_stop * 1.0 + wave * 0.15);
next.wolf_RBFoot.scale = Vec3::one() / 11.0;
next
}
}

View File

@ -0,0 +1,92 @@
pub mod idle;
pub mod jump;
pub mod run;
// Reexports
pub use self::idle::IdleAnimation;
pub use self::jump::JumpAnimation;
pub use self::run::RunAnimation;
// Crate
use crate::render::FigureBoneData;
// Local
use super::{Bone, Skeleton};
const SCALE: f32 = 11.0;
#[derive(Clone)]
pub struct QuadrupedMediumSkeleton {
wolf_upperhead: Bone,
wolf_jaw: Bone,
wolf_lowerhead: Bone,
wolf_tail: Bone,
wolf_torsoback: Bone,
wolf_torsomid: Bone,
wolf_ears: Bone,
wolf_LFFoot: Bone,
wolf_RFFoot: Bone,
wolf_LBFoot: Bone,
wolf_RBFoot: Bone,
}
impl QuadrupedMediumSkeleton {
pub fn new() -> Self {
Self {
wolf_upperhead: Bone::default(),
wolf_jaw: Bone::default(),
wolf_lowerhead: Bone::default(),
wolf_tail: Bone::default(),
wolf_torsoback: Bone::default(),
wolf_torsomid: Bone::default(),
wolf_ears: Bone::default(),
wolf_LFFoot: Bone::default(),
wolf_RFFoot: Bone::default(),
wolf_LBFoot: Bone::default(),
wolf_RBFoot: Bone::default(),
}
}
}
impl Skeleton for QuadrupedMediumSkeleton {
fn compute_matrices(&self) -> [FigureBoneData; 16] {
let ears_mat = self.wolf_ears.compute_base_matrix();
let upperhead_mat = self.wolf_upperhead.compute_base_matrix();
let lowerhead_mat = self.wolf_lowerhead.compute_base_matrix();
[
FigureBoneData::new(upperhead_mat),
FigureBoneData::new(
upperhead_mat * lowerhead_mat * self.wolf_jaw.compute_base_matrix(),
),
FigureBoneData::new(upperhead_mat * lowerhead_mat),
FigureBoneData::new(self.wolf_tail.compute_base_matrix()),
FigureBoneData::new(self.wolf_torsoback.compute_base_matrix()),
FigureBoneData::new(self.wolf_torsomid.compute_base_matrix()),
FigureBoneData::new(upperhead_mat * ears_mat),
FigureBoneData::new(self.wolf_LFFoot.compute_base_matrix()),
FigureBoneData::new(self.wolf_RFFoot.compute_base_matrix()),
FigureBoneData::new(self.wolf_LBFoot.compute_base_matrix()),
FigureBoneData::new(self.wolf_RBFoot.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
]
}
fn interpolate(&mut self, target: &Self) {
self.wolf_upperhead.interpolate(&target.wolf_upperhead);
self.wolf_jaw.interpolate(&target.wolf_jaw);
self.wolf_lowerhead.interpolate(&target.wolf_lowerhead);
self.wolf_tail.interpolate(&target.wolf_tail);
self.wolf_torsoback.interpolate(&target.wolf_torsoback);
self.wolf_torsomid.interpolate(&target.wolf_torsomid);
self.wolf_ears.interpolate(&target.wolf_ears);
self.wolf_LFFoot.interpolate(&target.wolf_LFFoot);
self.wolf_RFFoot.interpolate(&target.wolf_RFFoot);
self.wolf_LBFoot.interpolate(&target.wolf_LBFoot);
self.wolf_RBFoot.interpolate(&target.wolf_RBFoot);
}
}

View File

@ -0,0 +1,116 @@
// Standard
use std::{f32::consts::PI, ops::Mul};
// Library
use vek::*;
// Local
use super::{super::Animation, QuadrupedMediumSkeleton, SCALE};
pub struct RunAnimation;
impl Animation for RunAnimation {
type Skeleton = QuadrupedMediumSkeleton;
type Dependency = (f32, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
(velocity, global_time): Self::Dependency,
anim_time: f64,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 3.5 + PI).sin();
let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
let wave_quick = (anim_time as f32 * 18.0).sin();
let wave_med = (anim_time as f32 * 12.0).sin();
let wave_med_cos = (anim_time as f32 * 12.0).cos();
let wave_quick_cos = (anim_time as f32 * 18.0).cos();
let wolf_look = Vec2::new(
((global_time + anim_time) as f32 / 4.0)
.floor()
.mul(7331.0)
.sin()
* 0.25,
((global_time + anim_time) as f32 / 4.0)
.floor()
.mul(1337.0)
.sin()
* 0.125,
);
let wolf_tail = Vec2::new(
((global_time + anim_time) as f32 / 2.0)
.floor()
.mul(7331.0)
.sin()
* 0.25,
((global_time + anim_time) as f32 / 2.0)
.floor()
.mul(1337.0)
.sin()
* 0.125,
);
next.wolf_upperhead.offset =
Vec3::new(0.0, 9.5 + wave_quick_cos * 2.0, 15.0 + wave_med * 3.0) / 11.0;
next.wolf_upperhead.ori =
Quaternion::rotation_x(-0.12 + wave_quick_cos * 0.12 + wolf_look.y)
* Quaternion::rotation_z(wolf_look.x);
next.wolf_upperhead.scale = Vec3::one() / 10.88;
next.wolf_jaw.offset = Vec3::new(0.0, 4.5, 2.0 + wave_slow_cos * 1.0);
next.wolf_jaw.ori = Quaternion::rotation_x(wave_slow * 0.05);
next.wolf_jaw.scale = Vec3::one() * 1.01;
next.wolf_lowerhead.offset = Vec3::new(0.0, 3.1, -4.5 + wave_med * 1.0);
next.wolf_lowerhead.ori = Quaternion::rotation_z(0.0);
next.wolf_lowerhead.scale = Vec3::one() * 0.98;
next.wolf_tail.offset = Vec3::new(0.0, -12.0, 10.0) / 11.0;
next.wolf_tail.ori = Quaternion::rotation_x(wave_quick * 0.18);
next.wolf_tail.scale = Vec3::one() / 11.0;
next.wolf_torsoback.offset =
Vec3::new(0.0, -9.5 + wave_quick_cos * 2.2, 13.0 + wave_med * 2.8) / 11.0;
next.wolf_torsoback.ori = Quaternion::rotation_x(-0.15 + wave_med_cos * 0.14);
next.wolf_torsoback.scale = Vec3::one() / 11.0;
next.wolf_torsomid.offset =
Vec3::new(0.0, 0.0 + wave_quick_cos * 2.2, 14.0 + wave_med * 3.2) / 11.0;
next.wolf_torsomid.ori = Quaternion::rotation_x(-0.15 + wave_med_cos * 0.12);
next.wolf_torsomid.scale = Vec3::one() / 10.9;
next.wolf_ears.offset = Vec3::new(0.0, 0.75 + wave * 0.4, 6.25);
next.wolf_ears.ori = Quaternion::rotation_x(wave * 0.2);
next.wolf_ears.scale = Vec3::one() * 1.05;
next.wolf_LFFoot.offset =
Vec3::new(-5.0, 5.0 + wave_quick * 3.0, 7.0 + wave_quick_cos * 4.0) / 11.0;
next.wolf_LFFoot.ori = Quaternion::rotation_x(0.0 + wave_quick * 0.8);
next.wolf_LFFoot.scale = Vec3::one() / 11.0;
next.wolf_RFFoot.offset =
Vec3::new(5.0, 5.0 - wave_quick_cos * 3.0, 7.0 + wave_quick * 4.0) / 11.0;
next.wolf_RFFoot.ori = Quaternion::rotation_x(0.0 - wave_quick_cos * 0.8);
next.wolf_RFFoot.scale = Vec3::one() / 11.0;
next.wolf_LBFoot.offset =
Vec3::new(-5.0, -10.0 - wave_quick_cos * 3.0, 7.0 + wave_quick * 4.0) / 11.0;
next.wolf_LBFoot.ori = Quaternion::rotation_x(0.0 - wave_quick_cos * 0.8);
next.wolf_LBFoot.scale = Vec3::one() / 11.0;
next.wolf_RBFoot.offset =
Vec3::new(5.0, -10.0 + wave_quick * 3.0, 7.0 + wave_quick_cos * 4.0) / 11.0;
next.wolf_RBFoot.ori = Quaternion::rotation_x(0.0 + wave_quick * 0.8);
next.wolf_RBFoot.scale = Vec3::one() / 11.0;
next
}
}

View File

@ -2,6 +2,7 @@ use crate::{
anim::{
character::{self, CharacterSkeleton},
quadruped::{self, QuadrupedSkeleton},
quadrupedmedium::{self, QuadrupedMediumSkeleton},
Animation, Skeleton,
},
mesh::Meshable,
@ -17,9 +18,10 @@ use common::{
self,
actor::{
Belt, Chest, Draw, Foot, Hand, Head, Pants, PigChest, PigHead, PigLegL, PigLegR,
Shoulder, Weapon,
Shoulder, Weapon, WolfEars, WolfJaw, WolfLBFoot, WolfLFFoot, WolfLowerHead, WolfRBFoot,
WolfRFFoot, WolfTail, WolfTorsoBack, WolfTorsoMid, WolfUpperHead,
},
Body, HumanoidBody, QuadrupedBody,
Body, HumanoidBody, QuadrupedBody, QuadrupedMediumBody,
},
figure::Segment,
msg,
@ -95,6 +97,24 @@ impl FigureModelCache {
None,
None,
],
Body::QuadrupedMedium(body) => [
Some(Self::load_wolf_upperhead(body.wolf_upperhead)),
Some(Self::load_wolf_jaw(body.wolf_jaw)),
Some(Self::load_wolf_lowerhead(body.wolf_lowerhead)),
Some(Self::load_wolf_tail(body.wolf_tail)),
Some(Self::load_wolf_torsoback(body.wolf_torsoback)),
Some(Self::load_wolf_torsomid(body.wolf_torsomid)),
Some(Self::load_wolf_ears(body.wolf_ears)),
Some(Self::load_wolf_lffoot(body.wolf_lffoot)),
Some(Self::load_wolf_rffoot(body.wolf_rffoot)),
Some(Self::load_wolf_lbfoot(body.wolf_lbfoot)),
Some(Self::load_wolf_rbfoot(body.wolf_rbfoot)),
None,
None,
None,
None,
None,
],
};
let mut mesh = Mesh::new();
@ -220,9 +240,9 @@ impl FigureModelCache {
fn load_weapon(weapon: Weapon) -> Mesh<FigurePipeline> {
Self::load_mesh(
match weapon {
Weapon::Sword => "weapon/sword/sword_wood_2h.vox",
Weapon::Sword => "weapon/sword/sword_rusty_2h.vox",
// TODO actually match against other weapons and set the right model
_ => "weapon/sword/sword_wood_2h.vox",
_ => "weapon/sword/sword_rusty_2h.vox",
},
Vec3::new(-6.5, -1.5, -4.0),
)
@ -258,8 +278,8 @@ impl FigureModelCache {
fn load_left_equip(weapon: Weapon) -> Mesh<FigurePipeline> {
Self::load_mesh(
match weapon {
Weapon::Sword => "weapon/sword/sword_wood_2h.vox",
_ => "weapon/sword/sword_wood_2h.vox",
Weapon::Sword => "weapon/sword/sword_rusty_2h.vox",
_ => "weapon/sword/sword_rusty_2h.vox",
},
Vec3::new(-6.5, -1.5, -5.0),
)
@ -272,7 +292,7 @@ impl FigureModelCache {
Vec3::new(-2.0, -2.5, -2.0),
)
}
/////////
fn load_pig_head(pig_head: PigHead) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pig_head {
@ -326,12 +346,102 @@ impl FigureModelCache {
Vec3::new(0.0, -1.0, -1.5),
)
}
//////
fn load_wolf_upperhead(wolf_upperhead: WolfUpperHead) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_upperhead {
WolfUpperHead::Default => "npc/wolf/wolf_upper_head.vox",
},
Vec3::new(-7.0, -6.0, -5.5),
)
}
fn load_wolf_jaw(wolf_jaw: WolfJaw) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_jaw {
WolfJaw::Default => "npc/wolf/wolf_jaw.vox",
},
Vec3::new(-3.0, -3.0, -2.5),
)
}
fn load_wolf_lowerhead(wolf_lowerhead: WolfLowerHead) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_lowerhead {
WolfLowerHead::Default => "npc/wolf/wolf_lower_head.vox",
},
Vec3::new(-7.0, -6.0, -5.5),
)
}
fn load_wolf_tail(wolf_tail: WolfTail) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_tail {
WolfTail::Default => "npc/wolf/wolf_tail.vox",
},
Vec3::new(-2.0, -12.0, -5.0),
)
}
fn load_wolf_torsoback(wolf_torsoback: WolfTorsoBack) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_torsoback {
WolfTorsoBack::Default => "npc/wolf/wolf_torso_back.vox",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
fn load_wolf_torsomid(wolf_torsomid: WolfTorsoMid) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_torsomid {
WolfTorsoMid::Default => "npc/wolf/wolf_torso_mid.vox",
},
Vec3::new(-8.0, -5.5, -6.0),
)
}
fn load_wolf_ears(wolf_ears: WolfEars) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_ears {
WolfEars::Default => "npc/wolf/wolf_ears.vox",
},
Vec3::new(-4.0, -1.0, -1.0),
)
}
fn load_wolf_lffoot(wolf_lffoot: WolfLFFoot) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_lffoot {
WolfLFFoot::Default => "npc/wolf/wolf_lf_foot.vox",
},
Vec3::new(-2.5, -4.0, -2.5),
)
}
fn load_wolf_rffoot(wolf_rffoot: WolfRFFoot) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_rffoot {
WolfRFFoot::Default => "npc/wolf/wolf_rf_foot.vox",
},
Vec3::new(-2.5, -4.0, -2.5),
)
}
fn load_wolf_lbfoot(wolf_lbfoot: WolfLBFoot) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_lbfoot {
WolfLBFoot::Default => "npc/wolf/wolf_lb_foot.vox",
},
Vec3::new(-2.5, -4.0, -2.5),
)
}
fn load_wolf_rbfoot(wolf_rbfoot: WolfRBFoot) -> Mesh<FigurePipeline> {
Self::load_mesh(
match wolf_rbfoot {
WolfRBFoot::Default => "npc/wolf/wolf_rb_foot.vox",
},
Vec3::new(-2.5, -4.0, -2.5),
)
}
}
pub struct FigureMgr {
model_cache: FigureModelCache,
character_states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
quadruped_states: HashMap<EcsEntity, FigureState<QuadrupedSkeleton>>,
QuadrupedMedium_states: HashMap<EcsEntity, FigureState<QuadrupedMediumSkeleton>>,
}
impl FigureMgr {
@ -340,6 +450,7 @@ impl FigureMgr {
model_cache: FigureModelCache::new(),
character_states: HashMap::new(),
quadruped_states: HashMap::new(),
QuadrupedMedium_states: HashMap::new(),
}
}
@ -440,6 +551,57 @@ impl FigureMgr {
state.skeleton.interpolate(&target_skeleton);
state.update(renderer, pos.0, dir.0, col);
}
Body::QuadrupedMedium(body) => {
let state =
self.QuadrupedMedium_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(renderer, QuadrupedMediumSkeleton::new())
});
let target_skeleton = match animation_info.animation {
comp::Animation::Run => quadrupedmedium::RunAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
),
comp::Animation::Idle => {
quadrupedmedium::IdleAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_info.time,
)
}
comp::Animation::Jump => {
quadrupedmedium::JumpAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
)
}
// TODO!
_ => state.skeleton_mut().clone(),
};
state.skeleton.interpolate(&target_skeleton);
// Change in health as color!
let col = stats
.and_then(|stats| stats.hp.last_change)
.map(|(change_by, change_time)| Rgba::new(1.0, 0.7, 0.7, 1.0))
.unwrap_or(Rgba::broadcast(1.0));
// Change in health as color!
let col = stats
.and_then(|stats| stats.hp.last_change)
.map(|(change_by, change_time)| Rgba::new(1.0, 0.7, 0.7, 1.0))
.unwrap_or(Rgba::broadcast(1.0));
state.update(renderer, pos.0, dir.0, col);
state.update(renderer, pos.0, dir.0, col);
}
},
// TODO: Non-character actors
}
@ -450,6 +612,8 @@ impl FigureMgr {
.retain(|entity, _| ecs.entities().is_alive(*entity));
self.quadruped_states
.retain(|entity, _| ecs.entities().is_alive(*entity));
self.QuadrupedMedium_states
.retain(|entity, _| ecs.entities().is_alive(*entity));
}
pub fn render(
@ -483,6 +647,10 @@ impl FigureMgr {
.quadruped_states
.get(&entity)
.map(|state| (state.locals(), state.bone_consts())),
Body::QuadrupedMedium(_) => self
.QuadrupedMedium_states
.get(&entity)
.map(|state| (state.locals(), state.bone_consts())),
} {
let model = self.model_cache.get_or_create_model(renderer, *body, tick);