Added dimensional door ability for mindflayer

This commit is contained in:
Sam 2021-03-20 23:28:13 -04:00
parent f1156c9ce5
commit 30da614e89
19 changed files with 265 additions and 55 deletions

View File

@ -1 +1,5 @@
BasicBlock Blink(
buildup_duration: 0.5,
recover_duration: 0.25,
max_range: 100.0,
)

View File

@ -999,11 +999,17 @@ impl Client {
} }
} }
pub fn handle_input(&mut self, input: InputKind, pressed: bool, select_pos: Option<Vec3<f32>>) { pub fn handle_input(
&mut self,
input: InputKind,
pressed: bool,
select_pos: Option<Vec3<f32>>,
target_entity: Option<EcsEntity>,
) {
if pressed { if pressed {
self.control_action(ControlAction::StartInput { self.control_action(ControlAction::StartInput {
input, input,
target: None, target_entity: target_entity.and_then(|e| self.state.read_component_copied(e)),
select_pos, select_pos,
}); });
} else { } else {
@ -1638,6 +1644,15 @@ impl Client {
impulse, impulse,
}); });
}, },
ServerGeneral::PositionUpdate(pos) => {
self.state
.ecs()
.read_resource::<EventBus<LocalEvent>>()
.emit_now(LocalEvent::PositionUpdate {
entity: self.entity(),
pos,
});
},
ServerGeneral::UpdatePendingTrade(id, trade, pricing) => { ServerGeneral::UpdatePendingTrade(id, trade, pricing) => {
tracing::trace!("UpdatePendingTrade {:?} {:?}", id, trade); tracing::trace!("UpdatePendingTrade {:?} {:?}", id, trade);
self.pending_trade = Some((id, trade, pricing)); self.pending_trade = Some((id, trade, pricing));

View File

@ -104,6 +104,7 @@ pub enum ServerGeneral {
SetViewDistance(u32), SetViewDistance(u32),
Outcomes(Vec<Outcome>), Outcomes(Vec<Outcome>),
Knockback(Vec3<f32>), Knockback(Vec3<f32>),
PositionUpdate(comp::Pos),
// Ingame related AND terrain stream // Ingame related AND terrain stream
TerrainChunkUpdate { TerrainChunkUpdate {
key: Vec2<i32>, key: Vec2<i32>,
@ -235,6 +236,7 @@ impl ServerMsg {
| ServerGeneral::SetViewDistance(_) | ServerGeneral::SetViewDistance(_)
| ServerGeneral::Outcomes(_) | ServerGeneral::Outcomes(_)
| ServerGeneral::Knockback(_) | ServerGeneral::Knockback(_)
| ServerGeneral::PositionUpdate(_)
| ServerGeneral::UpdatePendingTrade(_, _, _) | ServerGeneral::UpdatePendingTrade(_, _, _)
| ServerGeneral::FinishedTrade(_) | ServerGeneral::FinishedTrade(_)
| ServerGeneral::SiteEconomy(_) => { | ServerGeneral::SiteEconomy(_) => {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
assets::{self, Asset}, assets::{self, Asset},
combat::{self, CombatEffect}, combat::{self, CombatEffect, Knockback},
comp::{ comp::{
aura, beam, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills, aura, beam, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills,
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate, Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
@ -10,7 +10,6 @@ use crate::{
utils::{AbilityInfo, StageSection}, utils::{AbilityInfo, StageSection},
*, *,
}, },
Knockback,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
@ -252,6 +251,11 @@ pub enum CharacterAbility {
energy_cost: f32, energy_cost: f32,
specifier: beam::FrontendSpecifier, specifier: beam::FrontendSpecifier,
}, },
Blink {
buildup_duration: f32,
recover_duration: f32,
max_range: f32,
},
} }
impl Default for CharacterAbility { impl Default for CharacterAbility {
@ -532,6 +536,14 @@ impl CharacterAbility {
*heal *= power; *heal *= power;
*tick_rate *= speed; *tick_rate *= speed;
}, },
Blink {
ref mut buildup_duration,
ref mut recover_duration,
..
} => {
*buildup_duration /= speed;
*recover_duration /= speed;
},
} }
self self
} }
@ -558,7 +570,7 @@ impl CharacterAbility {
0 0
} }
}, },
BasicBlock | Boost { .. } | ComboMelee { .. } => 0, BasicBlock | Boost { .. } | ComboMelee { .. } | Blink { .. } => 0,
} }
} }
@ -1560,6 +1572,20 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
}), }),
CharacterAbility::Blink {
buildup_duration,
recover_duration,
max_range,
} => CharacterState::Blink(blink::Data {
static_data: blink::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
recover_duration: Duration::from_secs_f32(*recover_duration),
max_range: *max_range,
ability_info,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
}),
} }
} }
} }

