Add key to select entities

This commit is contained in:
Imbris 2020-04-26 23:40:56 -04:00 committed by Monty Marz
parent 10c3d01466
commit 6aba810517
6 changed files with 31 additions and 8 deletions

View File

@ -377,7 +377,8 @@ magically infused items?"#,
"gameinput.freelook": "Free Look", "gameinput.freelook": "Free Look",
"gameinput.autowalk": "Auto Walk", "gameinput.autowalk": "Auto Walk",
"gameinput.dance": "Dance", "gameinput.dance": "Dance",
"gameinput.select": "Select Entity",
/// End GameInput section /// End GameInput section

View File

@ -996,7 +996,6 @@ impl Client {
// the view distance // the view distance
match change_notification { match change_notification {
Added(uid) => { Added(uid) => {
warn!("message to add: {}", uid);
if !self.group_members.insert(uid) { if !self.group_members.insert(uid) {
warn!( warn!(
"Received msg to add uid {} to the group members but they \ "Received msg to add uid {} to the group members but they \

View File

@ -243,6 +243,7 @@ pub struct HudInfo {
pub is_aiming: bool, pub is_aiming: bool,
pub is_first_person: bool, pub is_first_person: bool,
pub target_entity: Option<specs::Entity>, pub target_entity: Option<specs::Entity>,
pub selected_entity: Option<specs::Entity>,
} }
pub enum Event { pub enum Event {
@ -1047,8 +1048,10 @@ impl Hud {
) )
.join() .join()
.filter(|(entity, _, _, stats, _, _, _, _, _, _)| *entity != me && !stats.is_dead .filter(|(entity, _, _, stats, _, _, _, _, _, _)| *entity != me && !stats.is_dead
&& (stats.health.current() != stats.health.maximum() || info.target_entity.map_or(false, |e| e == *entity)) && (stats.health.current() != stats.health.maximum()
) || info.target_entity.map_or(false, |e| e == *entity)
|| info.selected_entity.map_or(false, |e| e == *entity)
))
// Don't show outside a certain range // Don't show outside a certain range
.filter(|(_, pos, _, _, _, _, _, _, hpfl, _)| { .filter(|(_, pos, _, _, _, _, _, _, hpfl, _)| {
pos.0.distance_squared(player_pos) pos.0.distance_squared(player_pos)

View File

@ -52,6 +52,8 @@ pub struct SessionState {
free_look: bool, free_look: bool,
auto_walk: bool, auto_walk: bool,
is_aiming: bool, is_aiming: bool,
target_entity: Option<specs::Entity>,
selected_entity: Option<specs::Entity>,
} }
/// Represents an active game session (i.e., the one being played). /// Represents an active game session (i.e., the one being played).
@ -86,6 +88,8 @@ impl SessionState {
free_look: false, free_look: false,
auto_walk: false, auto_walk: false,
is_aiming: false, is_aiming: false,
target_entity: None,
selected_entity: None,
} }
} }
@ -234,7 +238,7 @@ impl PlayState for SessionState {
let (build_pos, select_pos, target_entity) = let (build_pos, select_pos, target_entity) =
under_cursor(&self.client.borrow(), cam_pos, cam_dir); under_cursor(&self.client.borrow(), cam_pos, cam_dir);
// Throw out distance info, it will be useful in the future // Throw out distance info, it will be useful in the future
let target_entity = target_entity.map(|x| x.0); self.target_entity = target_entity.map(|x| x.0);
let can_build = self let can_build = self
.client .client
@ -527,6 +531,11 @@ impl PlayState for SessionState {
let camera = self.scene.camera_mut(); let camera = self.scene.camera_mut();
camera.next_mode(self.client.borrow().is_admin()); camera.next_mode(self.client.borrow().is_admin());
}, },
Event::InputUpdate(GameInput::Select, state) => {
if !state {
self.selected_entity = self.target_entity;
}
},
Event::AnalogGameInput(input) => match input { Event::AnalogGameInput(input) => match input {
AnalogGameInput::MovementX(v) => { AnalogGameInput::MovementX(v) => {
self.key_state.analog_matrix.x = v; self.key_state.analog_matrix.x = v;
@ -676,7 +685,8 @@ impl PlayState for SessionState {
self.scene.camera().get_mode(), self.scene.camera().get_mode(),
camera::CameraMode::FirstPerson camera::CameraMode::FirstPerson
), ),
target_entity, target_entity: self.target_entity,
selected_entity: self.selected_entity,
}, },
); );
@ -948,7 +958,7 @@ impl PlayState for SessionState {
let scene_data = SceneData { let scene_data = SceneData {
state: client.state(), state: client.state(),
player_entity: client.entity(), player_entity: client.entity(),
target_entity, target_entity: self.target_entity,
loaded_distance: client.loaded_distance(), loaded_distance: client.loaded_distance(),
view_distance: client.view_distance().unwrap_or(1), view_distance: client.view_distance().unwrap_or(1),
tick: client.get_tick(), tick: client.get_tick(),
@ -1003,6 +1013,7 @@ impl PlayState for SessionState {
let scene_data = SceneData { let scene_data = SceneData {
state: client.state(), state: client.state(),
player_entity: client.entity(), player_entity: client.entity(),
target_entity: self.target_entity,
loaded_distance: client.loaded_distance(), loaded_distance: client.loaded_distance(),
view_distance: client.view_distance().unwrap_or(1), view_distance: client.view_distance().unwrap_or(1),
tick: client.get_tick(), tick: client.get_tick(),
@ -1097,14 +1108,18 @@ fn under_cursor(
let radius = s.map_or(1.0, |s| s.0) * b.radius() * RADIUS_SCALE; let radius = s.map_or(1.0, |s| s.0) * b.radius() * RADIUS_SCALE;
// Move position up from the feet // Move position up from the feet
let pos = Vec3::new(p.0.x, p.0.y, p.0.z + radius); let pos = Vec3::new(p.0.x, p.0.y, p.0.z + radius);
// Distance squared from camera to the entity
let dist_sqr = pos.distance_squared(cam_pos); let dist_sqr = pos.distance_squared(cam_pos);
(e, pos, radius, dist_sqr) (e, pos, radius, dist_sqr)
}) })
// Roughly filter out entities farther than ray distance
.filter(|(_, _, r, d_sqr)| *d_sqr <= cast_dist.powi(2) + 2.0 * cast_dist * r + r.powi(2))
// Ignore entities intersecting the camera // Ignore entities intersecting the camera
.filter(|(_, _, r, d_sqr)| *d_sqr > r.powi(2)) .filter(|(_, _, r, d_sqr)| *d_sqr > r.powi(2))
.filter(|(_, _, r, d_sqr)| *d_sqr <= cast_dist.powi(2) + 2.0 * cast_dist * r + r.powi(2)) // Substract sphere radius from distance to the camera
.map(|(e, p, r, d_sqr)| (e, p, r, d_sqr.sqrt() - r)) .map(|(e, p, r, d_sqr)| (e, p, r, d_sqr.sqrt() - r))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Sort by distance
nearby.sort_unstable_by(|a, b| a.3.partial_cmp(&b.3).unwrap()); nearby.sort_unstable_by(|a, b| a.3.partial_cmp(&b.3).unwrap());
let seg_ray = LineSegment3 { let seg_ray = LineSegment3 {
@ -1115,6 +1130,7 @@ fn under_cursor(
let target_entity = nearby let target_entity = nearby
.iter() .iter()
.map(|(e, p, r, _)| (e, *p, r)) .map(|(e, p, r, _)| (e, *p, r))
// Find first one that intersects the ray segment
.find(|(_, p, r)| seg_ray.projected_point(*p).distance_squared(*p) < r.powi(2)) .find(|(_, p, r)| seg_ray.projected_point(*p).distance_squared(*p) < r.powi(2))
.and_then(|(e, p, r)| { .and_then(|(e, p, r)| {
let dist_to_player = p.distance(player_pos); let dist_to_player = p.distance(player_pos);

View File

@ -169,6 +169,7 @@ impl ControlSettings {
GameInput::Slot9 => KeyMouse::Key(VirtualKeyCode::Key9), GameInput::Slot9 => KeyMouse::Key(VirtualKeyCode::Key9),
GameInput::Slot10 => KeyMouse::Key(VirtualKeyCode::Q), GameInput::Slot10 => KeyMouse::Key(VirtualKeyCode::Q),
GameInput::SwapLoadout => KeyMouse::Key(VirtualKeyCode::LAlt), GameInput::SwapLoadout => KeyMouse::Key(VirtualKeyCode::LAlt),
GameInput::Select => KeyMouse::Key(VirtualKeyCode::I),
} }
} }
} }
@ -234,6 +235,7 @@ impl Default for ControlSettings {
GameInput::Slot9, GameInput::Slot9,
GameInput::Slot10, GameInput::Slot10,
GameInput::SwapLoadout, GameInput::SwapLoadout,
GameInput::Select,
]; ];
for game_input in game_inputs { for game_input in game_inputs {
new_settings.insert_binding(game_input, ControlSettings::default_binding(game_input)); new_settings.insert_binding(game_input, ControlSettings::default_binding(game_input));

View File

@ -67,6 +67,7 @@ pub enum GameInput {
FreeLook, FreeLook,
AutoWalk, AutoWalk,
CycleCamera, CycleCamera,
Select,
} }
impl GameInput { impl GameInput {
@ -123,6 +124,7 @@ impl GameInput {
GameInput::Slot9 => "gameinput.slot9", GameInput::Slot9 => "gameinput.slot9",
GameInput::Slot10 => "gameinput.slot10", GameInput::Slot10 => "gameinput.slot10",
GameInput::SwapLoadout => "gameinput.swaploadout", GameInput::SwapLoadout => "gameinput.swaploadout",
GameInput::Select => "gameinput.select",
} }
} }