diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bc52937dc..ff9424baef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Explosions no longer change block colours within safe zones - The 'spot' system, which generates smaller site-like structures and scenarios - Chestnut and cedar tree varieties +- Shooting sprites, such as apples and hives, can knock them out of trees ### Changed diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 20ab8f2788..972fdf9a6c 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -1020,14 +1020,13 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o } } -pub fn handle_bonk(server: &mut Server, pos: Vec3, owner: Option, target: Option) { +pub fn handle_bonk(server: &mut Server, pos: Vec3, _owner: Option, target: Option) { let ecs = &server.state.ecs(); let terrain = ecs.read_resource::(); let mut block_change = ecs.write_resource::(); if let Some(_target) = target { // TODO: bonk entities but do no damage? - drop(owner); } else { use common::terrain::SpriteKind; let pos = pos.map(|e| e.floor() as i32); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index b5db7df96d..01dda44cb8 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -49,6 +49,8 @@ pub struct Camera { dist: f32, tgt_fov: f32, fov: f32, + tgt_fixate: f32, + fixate: f32, aspect: f32, mode: CameraMode, @@ -327,6 +329,8 @@ impl Camera { dist: 10.0, tgt_fov: 1.1, fov: 1.1, + tgt_fixate: 1.0, + fixate: 1.0, aspect, mode, @@ -466,13 +470,14 @@ impl Camera { * Mat4::translation_3d(-self.focus.map(|e| e.fract())); let view_mat_inv: Mat4 = view_mat.inverted(); + let fov = self.get_effective_fov(); // NOTE: We reverse the far and near planes to produce an inverted depth // buffer (1 to 0 z planes). let proj_mat = - perspective_rh_zo_general(self.fov, self.aspect, 1.0 / FAR_PLANE, 1.0 / NEAR_PLANE); + perspective_rh_zo_general(fov, self.aspect, 1.0 / FAR_PLANE, 1.0 / NEAR_PLANE); // For treeculler, we also produce a version without inverted depth. let proj_mat_treeculler = - perspective_rh_zo_general(self.fov, self.aspect, 1.0 / NEAR_PLANE, 1.0 / FAR_PLANE); + perspective_rh_zo_general(fov, self.aspect, 1.0 / NEAR_PLANE, 1.0 / FAR_PLANE); Dependents { view_mat, @@ -501,6 +506,7 @@ impl Camera { /// Rotate the camera about its focus by the given delta, limiting the input /// accordingly. pub fn rotate_by(&mut self, delta: Vec3) { + let delta = delta * self.fixate; // Wrap camera yaw self.tgt_ori.x = (self.tgt_ori.x + delta.x).rem_euclid(2.0 * PI); // Clamp camera pitch to the vertical limits @@ -575,6 +581,14 @@ impl Camera { ); } + if (self.fixate - self.tgt_fixate).abs() > 0.01 { + self.fixate = vek::Lerp::lerp( + self.fixate, + self.tgt_fixate, + 0.65 * (delta as f32) / self.interp_time(), + ); + } + if (self.focus - self.tgt_focus).magnitude_squared() > 0.001 { let lerped_focus = Lerp::lerp( self.focus, @@ -639,12 +653,20 @@ impl Camera { /// Get the orientation of the camera. pub fn get_orientation(&self) -> Vec3 { self.ori } - /// Get the field of view of the camera in radians. - pub fn get_fov(&self) -> f32 { self.fov } + /// Get the field of view of the camera in radians, taking into account + /// fixation. + pub fn get_effective_fov(&self) -> f32 { self.fov * self.fixate } + + // /// Get the field of view of the camera in radians. + // pub fn get_fov(&self) -> f32 { self.fov } /// Set the field of view of the camera in radians. pub fn set_fov(&mut self, fov: f32) { self.tgt_fov = fov; } + /// Set the 'fixation' proportion, allowing the camera to focus in with + /// precise aiming. Fixation is applied on top of the regular FoV. + pub fn set_fixate(&mut self, fixate: f32) { self.tgt_fixate = fixate; } + /// Set the FOV in degrees pub fn set_fov_deg(&mut self, fov: u16) { //Magic value comes from pi/180; no use recalculating. diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 4f6d0af4d5..fe7aa247c5 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -682,7 +682,7 @@ impl Scene { let sun_dir = scene_data.get_sun_dir(); let is_daylight = sun_dir.z < 0.0; if renderer.pipeline_modes().shadow.is_map() && (is_daylight || !lights.is_empty()) { - let fov = self.camera.get_fov(); + let fov = self.camera.get_effective_fov(); let aspect_ratio = self.camera.get_aspect_ratio(); let view_dir = ((focus_pos.map(f32::fract)) - cam_pos).normalized(); diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 07114633fb..fbfb92277b 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -77,7 +77,6 @@ pub struct SessionState { target_entity: Option, selected_entity: Option<(specs::Entity, std::time::Instant)>, interactable: Option, - saved_zoom_dist: Option, hitboxes: HashMap, } @@ -125,7 +124,6 @@ impl SessionState { target_entity: None, selected_entity: None, interactable: None, - saved_zoom_dist: None, hitboxes: HashMap::new(), } } @@ -328,18 +326,8 @@ impl PlayState for SessionState { if cr.charge_frac() > 0.5 { fov_scaling -= 3.0 * cr.charge_frac() / 5.0; } - let max_dist = if let Some(dist) = self.saved_zoom_dist { - dist - } else { - let dist = camera.get_distance(); - self.saved_zoom_dist = Some(dist); - dist - }; - camera.set_distance(Lerp::lerp(max_dist, 2.0, 1.0 - fov_scaling)); - } else if let Some(dist) = self.saved_zoom_dist.take() { - camera.set_distance(dist); } - camera.set_fov((global_state.settings.graphics.fov as f32 * fov_scaling).to_radians()); + camera.set_fixate(fov_scaling); // Compute camera data camera.compute_dependents(&*self.client.borrow().state().terrain());