View File

@ -93,6 +93,8 @@ pub enum CharacterState {
/// specifically for the healing beam. There was also functionality present /// specifically for the healing beam. There was also functionality present
/// on basic beam which was unnecessary for the healing beam. /// on basic beam which was unnecessary for the healing beam.
HealingBeam(healing_beam::Data), HealingBeam(healing_beam::Data),
/// A short teleport that targets either a position or entity
Blink(blink::Data),
} }
impl CharacterState { impl CharacterState {

View File

@ -110,7 +110,7 @@ pub enum ControlAction {
Talk, Talk,
StartInput { StartInput {
input: InputKind, input: InputKind,
target: Option<Uid>, target_entity: Option<Uid>,
// Some inputs need a selected position, such as mining // Some inputs need a selected position, such as mining
select_pos: Option<Vec3<f32>>, select_pos: Option<Vec3<f32>>,
}, },
@ -121,7 +121,7 @@ impl ControlAction {
pub fn basic_input(input: InputKind) -> Self { pub fn basic_input(input: InputKind) -> Self {
ControlAction::StartInput { ControlAction::StartInput {
input, input,
target: None, target_entity: None,
select_pos: None, select_pos: None,
} }
} }
@ -144,9 +144,10 @@ impl InputKind {
} }
} }
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct InputAttr { pub struct InputAttr {
pub select_pos: Option<Vec3<f32>>, pub select_pos: Option<Vec3<f32>>,
pub target_entity: Option<Uid>,
} }
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -28,6 +28,8 @@ pub enum LocalEvent {
}, },
/// Applies `vel` velocity to `entity` /// Applies `vel` velocity to `entity`
Boost { entity: EcsEntity, vel: Vec3<f32> }, Boost { entity: EcsEntity, vel: Vec3<f32> },
/// Updates the position of the entity
PositionUpdate { entity: EcsEntity, pos: Pos },
} }
#[allow(clippy::large_enum_variant)] // TODO: Pending review in #587 #[allow(clippy::large_enum_variant)] // TODO: Pending review in #587
@ -161,6 +163,11 @@ pub enum ServerEvent {
pos: Vec3<i32>, pos: Vec3<i32>,
tool: Option<comp::tool::ToolKind>, tool: Option<comp::tool::ToolKind>,
}, },
TeleportTo {
entity: EcsEntity,
target: Uid,
max_range: Option<f32>,
},
} }
pub struct EventBus<E> { pub struct EventBus<E> {

View File

@ -34,11 +34,14 @@ pub trait CharacterBehavior {
&self, &self,
data: &JoinData, data: &JoinData,
input: InputKind, input: InputKind,
_target: Option<Uid>, target_entity: Option<Uid>,
select_pos: Option<Vec3<f32>>, select_pos: Option<Vec3<f32>>,
) -> StateUpdate { ) -> StateUpdate {
let mut update = StateUpdate::from(data); let mut update = StateUpdate::from(data);
update.queued_inputs.insert(input, InputAttr { select_pos }); update.queued_inputs.insert(input, InputAttr {
select_pos,
target_entity,
});
update update
} }
fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate { fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
@ -60,9 +63,9 @@ pub trait CharacterBehavior {
ControlAction::Talk => self.talk(data), ControlAction::Talk => self.talk(data),
ControlAction::StartInput { ControlAction::StartInput {
input, input,
target, target_entity,
select_pos, select_pos,
} => self.start_input(data, input, target, select_pos), } => self.start_input(data, input, target_entity, select_pos),
ControlAction::CancelInput(input) => self.cancel_input(data, input), ControlAction::CancelInput(input) => self.cancel_input(data, input),
} }
} }

