diff --git a/CHANGELOG.md b/CHANGELOG.md index 59afead121..ac752d39f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Dutch translations - Buff system - Sneaking lets you be closer to enemies without being detected +- Flight ### Changed diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron index 778a21c5f7..78c21cfa44 100644 --- a/assets/voxygen/i18n/en.ron +++ b/assets/voxygen/i18n/en.ron @@ -185,7 +185,7 @@ https://account.veloren.net."#, "hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]", "hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic", "hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]", - + "hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]", "hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]", @@ -460,6 +460,7 @@ magically infused items?"#, "gameinput.acceptgroupinvite": "Accept Group Invite", "gameinput.declinegroupinvite": "Decline Group Invite", "gameinput.crafting": "Crafting", + "gameinput.fly": "Fly", "gameinput.sneak": "Sneak", "gameinput.swimdown": "Swim downwards", "gameinput.swimup": "Swim upwards", @@ -515,13 +516,13 @@ Protection /// Buffs and Debuffs "buff.remove": "Click to remove", - "buff.title.missing": "Missing Title", - "buff.desc.missing": "Missing Description", + "buff.title.missing": "Missing Title", + "buff.desc.missing": "Missing Description", // Buffs - "buff.title.heal_test": "Heal Test", - "buff.desc.heal_test": "This is a test buff to test healing.", - // Debuffs - "debuff.title.bleed_test": "Bleeding", + "buff.title.heal_test": "Heal Test", + "buff.desc.heal_test": "This is a test buff to test healing.", + // Debuffs + "debuff.title.bleed_test": "Bleeding", "debuff.desc.bleed_test": "Inflicts regular damage.", }, diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 5c7f3558c8..6dac0ecc88 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -175,12 +175,13 @@ pub struct ControllerInputs { pub jump: Input, pub roll: Input, pub glide: Input, + pub fly: Input, // Flying entities only pub wall_leap: Input, pub charge: Input, pub climb: Option, - pub swimup: Input, - pub swimdown: Input, pub move_dir: Vec2, + pub move_z: f32, /* z axis (not combined with move_dir because they may have independent + * limits) */ pub look_dir: Dir, } @@ -201,10 +202,9 @@ impl ControllerInputs { self.jump.tick(dt); self.roll.tick(dt); self.glide.tick(dt); + self.fly.tick(dt); self.wall_leap.tick(dt); self.charge.tick(dt); - self.swimup.tick(dt); - self.swimdown.tick(dt); } pub fn tick_freshness(&mut self) { @@ -214,10 +214,9 @@ impl ControllerInputs { self.jump.tick_freshness(); self.roll.tick_freshness(); self.glide.tick_freshness(); + self.fly.tick_freshness(); self.wall_leap.tick_freshness(); self.charge.tick_freshness(); - self.swimup.tick_freshness(); - self.swimdown.tick_freshness(); } /// Updates Controller inputs with new version received from the client @@ -228,12 +227,12 @@ impl ControllerInputs { self.jump.update_with_new(new.jump); self.roll.update_with_new(new.roll); self.glide.update_with_new(new.glide); + self.fly.update_with_new(new.fly); self.wall_leap.update_with_new(new.wall_leap); self.charge.update_with_new(new.charge); self.climb = new.climb; - self.swimup.update_with_new(new.swimup); - self.swimdown.update_with_new(new.swimdown); self.move_dir = new.move_dir; + self.move_z = new.move_z; self.look_dir = new.look_dir; } diff --git a/common/src/path.rs b/common/src/path.rs index 83d3ea52a5..6f26190773 100644 --- a/common/src/path.rs +++ b/common/src/path.rs @@ -94,7 +94,7 @@ impl Route { vol: &V, pos: Vec3, vel: Vec3, - traversal_cfg: TraversalConfig, + traversal_cfg: &TraversalConfig, ) -> Option<(Vec3, f32)> where V: BaseVol + ReadVol, @@ -364,7 +364,7 @@ impl Chaser { } else { self.route .as_mut() - .and_then(|(r, _)| r.traverse(vol, pos, vel, traversal_cfg)) + .and_then(|(r, _)| r.traverse(vol, pos, vel, &traversal_cfg)) } } else { None diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index df382ea93a..c744d9a485 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -14,6 +14,7 @@ use vek::*; pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; const BASE_HUMANOID_AIR_ACCEL: f32 = 8.0; +const BASE_FLIGHT_ACCEL: f32 = 16.0; const BASE_HUMANOID_WATER_ACCEL: f32 = 150.0; const BASE_HUMANOID_WATER_SPEED: f32 = 180.0; // const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0; @@ -65,12 +66,23 @@ impl Body { Body::QuadrupedLow(_) => 12.0, } } + + pub fn can_fly(&self) -> bool { + match self { + Body::BirdMedium(_) => true, + Body::Dragon(_) => true, + Body::BirdSmall(_) => true, + _ => false, + } + } } /// Handles updating `Components` to move player based on state of `JoinData` pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) { if let Some(depth) = data.physics.in_fluid { swim_move(data, update, efficiency, depth); + } else if data.inputs.fly.is_pressed() && !data.physics.on_ground && data.body.can_fly() { + fly_move(data, update, efficiency); } else { basic_move(data, update, efficiency); } @@ -171,16 +183,31 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth: handle_orientation(data, update, if data.physics.on_ground { 9.0 } else { 2.0 }); // Swim - if data.inputs.swimup.is_pressed() { - update.vel.0.z = (update.vel.0.z - + data.dt.0 * GRAVITY * 4.0 * depth.clamped(0.0, 1.0).powf(3.0)) - .min(BASE_HUMANOID_WATER_SPEED); - } - // Swim - if data.inputs.swimdown.is_pressed() { - update.vel.0.z = - (update.vel.0.z + data.dt.0 * GRAVITY * -3.5).min(BASE_HUMANOID_WATER_SPEED); - } + update.vel.0.z = (update.vel.0.z + + data.dt.0 + * GRAVITY + * 4.0 + * data + .inputs + .move_z + .clamped(-1.0, depth.clamped(0.0, 1.0).powf(3.0))) + .min(BASE_HUMANOID_WATER_SPEED); +} + +/// Updates components to move entity as if it's flying +fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) { + // Update velocity (counteract gravity with lift) + // TODO: Do this better + update.vel.0 += Vec3::unit_z() * data.dt.0 * GRAVITY + + Vec3::new( + data.inputs.move_dir.x, + data.inputs.move_dir.y, + data.inputs.move_z, + ) * data.dt.0 + * BASE_FLIGHT_ACCEL + * efficiency; + + handle_orientation(data, update, 1.0); } /// First checks whether `primary`, `secondary` or `ability3` input is pressed, diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index ba1bd17340..fa9af1771e 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -283,8 +283,7 @@ impl<'a> System<'a> for Sys { bearing.xy().try_normalized().unwrap_or(Vec2::zero()) * speed.min(0.2 + (dist - AVG_FOLLOW_DIST) / 8.0); inputs.jump.set_state(bearing.z > 1.5); - inputs.swimup.set_state(bearing.z > 0.5); - inputs.swimdown.set_state(bearing.z < 0.5); + inputs.move_z = bearing.z; } } else { do_idle = true; @@ -388,8 +387,7 @@ impl<'a> System<'a> for Sys { * speed * 0.2; //Let small/slow animals flee slower than the player inputs.jump.set_state(bearing.z > 1.5); - inputs.swimup.set_state(bearing.z > 0.5); - inputs.swimdown.set_state(bearing.z < 0.5); + inputs.move_z = bearing.z; } } else { do_idle = true; @@ -530,8 +528,7 @@ impl<'a> System<'a> for Sys { bearing.xy().try_normalized().unwrap_or(Vec2::zero()) * speed; inputs.jump.set_state(bearing.z > 1.5); - inputs.swimup.set_state(bearing.z > 0.5); - inputs.swimdown.set_state(bearing.z < 0.5); + inputs.move_z = bearing.z; } } diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 3fe6b8bedb..c4c59e7718 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -13,6 +13,7 @@ use specs::{ saveload::{Marker, MarkerAllocator}, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage, }; +use vek::*; // const CHARGE_COST: i32 = 200; // const ROLL_COST: i32 = 30; @@ -72,6 +73,7 @@ impl<'a> System<'a> for Sys { } else { inputs.move_dir }; + inputs.move_z = inputs.move_z.clamped(-1.0, 1.0); // Process other controller events for event in controller.events.drain(..) { diff --git a/voxygen/src/key_state.rs b/voxygen/src/key_state.rs index 775c556058..9e5733df37 100644 --- a/voxygen/src/key_state.rs +++ b/voxygen/src/key_state.rs @@ -7,6 +7,9 @@ pub struct KeyState { pub down: bool, pub climb_up: bool, pub climb_down: bool, + pub swim_up: bool, + pub swim_down: bool, + pub fly: bool, pub toggle_wield: bool, pub toggle_glide: bool, pub toggle_lantern: bool, @@ -29,6 +32,9 @@ impl Default for KeyState { down: false, climb_up: false, climb_down: false, + swim_up: false, + swim_down: false, + fly: false, toggle_wield: false, toggle_glide: false, toggle_lantern: false, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index b51a178346..cd46775585 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -356,10 +356,10 @@ impl PlayState for SessionState { self.inputs.jump.set_state(state); }, Event::InputUpdate(GameInput::SwimUp, state) => { - self.inputs.swimup.set_state(state); + self.key_state.swim_up = state; }, Event::InputUpdate(GameInput::SwimDown, state) => { - self.inputs.swimdown.set_state(state); + self.key_state.swim_down = state; }, Event::InputUpdate(GameInput::Sit, state) if state != self.key_state.toggle_sit => @@ -421,6 +421,9 @@ impl PlayState for SessionState { self.client.borrow_mut().toggle_glide(); } } + Event::InputUpdate(GameInput::Fly, state) => { + self.key_state.fly ^= state; + }, Event::InputUpdate(GameInput::Climb, state) => { self.key_state.climb_up = state; }, @@ -656,6 +659,9 @@ impl PlayState for SessionState { }; self.inputs.climb = self.key_state.climb(); + self.inputs.fly.set_state(self.key_state.fly); + self.inputs.move_z = + self.key_state.swim_up as i32 as f32 - self.key_state.swim_down as i32 as f32; let mut outcomes = Vec::new(); diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 1f65e800de..0d058518c2 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -136,6 +136,7 @@ impl ControlSettings { GameInput::ClimbDown => KeyMouse::Key(VirtualKeyCode::LControl), GameInput::SwimUp => KeyMouse::Key(VirtualKeyCode::Space), GameInput::SwimDown => KeyMouse::Key(VirtualKeyCode::LShift), + GameInput::Fly => KeyMouse::Key(VirtualKeyCode::F), GameInput::Sneak => KeyMouse::Key(VirtualKeyCode::LControl), //GameInput::WallLeap => MIDDLE_CLICK_KEY, GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G), @@ -203,6 +204,7 @@ impl Default for ControlSettings { GameInput::ClimbDown, GameInput::SwimUp, GameInput::SwimDown, + GameInput::Fly, GameInput::Sneak, //GameInput::WallLeap, GameInput::ToggleLantern, diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 1a1c868ce9..79eb08a429 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -44,6 +44,7 @@ pub enum GameInput { ClimbDown, SwimUp, SwimDown, + Fly, Sneak, //WallLeap, ToggleLantern, @@ -95,6 +96,7 @@ impl GameInput { GameInput::ClimbDown => "gameinput.climbdown", GameInput::SwimUp => "gameinput.swimup", GameInput::SwimDown => "gameinput.swimdown", + GameInput::Fly => "gameinput.fly", GameInput::Sneak => "gameinput.sneak", //GameInput::WallLeap => "gameinput.wallleap", GameInput::ToggleLantern => "gameinput.togglelantern", @@ -156,6 +158,7 @@ impl GameInput { GameInput::ClimbDown, GameInput::SwimUp, GameInput::SwimDown, + GameInput::Fly, GameInput::Sneak, GameInput::ToggleLantern, GameInput::Mount,