diff --git a/common/src/consts.rs b/common/src/consts.rs index 4cbaa9598e..19b9b8888a 100644 --- a/common/src/consts.rs +++ b/common/src/consts.rs @@ -1,5 +1,5 @@ // The limit on distance between the entity and a collectible (squared) -pub const MAX_PICKUP_RANGE: f32 = 8.0; +pub const MAX_PICKUP_RANGE: f32 = 5.0; pub const MAX_MOUNT_RANGE: f32 = 14.0; pub const GRAVITY: f32 = 25.0; diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index c4e8baa05d..6bdd3ad666 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -9,7 +9,7 @@ use crate::{ theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind, InventoryAction, StateUpdate, }, - consts::{FRIC_GROUND, GRAVITY}, + consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE}, event::{LocalEvent, ServerEvent}, states::{behavior::JoinData, *}, util::Dir, @@ -355,12 +355,12 @@ pub fn handle_orientation( efficiency: f32, dir_override: Option, ) { - let dir = dir_override.unwrap_or_else(|| + let dir = dir_override.unwrap_or_else(|| { (is_strafing(data, update) || update.character.is_attack()) .then(|| data.inputs.look_dir.to_horizontal().unwrap_or_default()) .or_else(|| Dir::from_unnormalized(data.inputs.move_dir.into())) - .unwrap_or_else(|| data.ori.to_horizontal().look_dir()), - ); + .unwrap_or_else(|| data.ori.to_horizontal().look_dir()) + }); let rate = { let angle = update.ori.look_dir().angle_between(*dir); data.body.base_ori_rate() * efficiency * std::f32::consts::PI / angle @@ -626,45 +626,56 @@ pub fn handle_manipulate_loadout( .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); } }, - InventoryAction::Collect(pos) => { - // First, get sprite data for position, if there is a sprite - use sprite_interact::SpriteInteractKind; - let sprite_at_pos = data - .terrain - .get(pos) - .ok() - .copied() - .and_then(|b| b.get_sprite()); + InventoryAction::Collect(sprite_pos) => { + // CLosure to check if distance between a point and the sprite is less than + // MAX_PICKUP_RANGE + let sprite_range_check = |pos: Vec3| { + (sprite_pos.map(|x| x as f32) - pos).magnitude_squared() + < MAX_PICKUP_RANGE.powi(2) + }; + // Checks if player's feet or head is near to sprite + let close_to_sprite = sprite_range_check(data.pos.0) + || sprite_range_check(data.pos.0 + Vec3::new(0.0, 0.0, data.body.height())); + if close_to_sprite { + // First, get sprite data for position, if there is a sprite + use sprite_interact::SpriteInteractKind; + let sprite_at_pos = data + .terrain + .get(sprite_pos) + .ok() + .copied() + .and_then(|b| b.get_sprite()); - // Checks if position has a collectible sprite as wella s what sprite is at the - // position - let sprite_interact = sprite_at_pos.and_then(Option::::from); + // Checks if position has a collectible sprite as wella s what sprite is at the + // position + let sprite_interact = sprite_at_pos.and_then(Option::::from); - if let Some(sprite_interact) = sprite_interact { - // If the sprite is collectible, enter the sprite interaction character state - // TODO: Handle cases for sprite being interactible, but not collectible (none - // currently exist) - let (buildup_duration, use_duration, recover_duration) = - sprite_interact.durations(); + if let Some(sprite_interact) = sprite_interact { + // If the sprite is collectible, enter the sprite interaction character state + // TODO: Handle cases for sprite being interactible, but not collectible (none + // currently exist) + let (buildup_duration, use_duration, recover_duration) = + sprite_interact.durations(); - update.character = CharacterState::SpriteInteract(sprite_interact::Data { - static_data: sprite_interact::StaticData { - buildup_duration, - use_duration, - recover_duration, - sprite_pos: pos, - sprite_kind: sprite_interact, - was_wielded: matches!(data.character, CharacterState::Wielding), - was_sneak: matches!(data.character, CharacterState::Sneak), - }, - timer: Duration::default(), - stage_section: StageSection::Buildup, - }) - } else { - // Otherwise send server event immediately - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + update.character = CharacterState::SpriteInteract(sprite_interact::Data { + static_data: sprite_interact::StaticData { + buildup_duration, + use_duration, + recover_duration, + sprite_pos, + sprite_kind: sprite_interact, + was_wielded: matches!(data.character, CharacterState::Wielding), + was_sneak: matches!(data.character, CharacterState::Sneak), + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, + }) + } else { + // Otherwise send server event immediately + update + .server_events + .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + } } }, _ => {