View File

@ -0,0 +1,94 @@
use crate::{
comp::{CharacterState, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
},
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
/// Separated out to condense update portions of character state
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StaticData {
pub buildup_duration: Duration,
pub recover_duration: Duration,
pub max_range: f32,
pub ability_info: AbilityInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Data {
/// Struct containing data that does not change over the course of the
/// character state
pub static_data: StaticData,
/// Timer for each stage
pub timer: Duration,
/// What section the character stage is in
pub stage_section: StageSection,
}
impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data);
match self.stage_section {
StageSection::Buildup => {
if self.timer < self.static_data.buildup_duration {
// Build up
update.character = CharacterState::Blink(Data {
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
..*self
});
} else {
// Blinks to target location, defaults to 25 meters in front if no target
// provided
if let Some(input_attr) = self.static_data.ability_info.input_attr {
if let Some(target) = input_attr.target_entity {
update.server_events.push_front(ServerEvent::TeleportTo {
entity: data.entity,
target,
max_range: Some(self.static_data.max_range),
});
} else if let Some(pos) = input_attr.select_pos {
update.pos.0 = pos;
} else {
update.pos.0 += *data.inputs.look_dir * 25.0;
}
}
// Transitions to recover section of stage
update.character = CharacterState::Blink(Data {
timer: Duration::default(),
stage_section: StageSection::Recover,
..*self
});
}
},
StageSection::Recover => {
if self.timer < self.static_data.recover_duration {
// Recovery
update.character = CharacterState::Blink(Data {
timer: self
.timer
.checked_add(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
..*self
});
} else {
// Done
update.character = CharacterState::Wielding;
}
},
_ => {
// If it somehow ends up in an incorrect stage section
update.character = CharacterState::Wielding;
},
}
update
}
}

View File

@ -4,6 +4,7 @@ pub mod basic_block;
pub mod basic_melee; pub mod basic_melee;
pub mod basic_ranged; pub mod basic_ranged;
pub mod behavior; pub mod behavior;
pub mod blink;
pub mod boost; pub mod boost;
pub mod charged_melee; pub mod charged_melee;
pub mod charged_ranged; pub mod charged_ranged;

View File

@ -5,7 +5,8 @@ use crate::{
item::{Hands, ItemKind, Tool, ToolKind}, item::{Hands, ItemKind, Tool, ToolKind},
quadruped_low, quadruped_medium, quadruped_small, ship, quadruped_low, quadruped_medium, quadruped_small, ship,
skills::{Skill, SwimSkill}, skills::{Skill, SwimSkill},
theropod, Body, CharacterAbility, CharacterState, InputKind, InventoryAction, StateUpdate, theropod, Body, CharacterAbility, CharacterState, InputAttr, InputKind, InventoryAction,
StateUpdate,
}, },
consts::{FRIC_GROUND, GRAVITY}, consts::{FRIC_GROUND, GRAVITY},
event::{LocalEvent, ServerEvent}, event::{LocalEvent, ServerEvent},
@ -523,11 +524,10 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = ( update.character = CharacterState::from((
&ability, &ability,
AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input), AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input),
) ));
.into();
} }
} }
} }
@ -578,40 +578,23 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = CharacterState::from((
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
));
if let CharacterState::ComboMelee(c) = data.character { if let CharacterState::ComboMelee(c) = data.character {
update.character = (
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_combo = Some((c.static_data.ability_info.input, c.stage)); roll.was_combo = Some((c.static_data.ability_info.input, c.stage));
roll.was_wielded = true; roll.was_wielded = true;
} }
} else if data.character.is_wield() { } else if data.character.is_wield() {
update.character = (
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_wielded = true; roll.was_wielded = true;
} }
} else if data.character.is_stealthy() { } else if data.character.is_stealthy() {
update.character = (
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_sneak = true; roll.was_sneak = true;
} }
} else {
update.character = (
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
)
.into();
} }
} }
} }
@ -707,7 +690,7 @@ pub struct AbilityInfo {
pub tool: Option<ToolKind>, pub tool: Option<ToolKind>,
pub hand: Option<HandInfo>, pub hand: Option<HandInfo>,
pub input: InputKind, pub input: InputKind,
pub select_pos: Option<Vec3<f32>>, pub input_attr: Option<InputAttr>,
} }
impl AbilityInfo { impl AbilityInfo {
@ -730,13 +713,7 @@ impl AbilityInfo {
tool, tool,
hand, hand,
input, input,
select_pos: data input_attr: data.controller.queued_inputs.get(&input).copied(),
.controller
.queued_inputs
.get(&input)
.cloned()
.unwrap_or_default()
.select_pos,
} }
} }
} }

