Merge branch 'refactor-controller-movement-states' into 'master'

Refactor controller movement states

See merge request veloren/veloren!672
This commit is contained in:
Acrimon 2019-12-03 06:30:09 +00:00
commit ea6374b1e4
34 changed files with 1257 additions and 854 deletions

View File

@ -8,28 +8,20 @@ pub enum MovementState {
Sit,
Run,
Jump,
Fall,
Glide,
Roll { time_left: Duration },
Swim,
Climb,
}
impl MovementState {
pub fn is_roll(&self) -> bool {
if let Self::Roll { .. } = self {
true
} else {
false
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub enum ActionState {
Idle,
Wield { time_left: Duration },
Attack { time_left: Duration, applied: bool },
Block { time_left: Duration },
Block { time_active: Duration },
Roll { time_left: Duration },
Charge { time_left: Duration },
//Carry,
}
@ -42,6 +34,16 @@ impl ActionState {
}
}
pub fn is_action_finished(&self) -> bool {
match self {
Self::Wield { time_left }
| Self::Attack { time_left, .. }
| Self::Roll { time_left }
| Self::Charge { time_left } => *time_left == Duration::default(),
Self::Idle | Self::Block { .. } => false,
}
}
pub fn is_attack(&self) -> bool {
if let Self::Attack { .. } = self {
true
@ -57,6 +59,22 @@ impl ActionState {
false
}
}
pub fn is_roll(&self) -> bool {
if let Self::Roll { .. } = self {
true
} else {
false
}
}
pub fn is_charge(&self) -> bool {
if let Self::Charge { .. } = self {
true
} else {
false
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]

View File

@ -1,12 +1,11 @@
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use sphynx::Uid;
use std::ops::Add;
use std::time::Duration;
use vek::*;
/// Default duration for how long before an input is considered 'held'.
pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(250);
/// Default duration before an input is considered 'held'.
pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ControlEvent {
@ -27,39 +26,62 @@ pub enum InputState {
/// and how long it has been in that state
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Input {
// Should not be pub because duration should
// always be reset when state is updated
/// Should not be pub because duration should
/// always be reset when state is updated
state: InputState,
// Should only be updated by npc agents
// through appropriate fn
/// Should only be updated by npc agents
/// through appropriate fn
duration: Duration,
/// Turned off first tick after switching states
just_changed: bool,
/// Set when `set_state` is called. Needed so
/// tick after change doesn't immediately unset `just_changed`
dirty: bool,
}
impl Input {
fn tick(&mut self, dt: Duration) {
// Increase how long input has been in current state
self.duration = self.duration.checked_add(dt).unwrap_or_default();
if self.dirty {
// Unset dirty first tick after changing into current state
self.dirty = false;
} else {
// Otherwise, just changed is always false
self.just_changed = false;
}
}
/// Whether input is in `InputState::Pressed` state
pub fn is_pressed(&self) -> bool {
self.state == InputState::Pressed
}
/// Whether it's the first frame this input has been in
/// its current state
pub fn is_just_pressed(&self) -> bool {
(self.just_changed && self.is_pressed())
}
/// Whether input has been in current state longer than
/// `DEFAULT_HOLD_DURATION`
pub fn is_held_down(&self) -> bool {
(self.is_pressed() && self.duration >= DEFAULT_HOLD_DURATION)
}
/// Sets the `input::state` and resets `input::duration`
///
///
/// `new_state` == `true` -> `InputState::Pressed`
///
/// `new_state` == `false` -> `InputState::Unpressed`
/// Handles logic of updating state of Input
pub fn set_state(&mut self, new_state: bool) {
// Only update if state switches
match (new_state, self.is_pressed()) {
(true, false) => {
match (self.is_pressed(), new_state) {
(false, true) => {
self.just_changed = true;
self.dirty = true;
self.state = InputState::Pressed;
self.duration = Duration::default();
}
(false, true) => {
(true, false) => {
self.just_changed = true;
self.dirty = true;
self.state = InputState::Unpressed;
self.duration = Duration::default();
}
@ -67,9 +89,9 @@ impl Input {
};
}
/// Sets `input::duration`
/// Increases `input::duration` by `dur`
pub fn inc_dur(&mut self, dur: Duration) {
self.duration = self.duration + dur;
self.duration = self.duration.checked_add(dur).unwrap_or_default();
}
/// Returns `input::duration`
@ -83,23 +105,16 @@ impl Default for Input {
Self {
state: InputState::Unpressed,
duration: Duration::default(),
}
}
}
impl Add<Duration> for Input {
type Output = Self;
fn add(self, dur: Duration) -> Self {
Self {
state: self.state,
duration: self.duration.checked_add(dur).unwrap_or_default(),
just_changed: false,
dirty: false,
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ControllerInputs {
// When adding new inputs:
// 1. Add to tick() update
pub primary: Input,
pub secondary: Input,
pub sit: Input,
@ -111,6 +126,7 @@ pub struct ControllerInputs {
pub wall_leap: Input,
pub respawn: Input,
pub toggle_wield: Input,
pub charge: Input,
pub move_dir: Vec2<f32>,
pub look_dir: Vec3<f32>,
}
@ -125,17 +141,33 @@ pub struct Controller {
impl ControllerInputs {
/// Updates all inputs, accounting for delta time
pub fn tick(&mut self, dt: Duration) {
self.primary = self.primary + dt;
self.secondary = self.secondary + dt;
self.sit = self.sit + dt;
self.jump = self.jump + dt;
self.roll = self.roll + dt;
self.glide = self.glide + dt;
self.climb = self.climb + dt;
self.climb_down = self.climb_down + dt;
self.wall_leap = self.wall_leap + dt;
self.respawn = self.respawn + dt;
self.toggle_wield = self.toggle_wield + dt;
self.primary.tick(dt);
self.secondary.tick(dt);
self.sit.tick(dt);
self.jump.tick(dt);
self.roll.tick(dt);
self.glide.tick(dt);
self.climb.tick(dt);
self.climb_down.tick(dt);
self.wall_leap.tick(dt);
self.respawn.tick(dt);
self.toggle_wield.tick(dt);
self.charge.tick(dt);
}
/// Updates `inputs.move_dir`.
pub fn update_move_dir(&mut self) {
self.move_dir = if self.move_dir.magnitude_squared() > 1.0 {
// Cap move_dir to 1
self.move_dir.normalized()
} else {
self.move_dir
};
}
/// Updates `inputs.look_dir`
pub fn update_look_dir(&mut self) {
self.look_dir
.try_normalized()
.unwrap_or(self.move_dir.into());
}
}

View File

@ -8,19 +8,63 @@ use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use std::fs::File;
use std::io::BufReader;
use std::time::Duration;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Tool {
Dagger,
Shield,
Sword,
Axe,
Hammer,
Bow,
Dagger,
Staff,
Shield,
Debug(Debug),
}
// TODO: Allow override in item ron?
impl Tool {
pub fn wield_duration(&self) -> Duration {
match self {
Tool::Sword => Duration::from_millis(800),
Tool::Axe => Duration::from_millis(1000),
Tool::Hammer => Duration::from_millis(1000),
Tool::Bow => Duration::from_millis(800),
Tool::Dagger => Duration::from_millis(300),
Tool::Staff => Duration::from_millis(800),
Tool::Shield => Duration::from_millis(1000),
Tool::Debug(_) => Duration::from_millis(0),
}
}
pub fn attack_buildup_duration(&self) -> Duration {
match self {
Tool::Sword => Duration::from_millis(100),
Tool::Axe => Duration::from_millis(700),
Tool::Hammer => Duration::from_millis(700),
Tool::Bow => Duration::from_millis(0),
Tool::Dagger => Duration::from_millis(100),
Tool::Staff => Duration::from_millis(400),
Tool::Shield => Duration::from_millis(100),
Tool::Debug(_) => Duration::from_millis(0),
}
}
pub fn attack_recover_duration(&self) -> Duration {
match self {
Tool::Sword => Duration::from_millis(500),
Tool::Axe => Duration::from_millis(100),
Tool::Hammer => Duration::from_millis(100),
Tool::Bow => Duration::from_millis(800),
Tool::Dagger => Duration::from_millis(400),
Tool::Staff => Duration::from_millis(300),
Tool::Shield => Duration::from_millis(1000),
Tool::Debug(_) => Duration::from_millis(0),
}
}
pub fn attack_duration(&self) -> Duration {
self.attack_buildup_duration() + self.attack_recover_duration()
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Debug {
Boost,
@ -43,6 +87,7 @@ pub enum Armor {
Necklace,
}
//TODO: Do we even need this?
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Consumable {
Apple,

View File

@ -1,5 +1,6 @@
use crate::comp::{
Agent, CharacterState, Controller, MountState, MovementState::Glide, Pos, Stats,
Agent, CharacterState, Controller, ControllerInputs, MountState, MovementState::Glide, Pos,
Stats,
};
use rand::{seq::SliceRandom, thread_rng};
use specs::{Entities, Join, ReadStorage, System, WriteStorage};
@ -47,7 +48,7 @@ impl<'a> System<'a> for Sys {
controller.reset();
let mut inputs = &mut controller.inputs;
let mut inputs = ControllerInputs::default();
match agent {
Agent::Wanderer(bearing) => {
@ -92,7 +93,7 @@ impl<'a> System<'a> for Sys {
}
Agent::Enemy { bearing, target } => {
const SIGHT_DIST: f32 = 30.0;
const MIN_ATTACK_DIST: f32 = 3.5;
const MIN_ATTACK_DIST: f32 = 3.25;
let mut choose_new = false;
if let Some((Some(target_pos), Some(target_stats), Some(target_character))) =
@ -109,7 +110,10 @@ impl<'a> System<'a> for Sys {
let dist = Vec2::<f32>::from(target_pos.0 - pos.0).magnitude();
if target_stats.is_dead {
choose_new = true;
} else if dist < MIN_ATTACK_DIST && dist > 0.001 {
} else if dist < MIN_ATTACK_DIST
&& dist > 0.001
&& rand::random::<f32>() < 0.3
{
// Fight (and slowly move closer)
inputs.move_dir =
Vec2::<f32>::from(target_pos.0 - pos.0).normalized() * 0.01;
@ -161,6 +165,8 @@ impl<'a> System<'a> for Sys {
}
}
}
controller.inputs = inputs;
}
}
}

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
ActionState::*, CharacterState, Controller, HealthChange, HealthSource, ItemKind, Ori, Pos,
Stats,
ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Item, ItemKind,
Ori, Pos, Stats,
},
event::{EventBus, LocalEvent, ServerEvent},
state::{DeltaTime, Uid},
@ -10,12 +10,6 @@ use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
use std::time::Duration;
use vek::*;
pub const WIELD_DURATION: Duration = Duration::from_millis(300);
pub const ATTACK_DURATION: Duration = Duration::from_millis(500);
// Delay before hit
const PREPARE_DURATION: Duration = Duration::from_millis(100);
const BLOCK_EFFICIENCY: f32 = 0.9;
const ATTACK_RANGE: f32 = 4.0;
@ -66,13 +60,23 @@ impl<'a> System<'a> for Sys {
)
.join()
{
let recover_duration = if let Some(Item {
kind: ItemKind::Tool { kind, .. },
..
}) = stat.equipment.main
{
kind.attack_recover_duration()
} else {
Duration::from_secs(1)
};
let (deal_damage, should_end) = if let Some(Attack { time_left, applied }) =
&mut character_states.get_mut(entity).map(|c| &mut c.action)
{
*time_left = time_left
.checked_sub(Duration::from_secs_f32(dt.0))
.unwrap_or_default();
if !*applied && ATTACK_DURATION - *time_left > PREPARE_DURATION {
if !*applied && recover_duration > *time_left {
*applied = true;
(true, false)
} else if *time_left == Duration::default() {
@ -107,7 +111,7 @@ impl<'a> System<'a> for Sys {
&& !stat_b.is_dead
&& pos.0.distance_squared(pos_b.0) < ATTACK_RANGE.powi(2)
// TODO: Use size instead of 1.0
&& ori2.angle_between(pos_b2 - pos2) < (1.0 / pos2.distance(pos_b2)).atan()
&& ori2.angle_between(pos_b2 - pos2) < (2.0 / pos2.distance(pos_b2)).atan()
{
// Weapon gives base damage
let mut dmg = if let Some(ItemKind::Tool { power, .. }) =

View File

@ -1,388 +1,641 @@
use super::{
combat::{ATTACK_DURATION, WIELD_DURATION},
movement::ROLL_DURATION,
};
use super::movement::ROLL_DURATION;
use crate::{
comp::{
self, item, projectile, ActionState::*, Body, CharacterState, ControlEvent, Controller,
HealthChange, HealthSource, ItemKind, MovementState::*, PhysicsState, Projectile, Stats,
Vel,
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
},
event::{EventBus, LocalEvent, ServerEvent},
event::{Emitter, EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
};
use specs::{
saveload::{Marker, MarkerAllocator},
Entities, Join, Read, ReadStorage, System, WriteStorage,
Entities, Entity, Join, Read, ReadStorage, System, WriteStorage,
};
use sphynx::{Uid, UidAllocator};
use std::time::Duration;
use vek::*;
/// This system is responsible for validating controller inputs
/// # Controller System
/// #### Responsible for validating controller inputs and setting new Character States
/// ----
///
/// **Writes:**
/// `CharacterState`, `ControllerInputs`
///
/// **Reads:**
/// `Stats`, `Vel`, `PhysicsState`, `Uid`, `Mounting`
///
/// _TODO: Join ActionStates and MovementStates into one and have a handle() trait / fn?_
/// _TODO: Move weapon action to trait fn?_
pub struct Sys;
impl Sys {
/// Assumes `input.primary` has been pressed
/// handles primary actions. ie. equipping, mainhand weapon attacks.
///
/// Returns the `ActionState` that occurred
fn handle_primary(
inputs: &mut ControllerInputs,
character: &mut CharacterState,
stats: &Stats,
entity: Entity,
uid: &Uid,
server_emitter: &mut Emitter<'_, ServerEvent>,
local_emitter: &mut Emitter<'_, LocalEvent>,
) -> ActionState {
match stats.equipment.main.as_ref().map(|i| &i.kind) {
// Character is wielding something
Some(ItemKind::Tool { kind, power, .. }) => {
let attack_duration = kind.attack_duration();
let wield_duration = kind.wield_duration();
// Since primary input was pressed, set
// action to new Wield, in case of
// instant primary actions
if character.action == Idle {
character.action = Wield {
time_left: wield_duration,
};
}
match kind {
item::Tool::Bow if character.action.is_action_finished() => {
// Immediately end the wield
server_emitter.emit(ServerEvent::Shoot {
entity,
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::Arrow),
light: None,
gravity: Some(comp::Gravity(0.3)),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Stick],
hit_wall: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(HealthChange {
amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid },
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(30),
},
});
character.action
}
item::Tool::Debug(item::Debug::Boost) => {
local_emitter.emit(LocalEvent::Boost {
entity,
vel: inputs.look_dir * 7.0,
});
character.action
}
item::Tool::Debug(item::Debug::Possess)
if character.action.is_action_finished() =>
{
server_emitter.emit(ServerEvent::Shoot {
entity,
gravity: Some(comp::Gravity(0.1)),
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::ArrowSnake),
light: Some(comp::LightEmitter {
col: (0.0, 1.0, 0.3).into(),
..Default::default()
}),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Stick],
hit_wall: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Stick,
projectile::Effect::Possess,
],
time_left: Duration::from_secs(10),
},
});
character.action
}
// All other weapons
_ if character.action.is_action_finished() => Attack {
time_left: attack_duration,
applied: false,
},
_ => {
// Return the new Wield action
character.action
}
}
}
// Without a weapon
None => {
// Attack
if !character.action.is_attack() {
Attack {
time_left: Duration::from_millis(100),
applied: false,
}
} else {
character.action
}
}
_ => character.action,
}
}
/// Assumes `input.seconday` has been pressed
/// handles seconday actions. ie. blocking, althand weapons
///
/// Returns the `ActionState` that occurred
fn handle_secondary(
inputs: &mut ControllerInputs,
character: &mut CharacterState,
stats: &Stats,
entity: Entity,
uid: &Uid,
server_emitter: &mut Emitter<'_, ServerEvent>,
local_emitter: &mut Emitter<'_, LocalEvent>,
) -> ActionState {
match stats.equipment.main.as_ref().map(|i| &i.kind) {
// Character is wielding something
Some(ItemKind::Tool { kind, power, .. }) => {
let attack_duration = kind.attack_duration();
let wield_duration = kind.wield_duration();
// Since primary input was pressed, set
// action to new Wield, in case of
// instant primary actions
if character.action == Idle {
character.action = Wield {
time_left: wield_duration,
};
}
match kind {
// Magical Bolt
item::Tool::Staff
if character.movement == Stand && character.action.is_action_finished() =>
{
server_emitter.emit(ServerEvent::Shoot {
entity,
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::BoltFire),
gravity: Some(comp::Gravity(0.0)),
light: Some(comp::LightEmitter {
col: (0.72, 0.11, 0.11).into(),
strength: 10.0,
offset: Vec3::new(0.0, -5.0, 2.0),
}),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Vanish],
hit_wall: vec![projectile::Effect::Vanish],
hit_entity: vec![
projectile::Effect::Damage(HealthChange {
amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid },
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(5),
},
});
// TODO: Don't play melee animation
Attack {
time_left: attack_duration,
applied: true, // We don't want to do a melee attack
}
}
// Go upward
item::Tool::Debug(item::Debug::Boost) => {
local_emitter.emit(LocalEvent::Boost {
entity,
vel: Vec3::new(0.0, 0.0, 7.0),
});
character.action
}
// All other weapons block
_ if character.action.is_action_finished() => Block {
time_active: Duration::from_secs(0),
},
_ => character.action,
}
}
_ => character.action,
}
}
}
impl<'a> System<'a> for Sys {
type SystemData = (
Read<'a, UidAllocator>,
Entities<'a>,
Read<'a, UidAllocator>,
Read<'a, EventBus<ServerEvent>>,
Read<'a, EventBus<LocalEvent>>,
Read<'a, DeltaTime>,
WriteStorage<'a, Controller>,
WriteStorage<'a, CharacterState>,
ReadStorage<'a, Stats>,
ReadStorage<'a, Body>,
ReadStorage<'a, Vel>,
ReadStorage<'a, PhysicsState>,
ReadStorage<'a, Uid>,
WriteStorage<'a, CharacterState>,
ReadStorage<'a, Mounting>,
);
fn run(
&mut self,
(
uid_allocator,
entities,
uid_allocator,
server_bus,
local_bus,
dt,
mut controllers,
mut character_states,
stats,
bodies,
velocities,
physics_states,
uids,
mut character_states,
mountings,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
let mut local_emitter = local_bus.emitter();
for (entity, uid, controller, stats, body, vel, physics, mut character) in (
for (entity, uid, controller, mut character, stats, body, vel, physics, mount) in (
&entities,
&uids,
&mut controllers,
&mut character_states,
&stats,
&bodies,
&velocities,
&physics_states,
&mut character_states,
mountings.maybe(),
)
.join()
{
let mut inputs = &mut controller.inputs;
let inputs = &mut controller.inputs;
// ---------------------------------------
// Common actions for multiple states as closure fn's for convenience
// Returns a Wield action, or Idle if nothing to wield
let try_wield = |stats: &Stats| -> ActionState {
// Get weapon to wield
if let Some(ItemKind::Tool { kind, .. }) =
stats.equipment.main.as_ref().map(|i| &i.kind)
{
let wield_duration = kind.wield_duration();
Wield {
time_left: wield_duration,
}
} else {
Idle
}
};
let get_state_from_move_dir = |move_dir: &Vec2<f32>| -> MovementState {
if move_dir.magnitude_squared() > 0.0 {
Run
} else {
Stand
}
};
// End common actions
// ---------------------------------------
// Being dead overrides all other states
if stats.is_dead {
// Respawn
if inputs.respawn.is_pressed() {
// Only options: click respawn
// prevent instant-respawns (i.e. player was holding attack)
// by disallowing while input is held down
if inputs.respawn.is_pressed() && !inputs.respawn.is_held_down() {
server_emitter.emit(ServerEvent::Respawn(entity));
}
// Or do nothing
continue;
}
// If mounted, character state is controlled by mount
if mount.is_some() {
character.movement = Sit;
continue;
}
// Move
inputs.move_dir = if inputs.move_dir.magnitude_squared() > 1.0 {
inputs.move_dir.normalized()
} else {
inputs.move_dir
match (character.action, character.movement) {
// Jumping, one frame state that calls jump server event
(_, Jump) => {
inputs.update_look_dir();
inputs.update_move_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
character.movement = Fall;
local_emitter.emit(LocalEvent::Jump(entity));
}
// Charging + Any Movement, prioritizes finishing charge
// over movement states
(Charge { time_left }, _) => {
println!("{:?}", character);
inputs.update_move_dir();
if time_left == Duration::default() || vel.0.magnitude_squared() < 10.0 {
character.action = try_wield(stats);
} else {
character.action = Charge {
time_left: time_left
.checked_sub(Duration::from_secs_f32(dt.0))
.unwrap_or_default(),
};
}
if let Some(uid_b) = physics.touch_entity {
server_emitter.emit(ServerEvent::Damage {
uid: uid_b,
change: HealthChange {
amount: -20,
cause: HealthSource::Attack { by: *uid },
},
});
character.action = try_wield(stats);
}
}
// Rolling + Any Movement, prioritizes finishing charge
// over movement states
(Roll { time_left }, _) => {
if time_left == Duration::default() {
character.action = try_wield(stats);
} else {
character.action = Roll {
time_left: time_left
.checked_sub(Duration::from_secs_f32(dt.0))
.unwrap_or_default(),
}
}
}
// Any Action + Falling
(action_state, Fall) => {
inputs.update_move_dir();
inputs.update_look_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
// Reset to Falling while not standing on ground,
// otherwise keep the state given above
if !physics.on_ground {
if physics.in_fluid {
character.movement = Swim;
} else {
character.movement = Fall;
}
}
if inputs.glide.is_pressed() && !inputs.glide.is_held_down() {
character.movement = Glide;
continue;
}
match action_state {
// Unwield if buttons pressed
Wield { .. } | Attack { .. } => {
if inputs.toggle_wield.is_just_pressed() {
character.action = Idle;
}
}
// Try to wield if any of buttons pressed
Idle => {
if inputs.primary.is_pressed() || inputs.secondary.is_pressed() {
character.action = try_wield(stats);
}
}
// Cancel blocks
Block { .. } => {
character.action = try_wield(stats);
}
// Don't change action
Charge { .. } | Roll { .. } => {}
}
}
// Any Action + Swimming
(_action_state, Swim) => {
inputs.update_move_dir();
inputs.update_look_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
if !physics.on_ground && physics.in_fluid {
character.movement = Swim;
}
if inputs.primary.is_pressed() {
character.action = Self::handle_primary(
inputs,
character,
stats,
entity,
uid,
&mut server_emitter,
&mut local_emitter,
);
} else if inputs.secondary.is_pressed() {
character.action = Self::handle_secondary(
inputs,
character,
stats,
entity,
uid,
&mut server_emitter,
&mut local_emitter,
);
}
}
// Blocking, restricted look_dir compared to other states
(Block { .. }, Stand) | (Block { .. }, Run) => {
inputs.update_move_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
if !inputs.secondary.is_pressed() {
character.action = try_wield(stats);
} else {
character.action = Self::handle_secondary(
inputs,
character,
stats,
entity,
uid,
&mut server_emitter,
&mut local_emitter,
);
}
if !physics.on_ground && physics.in_fluid {
character.movement = Swim;
}
}
// Standing and Running states, typical states :shrug:
(action_state, Run) | (action_state, Stand) => {
inputs.update_move_dir();
inputs.update_look_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
// Try to sit
if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() {
character.movement = Sit;
continue;
}
// Try to climb
if let (true, Some(_wall_dir)) = (
inputs.climb.is_pressed() | inputs.climb_down.is_pressed()
&& body.is_humanoid(),
physics.on_wall,
) {
character.movement = Climb;
continue;
}
// Try to swim
if !physics.on_ground && physics.in_fluid {
character.movement = Swim;
continue;
}
// While on ground ...
if physics.on_ground {
// Try to jump
if inputs.jump.is_pressed() && !inputs.jump.is_held_down() {
character.movement = Jump;
continue;
}
// Try to charge
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
character.action = Charge {
time_left: Duration::from_millis(250),
};
continue;
}
// Try to roll
if character.movement == Run
&& inputs.roll.is_pressed()
&& body.is_humanoid()
{
character.action = Roll {
time_left: ROLL_DURATION,
};
continue;
}
}
// While not on ground ...
else {
// Try to glide
if physics.on_wall == None
&& inputs.glide.is_pressed()
&& !inputs.glide.is_held_down()
&& body.is_humanoid()
{
character.movement = Glide;
continue;
}
}
// Tool Actions
if inputs.toggle_wield.is_just_pressed() {
match action_state {
Wield { .. } | Attack { .. } => {
// Prevent instantaneous reequipping by checking
// for done wielding
if character.action.is_action_finished() {
character.action = Idle;
}
continue;
}
Idle => {
character.action = try_wield(stats);
}
Charge { .. } | Roll { .. } | Block { .. } => {}
}
}
if inputs.primary.is_pressed() {
character.action = Self::handle_primary(
inputs,
character,
stats,
entity,
uid,
&mut server_emitter,
&mut local_emitter,
);
} else if inputs.secondary.is_pressed() {
character.action = Self::handle_secondary(
inputs,
character,
stats,
entity,
uid,
&mut server_emitter,
&mut local_emitter,
);
}
}
// Sitting
(Idle, Sit) => {
inputs.update_move_dir();
character.movement = get_state_from_move_dir(&inputs.move_dir);
// character.movement will be Stand after updating when
// no movement has occurred
if character.movement == Stand {
character.movement = Sit;
}
if inputs.jump.is_pressed() && !inputs.jump.is_held_down() {
character.movement = Jump;
continue;
}
if !physics.on_ground {
character.movement = Fall;
}
}
// Any Action + Gliding, shouldnt care about action,
// because should be Idle
(_, Glide) => {
character.action = Idle;
inputs.update_look_dir();
inputs.update_move_dir();
if !inputs.glide.is_pressed() {
character.movement = Fall;
} else if let Some(_wall_dir) = physics.on_wall {
character.movement = Fall;
}
if physics.on_ground {
character.movement = Stand
}
}
// Any Action + Climbing, shouldnt care about action,
// because should be Idle
(_, Climb) => {
if let None = physics.on_wall {
if physics.on_ground {
character.movement = Stand;
} else if inputs.jump.is_pressed() && !inputs.jump.is_held_down() {
character.movement = Jump;
} else {
character.movement = Fall;
}
}
}
// In case of adding new states
(_, _) => {
println!("UNKNOWN STATE");
character.action = Idle;
character.movement = Fall;
}
};
if character.movement == Stand && inputs.move_dir.magnitude_squared() > 0.0 {
character.movement = Run;
} else if character.movement == Run && inputs.move_dir.magnitude_squared() == 0.0 {
character.movement = Stand;
}
// Look
inputs.look_dir = inputs
.look_dir
.try_normalized()
.unwrap_or(inputs.move_dir.into());
// Glide
// TODO: Check for glide ability/item
if inputs.glide.is_pressed()
&& !physics.on_ground
&& (character.action == Idle || character.action.is_wield())
&& character.movement == Jump
&& body.is_humanoid()
{
character.movement = Glide;
} else if !inputs.glide.is_pressed() && character.movement == Glide {
// character.movement = Jump;
}
// Sit
if inputs.sit.is_pressed()
&& physics.on_ground
&& character.action == Idle
&& character.movement != Sit
&& body.is_humanoid()
{
character.movement = Sit;
} else if character.movement == Sit
&& (inputs.move_dir.magnitude_squared() > 0.0 || !physics.on_ground)
{
character.movement = Run;
}
// Wield
if inputs.primary.is_pressed()
&& character.action == Idle
&& (character.movement == Stand || character.movement == Run)
{
character.action = Wield {
time_left: WIELD_DURATION,
};
}
match stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(ItemKind::Tool {
kind: item::Tool::Bow,
power,
..
}) => {
if inputs.primary.is_pressed()
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
{
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
// Immediately end the wield
character.action = Idle;
server_emitter.emit(ServerEvent::Shoot {
entity,
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::Arrow),
light: None,
gravity: Some(comp::Gravity(0.3)),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Stick],
hit_wall: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Damage(HealthChange {
amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid },
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(30),
},
});
}
}
}
}
Some(ItemKind::Tool {
kind: item::Tool::Staff,
power,
..
}) => {
// Melee Attack
if inputs.primary.is_pressed()
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
{
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
character.action = Attack {
time_left: ATTACK_DURATION,
applied: false,
};
}
}
}
// Magical Bolt
if inputs.secondary.is_pressed()
&& (
character.movement == Stand
//|| character.movement == Run
//|| character.movement == Jump
)
{
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
character.action = Attack {
time_left: ATTACK_DURATION,
applied: false,
};
server_emitter.emit(ServerEvent::Shoot {
entity,
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::BoltFire),
gravity: Some(comp::Gravity(0.0)),
light: Some(comp::LightEmitter {
col: (0.72, 0.11, 0.11).into(),
strength: 10.0,
offset: Vec3::new(0.0, -5.0, 2.0),
}),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Vanish],
hit_wall: vec![projectile::Effect::Vanish],
hit_entity: vec![
projectile::Effect::Damage(HealthChange {
amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid },
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(5),
},
});
}
}
}
}
Some(ItemKind::Tool {
kind: item::Tool::Debug(item::Debug::Boost),
..
}) => {
if inputs.primary.is_pressed() {
local_emitter.emit(LocalEvent::Boost {
entity,
vel: inputs.look_dir * 7.0,
});
}
if inputs.secondary.is_pressed() {
// Go upward
local_emitter.emit(LocalEvent::Boost {
entity,
vel: Vec3::new(0.0, 0.0, 7.0),
});
}
}
Some(ItemKind::Tool {
kind: item::Tool::Debug(item::Debug::Possess),
..
}) => {
if inputs.primary.is_pressed()
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
{
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
// Immediately end the wield
character.action = Idle;
server_emitter.emit(ServerEvent::Shoot {
entity,
gravity: Some(comp::Gravity(0.1)),
dir: inputs.look_dir,
body: comp::Body::Object(comp::object::Body::ArrowSnake),
light: Some(comp::LightEmitter {
col: (0.0, 1.0, 0.3).into(),
..Default::default()
}),
projectile: Projectile {
owner: *uid,
hit_ground: vec![projectile::Effect::Stick],
hit_wall: vec![projectile::Effect::Stick],
hit_entity: vec![
projectile::Effect::Stick,
projectile::Effect::Possess,
],
time_left: Duration::from_secs(10),
},
});
}
}
}
// Block
if inputs.secondary.is_pressed()
&& (character.movement == Stand || character.movement == Run)
&& character.action.is_wield()
{
character.action = Block {
time_left: Duration::from_secs(5),
};
} else if !inputs.secondary.is_pressed() && character.action.is_block() {
character.action = Wield {
time_left: Duration::default(),
};
}
}
// All other tools
Some(ItemKind::Tool { .. }) => {
// Attack
if inputs.primary.is_pressed()
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
{
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
character.action = Attack {
time_left: ATTACK_DURATION,
applied: false,
};
}
}
}
// Block
if inputs.secondary.is_pressed()
&& (character.movement == Stand || character.movement == Run)
&& character.action.is_wield()
{
character.action = Block {
time_left: Duration::from_secs(5),
};
} else if !inputs.secondary.is_pressed() && character.action.is_block() {
character.action = Wield {
time_left: Duration::default(),
};
}
}
None => {
// Attack
if inputs.primary.is_pressed()
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
&& !character.action.is_attack()
{
character.action = Attack {
time_left: ATTACK_DURATION,
applied: false,
};
}
}
_ => {}
}
// Roll
if inputs.roll.is_pressed()
&& (character.action == Idle || character.action.is_wield())
&& character.movement == Run
&& physics.on_ground
{
character.movement = Roll {
time_left: ROLL_DURATION,
};
}
// Jump
if (inputs.jump.is_pressed() && !inputs.jump.is_held_down())
&& physics.on_ground
&& vel.0.z <= 0.0
&& !character.movement.is_roll()
|| (inputs.jump.is_pressed() && character.movement == Swim)
{
local_emitter.emit(LocalEvent::Jump(entity));
}
// Wall leap
if inputs.wall_leap.is_pressed() {
if let (Some(_wall_dir), Climb) = (physics.on_wall, character.movement) {
//local_emitter.emit(LocalEvent::WallLeap { entity, wall_dir });
}
}
if let (true, Wield { .. }) = (inputs.toggle_wield.is_pressed(), character.action) {
character.action = Idle;
}
// Process controller events
// Process other controller events
for event in controller.events.drain(..) {
match event {
ControlEvent::Mount(mountee_uid) => {

View File

@ -1,17 +1,18 @@
use super::phys::GRAVITY;
use crate::{
comp::{
ActionState::*, CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState,
Pos, Stats, Vel,
CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, Stats, Vel,
},
event::{EventBus, ServerEvent},
state::DeltaTime,
terrain::TerrainGrid,
};
use specs::prelude::*;
use sphynx::Uid;
use std::time::Duration;
use vek::*;
pub const ROLL_DURATION: Duration = Duration::from_millis(600);
pub const ROLL_DURATION: Duration = Duration::from_millis(250);
const HUMANOID_ACCEL: f32 = 50.0;
const HUMANOID_SPEED: f32 = 120.0;
@ -20,7 +21,8 @@ const HUMANOID_AIR_SPEED: f32 = 100.0;
const HUMANOID_WATER_ACCEL: f32 = 70.0;
const HUMANOID_WATER_SPEED: f32 = 120.0;
const HUMANOID_CLIMB_ACCEL: f32 = 5.0;
const ROLL_SPEED: f32 = 13.0;
const ROLL_SPEED: f32 = 17.0;
const CHARGE_SPEED: f32 = 20.0;
const GLIDE_ACCEL: f32 = 15.0;
const GLIDE_SPEED: f32 = 45.0;
const BLOCK_ACCEL: f32 = 30.0;
@ -31,20 +33,31 @@ const CLIMB_SPEED: f32 = 5.0;
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
/// This system applies forces and calculates new positions and velocities.
/// # Movement System
/// #### Applies forces, calculates new positions and velocities,7
/// #### based on Controller(Inputs) and CharacterState.
/// ----
///
/// **Writes:**
/// Pos, Vel, Ori
///
/// **Reads:**
/// Uid, Stats, Controller, PhysicsState, CharacterState, Mounting
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
ReadExpect<'a, TerrainGrid>,
Read<'a, EventBus<ServerEvent>>,
Read<'a, DeltaTime>,
ReadStorage<'a, Stats>,
ReadStorage<'a, Controller>,
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, CharacterState>,
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
ReadStorage<'a, Uid>,
ReadStorage<'a, Stats>,
ReadStorage<'a, Controller>,
ReadStorage<'a, PhysicsState>,
ReadStorage<'a, CharacterState>,
ReadStorage<'a, Mounting>,
);
@ -53,37 +66,41 @@ impl<'a> System<'a> for Sys {
(
entities,
_terrain,
_server_bus,
dt,
stats,
controllers,
physics_states,
mut character_states,
mut positions,
mut velocities,
mut orientations,
uids,
stats,
controllers,
physics_states,
character_states,
mountings,
): Self::SystemData,
) {
// Apply movement inputs
for (
_entity,
stats,
controller,
physics,
mut character,
mut _pos,
mut vel,
mut ori,
mounting,
_uid,
stats,
controller,
physics,
character,
mount,
) in (
&entities,
&stats,
&controllers,
&physics_states,
&mut character_states,
&mut positions,
&mut velocities,
&mut orientations,
&uids,
&stats,
&controllers,
&physics_states,
&character_states,
mountings.maybe(),
)
.join()
@ -92,22 +109,27 @@ impl<'a> System<'a> for Sys {
continue;
}
if mounting.is_some() {
character.movement = Sit;
if mount.is_some() {
continue;
}
let inputs = &controller.inputs;
if character.movement.is_roll() {
if character.action.is_roll() {
vel.0 = Vec3::new(0.0, 0.0, vel.0.z)
+ (vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5 * inputs.move_dir.try_normalized().unwrap_or_default())
.try_normalized()
.unwrap_or_default()
* ROLL_SPEED;
}
if character.action.is_block() || character.action.is_attack() {
} else if character.action.is_charge() {
vel.0 = Vec3::new(0.0, 0.0, vel.0.z)
+ (vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5 * inputs.move_dir.try_normalized().unwrap_or_default())
.try_normalized()
.unwrap_or_default()
* CHARGE_SPEED;
} else if character.action.is_block() {
vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir
* match physics.on_ground {
@ -143,10 +165,9 @@ impl<'a> System<'a> for Sys {
}
// Set direction based on move direction when on the ground
let ori_dir = if character.action.is_wield()
|| character.action.is_attack()
|| character.action.is_block()
{
let ori_dir = if
//character.action.is_wield() ||
character.action.is_attack() || character.action.is_block() {
Vec2::from(inputs.look_dir).normalized()
} else if let (Climb, Some(wall_dir)) = (character.movement, physics.on_wall) {
if Vec2::<f32>::from(wall_dir).magnitude_squared() > 0.001 {
@ -174,7 +195,6 @@ impl<'a> System<'a> for Sys {
&& Vec2::<f32>::from(vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)
&& vel.0.z < 0.0
{
character.action = Idle;
let lift = GLIDE_ANTIGRAV + vel.0.z.abs().powf(2.0) * 0.15;
vel.0.z += dt.0
* lift
@ -183,18 +203,6 @@ impl<'a> System<'a> for Sys {
.max(0.2);
}
// Roll
if let Roll { time_left } = &mut character.movement {
character.action = Idle;
if *time_left == Duration::default() || vel.0.magnitude_squared() < 10.0 {
character.movement = Run;
} else {
*time_left = time_left
.checked_sub(Duration::from_secs_f32(dt.0))
.unwrap_or_default();
}
}
// Climb
if let (true, Some(_wall_dir)) = (
(inputs.climb.is_pressed() | inputs.climb_down.is_pressed())
@ -213,34 +221,10 @@ impl<'a> System<'a> for Sys {
30.0 * dt.0 / (1.0 - vel.0.z.min(0.0) * 5.0),
);
}
character.movement = Climb;
character.action = Idle;
} else if let Climb = character.movement {
character.movement = Jump;
}
if physics.on_ground
&& (character.movement == Jump
|| character.movement == Climb
|| character.movement == Glide
|| character.movement == Swim)
{
character.movement = Stand;
}
if !physics.on_ground
&& (character.movement == Stand
|| character.movement.is_roll()
|| character.movement == Run)
{
character.movement = Jump;
}
if !physics.on_ground && physics.in_fluid {
character.movement = Swim;
} else if let Swim = character.movement {
character.movement = Stand;
if character.movement == Swim && inputs.jump.is_pressed() {
vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED);
}
}
}

View File

@ -353,6 +353,8 @@ impl<'a> System<'a> for Sys {
)
.join()
{
physics.touch_entity = None;
let scale = scale.map(|s| s.0).unwrap_or(1.0);
let mass = mass.map(|m| m.0).unwrap_or(scale);

View File

@ -87,15 +87,15 @@ impl Animation for AttackAnimation {
//next.r_foot.ori = Quaternion::rotation_x(wave_stop_quick * 1.2);
//next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-8.0 + wave_quicken_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + wave_quicken_double * 3.0,
0.0,
);
next.weapon.ori = Quaternion::rotation_z(-0.8)
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + wave_quicken * -0.8)
* Quaternion::rotation_y(0.0 + wave_quicken * -0.4);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -105,9 +105,13 @@ impl Animation for AttackAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_z(wave_stop_quick * -0.2)

View File

@ -72,15 +72,15 @@ impl Animation for BlockAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Axe) => {
next.l_hand.offset = Vec3::new(
@ -97,15 +97,15 @@ impl Animation for BlockAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Hammer) => {
next.l_hand.offset = Vec3::new(-7.0, 3.5, 6.5);
@ -118,15 +118,15 @@ impl Animation for BlockAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.2);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
5.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(-0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Staff) => {
next.l_hand.offset = Vec3::new(
@ -143,15 +143,15 @@ impl Animation for BlockAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Shield) => {
next.l_hand.offset = Vec3::new(
@ -168,15 +168,15 @@ impl Animation for BlockAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Bow) => {
next.l_hand.offset = Vec3::new(
@ -193,15 +193,15 @@ impl Animation for BlockAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Dagger) => {
next.l_hand.offset = Vec3::new(
@ -214,15 +214,15 @@ impl Animation for BlockAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Debug(_)) => {
next.l_hand.offset = Vec3::new(-7.0, 3.5, 6.5);
@ -235,15 +235,15 @@ impl Animation for BlockAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.2);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
5.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(-0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
_ => {}
}
@ -263,9 +263,13 @@ impl Animation for BlockAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -71,15 +71,15 @@ impl Animation for BlockIdleAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Axe) => {
next.l_hand.offset = Vec3::new(
@ -96,15 +96,15 @@ impl Animation for BlockIdleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Hammer) => {
next.l_hand.offset = Vec3::new(-7.0, 3.5 + wave_ultra_slow * 2.0, 6.5);
@ -117,15 +117,15 @@ impl Animation for BlockIdleAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.2);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + wave_ultra_slow * 2.0 + skeleton_attr.weapon_y,
5.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(-0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Staff) => {
next.l_hand.offset = Vec3::new(
@ -142,15 +142,15 @@ impl Animation for BlockIdleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Shield) => {
next.l_hand.offset = Vec3::new(
@ -167,15 +167,15 @@ impl Animation for BlockIdleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Bow) => {
next.l_hand.offset = Vec3::new(
@ -192,15 +192,15 @@ impl Animation for BlockIdleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Dagger) => {
next.l_hand.offset = Vec3::new(
@ -213,15 +213,15 @@ impl Animation for BlockIdleAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Debug(_)) => {
next.l_hand.offset = Vec3::new(-7.0, 3.5 + wave_ultra_slow * 2.0, 6.5);
@ -234,15 +234,15 @@ impl Animation for BlockIdleAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.2);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + wave_ultra_slow * 2.0 + skeleton_attr.weapon_y,
5.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(-0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
_ => {}
}
@ -262,9 +262,13 @@ impl Animation for BlockIdleAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -0,0 +1,111 @@
use super::{
super::{Animation, SkeletonAttr},
CharacterSkeleton,
};
use common::comp::item::Tool;
use std::f32::consts::PI;
use vek::*;
pub struct Input {
pub attack: bool,
}
pub struct ChargeAnimation;
impl Animation for ChargeAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = (Option<Tool>, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
(_active_tool_kind, _global_time): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave_stop_quick = (anim_time as f32 * 8.0).min(PI / 2.0).sin();
let constant = 8.0;
let wave_cos = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 2.4).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * constant as f32 * 1.5).sin());
let wave_cos_dub = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 4.8).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * constant as f32 * 1.5).sin());
next.head.offset = Vec3::new(
0.0 + skeleton_attr.neck_right,
5.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 19.0 + wave_cos * 2.0,
);
next.head.ori =
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0);
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_cos * 2.0);
next.chest.ori = Quaternion::rotation_x(-0.7) * Quaternion::rotation_z(-0.9);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0, 5.0 + wave_cos * 2.0);
next.belt.ori = Quaternion::rotation_x(-0.6) * Quaternion::rotation_z(-0.9);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, 0.0, 2.0 + wave_cos * 2.0);
next.shorts.ori = Quaternion::rotation_x(-0.5) * Quaternion::rotation_z(-0.9);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(-8.0, -7.5, 5.0);
next.l_hand.ori = Quaternion::rotation_z(0.5)
* Quaternion::rotation_x(wave_stop_quick * -1.5 + 0.5 + 1.57)
* Quaternion::rotation_y(-0.6);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-8.0, -8.0, 3.0);
next.r_hand.ori = Quaternion::rotation_z(0.5)
* Quaternion::rotation_x(wave_stop_quick * -1.5 + 0.5 + 1.57)
* Quaternion::rotation_y(-0.6);
next.r_hand.scale = Vec3::one() * 1.01;
next.l_foot.offset = Vec3::new(-3.4, 0.0 + wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.l_foot.ori = Quaternion::rotation_x(-0.0 - wave_cos * 0.8);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 0.0 - wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 0.8);
next.r_foot.scale = Vec3::one();
next.main.offset = Vec3::new(
-8.0 + skeleton_attr.weapon_x,
0.0 + skeleton_attr.weapon_y,
5.0,
);
next.main.ori = Quaternion::rotation_z(-0.0)
* Quaternion::rotation_x(wave_stop_quick * -1.5 + 0.7)
* Quaternion::rotation_y(-0.5);
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.0, 0.1) * skeleton_attr.scaler;
next.torso.ori =
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -57,7 +57,7 @@ impl Animation for CidleAnimation {
next.belt.offset = Vec3::new(0.0 + wave_slow_cos * 0.5, 0.0, 5.0 + wave_ultra_slow * 0.5);
next.belt.ori = Quaternion::rotation_y(wave_ultra_slow_cos * 0.03);
next.belt.scale = Vec3::one();
next.belt.scale = Vec3::one() * 1.02;
next.shorts.offset = Vec3::new(0.0 + wave_slow_cos * 0.5, 0.0, 2.0 + wave_ultra_slow * 0.5);
next.shorts.ori = Quaternion::rotation_x(0.0);
@ -68,52 +68,54 @@ impl Animation for CidleAnimation {
Some(Tool::Sword) => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
-2.0 + wave_ultra_slow_cos * 0.5,
1.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.0;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
-2.5 + wave_ultra_slow_cos * 0.5,
-1.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
5.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
1.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Axe) => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
-6.5 + wave_ultra_slow_cos * 1.0,
-0.5 + wave_ultra_slow_cos * 0.5,
6.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.ori = Quaternion::rotation_x(0.13) * Quaternion::rotation_z(-0.25);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
-3.0 + wave_ultra_slow_cos * 1.0,
6.5 + wave_ultra_slow_cos * 0.5,
6.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.ori = Quaternion::rotation_x(0.13)
* Quaternion::rotation_z(2.98)
* Quaternion::rotation_y(-0.50);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
next.main.offset = Vec3::new(
-5.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
8.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
-0.5 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(1.27)
* Quaternion::rotation_y(0.0)
next.main.ori = Quaternion::rotation_x(1.70)
* Quaternion::rotation_y(-0.25)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Hammer) => {
next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
@ -126,15 +128,15 @@ impl Animation for CidleAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
-2.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.27)
* Quaternion::rotation_z(wave_ultra_slow * 0.2);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Staff) => {
next.l_hand.offset = Vec3::new(
@ -151,15 +153,15 @@ impl Animation for CidleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Shield) => {
next.l_hand.offset = Vec3::new(
@ -176,15 +178,15 @@ impl Animation for CidleAnimation {
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Bow) => {
next.l_hand.offset = Vec3::new(
@ -205,15 +207,15 @@ impl Animation for CidleAnimation {
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(0.85);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
9.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
10.0 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
-3.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(0.0)
next.main.ori = Quaternion::rotation_x(0.0)
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Dagger) => {
next.l_hand.offset = Vec3::new(
@ -226,15 +228,15 @@ impl Animation for CidleAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Debug(_)) => {
next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
@ -247,15 +249,15 @@ impl Animation for CidleAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
-2.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.27)
* Quaternion::rotation_z(wave_ultra_slow * 0.2);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
_ => {}
}
@ -275,9 +277,13 @@ impl Animation for CidleAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -78,14 +78,14 @@ impl Animation for ClimbAnimation {
next.r_foot.ori = Quaternion::rotation_x(0.2 + wave_testc * 0.5);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori =
next.main.ori =
Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15);
@ -95,9 +95,13 @@ impl Animation for ClimbAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0);

View File

@ -108,13 +108,13 @@ impl Animation for GlidingAnimation {
);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one();
next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -124,10 +124,14 @@ impl Animation for GlidingAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, -13.0 + wave_very_slow * 0.10, 6.0);
next.draw.ori =
next.glider.offset = Vec3::new(0.0, -13.0 + wave_very_slow * 0.10, 6.0);
next.glider.ori =
Quaternion::rotation_x(1.0) * Quaternion::rotation_y(wave_very_slow_cos * 0.04);
next.draw.scale = Vec3::one();
next.glider.scale = Vec3::one();
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 6.0, 15.0) / 11.0 * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(-0.05 * speed.max(12.0) + wave_very_slow * 0.10)

View File

@ -83,13 +83,13 @@ impl Animation for IdleAnimation {
next.r_foot.ori = Quaternion::identity();
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one() + wave_ultra_slow_abs * -0.05;
next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.main.scale = Vec3::one() + wave_ultra_slow_abs * -0.05;
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 5.0);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -99,9 +99,13 @@ impl Animation for IdleAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = (Vec3::one() + wave_ultra_slow_abs * -0.05) * 1.15;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -71,13 +71,13 @@ impl Animation for JumpAnimation {
next.r_foot.ori = Quaternion::rotation_x(wave_stop * 1.2 + wave_slow * 0.2);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one();
next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_stop_alt * 0.3);
@ -87,9 +87,13 @@ impl Animation for JumpAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(-wave_stop_alt * 0.3);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.0, 0.0) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(-0.2);

View File

@ -1,6 +1,7 @@
pub mod attack;
pub mod block;
pub mod blockidle;
pub mod charge;
pub mod cidle;
pub mod climb;
pub mod gliding;
@ -17,6 +18,7 @@ pub mod wield;
pub use self::attack::AttackAnimation;
pub use self::block::BlockAnimation;
pub use self::blockidle::BlockIdleAnimation;
pub use self::charge::ChargeAnimation;
pub use self::cidle::CidleAnimation;
pub use self::climb::ClimbAnimation;
pub use self::gliding::GlidingAnimation;
@ -42,10 +44,11 @@ pub struct CharacterSkeleton {
r_hand: Bone,
l_foot: Bone,
r_foot: Bone,
weapon: Bone,
main: Bone,
l_shoulder: Bone,
r_shoulder: Bone,
draw: Bone,
glider: Bone,
lantern: Bone,
torso: Bone,
}
@ -60,10 +63,11 @@ impl CharacterSkeleton {
r_hand: Bone::default(),
l_foot: Bone::default(),
r_foot: Bone::default(),
weapon: Bone::default(),
main: Bone::default(),
l_shoulder: Bone::default(),
r_shoulder: Bone::default(),
draw: Bone::default(),
glider: Bone::default(),
lantern: Bone::default(),
torso: Bone::default(),
}
}
@ -74,7 +78,8 @@ impl Skeleton for CharacterSkeleton {
let chest_mat = self.chest.compute_base_matrix();
let torso_mat = self.torso.compute_base_matrix();
let l_hand_mat = self.l_hand.compute_base_matrix();
let weapon_mat = self.weapon.compute_base_matrix();
let main_mat = self.main.compute_base_matrix();
let head_mat = self.head.compute_base_matrix();
[
FigureBoneData::new(torso_mat * head_mat),
@ -85,14 +90,14 @@ impl Skeleton for CharacterSkeleton {
FigureBoneData::new(torso_mat * chest_mat * self.r_hand.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * weapon_mat),
FigureBoneData::new(torso_mat * chest_mat * main_mat),
FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.draw.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.glider.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.lantern.compute_base_matrix()),
FigureBoneData::new(torso_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
]
}
@ -105,10 +110,11 @@ impl Skeleton for CharacterSkeleton {
self.r_hand.interpolate(&target.r_hand, dt);
self.l_foot.interpolate(&target.l_foot, dt);
self.r_foot.interpolate(&target.r_foot, dt);
self.weapon.interpolate(&target.weapon, dt);
self.main.interpolate(&target.main, dt);
self.l_shoulder.interpolate(&target.l_shoulder, dt);
self.r_shoulder.interpolate(&target.r_shoulder, dt);
self.draw.interpolate(&target.draw, dt);
self.glider.interpolate(&target.glider, dt);
self.lantern.interpolate(&target.lantern, dt);
self.torso.interpolate(&target.torso, dt);
}
}

View File

@ -74,15 +74,15 @@ impl Animation for RollAnimation {
next.r_foot.ori = Quaternion::rotation_x(wave * -0.4);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5)
next.main.ori = Quaternion::rotation_y(2.5)
* Quaternion::rotation_z(1.57)
* Quaternion::rotation_x(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -92,9 +92,13 @@ impl Animation for RollAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset =
Vec3::new(0.0, 11.0, 0.1 + wave_dub * 16.0) / 11.0 * skeleton_attr.scaler;

View File

@ -1,147 +0,0 @@
use super::{
super::{Animation, SkeletonAttr},
CharacterSkeleton,
};
use std::f32::consts::PI;
use std::ops::Mul;
use vek::*;
pub struct SneakAnimation;
impl Animation for SneakAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori, global_time): Self::Dependency,
anim_time: f64,
rate: &mut f32,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let speed = Vec2::<f32>::from(velocity).magnitude();
*rate = speed;
let constant = 1.0;
let wave = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 1.2).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * constant as f32 * 1.2).sin());
let wave_cos = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 2.4).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * constant as f32 * 1.5).sin());
let wave_cos_dub = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 4.8).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * constant as f32 * 1.5).sin());
let wave_diff = (anim_time as f32 * 0.6).sin();
let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin();
let head_look = Vec2::new(
((global_time + anim_time) as f32 / 4.0)
.floor()
.mul(7331.0)
.sin()
* 0.2,
((global_time + anim_time) as f32 / 4.0)
.floor()
.mul(1337.0)
.sin()
* 0.1,
);
let ori = Vec2::from(orientation);
let last_ori = Vec2::from(last_ori);
let tilt = if Vec2::new(ori, last_ori)
.map(|o| Vec2::<f32>::from(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.5)
* last_ori.determine_side(Vec2::zero(), ori).signum()
} else {
0.0
} * 1.3;
next.head.offset = Vec3::new(
0.0,
-3.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 20.0 + wave_cos * 1.3,
);
next.head.ori = Quaternion::rotation_z(head_look.x + wave * 0.1)
* Quaternion::rotation_x(head_look.y + 0.35);
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_cos * 1.1);
next.chest.ori = Quaternion::rotation_z(wave * 0.2);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0, 5.0 + wave_cos * 1.1);
next.belt.ori = Quaternion::rotation_z(wave * 0.35);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, 0.0, 2.0 + wave_cos * 1.1);
next.shorts.ori = Quaternion::rotation_z(wave * 0.6);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(
-6.0 + wave_stop * -1.0,
-0.25 + wave_cos * 2.0,
5.0 - wave * 1.5,
);
next.l_hand.ori =
Quaternion::rotation_x(0.8 + wave_cos * 1.2) * Quaternion::rotation_y(wave_stop * 0.1);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(
6.0 + wave_stop * 1.0,
-0.25 - wave_cos * 2.0,
5.0 + wave * 1.5,
);
next.r_hand.ori = Quaternion::rotation_x(0.8 + wave_cos * -1.2)
* Quaternion::rotation_y(wave_stop * -0.1);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.4, 0.0 + wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.l_foot.ori = Quaternion::rotation_x(-0.0 - wave_cos * 1.2);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 0.0 - wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 1.2);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori =
Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25);
next.weapon.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori =
Quaternion::rotation_x(wave_stop * speed * -0.06 + wave_diff * speed * -0.005)
* Quaternion::rotation_y(tilt);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -116,14 +116,14 @@ impl Animation for RunAnimation {
next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 1.2);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori =
next.main.ori =
Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15);
@ -133,9 +133,13 @@ impl Animation for RunAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 5.0, 0.0);
next.lantern.ori = Quaternion::rotation_y(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori =

View File

@ -98,13 +98,13 @@ impl Animation for SitAnimation {
);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one() + wave_slow_abs * -0.05;
next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.main.scale = Vec3::one() + wave_slow_abs * -0.05;
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -114,9 +114,13 @@ impl Animation for SitAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = (Vec3::one() + wave_slow_abs * -0.05) * 1.15;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, wave_stop * -0.16) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -111,14 +111,14 @@ impl Animation for SneakAnimation {
next.r_foot.ori = Quaternion::rotation_x(-0.8 - wavecos * 0.15);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori =
next.main.ori =
Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wavecos * 0.05);
@ -128,9 +128,13 @@ impl Animation for SneakAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.05);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 5.0, 0.0);
next.lantern.ori = Quaternion::rotation_y(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori =

View File

@ -82,13 +82,13 @@ impl Animation for StandAnimation {
next.r_foot.ori = Quaternion::identity();
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one() + wave_ultra_slow_abs * -0.05;
next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.main.scale = Vec3::one() + wave_ultra_slow_abs * -0.05;
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 5.0);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
@ -98,9 +98,13 @@ impl Animation for StandAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = (Vec3::one() + wave_ultra_slow_abs * -0.05) * 1.15;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.1, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);

