mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added dimensional door ability for mindflayer
This commit is contained in:
parent
f1156c9ce5
commit
30da614e89
@ -1 +1,5 @@
|
|||||||
BasicBlock
|
Blink(
|
||||||
|
buildup_duration: 0.5,
|
||||||
|
recover_duration: 0.25,
|
||||||
|
max_range: 100.0,
|
||||||
|
)
|
@ -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));
|
||||||
|
@ -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(_) => {
|
||||||
|
@ -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,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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)]
|
||||||
|
@ -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> {
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
94
common/src/states/blink.rs
Normal file
94
common/src/states/blink.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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(_) => {
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user