View File

@ -302,6 +302,7 @@ impl<'a> System<'a> for Sys {
CharacterState::BasicBeam(data) => data.handle_event(&j, action), CharacterState::BasicBeam(data) => data.handle_event(&j, action),
CharacterState::BasicAura(data) => data.handle_event(&j, action), CharacterState::BasicAura(data) => data.handle_event(&j, action),
CharacterState::HealingBeam(data) => data.handle_event(&j, action), CharacterState::HealingBeam(data) => data.handle_event(&j, action),
CharacterState::Blink(data) => data.handle_event(&j, action),
}; };
local_emitter.append(&mut state_update.local_events); local_emitter.append(&mut state_update.local_events);
server_emitter.append(&mut state_update.server_events); server_emitter.append(&mut state_update.server_events);
@ -354,6 +355,7 @@ impl<'a> System<'a> for Sys {
CharacterState::BasicBeam(data) => data.behavior(&j), CharacterState::BasicBeam(data) => data.behavior(&j),
CharacterState::BasicAura(data) => data.behavior(&j), CharacterState::BasicAura(data) => data.behavior(&j),
CharacterState::HealingBeam(data) => data.behavior(&j), CharacterState::HealingBeam(data) => data.behavior(&j),
CharacterState::Blink(data) => data.behavior(&j),
}; };
local_emitter.append(&mut state_update.local_events); local_emitter.append(&mut state_update.local_events);

View File

@ -489,6 +489,7 @@ impl State {
let events = self.ecs.read_resource::<EventBus<LocalEvent>>().recv_all(); let events = self.ecs.read_resource::<EventBus<LocalEvent>>().recv_all();
for event in events { for event in events {
let mut velocities = self.ecs.write_storage::<comp::Vel>(); let mut velocities = self.ecs.write_storage::<comp::Vel>();
let mut positions = self.ecs.write_storage::<comp::Pos>();
let physics = self.ecs.read_storage::<comp::PhysicsState>(); let physics = self.ecs.read_storage::<comp::PhysicsState>();
match event { match event {
LocalEvent::Jump(entity, impulse) => { LocalEvent::Jump(entity, impulse) => {
@ -509,6 +510,11 @@ impl State {
vel.0 += extra_vel; vel.0 += extra_vel;
} }
}, },
LocalEvent::PositionUpdate { entity, pos } => {
if let Some(position) = positions.get_mut(entity) {
*position = pos;
}
},
} }
} }
drop(guard); drop(guard);

View File

