Former-commit-id: b16aa2e7c382710c0705371cd36d57ddf62cf13c
This commit is contained in:
jshipsey 2019-05-25 23:31:41 -04:00
parent 1935240408
commit 83dd4a23ad
20 changed files with 726 additions and 12 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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;
@ -19,6 +20,8 @@ pub use inputs::Control;
pub use inputs::Gliding;
pub use inputs::Jumping;
pub use inputs::Respawning;
pub use agent::{Agent, Control};
>>>>>>> add wolf
pub use player::Player;
pub use stats::Dying;
pub use stats::Stats;

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,6 +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(pos) => {
server
.create_npc(
"Tobermory".to_owned(),
comp::Body::QuadrupedMedium(comp::QuadrupedMediumBody::random()),
)
.with(comp::Control::default())
.with(comp::Agent::Pet {
target: entity,
offset: Vec2::zero(),
})
.with(pos)
.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() {

View File

@ -1,3 +1,4 @@
pub mod QuadrupedMedium;
pub mod character;
pub mod fixture;
pub mod quadruped;

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,7 +2,9 @@ use crate::{
anim::{
character::{self, CharacterSkeleton},
quadruped::{self, QuadrupedSkeleton},
Animation, Skeleton,
Animation,
QuadrupedMedium::{self, QuadrupedMediumSkeleton},
Skeleton,
},
mesh::Meshable,
render::{
@ -17,9 +19,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 +98,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 +241,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 +279,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 +293,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 +347,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 +451,7 @@ impl FigureMgr {
model_cache: FigureModelCache::new(),
character_states: HashMap::new(),
quadruped_states: HashMap::new(),
QuadrupedMedium_states: HashMap::new(),
}
}
@ -440,6 +552,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_history.current {
comp::Animation::Run => QuadrupedMedium::RunAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_history.time,
),
comp::Animation::Idle => {
QuadrupedMedium::IdleAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_history.time,
)
}
comp::Animation::Jump => {
QuadrupedMedium::JumpAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_history.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 +613,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 +648,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);