View File

@ -99,14 +99,14 @@ impl Animation for SwimAnimation {
next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 1.5);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori =
next.main.ori =
Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15);
@ -116,9 +116,13 @@ impl Animation for SwimAnimation {
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 5.0, 0.0);
next.lantern.ori = Quaternion::rotation_y(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori =

View File

@ -3,6 +3,8 @@ use super::{
CharacterSkeleton,
};
use common::comp::item::Tool;
use std::f32::consts::PI;
use vek::*;
pub struct WieldAnimation;
@ -13,50 +15,55 @@ impl Animation for WieldAnimation {
fn update_skeleton(
skeleton: &Self::Skeleton,
(active_tool_kind, _velocity, _global_time): Self::Dependency,
(active_tool_kind, velocity, _global_time): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
rate: &mut f32,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 12.0).sin();
let speed = Vec2::<f32>::from(velocity).magnitude();
*rate = speed;
let wave = (anim_time as f32 * 1.0).sin();
let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin();
match active_tool_kind {
//TODO: Inventory
Some(Tool::Sword) => {
next.l_hand.offset = Vec3::new(-6.0, 3.75, 0.25);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.offset = Vec3::new(-6.0, -2.0, 1.0);
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.00;
next.r_hand.offset = Vec3::new(-6.0, -2.5, -1.0);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.0 + skeleton_attr.weapon_y,
0.0,
5.5 + skeleton_attr.weapon_y,
1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Axe) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.offset = Vec3::new(-6.5, -0.5, 6.0);
next.l_hand.ori = Quaternion::rotation_x(0.13) * Quaternion::rotation_z(-0.25);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.offset = Vec3::new(-3.0, 6.5, 6.0);
next.r_hand.ori = Quaternion::rotation_x(0.13)
* Quaternion::rotation_z(2.98)
* Quaternion::rotation_y(-0.50);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
next.main.offset = Vec3::new(
-5.0 + skeleton_attr.weapon_x,
8.5 + skeleton_attr.weapon_y,
-0.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
next.main.ori = Quaternion::rotation_x(1.70)
* Quaternion::rotation_y(-0.25)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Hammer) => {
next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
@ -69,15 +76,15 @@ impl Animation for WieldAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
-2.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.27)
* Quaternion::rotation_z(wave * -0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Staff) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
@ -86,15 +93,15 @@ impl Animation for WieldAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Shield) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
@ -103,15 +110,15 @@ impl Animation for WieldAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Bow) => {
next.l_hand.offset = Vec3::new(-4.0, 5.0, 0.0);
@ -124,15 +131,15 @@ impl Animation for WieldAnimation {
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(0.85);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
9.0 + skeleton_attr.weapon_x,
10.0 + skeleton_attr.weapon_y,
-3.0,
);
next.weapon.ori = Quaternion::rotation_x(0.0)
next.main.ori = Quaternion::rotation_x(0.0)
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(0.85);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Dagger) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
@ -141,15 +148,15 @@ impl Animation for WieldAnimation {
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
Some(Tool::Debug(_)) => {
next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
@ -162,19 +169,21 @@ impl Animation for WieldAnimation {
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
next.main.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
-2.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.27)
* Quaternion::rotation_z(wave * -0.25);
next.weapon.scale = Vec3::one();
next.main.scale = Vec3::one();
}
_ => {}
}
next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(wave_stop * -0.2);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -126,7 +126,7 @@ impl SfxEventMapper {
}
}
/// Voxygen has an existing list of character states via `MovementState::*` and `ActivityState::*`
/// Voxygen has an existing list of character states via `MovementState::*` and `ActionState::*`
/// however that list does not provide enough resolution to target specific entity events, such
/// as opening or closing the glider. These methods translate those entity states with some additional
/// data into more specific `SfxEvent`'s which we attach sounds to
@ -164,7 +164,7 @@ impl SfxEventMapper {
vel,
stats,
) {
(MovementState::Roll { .. }, ..) => SfxEvent::Roll,
(_, ActionState::Roll { .. }, ..) => SfxEvent::Roll,
(MovementState::Climb, ..) => SfxEvent::Climb,
(MovementState::Swim, ..) => SfxEvent::Swim,
(MovementState::Run, ..) => SfxEvent::Run,
@ -317,10 +317,10 @@ mod tests {
let result = SfxEventMapper::map_character_event(
&CharacterState {
movement: MovementState::Roll {
action: ActionState::Roll {
time_left: Duration::new(1, 0),
},
action: ActionState::Idle,
movement: MovementState::Run,
},
SfxEvent::Run,
Vec3::zero(),

View File

@ -132,7 +132,7 @@ impl FigureModelCache {
},
if camera_mode == CameraMode::FirstPerson
&& character_state
.map(|cs| cs.movement.is_roll())
.map(|cs| cs.action.is_roll())
.unwrap_or_default()
{
None
@ -140,7 +140,7 @@ impl FigureModelCache {
Some(humanoid_armor_hand_spec.mesh_left_hand(&body))
},
if character_state
.map(|cs| cs.movement.is_roll())
.map(|cs| cs.action.is_roll())
.unwrap_or_default()
{
None
@ -184,8 +184,8 @@ impl FigureModelCache {
),
CameraMode::FirstPerson => None,
},
Some(mesh_draw()),
None,
Some(mesh_glider()),
Some(mesh_lantern()),
None,
None,
None,

View File

@ -532,7 +532,10 @@ pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
}
// TODO: Inventory
pub fn mesh_draw() -> Mesh<FigurePipeline> {
pub fn mesh_glider() -> Mesh<FigurePipeline> {
load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0))
}
pub fn mesh_lantern() -> Mesh<FigurePipeline> {
load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0))
}

View File

@ -197,7 +197,7 @@ impl FigureMgr {
}
let target_base = match &character.movement {
Stand => anim::character::StandAnimation::update_skeleton(
Fall | Stand => anim::character::StandAnimation::update_skeleton(
&CharacterSkeleton::new(),
(active_tool_kind, time),
state.movement_time,
@ -218,13 +218,6 @@ impl FigureMgr {
&mut movement_animation_rate,
skeleton_attr,
),
Roll { .. } => anim::character::RollAnimation::update_skeleton(
&CharacterSkeleton::new(),
(active_tool_kind, time),
state.movement_time,
&mut movement_animation_rate,
skeleton_attr,
),
Glide => anim::character::GlidingAnimation::update_skeleton(
&CharacterSkeleton::new(),
(active_tool_kind, vel.0, ori.0, state.last_ori, time),
@ -254,7 +247,6 @@ impl FigureMgr {
skeleton_attr,
),
};
let target_bones = match (&character.movement, &character.action) {
(Stand, Wield { .. }) => anim::character::CidleAnimation::update_skeleton(
&target_base,
@ -286,6 +278,13 @@ impl FigureMgr {
&mut action_animation_rate,
skeleton_attr,
),
(_, Roll { .. }) => anim::character::RollAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
state.action_time,
&mut action_animation_rate,
skeleton_attr,
),
(_, Block { .. }) => anim::character::BlockAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
@ -293,10 +292,17 @@ impl FigureMgr {
&mut action_animation_rate,
skeleton_attr,
),
(_, Charge { .. }) => anim::character::ChargeAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
state.action_time,
&mut action_animation_rate,
skeleton_attr,
),
_ => target_base,
};
state.skeleton.interpolate(&target_bones, dt);
state.skeleton.interpolate(&target_bones, dt);
state.update(
renderer,
pos.0,

View File

@ -160,7 +160,7 @@ impl Scene {
.ecs()
.read_storage::<comp::CharacterState>()
.get(client.entity())
.map_or(false, |cs| cs.movement.is_roll());
.map_or(false, |cs| cs.action.is_roll());
let player_scale = match client
.state()

View File

@ -201,7 +201,11 @@ impl PlayState for SessionState {
.state()
.read_storage::<comp::CharacterState>()
.get(client.entity())
.map(|cs| cs.action.is_wield())
.map(|cs| {
cs.action.is_wield()
|| cs.action.is_block()
|| cs.action.is_attack()
})
.unwrap_or(false)
{
self.inputs.secondary.set_state(state);
@ -323,6 +327,9 @@ impl PlayState for SessionState {
Event::InputUpdate(GameInput::ToggleWield, state) => {
self.inputs.toggle_wield.set_state(state)
}
Event::InputUpdate(GameInput::Charge, state) => {
self.inputs.charge.set_state(state);
}
// Pass all other events to the scene
event => {

View File

@ -48,6 +48,7 @@ pub struct ControlSettings {
pub respawn: KeyMouse,
pub interact: KeyMouse,
pub toggle_wield: KeyMouse,
pub charge: KeyMouse,
}
impl Default for ControlSettings {
@ -87,6 +88,7 @@ impl Default for ControlSettings {
respawn: KeyMouse::Mouse(MouseButton::Left),
interact: KeyMouse::Key(VirtualKeyCode::E),
toggle_wield: KeyMouse::Key(VirtualKeyCode::T),
charge: KeyMouse::Key(VirtualKeyCode::V),
}
}
}

View File

@ -45,6 +45,7 @@ pub enum GameInput {
Respawn,
Interact,
ToggleWield,
Charge,
}
/// Represents an incoming event from the window.
@ -225,6 +226,9 @@ impl Window {
map.entry(settings.controls.toggle_wield)
.or_default()
.push(GameInput::ToggleWield);
map.entry(settings.controls.charge)
.or_default()
.push(GameInput::Charge);
let keypress_map = HashMap::new();