@ -246,7 +246,8 @@ impl<'a> System<'a> for Sys {
| CharacterState::Shockwave { .. } | CharacterState::Shockwave { .. }
| CharacterState::BasicBeam { .. } | CharacterState::BasicBeam { .. }
| CharacterState::BasicAura { .. } | CharacterState::BasicAura { .. }
| CharacterState::HealingBeam { .. } => { | CharacterState::HealingBeam { .. }
| CharacterState::Blink { .. } => {
if energy.get_unchecked().regen_rate != 0.0 { if energy.get_unchecked().regen_rate != 0.0 {
energy.get_mut_unchecked().regen_rate = 0.0 energy.get_mut_unchecked().regen_rate = 0.0
} }

View File

@ -110,6 +110,7 @@ impl Client {
| ServerGeneral::SiteEconomy(_) | ServerGeneral::SiteEconomy(_)
| ServerGeneral::Outcomes(_) | ServerGeneral::Outcomes(_)
| ServerGeneral::Knockback(_) | ServerGeneral::Knockback(_)
| ServerGeneral::PositionUpdate(_)
| ServerGeneral::UpdatePendingTrade(_, _, _) | ServerGeneral::UpdatePendingTrade(_, _, _)
| ServerGeneral::FinishedTrade(_) => { | ServerGeneral::FinishedTrade(_) => {
self.in_game_stream.lock().unwrap().send(g) self.in_game_stream.lock().unwrap().send(g)
@ -180,6 +181,7 @@ impl Client {
| ServerGeneral::SetViewDistance(_) | ServerGeneral::SetViewDistance(_)
| ServerGeneral::Outcomes(_) | ServerGeneral::Outcomes(_)
| ServerGeneral::Knockback(_) | ServerGeneral::Knockback(_)
| ServerGeneral::PositionUpdate(_)
| ServerGeneral::SiteEconomy(_) | ServerGeneral::SiteEconomy(_)
| ServerGeneral::UpdatePendingTrade(_, _, _) | ServerGeneral::UpdatePendingTrade(_, _, _)
| ServerGeneral::FinishedTrade(_) => { | ServerGeneral::FinishedTrade(_) => {

View File

@ -941,3 +941,25 @@ pub fn handle_combo_change(server: &Server, entity: EcsEntity, change: i32) {
} }
} }
} }
pub fn handle_teleport_to(server: &Server, entity: EcsEntity, target: Uid, max_range: Option<f32>) {
let ecs = &server.state.ecs();
let mut positions = ecs.write_storage::<Pos>();
let clients = ecs.read_storage::<Client>();
let target_pos = server
.state
.ecs()
.entity_from_uid(target.into())
.and_then(|e| positions.get(e))
.copied();
if let (Some(pos), Some(target_pos)) = (positions.get_mut(entity), target_pos) {
if max_range.map_or(true, |r| pos.0.distance_squared(target_pos.0) < r.powi(2)) {
*pos = target_pos;
if let Some(client) = clients.get(entity) {
client.send_fallible(ServerGeneral::PositionUpdate(target_pos));
}
}
}
}

View File

@ -8,7 +8,7 @@ use entity_creation::{
use entity_manipulation::{ use entity_manipulation::{
handle_aura, handle_buff, handle_combo_change, handle_damage, handle_delete, handle_destroy, handle_aura, handle_buff, handle_combo_change, handle_damage, handle_delete, handle_destroy,
handle_energy_change, handle_explosion, handle_knockback, handle_land_on_ground, handle_poise, handle_energy_change, handle_explosion, handle_knockback, handle_land_on_ground, handle_poise,
handle_respawn, handle_respawn, handle_teleport_to,
}; };
use group_manip::handle_group; use group_manip::handle_group;
use information::handle_site_info; use information::handle_site_info;
@ -199,6 +199,11 @@ impl Server {
}, },
ServerEvent::RequestSiteInfo { entity, id } => handle_site_info(&self, entity, id), ServerEvent::RequestSiteInfo { entity, id } => handle_site_info(&self, entity, id),
ServerEvent::MineBlock { pos, tool } => handle_mine_block(self, pos, tool), ServerEvent::MineBlock { pos, tool } => handle_mine_block(self, pos, tool),
ServerEvent::TeleportTo {
entity,
target,
max_range,
} => handle_teleport_to(&self, entity, target, max_range),
} }
} }

View File

