From 92d99af53c13dc8cd0855adde83b104f0b8027cf Mon Sep 17 00:00:00 2001 From: Adam Whitehurst Date: Tue, 3 Dec 2019 06:30:08 +0000 Subject: [PATCH] feat: weapon-type dependent wield and attack durations also some controller.rs cleanup --- common/src/comp/character_state.rs | 42 +- common/src/comp/controller.rs | 112 ++- common/src/comp/inventory/item.rs | 49 +- common/src/sys/agent.rs | 14 +- common/src/sys/combat.rs | 24 +- common/src/sys/controller.rs | 905 +++++++++++++++-------- common/src/sys/movement.rs | 124 ++-- common/src/sys/phys.rs | 2 + voxygen/src/anim/character/attack.rs | 16 +- voxygen/src/anim/character/block.rs | 58 +- voxygen/src/anim/character/blockidle.rs | 58 +- voxygen/src/anim/character/charge.rs | 111 +++ voxygen/src/anim/character/cidle.rs | 104 +-- voxygen/src/anim/character/climb.rs | 16 +- voxygen/src/anim/character/gliding.rs | 16 +- voxygen/src/anim/character/idle.rs | 16 +- voxygen/src/anim/character/jump.rs | 16 +- voxygen/src/anim/character/mod.rs | 26 +- voxygen/src/anim/character/roll.rs | 16 +- voxygen/src/anim/character/run - Copy.rs | 147 ---- voxygen/src/anim/character/run.rs | 16 +- voxygen/src/anim/character/sit.rs | 16 +- voxygen/src/anim/character/sneak.rs | 16 +- voxygen/src/anim/character/stand.rs | 16 +- voxygen/src/anim/character/swim.rs | 16 +- voxygen/src/anim/character/wield.rs | 95 +-- voxygen/src/audio/sfx/event_mapper.rs | 8 +- voxygen/src/scene/figure/cache.rs | 8 +- voxygen/src/scene/figure/load.rs | 5 +- voxygen/src/scene/figure/mod.rs | 26 +- voxygen/src/scene/mod.rs | 2 +- voxygen/src/session.rs | 9 +- voxygen/src/settings.rs | 2 + voxygen/src/window.rs | 4 + 34 files changed, 1257 insertions(+), 854 deletions(-) create mode 100644 voxygen/src/anim/character/charge.rs delete mode 100644 voxygen/src/anim/character/run - Copy.rs diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 6f43315145..4775add5bc 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -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)] diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index a152da7db7..34ac6859bc 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -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 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, pub look_dir: Vec3, } @@ -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()); } } diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index 5877d80475..ead09e314a 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -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, diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 1519f0722b..c1603a6bdc 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -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::::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::() < 0.3 + { // Fight (and slowly move closer) inputs.move_dir = Vec2::::from(target_pos.0 - pos.0).normalized() * 0.01; @@ -161,6 +165,8 @@ impl<'a> System<'a> for Sys { } } } + + controller.inputs = inputs; } } } diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index f4d1e04d8f..6a23de568f 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -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, .. }) = diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index fe9785fd73..9e506154f4 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -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>, Read<'a, EventBus>, + 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| -> 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) => { diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index 3a46178278..9c58fa116a 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -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>, 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::::from(wall_dir).magnitude_squared() > 0.001 { @@ -174,7 +195,6 @@ impl<'a> System<'a> for Sys { && Vec2::::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); } } } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 2558c82ec4..401d1631f1 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -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); diff --git a/voxygen/src/anim/character/attack.rs b/voxygen/src/anim/character/attack.rs index a67e023ae5..fa4594822f 100644 --- a/voxygen/src/anim/character/attack.rs +++ b/voxygen/src/anim/character/attack.rs @@ -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) diff --git a/voxygen/src/anim/character/block.rs b/voxygen/src/anim/character/block.rs index 37698addf4..d5770e49d7 100644 --- a/voxygen/src/anim/character/block.rs +++ b/voxygen/src/anim/character/block.rs @@ -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); diff --git a/voxygen/src/anim/character/blockidle.rs b/voxygen/src/anim/character/blockidle.rs index 6841013e0d..e2bfda6833 100644 --- a/voxygen/src/anim/character/blockidle.rs +++ b/voxygen/src/anim/character/blockidle.rs @@ -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); diff --git a/voxygen/src/anim/character/charge.rs b/voxygen/src/anim/character/charge.rs new file mode 100644 index 0000000000..3e39ee86fc --- /dev/null +++ b/voxygen/src/anim/character/charge.rs @@ -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, 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 + } +} diff --git a/voxygen/src/anim/character/cidle.rs b/voxygen/src/anim/character/cidle.rs index 126331f060..165331fc7d 100644 --- a/voxygen/src/anim/character/cidle.rs +++ b/voxygen/src/anim/character/cidle.rs @@ -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); diff --git a/voxygen/src/anim/character/climb.rs b/voxygen/src/anim/character/climb.rs index 9866e8beca..84de64db14 100644 --- a/voxygen/src/anim/character/climb.rs +++ b/voxygen/src/anim/character/climb.rs @@ -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); diff --git a/voxygen/src/anim/character/gliding.rs b/voxygen/src/anim/character/gliding.rs index ce455200c8..d78f8a1142 100644 --- a/voxygen/src/anim/character/gliding.rs +++ b/voxygen/src/anim/character/gliding.rs @@ -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) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index cf40e1f7f6..10a7d58c4f 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -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); diff --git a/voxygen/src/anim/character/jump.rs b/voxygen/src/anim/character/jump.rs index ad4a2ca3b1..29fb164d83 100644 --- a/voxygen/src/anim/character/jump.rs +++ b/voxygen/src/anim/character/jump.rs @@ -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); diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 3a8f50d91a..086c63ea68 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -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); } } diff --git a/voxygen/src/anim/character/roll.rs b/voxygen/src/anim/character/roll.rs index de5dc75681..92e6149e2e 100644 --- a/voxygen/src/anim/character/roll.rs +++ b/voxygen/src/anim/character/roll.rs @@ -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; diff --git a/voxygen/src/anim/character/run - Copy.rs b/voxygen/src/anim/character/run - Copy.rs deleted file mode 100644 index 6e0a6aff0b..0000000000 --- a/voxygen/src/anim/character/run - Copy.rs +++ /dev/null @@ -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, Vec3, Vec3, 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::::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::::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 - } -} diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 8bca1b5006..38fdc58728 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -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 = diff --git a/voxygen/src/anim/character/sit.rs b/voxygen/src/anim/character/sit.rs index 78d36415df..2f1106eb2c 100644 --- a/voxygen/src/anim/character/sit.rs +++ b/voxygen/src/anim/character/sit.rs @@ -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); diff --git a/voxygen/src/anim/character/sneak.rs b/voxygen/src/anim/character/sneak.rs index 263afc4350..d48d9604d5 100644 --- a/voxygen/src/anim/character/sneak.rs +++ b/voxygen/src/anim/character/sneak.rs @@ -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 = diff --git a/voxygen/src/anim/character/stand.rs b/voxygen/src/anim/character/stand.rs index d5367d3708..c7f5a47efb 100644 --- a/voxygen/src/anim/character/stand.rs +++ b/voxygen/src/anim/character/stand.rs @@ -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); diff --git a/voxygen/src/anim/character/swim.rs b/voxygen/src/anim/character/swim.rs index 4769ea18cb..e22b827071 100644 --- a/voxygen/src/anim/character/swim.rs +++ b/voxygen/src/anim/character/swim.rs @@ -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 = diff --git a/voxygen/src/anim/character/wield.rs b/voxygen/src/anim/character/wield.rs index e5cab13d20..9c4d41c10a 100644 --- a/voxygen/src/anim/character/wield.rs +++ b/voxygen/src/anim/character/wield.rs @@ -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::::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 } } diff --git a/voxygen/src/audio/sfx/event_mapper.rs b/voxygen/src/audio/sfx/event_mapper.rs index 656c303eea..b03acf4e83 100644 --- a/voxygen/src/audio/sfx/event_mapper.rs +++ b/voxygen/src/audio/sfx/event_mapper.rs @@ -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(), diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index eb3874c159..54fe68a2d5 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -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, diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 18a0656ea4..fe553db45a 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -532,7 +532,10 @@ pub fn mesh_main(item: Option<&Item>) -> Mesh { } // TODO: Inventory -pub fn mesh_draw() -> Mesh { +pub fn mesh_glider() -> Mesh { + load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0)) +} +pub fn mesh_lantern() -> Mesh { load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0)) } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 2bbae70395..3ef4397fc8 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -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, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 03f48c0d4b..a98e30c436 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -160,7 +160,7 @@ impl Scene { .ecs() .read_storage::() .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() diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index ca422fcda1..7aee3cb17f 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -201,7 +201,11 @@ impl PlayState for SessionState { .state() .read_storage::() .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 => { diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index d37829a640..af353a0e9f 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -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), } } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 5f39c79f4f..80e18fbc3e 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -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();