@ -363,6 +363,7 @@ impl<'a> System<'a> for Sys {
tgt_pos, tgt_pos,
read_data.bodies.get(attacker), read_data.bodies.get(attacker),
&read_data.dt, &read_data.dt,
&read_data,
); );
} }
} }
@ -443,6 +444,7 @@ impl<'a> System<'a> for Sys {
tgt_pos, tgt_pos,
read_data.bodies.get(attacker), read_data.bodies.get(attacker),
&read_data.dt, &read_data.dt,
&read_data,
); );
// Remember this encounter if an RtSim entity // Remember this encounter if an RtSim entity
if let Some(tgt_stats) = if let Some(tgt_stats) =
@ -604,6 +606,7 @@ impl<'a> AgentData<'a> {
tgt_pos, tgt_pos,
read_data.bodies.get(target), read_data.bodies.get(target),
&read_data.dt, &read_data.dt,
&read_data,
); );
} else { } else {
agent.target = None; agent.target = None;
@ -1177,6 +1180,7 @@ impl<'a> AgentData<'a> {
} }
} }
#[allow(clippy::too_many_arguments)]
fn attack( fn attack(
&self, &self,
agent: &mut Agent, agent: &mut Agent,
@ -1185,6 +1189,7 @@ impl<'a> AgentData<'a> {
tgt_pos: &Pos, tgt_pos: &Pos,
tgt_body: Option<&Body>, tgt_body: Option<&Body>,
dt: &DeltaTime, dt: &DeltaTime,
_read_data: &ReadData,
) { ) {
let min_attack_dist = self.body.map_or(3.0, |b| b.radius() * self.scale + 2.0); let min_attack_dist = self.body.map_or(3.0, |b| b.radius() * self.scale + 2.0);
let tactic = match self let tactic = match self

View File

@ -390,7 +390,12 @@ impl PlayState for SessionState {
client.remove_block(select_pos.map(|e| e.floor() as i32)); client.remove_block(select_pos.map(|e| e.floor() as i32));
} }
} else { } else {
client.handle_input(InputKind::Primary, state, select_pos); client.handle_input(
InputKind::Primary,
state,
select_pos,
target_entity.map(|t| t.0),
);
} }
}, },
GameInput::Secondary => { GameInput::Secondary => {
@ -404,7 +409,12 @@ impl PlayState for SessionState {
); );
} }
} else { } else {
client.handle_input(InputKind::Secondary, state, select_pos); client.handle_input(
InputKind::Secondary,
state,
select_pos,
target_entity.map(|t| t.0),
);
} }
}, },
GameInput::Roll => { GameInput::Roll => {
@ -423,7 +433,12 @@ impl PlayState for SessionState {
} }
} }
} else { } else {
client.handle_input(InputKind::Roll, state, select_pos); client.handle_input(
InputKind::Roll,
state,
select_pos,
target_entity.map(|t| t.0),
);
} }
}, },
GameInput::Respawn => { GameInput::Respawn => {
@ -434,7 +449,12 @@ impl PlayState for SessionState {
}, },
GameInput::Jump => { GameInput::Jump => {
let mut client = self.client.borrow_mut(); let mut client = self.client.borrow_mut();
client.handle_input(InputKind::Jump, state, select_pos); client.handle_input(
InputKind::Jump,
state,
select_pos,
target_entity.map(|t| t.0),
);
}, },
GameInput::SwimUp => { GameInput::SwimUp => {
self.key_state.swim_up = state; self.key_state.swim_up = state;
@ -495,7 +515,12 @@ impl PlayState for SessionState {
// controller change // controller change
self.key_state.fly ^= state; self.key_state.fly ^= state;
let mut client = self.client.borrow_mut(); let mut client = self.client.borrow_mut();
client.handle_input(InputKind::Fly, self.key_state.fly, select_pos); client.handle_input(
InputKind::Fly,
self.key_state.fly,
select_pos,
target_entity.map(|t| t.0),
);
}, },
GameInput::Climb => { GameInput::Climb => {
self.key_state.climb_up = state; self.key_state.climb_up = state;
@ -1254,11 +1279,21 @@ impl PlayState for SessionState {
}, },
HudEvent::Ability3(state) => { HudEvent::Ability3(state) => {
let mut client = self.client.borrow_mut(); let mut client = self.client.borrow_mut();
client.handle_input(InputKind::Ability(0), state, select_pos); client.handle_input(
InputKind::Ability(0),
state,
select_pos,
target_entity.map(|t| t.0),
);
}, },
HudEvent::Ability4(state) => { HudEvent::Ability4(state) => {
let mut client = self.client.borrow_mut(); let mut client = self.client.borrow_mut();
client.handle_input(InputKind::Ability(1), state, select_pos); client.handle_input(
InputKind::Ability(1),
state,
select_pos,
target_entity.map(|t| t.0),
);
}, },
HudEvent::ChangeFOV(new_fov) => { HudEvent::ChangeFOV(new_fov) => {
global_state.settings.graphics.fov = new_fov; global_state.settings.graphics.fov = new_fov;