mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/yeet-inputs' into 'master'
Reworked Controller Inputs to use Control Actions See merge request veloren/veloren!1900
This commit is contained in:
commit
5570b57282
@ -11,5 +11,4 @@ BasicRanged(
|
|||||||
projectile_light: None,
|
projectile_light: None,
|
||||||
projectile_gravity: Some(Gravity(0.2)),
|
projectile_gravity: Some(Gravity(0.2)),
|
||||||
projectile_speed: 100.0,
|
projectile_speed: 100.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -11,5 +11,4 @@ BasicRanged(
|
|||||||
projectile_light: None,
|
projectile_light: None,
|
||||||
projectile_gravity: Some(Gravity(0.2)),
|
projectile_gravity: Some(Gravity(0.2)),
|
||||||
projectile_speed: 100.0,
|
projectile_speed: 100.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -10,5 +10,4 @@ BasicRanged(
|
|||||||
}),*/
|
}),*/
|
||||||
projectile_gravity: None,
|
projectile_gravity: None,
|
||||||
projectile_speed: 100.0,
|
projectile_speed: 100.0,
|
||||||
can_continue: false,
|
|
||||||
)
|
)
|
@ -14,5 +14,4 @@ BasicRanged(
|
|||||||
}),*/
|
}),*/
|
||||||
projectile_gravity: Some(Gravity(0.3)),
|
projectile_gravity: Some(Gravity(0.3)),
|
||||||
projectile_speed: 60.0,
|
projectile_speed: 60.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -14,5 +14,4 @@ BasicRanged(
|
|||||||
}),*/
|
}),*/
|
||||||
projectile_gravity: Some(Gravity(0.3)),
|
projectile_gravity: Some(Gravity(0.3)),
|
||||||
projectile_speed: 60.0,
|
projectile_speed: 60.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -14,5 +14,4 @@ BasicRanged(
|
|||||||
}),*/
|
}),*/
|
||||||
projectile_gravity: Some(Gravity(5.0)),
|
projectile_gravity: Some(Gravity(5.0)),
|
||||||
projectile_speed: 70.0,
|
projectile_speed: 70.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -11,5 +11,4 @@ BasicRanged(
|
|||||||
projectile_light: None,
|
projectile_light: None,
|
||||||
projectile_gravity: Some(Gravity(0.1)),
|
projectile_gravity: Some(Gravity(0.1)),
|
||||||
projectile_speed: 100.0,
|
projectile_speed: 100.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -13,5 +13,4 @@ BasicRanged(
|
|||||||
}),*/
|
}),*/
|
||||||
projectile_gravity: Some(Gravity(0.3)),
|
projectile_gravity: Some(Gravity(0.3)),
|
||||||
projectile_speed: 60.0,
|
projectile_speed: 60.0,
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ use common::{
|
|||||||
invite::{InviteKind, InviteResponse},
|
invite::{InviteKind, InviteResponse},
|
||||||
skills::Skill,
|
skills::Skill,
|
||||||
slot::Slot,
|
slot::Slot,
|
||||||
ChatMode, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip,
|
ChatMode, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip, InputKind,
|
||||||
InventoryAction, InventoryEvent, InventoryUpdateEvent,
|
InventoryAction, InventoryEvent, InventoryUpdateEvent,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent},
|
event::{EventBus, LocalEvent},
|
||||||
@ -60,7 +60,7 @@ use num::traits::FloatConst;
|
|||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use specs::Component;
|
use specs::Component;
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::{BTreeSet, VecDeque},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
@ -997,6 +997,17 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_input(&mut self, input: InputKind, pressed: bool) {
|
||||||
|
if pressed {
|
||||||
|
self.control_action(ControlAction::StartInput {
|
||||||
|
input,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.control_action(ControlAction::CancelInput(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn control_action(&mut self, control_action: ControlAction) {
|
fn control_action(&mut self, control_action: ControlAction) {
|
||||||
if let Some(controller) = self
|
if let Some(controller) = self
|
||||||
.state
|
.state
|
||||||
@ -1139,6 +1150,7 @@ impl Client {
|
|||||||
entry
|
entry
|
||||||
.or_insert_with(|| Controller {
|
.or_insert_with(|| Controller {
|
||||||
inputs: inputs.clone(),
|
inputs: inputs.clone(),
|
||||||
|
queued_inputs: BTreeSet::new(),
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
actions: Vec::new(),
|
actions: Vec::new(),
|
||||||
})
|
})
|
||||||
|
@ -75,7 +75,6 @@ pub enum CharacterAbility {
|
|||||||
projectile_light: Option<LightEmitter>,
|
projectile_light: Option<LightEmitter>,
|
||||||
projectile_gravity: Option<Gravity>,
|
projectile_gravity: Option<Gravity>,
|
||||||
projectile_speed: f32,
|
projectile_speed: f32,
|
||||||
can_continue: bool,
|
|
||||||
},
|
},
|
||||||
RepeaterRanged {
|
RepeaterRanged {
|
||||||
energy_cost: f32,
|
energy_cost: f32,
|
||||||
@ -1130,7 +1129,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
projectile_light,
|
projectile_light,
|
||||||
projectile_gravity,
|
projectile_gravity,
|
||||||
projectile_speed,
|
projectile_speed,
|
||||||
can_continue,
|
|
||||||
energy_cost: _,
|
energy_cost: _,
|
||||||
} => CharacterState::BasicRanged(basic_ranged::Data {
|
} => CharacterState::BasicRanged(basic_ranged::Data {
|
||||||
static_data: basic_ranged::StaticData {
|
static_data: basic_ranged::StaticData {
|
||||||
@ -1141,13 +1139,11 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
projectile_light: *projectile_light,
|
projectile_light: *projectile_light,
|
||||||
projectile_gravity: *projectile_gravity,
|
projectile_gravity: *projectile_gravity,
|
||||||
projectile_speed: *projectile_speed,
|
projectile_speed: *projectile_speed,
|
||||||
can_continue: *can_continue,
|
|
||||||
ability_info,
|
ability_info,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
exhausted: false,
|
exhausted: false,
|
||||||
continue_next: false,
|
|
||||||
}),
|
}),
|
||||||
CharacterAbility::Boost {
|
CharacterAbility::Boost {
|
||||||
movement_duration,
|
movement_duration,
|
||||||
@ -1156,6 +1152,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
static_data: boost::StaticData {
|
static_data: boost::StaticData {
|
||||||
movement_duration: Duration::from_secs_f32(*movement_duration),
|
movement_duration: Duration::from_secs_f32(*movement_duration),
|
||||||
only_up: *only_up,
|
only_up: *only_up,
|
||||||
|
ability_info,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
}),
|
}),
|
||||||
@ -1250,7 +1247,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
stage: 1,
|
stage: 1,
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
next_stage: false,
|
|
||||||
}),
|
}),
|
||||||
CharacterAbility::LeapMelee {
|
CharacterAbility::LeapMelee {
|
||||||
energy_cost: _,
|
energy_cost: _,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
combat::Attack,
|
combat::Attack,
|
||||||
comp::{Energy, Ori, Pos, Vel},
|
comp::{Energy, InputKind, Ori, Pos, Vel},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
states::{behavior::JoinData, *},
|
states::{behavior::JoinData, *},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DerefFlaggedStorage, VecStorage};
|
use specs::{Component, DerefFlaggedStorage, VecStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::collections::VecDeque;
|
use std::collections::{BTreeSet, VecDeque};
|
||||||
|
|
||||||
/// Data returned from character behavior fn's to Character Behavior System.
|
/// Data returned from character behavior fn's to Character Behavior System.
|
||||||
pub struct StateUpdate {
|
pub struct StateUpdate {
|
||||||
@ -17,6 +17,8 @@ pub struct StateUpdate {
|
|||||||
pub ori: Ori,
|
pub ori: Ori,
|
||||||
pub energy: Energy,
|
pub energy: Energy,
|
||||||
pub swap_equipped_weapons: bool,
|
pub swap_equipped_weapons: bool,
|
||||||
|
pub queued_inputs: BTreeSet<InputKind>,
|
||||||
|
pub removed_inputs: Vec<InputKind>,
|
||||||
pub local_events: VecDeque<LocalEvent>,
|
pub local_events: VecDeque<LocalEvent>,
|
||||||
pub server_events: VecDeque<ServerEvent>,
|
pub server_events: VecDeque<ServerEvent>,
|
||||||
}
|
}
|
||||||
@ -30,6 +32,8 @@ impl From<&JoinData<'_>> for StateUpdate {
|
|||||||
energy: *data.energy,
|
energy: *data.energy,
|
||||||
swap_equipped_weapons: false,
|
swap_equipped_weapons: false,
|
||||||
character: data.character.clone(),
|
character: data.character.clone(),
|
||||||
|
queued_inputs: BTreeSet::new(),
|
||||||
|
removed_inputs: Vec::new(),
|
||||||
local_events: VecDeque::new(),
|
local_events: VecDeque::new(),
|
||||||
server_events: VecDeque::new(),
|
server_events: VecDeque::new(),
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,9 @@ use crate::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DerefFlaggedStorage};
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::time::Duration;
|
use std::collections::BTreeSet;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// Default duration before an input is considered 'held'.
|
|
||||||
pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum InventoryEvent {
|
pub enum InventoryEvent {
|
||||||
Pickup(Uid),
|
Pickup(Uid),
|
||||||
@ -111,108 +108,27 @@ pub enum ControlAction {
|
|||||||
Sneak,
|
Sneak,
|
||||||
Stand,
|
Stand,
|
||||||
Talk,
|
Talk,
|
||||||
|
StartInput {
|
||||||
|
input: InputKind,
|
||||||
|
target: Option<Uid>,
|
||||||
|
},
|
||||||
|
CancelInput(InputKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)]
|
||||||
enum Freshness {
|
#[repr(u32)]
|
||||||
New,
|
pub enum InputKind {
|
||||||
TickedOnce,
|
Primary = 0,
|
||||||
Old,
|
Secondary = 1,
|
||||||
|
Ability(usize) = 2,
|
||||||
|
Roll = 3,
|
||||||
|
Jump = 4,
|
||||||
|
Fly = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a key is pressed or unpressed
|
impl InputKind {
|
||||||
/// and how long it has been in that state
|
pub fn is_ability(self) -> bool {
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
matches!(self, Self::Primary | Self::Secondary | Self::Ability(_))
|
||||||
pub struct Input {
|
|
||||||
/// Should not be pub because duration should
|
|
||||||
/// always be reset when state is updated
|
|
||||||
pressed: bool,
|
|
||||||
/// Should only be updated by npc agents
|
|
||||||
/// through appropriate fn
|
|
||||||
duration: Duration,
|
|
||||||
/// How fresh is the last change to the input state
|
|
||||||
freshness: Freshness,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Input {
|
|
||||||
fn tick(&mut self, dt: Duration) {
|
|
||||||
// Increase how long input has been in current state
|
|
||||||
self.duration = self.duration.checked_add(dt).unwrap_or_default();
|
|
||||||
self.tick_freshness();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tick_freshness(&mut self) {
|
|
||||||
self.freshness = match self.freshness {
|
|
||||||
Freshness::New => Freshness::TickedOnce,
|
|
||||||
Freshness::TickedOnce => Freshness::Old,
|
|
||||||
Freshness::Old => Freshness::Old,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update input with newer version
|
|
||||||
/// Used to update inputs with input received from clients
|
|
||||||
pub fn update_with_new(&mut self, new: Self) {
|
|
||||||
if self.pressed != new.pressed {
|
|
||||||
self.freshness = Freshness::New;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.pressed = new.pressed;
|
|
||||||
self.duration = new.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether input is being pressed down
|
|
||||||
pub fn is_pressed(&self) -> bool { self.pressed }
|
|
||||||
|
|
||||||
/// Whether it's the first frame this input has been pressed
|
|
||||||
pub fn is_just_pressed(&self) -> bool { self.is_pressed() && self.freshness != Freshness::Old }
|
|
||||||
|
|
||||||
/// Whether it's the first frame this input has been unpressed
|
|
||||||
pub fn is_just_unpressed(&self) -> bool {
|
|
||||||
!self.is_pressed() && self.freshness != Freshness::Old
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether input has been pressed longer than
|
|
||||||
/// `DEFAULT_HOLD_DURATION`
|
|
||||||
pub fn is_held_down(&self) -> bool {
|
|
||||||
self.is_pressed() && self.duration >= DEFAULT_HOLD_DURATION
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether input has been unpressed longer than
|
|
||||||
/// `DEFAULT_HOLD_DURATION`
|
|
||||||
pub fn is_held_up(&self) -> bool {
|
|
||||||
!self.is_pressed() && self.duration >= DEFAULT_HOLD_DURATION
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether input has been pressed for longer than `threshold` duration
|
|
||||||
pub fn held_for_dur(&self, threshold: Duration) -> bool {
|
|
||||||
self.is_pressed() && self.duration >= threshold
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handles logic of updating state of Input
|
|
||||||
pub fn set_state(&mut self, pressed: bool) {
|
|
||||||
if self.pressed != pressed {
|
|
||||||
self.pressed = pressed;
|
|
||||||
self.duration = Duration::default();
|
|
||||||
self.freshness = Freshness::New;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Increases `input.duration` by `dur`
|
|
||||||
pub fn inc_dur(&mut self, dur: Duration) {
|
|
||||||
self.duration = self.duration.checked_add(dur).unwrap_or_default();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `input.duration`
|
|
||||||
pub fn get_dur(&self) -> Duration { self.duration }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Input {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
pressed: false,
|
|
||||||
duration: Duration::default(),
|
|
||||||
freshness: Freshness::New,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,16 +141,6 @@ pub enum Climb {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ControllerInputs {
|
pub struct ControllerInputs {
|
||||||
pub primary: Input,
|
|
||||||
pub secondary: Input,
|
|
||||||
pub ability3: Input,
|
|
||||||
pub ability4: Input,
|
|
||||||
pub jump: Input,
|
|
||||||
pub roll: Input,
|
|
||||||
pub glide: Input,
|
|
||||||
pub fly: Input, // Flying entities only
|
|
||||||
pub wall_leap: Input,
|
|
||||||
pub charge: Input,
|
|
||||||
pub climb: Option<Climb>,
|
pub climb: Option<Climb>,
|
||||||
pub move_dir: Vec2<f32>,
|
pub move_dir: Vec2<f32>,
|
||||||
pub move_z: f32, /* z axis (not combined with move_dir because they may have independent
|
pub move_z: f32, /* z axis (not combined with move_dir because they may have independent
|
||||||
@ -245,63 +151,20 @@ pub struct ControllerInputs {
|
|||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
pub inputs: ControllerInputs,
|
pub inputs: ControllerInputs,
|
||||||
|
pub queued_inputs: BTreeSet<InputKind>,
|
||||||
// TODO: consider SmallVec
|
// TODO: consider SmallVec
|
||||||
pub events: Vec<ControlEvent>,
|
pub events: Vec<ControlEvent>,
|
||||||
pub actions: Vec<ControlAction>,
|
pub actions: Vec<ControlAction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControllerInputs {
|
impl ControllerInputs {
|
||||||
/// Updates all inputs, accounting for delta time
|
|
||||||
pub fn tick(&mut self, dt: Duration) {
|
|
||||||
self.primary.tick(dt);
|
|
||||||
self.secondary.tick(dt);
|
|
||||||
self.ability3.tick(dt);
|
|
||||||
self.ability4.tick(dt);
|
|
||||||
self.jump.tick(dt);
|
|
||||||
self.roll.tick(dt);
|
|
||||||
self.glide.tick(dt);
|
|
||||||
self.fly.tick(dt);
|
|
||||||
self.wall_leap.tick(dt);
|
|
||||||
self.charge.tick(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tick_freshness(&mut self) {
|
|
||||||
self.primary.tick_freshness();
|
|
||||||
self.secondary.tick_freshness();
|
|
||||||
self.ability3.tick_freshness();
|
|
||||||
self.ability4.tick_freshness();
|
|
||||||
self.jump.tick_freshness();
|
|
||||||
self.roll.tick_freshness();
|
|
||||||
self.glide.tick_freshness();
|
|
||||||
self.fly.tick_freshness();
|
|
||||||
self.wall_leap.tick_freshness();
|
|
||||||
self.charge.tick_freshness();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates Controller inputs with new version received from the client
|
/// Updates Controller inputs with new version received from the client
|
||||||
pub fn update_with_new(&mut self, new: Self) {
|
pub fn update_with_new(&mut self, new: Self) {
|
||||||
self.primary.update_with_new(new.primary);
|
|
||||||
self.secondary.update_with_new(new.secondary);
|
|
||||||
self.ability3.update_with_new(new.ability3);
|
|
||||||
self.ability4.update_with_new(new.ability4);
|
|
||||||
self.jump.update_with_new(new.jump);
|
|
||||||
self.roll.update_with_new(new.roll);
|
|
||||||
self.glide.update_with_new(new.glide);
|
|
||||||
self.fly.update_with_new(new.fly);
|
|
||||||
self.wall_leap.update_with_new(new.wall_leap);
|
|
||||||
self.charge.update_with_new(new.charge);
|
|
||||||
self.climb = new.climb;
|
self.climb = new.climb;
|
||||||
self.move_dir = new.move_dir;
|
self.move_dir = new.move_dir;
|
||||||
self.move_z = new.move_z;
|
self.move_z = new.move_z;
|
||||||
self.look_dir = new.look_dir;
|
self.look_dir = new.look_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn holding_ability_key(&self) -> bool {
|
|
||||||
self.primary.is_pressed()
|
|
||||||
|| self.secondary.is_pressed()
|
|
||||||
|| self.ability3.is_pressed()
|
|
||||||
|| self.ability4.is_pressed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Controller {
|
impl Controller {
|
||||||
|
@ -61,7 +61,7 @@ pub use self::{
|
|||||||
},
|
},
|
||||||
combo::Combo,
|
combo::Combo,
|
||||||
controller::{
|
controller::{
|
||||||
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip, Input,
|
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, GroupManip, InputKind,
|
||||||
InventoryAction, InventoryEvent, InventoryManip, MountState, Mounting,
|
InventoryAction, InventoryEvent, InventoryManip, MountState, Mounting,
|
||||||
},
|
},
|
||||||
energy::{Energy, EnergyChange, EnergySource},
|
energy::{Energy, EnergyChange, EnergySource},
|
||||||
|
@ -51,15 +51,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.8);
|
handle_move(data, &mut update, 0.8);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::BasicAura(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -132,6 +123,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,15 +71,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.4);
|
handle_move(data, &mut update, 0.4);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::BasicBeam(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -108,7 +99,7 @@ impl CharacterBehavior for Data {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
StageSection::Cast => {
|
StageSection::Cast => {
|
||||||
if ability_key_is_pressed(data, self.static_data.ability_info.key)
|
if input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
&& (self.static_data.energy_drain <= f32::EPSILON
|
&& (self.static_data.energy_drain <= f32::EPSILON
|
||||||
|| update.energy.current() > 0)
|
|| update.energy.current() > 0)
|
||||||
{
|
{
|
||||||
@ -203,6 +194,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(&data, &mut update, 0.4);
|
handle_move(&data, &mut update, 0.4);
|
||||||
|
|
||||||
if !data.physics.on_ground
|
|
||||||
|| !(data.inputs.secondary.is_pressed() || data.inputs.primary.is_pressed())
|
|
||||||
{
|
|
||||||
attempt_wield(data, &mut update);
|
|
||||||
}
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,15 +52,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.7);
|
handle_move(data, &mut update, 0.7);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::BasicMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -162,9 +153,11 @@ impl CharacterBehavior for Data {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
update.character = CharacterState::Wielding;
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
// Make sure attack component is removed
|
reset_state(self, data, &mut update);
|
||||||
data.updater.remove::<Melee>(data.entity);
|
} else {
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -175,6 +168,15 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {
|
||||||
|
handle_input(join, update, data.static_data.ability_info.input);
|
||||||
|
}
|
||||||
|
@ -24,8 +24,6 @@ pub struct StaticData {
|
|||||||
pub projectile_speed: f32,
|
pub projectile_speed: f32,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
/// Whether or not the ability can auto continue
|
|
||||||
pub can_continue: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -39,9 +37,6 @@ pub struct Data {
|
|||||||
pub stage_section: StageSection,
|
pub stage_section: StageSection,
|
||||||
/// Whether the attack fired already
|
/// Whether the attack fired already
|
||||||
pub exhausted: bool,
|
pub exhausted: bool,
|
||||||
/// If in buildup, whether the attack has continued form previous attack; if
|
|
||||||
/// in recover, whether the attack will continue to a new attack
|
|
||||||
pub continue_next: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterBehavior for Data {
|
impl CharacterBehavior for Data {
|
||||||
@ -50,15 +45,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.3);
|
handle_move(data, &mut update, 0.3);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::BasicRanged(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -103,41 +89,24 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
update.character = CharacterState::BasicRanged(Data {
|
update.character = CharacterState::BasicRanged(Data {
|
||||||
exhausted: true,
|
exhausted: true,
|
||||||
continue_next: false,
|
|
||||||
..*self
|
..*self
|
||||||
});
|
});
|
||||||
} else if self.timer < self.static_data.recover_duration {
|
} else if self.timer < self.static_data.recover_duration {
|
||||||
if ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
// Recovers
|
||||||
// Recovers
|
|
||||||
update.character = CharacterState::BasicRanged(Data {
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
continue_next: self.static_data.can_continue,
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Recovers
|
|
||||||
update.character = CharacterState::BasicRanged(Data {
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if self.continue_next {
|
|
||||||
// Restarts character state
|
|
||||||
update.character = CharacterState::BasicRanged(Data {
|
update.character = CharacterState::BasicRanged(Data {
|
||||||
timer: Duration::default(),
|
timer: self
|
||||||
stage_section: StageSection::Buildup,
|
.timer
|
||||||
exhausted: false,
|
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
..*self
|
..*self
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
update.character = CharacterState::Wielding;
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
reset_state(self, data, &mut update);
|
||||||
|
} else {
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -146,6 +115,15 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {
|
||||||
|
handle_input(join, update, data.static_data.ability_info.input);
|
||||||
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction, Controller,
|
item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction, Controller,
|
||||||
ControllerInputs, Energy, Health, Inventory, InventoryAction, Melee, Ori, PhysicsState,
|
ControllerInputs, Energy, Health, InputKind, Inventory, InventoryAction, Melee, Ori,
|
||||||
Pos, StateUpdate, Stats, Vel,
|
PhysicsState, Pos, StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
@ -29,6 +29,16 @@ pub trait CharacterBehavior {
|
|||||||
fn sneak(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
fn sneak(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
||||||
fn stand(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
fn stand(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
||||||
fn talk(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
fn talk(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
|
||||||
|
fn start_input(&self, data: &JoinData, input: InputKind, _target: Option<Uid>) -> StateUpdate {
|
||||||
|
let mut update = StateUpdate::from(data);
|
||||||
|
update.queued_inputs.insert(input);
|
||||||
|
update
|
||||||
|
}
|
||||||
|
fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
|
||||||
|
let mut update = StateUpdate::from(data);
|
||||||
|
update.removed_inputs.push(input);
|
||||||
|
update
|
||||||
|
}
|
||||||
fn handle_event(&self, data: &JoinData, event: ControlAction) -> StateUpdate {
|
fn handle_event(&self, data: &JoinData, event: ControlAction) -> StateUpdate {
|
||||||
match event {
|
match event {
|
||||||
ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data),
|
ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data),
|
||||||
@ -41,6 +51,8 @@ pub trait CharacterBehavior {
|
|||||||
ControlAction::Sneak => self.sneak(data),
|
ControlAction::Sneak => self.sneak(data),
|
||||||
ControlAction::Stand => self.stand(data),
|
ControlAction::Stand => self.stand(data),
|
||||||
ControlAction::Talk => self.talk(data),
|
ControlAction::Talk => self.talk(data),
|
||||||
|
ControlAction::StartInput { input, target } => self.start_input(data, input, target),
|
||||||
|
ControlAction::CancelInput(input) => self.cancel_input(data, input),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fn init(data: &JoinData) -> CharacterState;
|
// fn init(data: &JoinData) -> CharacterState;
|
||||||
|
@ -13,6 +13,7 @@ use std::time::Duration;
|
|||||||
pub struct StaticData {
|
pub struct StaticData {
|
||||||
pub movement_duration: Duration,
|
pub movement_duration: Duration,
|
||||||
pub only_up: bool,
|
pub only_up: bool,
|
||||||
|
pub ability_info: AbilityInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -46,9 +47,17 @@ impl CharacterBehavior for Data {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
update.character = CharacterState::Wielding;
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
reset_state(self, data, &mut update);
|
||||||
|
} else {
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {
|
||||||
|
handle_input(join, update, data.static_data.ability_info.input);
|
||||||
|
}
|
||||||
|
@ -68,19 +68,10 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.7);
|
handle_move(data, &mut update, 0.7);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::ChargedMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Charge => {
|
StageSection::Charge => {
|
||||||
if ability_key_is_pressed(data, self.static_data.ability_info.key)
|
if input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
&& update.energy.current() as f32 >= self.static_data.energy_cost
|
&& update.energy.current() as f32 >= self.static_data.energy_cost
|
||||||
&& self.timer < self.static_data.charge_duration
|
&& self.timer < self.static_data.charge_duration
|
||||||
{
|
{
|
||||||
@ -107,7 +98,7 @@ impl CharacterBehavior for Data {
|
|||||||
* self.static_data.speed) as i32,
|
* self.static_data.speed) as i32,
|
||||||
source: EnergySource::Ability,
|
source: EnergySource::Ability,
|
||||||
});
|
});
|
||||||
} else if ability_key_is_pressed(data, self.static_data.ability_info.key)
|
} else if input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
&& update.energy.current() as f32 >= self.static_data.energy_cost
|
&& update.energy.current() as f32 >= self.static_data.energy_cost
|
||||||
{
|
{
|
||||||
// Maintains charge
|
// Maintains charge
|
||||||
@ -240,6 +231,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,15 +68,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, self.static_data.move_speed);
|
handle_move(data, &mut update, self.static_data.move_speed);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::ChargedRanged(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -99,9 +90,7 @@ impl CharacterBehavior for Data {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
StageSection::Charge => {
|
StageSection::Charge => {
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key)
|
if !input_is_pressed(data, self.static_data.ability_info.input) && !self.exhausted {
|
||||||
&& !self.exhausted
|
|
||||||
{
|
|
||||||
let charge_frac = (self.timer.as_secs_f32()
|
let charge_frac = (self.timer.as_secs_f32()
|
||||||
/ self.static_data.charge_duration.as_secs_f32())
|
/ self.static_data.charge_duration.as_secs_f32())
|
||||||
.min(1.0);
|
.min(1.0);
|
||||||
@ -162,7 +151,7 @@ impl CharacterBehavior for Data {
|
|||||||
..*self
|
..*self
|
||||||
});
|
});
|
||||||
} else if self.timer < self.static_data.charge_duration
|
} else if self.timer < self.static_data.charge_duration
|
||||||
&& ability_key_is_pressed(data, self.static_data.ability_info.key)
|
&& input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
{
|
{
|
||||||
// Charges
|
// Charges
|
||||||
update.character = CharacterState::ChargedRanged(Data {
|
update.character = CharacterState::ChargedRanged(Data {
|
||||||
@ -182,7 +171,7 @@ impl CharacterBehavior for Data {
|
|||||||
* self.static_data.speed) as i32,
|
* self.static_data.speed) as i32,
|
||||||
source: EnergySource::Ability,
|
source: EnergySource::Ability,
|
||||||
});
|
});
|
||||||
} else if ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
} else if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
// Holds charge
|
// Holds charge
|
||||||
update.character = CharacterState::ChargedRanged(Data {
|
update.character = CharacterState::ChargedRanged(Data {
|
||||||
timer: self
|
timer: self
|
||||||
@ -225,6 +214,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{CharacterState, Climb, EnergySource, Ori, StateUpdate},
|
comp::{CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate},
|
||||||
consts::GRAVITY,
|
consts::GRAVITY,
|
||||||
event::LocalEvent,
|
event::LocalEvent,
|
||||||
states::behavior::{CharacterBehavior, JoinData},
|
states::{
|
||||||
|
behavior::{CharacterBehavior, JoinData},
|
||||||
|
utils::*,
|
||||||
|
},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -29,7 +32,7 @@ impl CharacterBehavior for Data {
|
|||||||
) {
|
) {
|
||||||
(wall_dir, climb)
|
(wall_dir, climb)
|
||||||
} else {
|
} else {
|
||||||
if data.inputs.jump.is_pressed() {
|
if input_is_pressed(data, InputKind::Jump) {
|
||||||
// They've climbed atop something, give them a boost
|
// They've climbed atop something, give them a boost
|
||||||
update
|
update
|
||||||
.local_events
|
.local_events
|
||||||
|
@ -113,8 +113,6 @@ pub struct Data {
|
|||||||
pub timer: Duration,
|
pub timer: Duration,
|
||||||
/// Checks what section a stage is in
|
/// Checks what section a stage is in
|
||||||
pub stage_section: StageSection,
|
pub stage_section: StageSection,
|
||||||
/// Whether the state should go onto the next stage
|
|
||||||
pub next_stage: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterBehavior for Data {
|
impl CharacterBehavior for Data {
|
||||||
@ -123,15 +121,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_orientation(data, &mut update, 1.0);
|
handle_orientation(data, &mut update, 1.0);
|
||||||
handle_move(data, &mut update, 0.3);
|
handle_move(data, &mut update, 0.3);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, self.static_data.is_interruptible);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::ComboMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let stage_index = (self.stage - 1) as usize;
|
let stage_index = (self.stage - 1) as usize;
|
||||||
|
|
||||||
@ -261,41 +250,21 @@ impl CharacterBehavior for Data {
|
|||||||
StageSection::Recover => {
|
StageSection::Recover => {
|
||||||
if self.timer < self.static_data.stage_data[stage_index].base_recover_duration {
|
if self.timer < self.static_data.stage_data[stage_index].base_recover_duration {
|
||||||
// Recovers
|
// Recovers
|
||||||
if ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
// Checks if state will transition to next stage after recover
|
|
||||||
update.character = CharacterState::ComboMelee(Data {
|
|
||||||
static_data: self.static_data.clone(),
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
next_stage: true,
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
update.character = CharacterState::ComboMelee(Data {
|
|
||||||
static_data: self.static_data.clone(),
|
|
||||||
timer: self
|
|
||||||
.timer
|
|
||||||
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
..*self
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if self.next_stage {
|
|
||||||
// Transitions to buildup section of next stage
|
|
||||||
update.character = CharacterState::ComboMelee(Data {
|
update.character = CharacterState::ComboMelee(Data {
|
||||||
static_data: self.static_data.clone(),
|
static_data: self.static_data.clone(),
|
||||||
stage: (self.stage % self.static_data.num_stages) + 1,
|
timer: self
|
||||||
timer: Duration::default(),
|
.timer
|
||||||
stage_section: StageSection::Buildup,
|
.checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer))
|
||||||
next_stage: false,
|
.unwrap_or_default(),
|
||||||
|
..*self
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
update.character = CharacterState::Wielding;
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
// Make sure attack component is removed
|
reset_state(self, data, &mut update);
|
||||||
data.updater.remove::<Melee>(data.entity);
|
} else {
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -306,20 +275,19 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grant energy on successful hit
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
if let Some(attack) = data.melee_attack {
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
if attack.applied && attack.hit_count > 0 {
|
handle_state_interrupt(data, &mut update, self.static_data.is_interruptible);
|
||||||
update.character = CharacterState::ComboMelee(Data {
|
|
||||||
static_data: self.static_data.clone(),
|
|
||||||
stage: self.stage,
|
|
||||||
timer: self.timer,
|
|
||||||
stage_section: self.stage_section,
|
|
||||||
next_stage: self.next_stage,
|
|
||||||
});
|
|
||||||
data.updater.remove::<Melee>(data.entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {
|
||||||
|
handle_input(join, update, data.static_data.ability_info.input);
|
||||||
|
|
||||||
|
if let CharacterState::ComboMelee(c) = &mut update.character {
|
||||||
|
c.stage = (data.stage % data.static_data.num_stages) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -55,7 +55,8 @@ pub struct Data {
|
|||||||
/// Struct containing data that does not change over the course of the
|
/// Struct containing data that does not change over the course of the
|
||||||
/// character state
|
/// character state
|
||||||
pub static_data: StaticData,
|
pub static_data: StaticData,
|
||||||
/// Whether the charge should end
|
/// Whether the charge should last a default amount of time or until the
|
||||||
|
/// mouse is released
|
||||||
pub auto_charge: bool,
|
pub auto_charge: bool,
|
||||||
/// Timer for each stage
|
/// Timer for each stage
|
||||||
pub timer: Duration,
|
pub timer: Duration,
|
||||||
@ -73,15 +74,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_orientation(data, &mut update, 1.0);
|
handle_orientation(data, &mut update, 1.0);
|
||||||
handle_move(data, &mut update, 0.1);
|
handle_move(data, &mut update, 0.1);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, self.static_data.is_interruptible);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::DashMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -97,10 +89,7 @@ impl CharacterBehavior for Data {
|
|||||||
} else {
|
} else {
|
||||||
// Transitions to charge section of stage
|
// Transitions to charge section of stage
|
||||||
update.character = CharacterState::DashMelee(Data {
|
update.character = CharacterState::DashMelee(Data {
|
||||||
auto_charge: !ability_key_is_pressed(
|
auto_charge: !input_is_pressed(data, self.static_data.ability_info.input),
|
||||||
data,
|
|
||||||
self.static_data.ability_info.key,
|
|
||||||
),
|
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Charge,
|
stage_section: StageSection::Charge,
|
||||||
..*self
|
..*self
|
||||||
@ -110,7 +99,7 @@ impl CharacterBehavior for Data {
|
|||||||
StageSection::Charge => {
|
StageSection::Charge => {
|
||||||
if (self.static_data.infinite_charge
|
if (self.static_data.infinite_charge
|
||||||
|| self.timer < self.static_data.charge_duration)
|
|| self.timer < self.static_data.charge_duration)
|
||||||
&& (ability_key_is_pressed(data, self.static_data.ability_info.key)
|
&& (input_is_pressed(data, self.static_data.ability_info.input)
|
||||||
|| (self.auto_charge && self.timer < self.static_data.charge_duration))
|
|| (self.auto_charge && self.timer < self.static_data.charge_duration))
|
||||||
&& update.energy.current() > 0
|
&& update.energy.current() > 0
|
||||||
{
|
{
|
||||||
@ -265,6 +254,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, self.static_data.is_interruptible);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,15 +54,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.4);
|
handle_move(data, &mut update, 0.4);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::HealingBeam(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -91,7 +82,7 @@ impl CharacterBehavior for Data {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
StageSection::Cast => {
|
StageSection::Cast => {
|
||||||
if ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
if input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
let speed =
|
let speed =
|
||||||
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
|
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
|
||||||
let heal = AttackEffect::new(
|
let heal = AttackEffect::new(
|
||||||
@ -162,6 +153,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,15 +58,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 0.3);
|
handle_move(data, &mut update, 0.3);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::LeapMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
// Delay before leaping into the air
|
// Delay before leaping into the air
|
||||||
@ -220,6 +211,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,15 +53,6 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
handle_move(data, &mut update, 1.0);
|
handle_move(data, &mut update, 1.0);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::RepeaterRanged(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Movement => {
|
StageSection::Movement => {
|
||||||
@ -220,6 +211,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{CharacterState, StateUpdate},
|
comp::{CharacterState, InputKind, StateUpdate},
|
||||||
states::{
|
states::{
|
||||||
behavior::{CharacterBehavior, JoinData},
|
behavior::{CharacterBehavior, JoinData},
|
||||||
utils::*,
|
utils::*,
|
||||||
@ -37,7 +37,7 @@ pub struct Data {
|
|||||||
/// Was sneaking
|
/// Was sneaking
|
||||||
pub was_sneak: bool,
|
pub was_sneak: bool,
|
||||||
/// Was in state with combo
|
/// Was in state with combo
|
||||||
pub was_combo: Option<(AbilityKey, u32)>,
|
pub was_combo: Option<(InputKind, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterBehavior for Data {
|
impl CharacterBehavior for Data {
|
||||||
@ -114,9 +114,9 @@ impl CharacterBehavior for Data {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
if let Some((key, stage)) = self.was_combo {
|
if let Some((input, stage)) = self.was_combo {
|
||||||
if ability_key_is_pressed(data, key) {
|
if input_is_pressed(data, input) {
|
||||||
handle_interrupt(data, &mut update, true);
|
handle_input(data, &mut update, input);
|
||||||
// If other states are introduced that progress through stages, add them
|
// If other states are introduced that progress through stages, add them
|
||||||
// here
|
// here
|
||||||
if let CharacterState::ComboMelee(c) = &mut update.character {
|
if let CharacterState::ComboMelee(c) = &mut update.character {
|
||||||
|
@ -60,15 +60,6 @@ impl CharacterBehavior for Data {
|
|||||||
let mut update = StateUpdate::from(data);
|
let mut update = StateUpdate::from(data);
|
||||||
|
|
||||||
handle_move(data, &mut update, self.static_data.move_efficiency);
|
handle_move(data, &mut update, self.static_data.move_efficiency);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, false);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::Shockwave(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
@ -171,6 +162,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, false);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,16 +75,6 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
|
||||||
handle_interrupt(data, &mut update, self.static_data.is_interruptible);
|
|
||||||
match update.character {
|
|
||||||
CharacterState::SpinMelee(_) => {},
|
|
||||||
_ => {
|
|
||||||
return update;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.stage_section {
|
match self.stage_section {
|
||||||
StageSection::Buildup => {
|
StageSection::Buildup => {
|
||||||
if self.timer < self.static_data.buildup_duration {
|
if self.timer < self.static_data.buildup_duration {
|
||||||
@ -179,7 +169,7 @@ impl CharacterBehavior for Data {
|
|||||||
} else if update.energy.current() as f32 >= self.static_data.energy_cost
|
} else if update.energy.current() as f32 >= self.static_data.energy_cost
|
||||||
&& (self.spins_remaining != 0
|
&& (self.spins_remaining != 0
|
||||||
|| (self.static_data.is_infinite
|
|| (self.static_data.is_infinite
|
||||||
&& ability_key_is_pressed(data, self.static_data.ability_info.key)))
|
&& input_is_pressed(data, self.static_data.ability_info.input)))
|
||||||
{
|
{
|
||||||
let new_spins_remaining = if self.static_data.is_infinite {
|
let new_spins_remaining = if self.static_data.is_infinite {
|
||||||
self.spins_remaining
|
self.spins_remaining
|
||||||
@ -231,6 +221,11 @@ impl CharacterBehavior for Data {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At end of state logic so an interrupt isn't overwritten
|
||||||
|
if !input_is_pressed(data, self.static_data.ability_info.input) {
|
||||||
|
handle_state_interrupt(data, &mut update, self.static_data.is_interruptible);
|
||||||
|
}
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
item::{Hands, ItemKind, Tool, ToolKind},
|
item::{Hands, ItemKind, Tool, ToolKind},
|
||||||
quadruped_low, quadruped_medium, quadruped_small,
|
quadruped_low, quadruped_medium, quadruped_small,
|
||||||
skills::Skill,
|
skills::Skill,
|
||||||
theropod, Body, CharacterAbility, CharacterState, InventoryAction, StateUpdate,
|
theropod, Body, CharacterAbility, CharacterState, InputKind, InventoryAction, StateUpdate,
|
||||||
},
|
},
|
||||||
consts::{FRIC_GROUND, GRAVITY},
|
consts::{FRIC_GROUND, GRAVITY},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
@ -185,7 +185,10 @@ impl Body {
|
|||||||
pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||||
if let Some(depth) = data.physics.in_liquid {
|
if let Some(depth) = data.physics.in_liquid {
|
||||||
swim_move(data, update, efficiency, depth);
|
swim_move(data, update, efficiency, depth);
|
||||||
} else if data.inputs.fly.is_pressed() && !data.physics.on_ground && data.body.can_fly() {
|
} else if input_is_pressed(data, InputKind::Fly)
|
||||||
|
&& !data.physics.on_ground
|
||||||
|
&& data.body.can_fly()
|
||||||
|
{
|
||||||
fly_move(data, update, efficiency);
|
fly_move(data, update, efficiency);
|
||||||
} else {
|
} else {
|
||||||
basic_move(data, update, efficiency);
|
basic_move(data, update, efficiency);
|
||||||
@ -316,14 +319,10 @@ fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
|||||||
handle_orientation(data, update, 1.0);
|
handle_orientation(data, update, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// First checks whether `primary`, `secondary`, `ability3`, or `ability4` input
|
/// Checks if an input related to an attack is held. If one is, moves entity
|
||||||
/// is pressed, then attempts to go into Equipping state, otherwise Idle
|
/// into wielding state
|
||||||
pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if data.inputs.primary.is_pressed()
|
if data.controller.queued_inputs.iter().any(|i| i.is_ability()) {
|
||||||
|| data.inputs.secondary.is_pressed()
|
|
||||||
|| data.inputs.ability3.is_pressed()
|
|
||||||
|| data.inputs.ability4.is_pressed()
|
|
||||||
{
|
|
||||||
attempt_wield(data, update);
|
attempt_wield(data, update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +422,7 @@ pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
|
|
||||||
/// Checks that player can jump and sends jump event if so
|
/// Checks that player can jump and sends jump event if so
|
||||||
pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if data.inputs.jump.is_pressed()
|
if input_is_pressed(data, InputKind::Jump)
|
||||||
&& data.physics.on_ground
|
&& data.physics.on_ground
|
||||||
&& !data
|
&& !data
|
||||||
.physics
|
.physics
|
||||||
@ -437,14 +436,14 @@ pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key: AbilityKey) {
|
fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
||||||
let hands = |equip_slot| match data.inventory.equipped(equip_slot).map(|i| i.kind()) {
|
let hands = |equip_slot| match data.inventory.equipped(equip_slot).map(|i| i.kind()) {
|
||||||
Some(ItemKind::Tool(tool)) => Some(tool.hands),
|
Some(ItemKind::Tool(tool)) => Some(tool.hands),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mouse1 and Skill1 always use the MainHand slot
|
// Mouse1 and Skill1 always use the MainHand slot
|
||||||
let always_main_hand = matches!(ability_key, AbilityKey::Mouse1 | AbilityKey::Skill1);
|
let always_main_hand = matches!(input, InputKind::Primary | InputKind::Ability(0));
|
||||||
// skill_index used to select ability for the AbilityKey::Skill2 input
|
// skill_index used to select ability for the AbilityKey::Skill2 input
|
||||||
let (equip_slot, skill_index) = if always_main_hand {
|
let (equip_slot, skill_index) = if always_main_hand {
|
||||||
(Some(EquipSlot::Mainhand), 0)
|
(Some(EquipSlot::Mainhand), 0)
|
||||||
@ -468,16 +467,16 @@ fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key
|
|||||||
.inventory
|
.inventory
|
||||||
.equipped(equip_slot)
|
.equipped(equip_slot)
|
||||||
.map(|i| &i.item_config_expect().abilities)
|
.map(|i| &i.item_config_expect().abilities)
|
||||||
.and_then(|abilities| match ability_key {
|
.and_then(|abilities| match input {
|
||||||
AbilityKey::Mouse1 => Some(abilities.primary.clone()),
|
InputKind::Primary => Some(abilities.primary.clone()),
|
||||||
AbilityKey::Mouse2 => Some(abilities.secondary.clone()),
|
InputKind::Secondary => Some(abilities.secondary.clone()),
|
||||||
AbilityKey::Skill1 => abilities.abilities.get(0).cloned().and_then(unlocked),
|
InputKind::Ability(0) => abilities.abilities.get(0).cloned().and_then(unlocked),
|
||||||
AbilityKey::Skill2 => abilities
|
InputKind::Ability(_) => abilities
|
||||||
.abilities
|
.abilities
|
||||||
.get(skill_index)
|
.get(skill_index)
|
||||||
.cloned()
|
.cloned()
|
||||||
.and_then(unlocked),
|
.and_then(unlocked),
|
||||||
AbilityKey::Dodge => None,
|
InputKind::Roll | InputKind::Jump | InputKind::Fly => None,
|
||||||
})
|
})
|
||||||
.map(|a| {
|
.map(|a| {
|
||||||
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
||||||
@ -487,41 +486,46 @@ fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key
|
|||||||
{
|
{
|
||||||
update.character = (
|
update.character = (
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_key(data, ability_key, matches!(equip_slot, EquipSlot::Offhand)),
|
AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_ability1_input(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_ability_input(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if data.inputs.primary.is_pressed() {
|
if let Some(input) = data
|
||||||
handle_ability_pressed(data, update, AbilityKey::Mouse1);
|
.controller
|
||||||
|
.queued_inputs
|
||||||
|
.iter()
|
||||||
|
.find(|i| i.is_ability())
|
||||||
|
{
|
||||||
|
handle_ability(data, update, *input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_ability2_input(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
||||||
if data.inputs.secondary.is_pressed() {
|
match input {
|
||||||
handle_ability_pressed(data, update, AbilityKey::Mouse2);
|
InputKind::Primary | InputKind::Secondary | InputKind::Ability(_) => {
|
||||||
|
handle_ability(data, update, input)
|
||||||
|
},
|
||||||
|
InputKind::Roll => handle_dodge_input(data, update),
|
||||||
|
InputKind::Jump => handle_jump(data, update),
|
||||||
|
InputKind::Fly => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) {
|
pub fn attempt_input(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if data.inputs.ability3.is_pressed() {
|
// TODO: look into using first() when it becomes stable
|
||||||
handle_ability_pressed(data, update, AbilityKey::Skill1);
|
if let Some(input) = data.controller.queued_inputs.iter().next() {
|
||||||
}
|
handle_input(data, update, *input);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_ability4_input(data: &JoinData, update: &mut StateUpdate) {
|
|
||||||
if data.inputs.ability4.is_pressed() {
|
|
||||||
handle_ability_pressed(data, update, AbilityKey::Skill2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that player can perform a dodge, then
|
/// Checks that player can perform a dodge, then
|
||||||
/// attempts to perform their dodge ability
|
/// attempts to perform their dodge ability
|
||||||
pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if data.inputs.roll.is_pressed() && data.body.is_humanoid() {
|
if input_is_pressed(data, InputKind::Roll) && data.body.is_humanoid() {
|
||||||
if let Some(ability) = data
|
if let Some(ability) = data
|
||||||
.inventory
|
.inventory
|
||||||
.equipped(EquipSlot::Mainhand)
|
.equipped(EquipSlot::Mainhand)
|
||||||
@ -536,17 +540,17 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
if let CharacterState::ComboMelee(c) = data.character {
|
if let CharacterState::ComboMelee(c) = data.character {
|
||||||
update.character = (
|
update.character = (
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
|
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||||
)
|
)
|
||||||
.into();
|
.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.key, 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 = (
|
update.character = (
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
|
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
if let CharacterState::Roll(roll) = &mut update.character {
|
if let CharacterState::Roll(roll) = &mut update.character {
|
||||||
@ -555,7 +559,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
} else if data.character.is_stealthy() {
|
} else if data.character.is_stealthy() {
|
||||||
update.character = (
|
update.character = (
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
|
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
if let CharacterState::Roll(roll) = &mut update.character {
|
if let CharacterState::Roll(roll) = &mut update.character {
|
||||||
@ -564,7 +568,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
} else {
|
} else {
|
||||||
update.character = (
|
update.character = (
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
|
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
@ -598,24 +602,15 @@ pub fn get_crit_data(data: &JoinData, ai: AbilityInfo) -> (f32, f32) {
|
|||||||
DEFAULT_CRIT_DATA
|
DEFAULT_CRIT_DATA
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_interrupt(data: &JoinData, update: &mut StateUpdate, attacks_interrupt: bool) {
|
pub fn handle_state_interrupt(data: &JoinData, update: &mut StateUpdate, attacks_interrupt: bool) {
|
||||||
if attacks_interrupt {
|
if attacks_interrupt {
|
||||||
handle_ability1_input(data, update);
|
handle_ability_input(data, update);
|
||||||
handle_ability2_input(data, update);
|
|
||||||
handle_ability3_input(data, update);
|
|
||||||
handle_ability4_input(data, update);
|
|
||||||
}
|
}
|
||||||
handle_dodge_input(data, update);
|
handle_dodge_input(data, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ability_key_is_pressed(data: &JoinData, ability_key: AbilityKey) -> bool {
|
pub fn input_is_pressed(data: &JoinData, input: InputKind) -> bool {
|
||||||
match ability_key {
|
data.controller.queued_inputs.contains(&input)
|
||||||
AbilityKey::Mouse1 => data.inputs.primary.is_pressed(),
|
|
||||||
AbilityKey::Mouse2 => data.inputs.secondary.is_pressed(),
|
|
||||||
AbilityKey::Skill1 => data.inputs.ability3.is_pressed(),
|
|
||||||
AbilityKey::Skill2 => data.inputs.ability4.is_pressed(),
|
|
||||||
AbilityKey::Dodge => data.inputs.roll.is_pressed(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines what portion a state is in. Used in all attacks (eventually). Is
|
/// Determines what portion a state is in. Used in all attacks (eventually). Is
|
||||||
@ -632,15 +627,6 @@ pub enum StageSection {
|
|||||||
Movement,
|
Movement,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum AbilityKey {
|
|
||||||
Mouse1,
|
|
||||||
Mouse2,
|
|
||||||
Skill1,
|
|
||||||
Skill2,
|
|
||||||
Dodge,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ForcedMovement {
|
pub enum ForcedMovement {
|
||||||
Forward {
|
Forward {
|
||||||
@ -679,11 +665,11 @@ impl MovementDirection {
|
|||||||
pub struct AbilityInfo {
|
pub struct AbilityInfo {
|
||||||
pub tool: Option<ToolKind>,
|
pub tool: Option<ToolKind>,
|
||||||
pub hand: Option<HandInfo>,
|
pub hand: Option<HandInfo>,
|
||||||
pub key: AbilityKey,
|
pub input: InputKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbilityInfo {
|
impl AbilityInfo {
|
||||||
pub fn from_key(data: &JoinData, key: AbilityKey, from_offhand: bool) -> Self {
|
pub fn from_input(data: &JoinData, from_offhand: bool, input: InputKind) -> Self {
|
||||||
let tool_data = if from_offhand {
|
let tool_data = if from_offhand {
|
||||||
unwrap_tool_data(data, EquipSlot::Offhand)
|
unwrap_tool_data(data, EquipSlot::Offhand)
|
||||||
} else {
|
} else {
|
||||||
@ -698,7 +684,7 @@ impl AbilityInfo {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self { tool, hand, key }
|
Self { tool, hand, input }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,13 +14,8 @@ impl CharacterBehavior for Data {
|
|||||||
let mut update = StateUpdate::from(data);
|
let mut update = StateUpdate::from(data);
|
||||||
|
|
||||||
handle_move(&data, &mut update, 1.0);
|
handle_move(&data, &mut update, 1.0);
|
||||||
handle_jump(&data, &mut update);
|
|
||||||
handle_climb(&data, &mut update);
|
handle_climb(&data, &mut update);
|
||||||
handle_ability1_input(&data, &mut update);
|
attempt_input(&data, &mut update);
|
||||||
handle_ability2_input(&data, &mut update);
|
|
||||||
handle_ability3_input(&data, &mut update);
|
|
||||||
handle_ability4_input(&data, &mut update);
|
|
||||||
handle_dodge_input(&data, &mut update);
|
|
||||||
|
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use common::{
|
|||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn incorporate_update(join: &mut JoinStruct, state_update: StateUpdate) {
|
fn incorporate_update(join: &mut JoinStruct, mut state_update: StateUpdate) {
|
||||||
// TODO: if checking equality is expensive use optional field in StateUpdate
|
// TODO: if checking equality is expensive use optional field in StateUpdate
|
||||||
if join.char_state.get_unchecked() != &state_update.character {
|
if join.char_state.get_unchecked() != &state_update.character {
|
||||||
*join.char_state.get_mut_unchecked() = state_update.character
|
*join.char_state.get_mut_unchecked() = state_update.character
|
||||||
@ -35,6 +35,12 @@ fn incorporate_update(join: &mut JoinStruct, state_update: StateUpdate) {
|
|||||||
if join.energy.get_unchecked() != &state_update.energy {
|
if join.energy.get_unchecked() != &state_update.energy {
|
||||||
*join.energy.get_mut_unchecked() = state_update.energy
|
*join.energy.get_mut_unchecked() = state_update.energy
|
||||||
};
|
};
|
||||||
|
join.controller
|
||||||
|
.queued_inputs
|
||||||
|
.append(&mut state_update.queued_inputs);
|
||||||
|
for input in state_update.removed_inputs {
|
||||||
|
join.controller.queued_inputs.remove(&input);
|
||||||
|
}
|
||||||
if state_update.swap_equipped_weapons {
|
if state_update.swap_equipped_weapons {
|
||||||
let mut inventory = join.inventory.get_mut_unchecked();
|
let mut inventory = join.inventory.get_mut_unchecked();
|
||||||
let inventory = &mut *inventory;
|
let inventory = &mut *inventory;
|
||||||
|
@ -34,15 +34,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
for (entity, controller) in (&read_data.entities, &mut controllers).join() {
|
for (entity, controller) in (&read_data.entities, &mut controllers).join() {
|
||||||
let mut inputs = &mut controller.inputs;
|
let mut inputs = &mut controller.inputs;
|
||||||
|
|
||||||
// Note(imbris): I avoided incrementing the duration with inputs.tick() because
|
|
||||||
// this is being done manually in voxygen right now so it would double up on
|
|
||||||
// speed of time.
|
|
||||||
// Perhaphs the duration aspects of inputs could be
|
|
||||||
// calculated exclusively on the server (since the client can't be
|
|
||||||
// trusted anyway). It needs to be considered if these calculations
|
|
||||||
// being on the client are critical for responsiveness/client-side prediction.
|
|
||||||
inputs.tick_freshness();
|
|
||||||
|
|
||||||
// Update `inputs.move_dir`.
|
// Update `inputs.move_dir`.
|
||||||
inputs.move_dir = if inputs.move_dir.magnitude_squared() > 1.0 {
|
inputs.move_dir = if inputs.move_dir.magnitude_squared() > 1.0 {
|
||||||
// Cap move_dir to 1
|
// Cap move_dir to 1
|
||||||
|
@ -11,8 +11,8 @@ use common::{
|
|||||||
},
|
},
|
||||||
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
||||||
Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent, Controller, Energy,
|
Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent, Controller, Energy,
|
||||||
Health, Inventory, LightEmitter, MountState, Ori, PhysicsState, Pos, Scale, Stats,
|
Health, InputKind, Inventory, LightEmitter, MountState, Ori, PhysicsState, Pos, Scale,
|
||||||
UnresolvedChatMsg, Vel,
|
Stats, UnresolvedChatMsg, Vel,
|
||||||
},
|
},
|
||||||
event::{Emitter, EventBus, ServerEvent},
|
event::{Emitter, EventBus, ServerEvent},
|
||||||
path::TraversalConfig,
|
path::TraversalConfig,
|
||||||
@ -571,16 +571,24 @@ impl<'a> AgentData<'a> {
|
|||||||
if let Some((travel_to, _destination)) = &agent.rtsim_controller.travel_to {
|
if let Some((travel_to, _destination)) = &agent.rtsim_controller.travel_to {
|
||||||
// if it has an rtsim destination and can fly then it should
|
// if it has an rtsim destination and can fly then it should
|
||||||
// if it is flying and bumps something above it then it should move down
|
// if it is flying and bumps something above it then it should move down
|
||||||
controller.inputs.fly.set_state(
|
if self.traversal_config.can_fly
|
||||||
self.traversal_config.can_fly
|
&& !read_data
|
||||||
&& !read_data
|
.terrain
|
||||||
.terrain
|
.ray(self.pos.0, self.pos.0 + (Vec3::unit_z() * 3.0))
|
||||||
.ray(self.pos.0, self.pos.0 + (Vec3::unit_z() * 3.0))
|
.until(Block::is_solid)
|
||||||
.until(Block::is_solid)
|
.cast()
|
||||||
.cast()
|
.1
|
||||||
.1
|
.map_or(true, |b| b.is_some())
|
||||||
.map_or(true, |b| b.is_some()),
|
{
|
||||||
);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Fly,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Fly))
|
||||||
|
}
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*read_data.terrain,
|
&*read_data.terrain,
|
||||||
self.pos.0,
|
self.pos.0,
|
||||||
@ -594,10 +602,18 @@ impl<'a> AgentData<'a> {
|
|||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero)
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero)
|
||||||
* speed.min(agent.rtsim_controller.speed_factor);
|
* speed.min(agent.rtsim_controller.speed_factor);
|
||||||
controller.inputs.jump.set_state(
|
if bearing.z > 1.5
|
||||||
bearing.z > 1.5
|
|| self.traversal_config.can_fly && self.traversal_config.on_ground
|
||||||
|| self.traversal_config.can_fly && self.traversal_config.on_ground,
|
{
|
||||||
);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.climb = Some(comp::Climb::Up);
|
controller.inputs.climb = Some(comp::Climb::Up);
|
||||||
//.filter(|_| bearing.z > 0.1 || self.physics_state.in_liquid.is_some());
|
//.filter(|_| bearing.z > 0.1 || self.physics_state.in_liquid.is_some());
|
||||||
|
|
||||||
@ -925,7 +941,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
@ -1085,7 +1110,10 @@ impl<'a> AgentData<'a> {
|
|||||||
match tactic {
|
match tactic {
|
||||||
Tactic::Melee => {
|
Tactic::Melee => {
|
||||||
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
@ -1100,7 +1128,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1108,7 +1145,10 @@ impl<'a> AgentData<'a> {
|
|||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
@ -1118,10 +1158,15 @@ impl<'a> AgentData<'a> {
|
|||||||
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
if agent.action_timer > 6.0 {
|
if agent.action_timer > 6.0 {
|
||||||
controller.inputs.secondary.set_state(false);
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Secondary));
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else if agent.action_timer > 4.0 && self.energy.current() > 10 {
|
} else if agent.action_timer > 4.0 && self.energy.current() > 10 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self
|
||||||
.stats
|
.stats
|
||||||
@ -1130,10 +1175,16 @@ impl<'a> AgentData<'a> {
|
|||||||
&& self.energy.current() > 800
|
&& self.energy.current() > 800
|
||||||
&& thread_rng().gen_bool(0.5)
|
&& thread_rng().gen_bool(0.5)
|
||||||
{
|
{
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
@ -1149,14 +1200,26 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
@ -1166,10 +1229,15 @@ impl<'a> AgentData<'a> {
|
|||||||
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
if agent.action_timer > 4.0 {
|
if agent.action_timer > 4.0 {
|
||||||
controller.inputs.secondary.set_state(false);
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Secondary));
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else if agent.action_timer > 2.0 {
|
} else if agent.action_timer > 2.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self
|
||||||
.stats
|
.stats
|
||||||
@ -1178,10 +1246,16 @@ impl<'a> AgentData<'a> {
|
|||||||
&& self.energy.current() > 700
|
&& self.energy.current() > 700
|
||||||
&& thread_rng().gen_bool(0.9)
|
&& thread_rng().gen_bool(0.9)
|
||||||
{
|
{
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
@ -1204,7 +1278,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
||||||
&& agent.action_timer > 5.0
|
&& agent.action_timer > 5.0
|
||||||
{
|
{
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
@ -1212,7 +1289,16 @@ impl<'a> AgentData<'a> {
|
|||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1220,7 +1306,10 @@ impl<'a> AgentData<'a> {
|
|||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
@ -1236,12 +1325,18 @@ impl<'a> AgentData<'a> {
|
|||||||
&& agent.action_timer < 2.0
|
&& agent.action_timer < 2.0
|
||||||
&& self.energy.current() > 600
|
&& self.energy.current() > 600
|
||||||
{
|
{
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer > 2.0 {
|
} else if agent.action_timer > 2.0 {
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
@ -1259,7 +1354,10 @@ impl<'a> AgentData<'a> {
|
|||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
if agent.action_timer > 4.0 {
|
if agent.action_timer > 4.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
@ -1267,7 +1365,16 @@ impl<'a> AgentData<'a> {
|
|||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1275,7 +1382,10 @@ impl<'a> AgentData<'a> {
|
|||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
@ -1285,7 +1395,10 @@ impl<'a> AgentData<'a> {
|
|||||||
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
||||||
&& dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2)
|
&& dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2)
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*terrain,
|
&*terrain,
|
||||||
@ -1305,10 +1418,15 @@ impl<'a> AgentData<'a> {
|
|||||||
.unwrap_or_else(Vec2::zero)
|
.unwrap_or_else(Vec2::zero)
|
||||||
* speed;
|
* speed;
|
||||||
if agent.action_timer > 4.0 {
|
if agent.action_timer > 4.0 {
|
||||||
controller.inputs.secondary.set_state(false);
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Secondary));
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else if agent.action_timer > 2.0 && self.energy.current() > 300 {
|
} else if agent.action_timer > 2.0 && self.energy.current() > 300 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self
|
||||||
.stats
|
.stats
|
||||||
@ -1317,18 +1435,37 @@ impl<'a> AgentData<'a> {
|
|||||||
&& self.energy.current() > 400
|
&& self.energy.current() > 400
|
||||||
&& thread_rng().gen_bool(0.8)
|
&& thread_rng().gen_bool(0.8)
|
||||||
{
|
{
|
||||||
controller.inputs.secondary.set_state(false);
|
controller
|
||||||
controller.inputs.ability3.set_state(true);
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Secondary));
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.secondary.set_state(false);
|
controller
|
||||||
controller.inputs.primary.set_state(true);
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Secondary));
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1336,7 +1473,10 @@ impl<'a> AgentData<'a> {
|
|||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
} else if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
@ -1351,7 +1491,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1362,7 +1511,10 @@ impl<'a> AgentData<'a> {
|
|||||||
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
|
||||||
&& dist_sqrd < (min_attack_dist * self.scale).powi(2)
|
&& dist_sqrd < (min_attack_dist * self.scale).powi(2)
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
|
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
|
||||||
if agent.action_timer < 1.5 {
|
if agent.action_timer < 1.5 {
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
@ -1388,11 +1540,20 @@ impl<'a> AgentData<'a> {
|
|||||||
&& self.energy.current() > 800
|
&& self.energy.current() > 800
|
||||||
&& thread_rng().gen::<f32>() > 0.8
|
&& thread_rng().gen::<f32>() > 0.8
|
||||||
{
|
{
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if self.energy.current() > 10 {
|
} else if self.energy.current() > 10 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
@ -1412,11 +1573,23 @@ impl<'a> AgentData<'a> {
|
|||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::zero)
|
.unwrap_or_else(Vec2::zero)
|
||||||
* speed;
|
* speed;
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1424,7 +1597,10 @@ impl<'a> AgentData<'a> {
|
|||||||
&& dist_sqrd < 16.0f32.powi(2)
|
&& dist_sqrd < 16.0f32.powi(2)
|
||||||
&& thread_rng().gen::<f32>() < 0.02
|
&& thread_rng().gen::<f32>() < 0.02
|
||||||
{
|
{
|
||||||
controller.inputs.roll.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Roll,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
} else if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
@ -1439,7 +1615,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1451,10 +1636,17 @@ impl<'a> AgentData<'a> {
|
|||||||
// 2.0 is temporary correction factor to allow them to melee with their
|
// 2.0 is temporary correction factor to allow them to melee with their
|
||||||
// large hitbox
|
// large hitbox
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
//controller.inputs.primary.set_state(true);
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if self.vel.0.is_approx_zero() {
|
if self.vel.0.is_approx_zero() {
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*terrain,
|
&*terrain,
|
||||||
@ -1470,7 +1662,10 @@ impl<'a> AgentData<'a> {
|
|||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
if agent.action_timer > 5.0 {
|
if agent.action_timer > 5.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
@ -1478,7 +1673,16 @@ impl<'a> AgentData<'a> {
|
|||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1493,7 +1697,10 @@ impl<'a> AgentData<'a> {
|
|||||||
if dist_sqrd < (min_attack_dist * self.scale).powi(2) && thread_rng().gen_bool(0.5)
|
if dist_sqrd < (min_attack_dist * self.scale).powi(2) && thread_rng().gen_bool(0.5)
|
||||||
{
|
{
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < (radius as f32 * min_attack_dist * self.scale).powi(2) {
|
} else if dist_sqrd < (radius as f32 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = (self.pos.0 - tgt_pos.0)
|
controller.inputs.move_dir = (self.pos.0 - tgt_pos.0)
|
||||||
.xy()
|
.xy()
|
||||||
@ -1510,7 +1717,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.unwrap_or_else(Vec2::unit_y);
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < circle_time as f32 + 0.5 {
|
} else if agent.action_timer < circle_time as f32 + 0.5 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < 2.0 * circle_time as f32 + 0.5 {
|
} else if agent.action_timer < 2.0 * circle_time as f32 + 0.5 {
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
@ -1520,7 +1730,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.unwrap_or_else(Vec2::unit_y);
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < 2.0 * circle_time as f32 + 1.0 {
|
} else if agent.action_timer < 2.0 * circle_time as f32 + 1.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
@ -1538,7 +1751,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1551,7 +1773,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.xy()
|
.xy()
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::unit_y);
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*terrain,
|
&*terrain,
|
||||||
@ -1583,13 +1808,34 @@ impl<'a> AgentData<'a> {
|
|||||||
* speed;
|
* speed;
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1602,13 +1848,21 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::TailSlap => {
|
Tactic::TailSlap => {
|
||||||
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
||||||
if agent.action_timer > 4.0 {
|
if agent.action_timer > 4.0 {
|
||||||
controller.inputs.primary.set_state(false);
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Primary));
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else if agent.action_timer > 1.0 {
|
} else if agent.action_timer > 1.0 {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
@ -1629,7 +1883,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1639,11 +1902,17 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::QuadLowQuick => {
|
Tactic::QuadLowQuick => {
|
||||||
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < (3.0 * min_attack_dist * self.scale).powi(2)
|
} else if dist_sqrd < (3.0 * min_attack_dist * self.scale).powi(2)
|
||||||
&& dist_sqrd > (2.0 * min_attack_dist * self.scale).powi(2)
|
&& dist_sqrd > (2.0 * min_attack_dist * self.scale).powi(2)
|
||||||
{
|
{
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
.xy()
|
.xy()
|
||||||
.rotated_z(-0.47 * PI)
|
.rotated_z(-0.47 * PI)
|
||||||
@ -1662,7 +1931,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1675,10 +1953,16 @@ impl<'a> AgentData<'a> {
|
|||||||
if agent.action_timer > 5.0 {
|
if agent.action_timer > 5.0 {
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
} else if agent.action_timer > 2.0 {
|
} else if agent.action_timer > 2.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
}
|
}
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
@ -1694,7 +1978,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1704,9 +1997,15 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::QuadMedJump => {
|
Tactic::QuadMedJump => {
|
||||||
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
|
} else if dist_sqrd < (5.0 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*terrain,
|
&*terrain,
|
||||||
@ -1719,13 +2018,25 @@ impl<'a> AgentData<'a> {
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
} else {
|
} else {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1737,10 +2048,16 @@ impl<'a> AgentData<'a> {
|
|||||||
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
if agent.action_timer < 2.0 {
|
if agent.action_timer < 2.0 {
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < 3.0 {
|
} else if agent.action_timer < 3.0 {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
@ -1758,7 +2075,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1768,7 +2094,10 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::Lavadrake | Tactic::QuadLowBeam => {
|
Tactic::Lavadrake | Tactic::QuadLowBeam => {
|
||||||
if dist_sqrd < (2.5 * min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (2.5 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.secondary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Secondary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < (7.0 * min_attack_dist * self.scale).powi(2) {
|
} else if dist_sqrd < (7.0 * min_attack_dist * self.scale).powi(2) {
|
||||||
if agent.action_timer < 2.0 {
|
if agent.action_timer < 2.0 {
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
@ -1776,7 +2105,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.rotated_z(0.47 * PI)
|
.rotated_z(0.47 * PI)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::unit_y);
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < 4.0 {
|
} else if agent.action_timer < 4.0 {
|
||||||
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
controller.inputs.move_dir = (tgt_pos.0 - self.pos.0)
|
||||||
@ -1784,10 +2116,16 @@ impl<'a> AgentData<'a> {
|
|||||||
.rotated_z(-0.47 * PI)
|
.rotated_z(-0.47 * PI)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::unit_y);
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if agent.action_timer < 6.0 {
|
} else if agent.action_timer < 6.0 {
|
||||||
controller.inputs.ability3.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Ability(0),
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else {
|
} else {
|
||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
@ -1805,7 +2143,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1815,7 +2162,10 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::Theropod => {
|
Tactic::Theropod => {
|
||||||
if dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2) {
|
if dist_sqrd < (2.0 * min_attack_dist * self.scale).powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
} else if dist_sqrd < MAX_CHASE_DIST.powi(2) {
|
||||||
if let Some((bearing, speed)) = agent.chaser.chase(
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
&*terrain,
|
&*terrain,
|
||||||
@ -1829,7 +2179,16 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1838,7 +2197,10 @@ impl<'a> AgentData<'a> {
|
|||||||
},
|
},
|
||||||
Tactic::Turret => {
|
Tactic::Turret => {
|
||||||
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
}
|
}
|
||||||
@ -1846,7 +2208,10 @@ impl<'a> AgentData<'a> {
|
|||||||
Tactic::FixedTurret => {
|
Tactic::FixedTurret => {
|
||||||
controller.inputs.look_dir = self.ori.look_dir();
|
controller.inputs.look_dir = self.ori.look_dir();
|
||||||
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
}
|
}
|
||||||
@ -1860,7 +2225,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
);
|
);
|
||||||
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
if can_see_tgt(&*terrain, self.pos, tgt_pos, dist_sqrd) {
|
||||||
controller.inputs.primary.set_state(true);
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Primary,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
}
|
}
|
||||||
@ -1888,7 +2256,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
|
let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
|
||||||
controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero)
|
controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero)
|
||||||
* speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0);
|
* speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0);
|
||||||
controller.inputs.jump.set_state(bearing.z > 1.5);
|
if bearing.z > 1.5 {
|
||||||
|
controller.actions.push(ControlAction::StartInput {
|
||||||
|
input: InputKind::Jump,
|
||||||
|
target: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::CancelInput(InputKind::Jump))
|
||||||
|
}
|
||||||
controller.inputs.move_z = bearing.z;
|
controller.inputs.move_z = bearing.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::audio::sfx::SfxEvent;
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
inventory::loadout_builder::LoadoutBuilder, item::tool::ToolKind, CharacterAbilityType,
|
inventory::loadout_builder::LoadoutBuilder, item::tool::ToolKind, CharacterAbilityType,
|
||||||
CharacterState, Item,
|
CharacterState, InputKind, Item,
|
||||||
},
|
},
|
||||||
states,
|
states,
|
||||||
};
|
};
|
||||||
@ -137,7 +137,6 @@ fn matches_ability_stage() {
|
|||||||
stage: 1,
|
stage: 1,
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: states::utils::StageSection::Swing,
|
stage_section: states::utils::StageSection::Swing,
|
||||||
next_stage: false,
|
|
||||||
}),
|
}),
|
||||||
&PreviousEntityState {
|
&PreviousEntityState {
|
||||||
event: SfxEvent::Idle,
|
event: SfxEvent::Idle,
|
||||||
@ -195,7 +194,6 @@ fn ignores_different_ability_stage() {
|
|||||||
stage: 1,
|
stage: 1,
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: states::utils::StageSection::Swing,
|
stage_section: states::utils::StageSection::Swing,
|
||||||
next_stage: false,
|
|
||||||
}),
|
}),
|
||||||
&PreviousEntityState {
|
&PreviousEntityState {
|
||||||
event: SfxEvent::Idle,
|
event: SfxEvent::Idle,
|
||||||
@ -218,6 +216,6 @@ fn empty_ability_info() -> states::utils::AbilityInfo {
|
|||||||
states::utils::AbilityInfo {
|
states::utils::AbilityInfo {
|
||||||
tool: None,
|
tool: None,
|
||||||
hand: None,
|
hand: None,
|
||||||
key: states::utils::AbilityKey::Mouse1,
|
input: InputKind::Primary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,9 +117,6 @@ impl From<&crate::settings::GamepadSettings> for ControllerSettings {
|
|||||||
map.entry(settings.game_buttons.sneak)
|
map.entry(settings.game_buttons.sneak)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(GameInput::Sneak);
|
.push(GameInput::Sneak);
|
||||||
/*map.entry(settings.game_buttons.wall_leap)
|
|
||||||
.or_default()
|
|
||||||
.push(GameInput::WallLeap);*/
|
|
||||||
map.entry(settings.game_buttons.toggle_lantern)
|
map.entry(settings.game_buttons.toggle_lantern)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(GameInput::ToggleLantern);
|
.push(GameInput::ToggleLantern);
|
||||||
@ -177,9 +174,6 @@ impl From<&crate::settings::GamepadSettings> for ControllerSettings {
|
|||||||
map.entry(settings.game_buttons.swap_loadout)
|
map.entry(settings.game_buttons.swap_loadout)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(GameInput::SwapLoadout);
|
.push(GameInput::SwapLoadout);
|
||||||
/*map.entry(settings.game_buttons.charge)
|
|
||||||
.or_default()
|
|
||||||
.push(GameInput::Charge);*/
|
|
||||||
map
|
map
|
||||||
},
|
},
|
||||||
menu_button_map: {
|
menu_button_map: {
|
||||||
|
@ -10,16 +10,7 @@ pub struct KeyState {
|
|||||||
pub swim_up: bool,
|
pub swim_up: bool,
|
||||||
pub swim_down: bool,
|
pub swim_down: bool,
|
||||||
pub fly: bool,
|
pub fly: bool,
|
||||||
pub toggle_wield: bool,
|
|
||||||
pub toggle_glide: bool,
|
|
||||||
pub toggle_lantern: bool,
|
|
||||||
pub toggle_sit: bool,
|
|
||||||
pub toggle_sneak: bool,
|
|
||||||
pub toggle_dance: bool,
|
|
||||||
pub auto_walk: bool,
|
pub auto_walk: bool,
|
||||||
pub swap_loadout: bool,
|
|
||||||
pub respawn: bool,
|
|
||||||
pub interact: bool,
|
|
||||||
pub trade: bool,
|
pub trade: bool,
|
||||||
pub analog_matrix: Vec2<f32>,
|
pub analog_matrix: Vec2<f32>,
|
||||||
}
|
}
|
||||||
@ -36,16 +27,7 @@ impl Default for KeyState {
|
|||||||
swim_up: false,
|
swim_up: false,
|
||||||
swim_down: false,
|
swim_down: false,
|
||||||
fly: false,
|
fly: false,
|
||||||
toggle_wield: false,
|
|
||||||
toggle_glide: false,
|
|
||||||
toggle_lantern: false,
|
|
||||||
toggle_sit: false,
|
|
||||||
toggle_sneak: false,
|
|
||||||
toggle_dance: false,
|
|
||||||
auto_walk: false,
|
auto_walk: false,
|
||||||
swap_loadout: false,
|
|
||||||
respawn: false,
|
|
||||||
interact: false,
|
|
||||||
trade: false,
|
trade: false,
|
||||||
analog_matrix: Vec2::zero(),
|
analog_matrix: Vec2::zero(),
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{cell::RefCell, rc::Rc, time::Duration};
|
use std::{cell::RefCell, collections::HashSet, rc::Rc, time::Duration};
|
||||||
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use specs::{Join, WorldExt};
|
use specs::{Join, WorldExt};
|
||||||
@ -10,8 +10,8 @@ use common::{
|
|||||||
assets::AssetExt,
|
assets::AssetExt,
|
||||||
comp,
|
comp,
|
||||||
comp::{
|
comp::{
|
||||||
inventory::slot::Slot, invite::InviteKind, ChatMsg, ChatType, InventoryUpdateEvent, Pos,
|
inventory::slot::Slot, invite::InviteKind, ChatMsg, ChatType, InputKind,
|
||||||
Vel,
|
InventoryUpdateEvent, Pos, Vel,
|
||||||
},
|
},
|
||||||
consts::{MAX_MOUNT_RANGE, MAX_PICKUP_RANGE},
|
consts::{MAX_MOUNT_RANGE, MAX_PICKUP_RANGE},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -61,6 +61,7 @@ pub struct SessionState {
|
|||||||
hud: Hud,
|
hud: Hud,
|
||||||
key_state: KeyState,
|
key_state: KeyState,
|
||||||
inputs: comp::ControllerInputs,
|
inputs: comp::ControllerInputs,
|
||||||
|
inputs_state: HashSet<GameInput>,
|
||||||
selected_block: Block,
|
selected_block: Block,
|
||||||
walk_forward_dir: Vec2<f32>,
|
walk_forward_dir: Vec2<f32>,
|
||||||
walk_right_dir: Vec2<f32>,
|
walk_right_dir: Vec2<f32>,
|
||||||
@ -96,6 +97,7 @@ impl SessionState {
|
|||||||
client,
|
client,
|
||||||
key_state: KeyState::default(),
|
key_state: KeyState::default(),
|
||||||
inputs: comp::ControllerInputs::default(),
|
inputs: comp::ControllerInputs::default(),
|
||||||
|
inputs_state: HashSet::new(),
|
||||||
hud,
|
hud,
|
||||||
selected_block: Block::new(BlockKind::Misc, Rgb::broadcast(255)),
|
selected_block: Block::new(BlockKind::Misc, Rgb::broadcast(255)),
|
||||||
walk_forward_dir,
|
walk_forward_dir,
|
||||||
@ -124,7 +126,6 @@ impl SessionState {
|
|||||||
outcomes: &mut Vec<Outcome>,
|
outcomes: &mut Vec<Outcome>,
|
||||||
) -> Result<TickAction, Error> {
|
) -> Result<TickAction, Error> {
|
||||||
span!(_guard, "tick", "Session::tick");
|
span!(_guard, "tick", "Session::tick");
|
||||||
self.inputs.tick(dt);
|
|
||||||
|
|
||||||
let mut client = self.client.borrow_mut();
|
let mut client = self.client.borrow_mut();
|
||||||
for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? {
|
for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? {
|
||||||
@ -349,313 +350,300 @@ impl PlayState for SessionState {
|
|||||||
Event::Close => {
|
Event::Close => {
|
||||||
return PlayStateResult::Shutdown;
|
return PlayStateResult::Shutdown;
|
||||||
},
|
},
|
||||||
Event::InputUpdate(GameInput::Primary, state) => {
|
Event::InputUpdate(input, state)
|
||||||
// If we can build, use LMB to break blocks, if not, use it to attack
|
if state != self.inputs_state.contains(&input) =>
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
if state && can_build {
|
|
||||||
if let Some(select_pos) = select_pos {
|
|
||||||
client.remove_block(select_pos);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.inputs.primary.set_state(state);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Event::InputUpdate(GameInput::Secondary, state) => {
|
|
||||||
self.inputs.secondary.set_state(false); // To be changed later on
|
|
||||||
|
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
|
|
||||||
if state && can_build {
|
|
||||||
if let Some(build_pos) = build_pos {
|
|
||||||
client.place_block(build_pos, self.selected_block);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.inputs.secondary.set_state(state);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Event::InputUpdate(GameInput::Roll, state) => {
|
|
||||||
let client = self.client.borrow();
|
|
||||||
if can_build {
|
|
||||||
if state {
|
|
||||||
if let Some(block) = select_pos
|
|
||||||
.and_then(|sp| client.state().terrain().get(sp).ok().copied())
|
|
||||||
{
|
|
||||||
self.selected_block = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.inputs.roll.set_state(state);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Respawn, state)
|
|
||||||
if state != self.key_state.respawn =>
|
|
||||||
{
|
{
|
||||||
self.stop_auto_walk();
|
if !self.inputs_state.insert(input) {
|
||||||
self.key_state.respawn = state;
|
self.inputs_state.remove(&input);
|
||||||
if state {
|
|
||||||
self.client.borrow_mut().respawn();
|
|
||||||
}
|
}
|
||||||
}
|
match input {
|
||||||
Event::InputUpdate(GameInput::Jump, state) => {
|
GameInput::Primary => {
|
||||||
self.inputs.jump.set_state(state);
|
// If we can build, use LMB to break blocks, if not, use it to
|
||||||
},
|
// attack
|
||||||
Event::InputUpdate(GameInput::SwimUp, state) => {
|
|
||||||
self.key_state.swim_up = state;
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::SwimDown, state) => {
|
|
||||||
self.key_state.swim_down = state;
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Sit, state)
|
|
||||||
if state != self.key_state.toggle_sit =>
|
|
||||||
{
|
|
||||||
self.key_state.toggle_sit = state;
|
|
||||||
|
|
||||||
if state {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
self.client.borrow_mut().toggle_sit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::Dance, state)
|
|
||||||
if state != self.key_state.toggle_dance =>
|
|
||||||
{
|
|
||||||
self.key_state.toggle_dance = state;
|
|
||||||
if state {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
self.client.borrow_mut().toggle_dance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::Sneak, state)
|
|
||||||
if state != self.key_state.toggle_sneak =>
|
|
||||||
{
|
|
||||||
self.key_state.toggle_sneak = state;
|
|
||||||
if state {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
self.client.borrow_mut().toggle_sneak();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::MoveForward, state) => {
|
|
||||||
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
}
|
|
||||||
self.key_state.up = state
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::MoveBack, state) => {
|
|
||||||
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
}
|
|
||||||
self.key_state.down = state
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::MoveLeft, state) => {
|
|
||||||
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
}
|
|
||||||
self.key_state.left = state
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::MoveRight, state) => {
|
|
||||||
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
|
||||||
self.stop_auto_walk();
|
|
||||||
}
|
|
||||||
self.key_state.right = state
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Glide, state)
|
|
||||||
if state != self.key_state.toggle_glide =>
|
|
||||||
{
|
|
||||||
self.key_state.toggle_glide = state;
|
|
||||||
if state {
|
|
||||||
self.client.borrow_mut().toggle_glide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::Fly, state) => {
|
|
||||||
self.key_state.fly ^= state;
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Climb, state) => {
|
|
||||||
self.key_state.climb_up = state;
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::ClimbDown, state) => {
|
|
||||||
self.key_state.climb_down = state;
|
|
||||||
},
|
|
||||||
/*Event::InputUpdate(GameInput::WallLeap, state) => {
|
|
||||||
self.inputs.wall_leap.set_state(state)
|
|
||||||
},*/
|
|
||||||
Event::InputUpdate(GameInput::ToggleWield, state)
|
|
||||||
if state != self.key_state.toggle_wield =>
|
|
||||||
{
|
|
||||||
self.key_state.toggle_wield = state;
|
|
||||||
if state {
|
|
||||||
self.client.borrow_mut().toggle_wield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::SwapLoadout, state)
|
|
||||||
if state != self.key_state.swap_loadout =>
|
|
||||||
{
|
|
||||||
self.key_state.swap_loadout = state;
|
|
||||||
if state {
|
|
||||||
self.client.borrow_mut().swap_loadout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::ToggleLantern, true) => {
|
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
if client.is_lantern_enabled() {
|
|
||||||
client.disable_lantern();
|
|
||||||
} else {
|
|
||||||
client.enable_lantern();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Mount, true) => {
|
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
if client.is_mounted() {
|
|
||||||
client.unmount();
|
|
||||||
} else {
|
|
||||||
let player_pos = client
|
|
||||||
.state()
|
|
||||||
.read_storage::<comp::Pos>()
|
|
||||||
.get(client.entity())
|
|
||||||
.copied();
|
|
||||||
if let Some(player_pos) = player_pos {
|
|
||||||
// Find closest mountable entity
|
|
||||||
let closest_mountable_entity = (
|
|
||||||
&client.state().ecs().entities(),
|
|
||||||
&client.state().ecs().read_storage::<comp::Pos>(),
|
|
||||||
&client.state().ecs().read_storage::<comp::MountState>(),
|
|
||||||
)
|
|
||||||
.join()
|
|
||||||
.filter(|(entity, _, mount_state)| {
|
|
||||||
*entity != client.entity()
|
|
||||||
&& **mount_state == comp::MountState::Unmounted
|
|
||||||
})
|
|
||||||
.map(|(entity, pos, _)| {
|
|
||||||
(entity, player_pos.0.distance_squared(pos.0))
|
|
||||||
})
|
|
||||||
.filter(|(_, dist_sqr)| *dist_sqr < MAX_MOUNT_RANGE.powi(2))
|
|
||||||
.min_by_key(|(_, dist_sqr)| OrderedFloat(*dist_sqr));
|
|
||||||
if let Some((mountee_entity, _)) = closest_mountable_entity {
|
|
||||||
client.mount(mountee_entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Interact, state)
|
|
||||||
if state != self.key_state.interact =>
|
|
||||||
{
|
|
||||||
self.key_state.interact = state;
|
|
||||||
|
|
||||||
if state {
|
|
||||||
if let Some(interactable) = self.interactable {
|
|
||||||
let mut client = self.client.borrow_mut();
|
let mut client = self.client.borrow_mut();
|
||||||
match interactable {
|
if state && can_build {
|
||||||
Interactable::Block(block, pos) => {
|
if let Some(select_pos) = select_pos {
|
||||||
if block.is_collectible() {
|
client.remove_block(select_pos);
|
||||||
client.collect_block(pos);
|
}
|
||||||
}
|
} else {
|
||||||
},
|
client.handle_input(InputKind::Primary, state);
|
||||||
Interactable::Entity(entity) => {
|
|
||||||
if client
|
|
||||||
.state()
|
|
||||||
.ecs()
|
|
||||||
.read_storage::<comp::Item>()
|
|
||||||
.get(entity)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
client.pick_up(entity);
|
|
||||||
} else {
|
|
||||||
client.npc_interact(entity);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
GameInput::Secondary => {
|
||||||
}
|
|
||||||
Event::InputUpdate(GameInput::Trade, state)
|
|
||||||
if state != self.key_state.trade =>
|
|
||||||
{
|
|
||||||
self.key_state.trade = state;
|
|
||||||
|
|
||||||
if state {
|
|
||||||
if let Some(interactable) = self.interactable {
|
|
||||||
let mut client = self.client.borrow_mut();
|
let mut client = self.client.borrow_mut();
|
||||||
match interactable {
|
|
||||||
Interactable::Block(_, _) => {},
|
if state && can_build {
|
||||||
Interactable::Entity(entity) => {
|
if let Some(build_pos) = build_pos {
|
||||||
if let Some(uid) =
|
client.place_block(build_pos, self.selected_block);
|
||||||
client.state().ecs().uid_from_entity(entity)
|
}
|
||||||
{
|
} else {
|
||||||
let name = client
|
client.handle_input(InputKind::Secondary, state);
|
||||||
.player_list()
|
|
||||||
.get(&uid)
|
|
||||||
.map(|info| info.player_alias.clone())
|
|
||||||
.unwrap_or_else(|| format!("<entity {:?}>", uid));
|
|
||||||
let msg = global_state
|
|
||||||
.i18n
|
|
||||||
.read()
|
|
||||||
.get("hud.trade.invite_sent")
|
|
||||||
.replace("{playername}", &name);
|
|
||||||
self.hud.new_message(ChatType::Meta.chat_msg(msg));
|
|
||||||
client.send_invite(uid, InviteKind::Trade)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*Event::InputUpdate(GameInput::Charge, state) => {
|
|
||||||
self.inputs.charge.set_state(state);
|
|
||||||
},*/
|
|
||||||
Event::InputUpdate(GameInput::FreeLook, state) => {
|
|
||||||
match (global_state.settings.gameplay.free_look_behavior, state) {
|
|
||||||
(PressBehavior::Toggle, true) => {
|
|
||||||
self.free_look = !self.free_look;
|
|
||||||
self.hud.free_look(self.free_look);
|
|
||||||
},
|
},
|
||||||
(PressBehavior::Hold, state) => {
|
GameInput::Roll => {
|
||||||
self.free_look = state;
|
let mut client = self.client.borrow_mut();
|
||||||
self.hud.free_look(self.free_look);
|
if can_build {
|
||||||
|
if state {
|
||||||
|
if let Some(block) = select_pos.and_then(|sp| {
|
||||||
|
client.state().terrain().get(sp).ok().copied()
|
||||||
|
}) {
|
||||||
|
self.selected_block = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
client.handle_input(InputKind::Roll, state);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
GameInput::Respawn => {
|
||||||
};
|
self.stop_auto_walk();
|
||||||
},
|
if state {
|
||||||
Event::InputUpdate(GameInput::AutoWalk, state) => {
|
self.client.borrow_mut().respawn();
|
||||||
match (global_state.settings.gameplay.auto_walk_behavior, state) {
|
}
|
||||||
(PressBehavior::Toggle, true) => {
|
|
||||||
self.auto_walk = !self.auto_walk;
|
|
||||||
self.key_state.auto_walk = self.auto_walk;
|
|
||||||
self.hud.auto_walk(self.auto_walk);
|
|
||||||
},
|
},
|
||||||
(PressBehavior::Hold, state) => {
|
GameInput::Jump => {
|
||||||
self.auto_walk = state;
|
let mut client = self.client.borrow_mut();
|
||||||
self.key_state.auto_walk = self.auto_walk;
|
client.handle_input(InputKind::Jump, state);
|
||||||
self.hud.auto_walk(self.auto_walk);
|
},
|
||||||
|
GameInput::SwimUp => {
|
||||||
|
self.key_state.swim_up = state;
|
||||||
|
},
|
||||||
|
GameInput::SwimDown => {
|
||||||
|
self.key_state.swim_down = state;
|
||||||
|
},
|
||||||
|
GameInput::Sit => {
|
||||||
|
if state {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
self.client.borrow_mut().toggle_sit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Dance => {
|
||||||
|
if state {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
self.client.borrow_mut().toggle_dance();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Sneak => {
|
||||||
|
if state {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
self.client.borrow_mut().toggle_sneak();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::MoveForward => {
|
||||||
|
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
}
|
||||||
|
self.key_state.up = state
|
||||||
|
},
|
||||||
|
GameInput::MoveBack => {
|
||||||
|
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
}
|
||||||
|
self.key_state.down = state
|
||||||
|
},
|
||||||
|
GameInput::MoveLeft => {
|
||||||
|
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
}
|
||||||
|
self.key_state.left = state
|
||||||
|
},
|
||||||
|
GameInput::MoveRight => {
|
||||||
|
if state && global_state.settings.gameplay.stop_auto_walk_on_input {
|
||||||
|
self.stop_auto_walk();
|
||||||
|
}
|
||||||
|
self.key_state.right = state
|
||||||
|
},
|
||||||
|
GameInput::Glide => {
|
||||||
|
if state {
|
||||||
|
self.client.borrow_mut().toggle_glide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Fly => {
|
||||||
|
// Not sure where to put comment, but I noticed when testing flight
|
||||||
|
// Syncing of inputs between mounter and mountee broke with
|
||||||
|
// controller change
|
||||||
|
self.key_state.fly ^= state;
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
client.handle_input(InputKind::Fly, self.key_state.fly);
|
||||||
|
},
|
||||||
|
GameInput::Climb => {
|
||||||
|
self.key_state.climb_up = state;
|
||||||
|
},
|
||||||
|
GameInput::ClimbDown => {
|
||||||
|
self.key_state.climb_down = state;
|
||||||
|
},
|
||||||
|
GameInput::ToggleWield => {
|
||||||
|
if state {
|
||||||
|
self.client.borrow_mut().toggle_wield();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::SwapLoadout => {
|
||||||
|
if state {
|
||||||
|
self.client.borrow_mut().swap_loadout();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::ToggleLantern if state => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
if client.is_lantern_enabled() {
|
||||||
|
client.disable_lantern();
|
||||||
|
} else {
|
||||||
|
client.enable_lantern();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Mount if state => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
if client.is_mounted() {
|
||||||
|
client.unmount();
|
||||||
|
} else {
|
||||||
|
let player_pos = client
|
||||||
|
.state()
|
||||||
|
.read_storage::<comp::Pos>()
|
||||||
|
.get(client.entity())
|
||||||
|
.copied();
|
||||||
|
if let Some(player_pos) = player_pos {
|
||||||
|
// Find closest mountable entity
|
||||||
|
let closest_mountable_entity = (
|
||||||
|
&client.state().ecs().entities(),
|
||||||
|
&client.state().ecs().read_storage::<comp::Pos>(),
|
||||||
|
&client
|
||||||
|
.state()
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<comp::MountState>(),
|
||||||
|
)
|
||||||
|
.join()
|
||||||
|
.filter(|(entity, _, mount_state)| {
|
||||||
|
*entity != client.entity()
|
||||||
|
&& **mount_state == comp::MountState::Unmounted
|
||||||
|
})
|
||||||
|
.map(|(entity, pos, _)| {
|
||||||
|
(entity, player_pos.0.distance_squared(pos.0))
|
||||||
|
})
|
||||||
|
.filter(|(_, dist_sqr)| {
|
||||||
|
*dist_sqr < MAX_MOUNT_RANGE.powi(2)
|
||||||
|
})
|
||||||
|
.min_by_key(|(_, dist_sqr)| OrderedFloat(*dist_sqr));
|
||||||
|
if let Some((mountee_entity, _)) = closest_mountable_entity
|
||||||
|
{
|
||||||
|
client.mount(mountee_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Interact => {
|
||||||
|
if state {
|
||||||
|
if let Some(interactable) = self.interactable {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
match interactable {
|
||||||
|
Interactable::Block(block, pos) => {
|
||||||
|
if block.is_collectible() {
|
||||||
|
client.collect_block(pos);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Interactable::Entity(entity) => {
|
||||||
|
if client
|
||||||
|
.state()
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<comp::Item>()
|
||||||
|
.get(entity)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
client.pick_up(entity);
|
||||||
|
} else {
|
||||||
|
client.npc_interact(entity);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::Trade => {
|
||||||
|
if state {
|
||||||
|
if let Some(interactable) = self.interactable {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
match interactable {
|
||||||
|
Interactable::Block(_, _) => {},
|
||||||
|
Interactable::Entity(entity) => {
|
||||||
|
if let Some(uid) =
|
||||||
|
client.state().ecs().uid_from_entity(entity)
|
||||||
|
{
|
||||||
|
let name = client
|
||||||
|
.player_list()
|
||||||
|
.get(&uid)
|
||||||
|
.map(|info| info.player_alias.clone())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
format!("<entity {:?}>", uid)
|
||||||
|
});
|
||||||
|
let msg = global_state
|
||||||
|
.i18n
|
||||||
|
.read()
|
||||||
|
.get("hud.trade.invite_sent")
|
||||||
|
.replace("{playername}", &name);
|
||||||
|
self.hud
|
||||||
|
.new_message(ChatType::Meta.chat_msg(msg));
|
||||||
|
client.send_invite(uid, InviteKind::Trade)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::FreeLook => {
|
||||||
|
match (global_state.settings.gameplay.free_look_behavior, state) {
|
||||||
|
(PressBehavior::Toggle, true) => {
|
||||||
|
self.free_look = !self.free_look;
|
||||||
|
self.hud.free_look(self.free_look);
|
||||||
|
},
|
||||||
|
(PressBehavior::Hold, state) => {
|
||||||
|
self.free_look = state;
|
||||||
|
self.hud.free_look(self.free_look);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
GameInput::AutoWalk => {
|
||||||
|
match (global_state.settings.gameplay.auto_walk_behavior, state) {
|
||||||
|
(PressBehavior::Toggle, true) => {
|
||||||
|
self.auto_walk = !self.auto_walk;
|
||||||
|
self.key_state.auto_walk = self.auto_walk;
|
||||||
|
self.hud.auto_walk(self.auto_walk);
|
||||||
|
},
|
||||||
|
(PressBehavior::Hold, state) => {
|
||||||
|
self.auto_walk = state;
|
||||||
|
self.key_state.auto_walk = self.auto_walk;
|
||||||
|
self.hud.auto_walk(self.auto_walk);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::CycleCamera if state => {
|
||||||
|
// Prevent accessing camera modes which aren't available in
|
||||||
|
// multiplayer unless you are an
|
||||||
|
// admin. This is an easily bypassed clientside check.
|
||||||
|
// The server should do its own filtering of which entities are sent
|
||||||
|
// to clients to prevent abuse.
|
||||||
|
let camera = self.scene.camera_mut();
|
||||||
|
camera.next_mode(self.client.borrow().is_admin());
|
||||||
|
},
|
||||||
|
GameInput::Select => {
|
||||||
|
if !state {
|
||||||
|
self.selected_entity =
|
||||||
|
self.target_entity.map(|e| (e, std::time::Instant::now()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::AcceptGroupInvite if state => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
if client.invite().is_some() {
|
||||||
|
client.accept_invite();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GameInput::DeclineGroupInvite if state => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
if client.invite().is_some() {
|
||||||
|
client.decline_invite();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Event::InputUpdate(GameInput::CycleCamera, true) => {
|
|
||||||
// Prevent accessing camera modes which aren't available in multiplayer
|
|
||||||
// unless you are an admin. This is an easily bypassed clientside check.
|
|
||||||
// The server should do its own filtering of which entities are sent to
|
|
||||||
// clients to prevent abuse.
|
|
||||||
let camera = self.scene.camera_mut();
|
|
||||||
camera.next_mode(self.client.borrow().is_admin());
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::Select, state) => {
|
|
||||||
if !state {
|
|
||||||
self.selected_entity =
|
|
||||||
self.target_entity.map(|e| (e, std::time::Instant::now()));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::AcceptGroupInvite, true) => {
|
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
if client.invite().is_some() {
|
|
||||||
client.accept_invite();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::InputUpdate(GameInput::DeclineGroupInvite, true) => {
|
|
||||||
let mut client = self.client.borrow_mut();
|
|
||||||
if client.invite().is_some() {
|
|
||||||
client.decline_invite();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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;
|
||||||
@ -739,7 +727,6 @@ impl PlayState for SessionState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.inputs.climb = self.key_state.climb();
|
self.inputs.climb = self.key_state.climb();
|
||||||
self.inputs.fly.set_state(self.key_state.fly);
|
|
||||||
self.inputs.move_z =
|
self.inputs.move_z =
|
||||||
self.key_state.swim_up as i32 as f32 - self.key_state.swim_down as i32 as f32;
|
self.key_state.swim_up as i32 as f32 - self.key_state.swim_down as i32 as f32;
|
||||||
|
|
||||||
@ -1232,8 +1219,14 @@ impl PlayState for SessionState {
|
|||||||
let mut client = self.client.borrow_mut();
|
let mut client = self.client.borrow_mut();
|
||||||
client.perform_trade_action(action);
|
client.perform_trade_action(action);
|
||||||
},
|
},
|
||||||
HudEvent::Ability3(state) => self.inputs.ability3.set_state(state),
|
HudEvent::Ability3(state) => {
|
||||||
HudEvent::Ability4(state) => self.inputs.ability4.set_state(state),
|
let mut client = self.client.borrow_mut();
|
||||||
|
client.handle_input(InputKind::Ability(0), state);
|
||||||
|
},
|
||||||
|
HudEvent::Ability4(state) => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
client.handle_input(InputKind::Ability(1), state);
|
||||||
|
},
|
||||||
HudEvent::ChangeFOV(new_fov) => {
|
HudEvent::ChangeFOV(new_fov) => {
|
||||||
global_state.settings.graphics.fov = new_fov;
|
global_state.settings.graphics.fov = new_fov;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
|
@ -138,7 +138,6 @@ impl ControlSettings {
|
|||||||
GameInput::SwimDown => KeyMouse::Key(VirtualKeyCode::LShift),
|
GameInput::SwimDown => KeyMouse::Key(VirtualKeyCode::LShift),
|
||||||
GameInput::Fly => KeyMouse::Key(VirtualKeyCode::H),
|
GameInput::Fly => KeyMouse::Key(VirtualKeyCode::H),
|
||||||
GameInput::Sneak => KeyMouse::Key(VirtualKeyCode::LControl),
|
GameInput::Sneak => KeyMouse::Key(VirtualKeyCode::LControl),
|
||||||
//GameInput::WallLeap => MIDDLE_CLICK_KEY,
|
|
||||||
GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G),
|
GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G),
|
||||||
GameInput::Mount => KeyMouse::Key(VirtualKeyCode::F),
|
GameInput::Mount => KeyMouse::Key(VirtualKeyCode::F),
|
||||||
GameInput::Map => KeyMouse::Key(VirtualKeyCode::M),
|
GameInput::Map => KeyMouse::Key(VirtualKeyCode::M),
|
||||||
@ -158,7 +157,6 @@ impl ControlSettings {
|
|||||||
GameInput::Respawn => KeyMouse::Key(VirtualKeyCode::Space),
|
GameInput::Respawn => KeyMouse::Key(VirtualKeyCode::Space),
|
||||||
GameInput::Interact => KeyMouse::Key(VirtualKeyCode::E),
|
GameInput::Interact => KeyMouse::Key(VirtualKeyCode::E),
|
||||||
GameInput::ToggleWield => KeyMouse::Key(VirtualKeyCode::T),
|
GameInput::ToggleWield => KeyMouse::Key(VirtualKeyCode::T),
|
||||||
//GameInput::Charge => KeyMouse::Key(VirtualKeyCode::Key1),
|
|
||||||
GameInput::FreeLook => KeyMouse::Key(VirtualKeyCode::L),
|
GameInput::FreeLook => KeyMouse::Key(VirtualKeyCode::L),
|
||||||
GameInput::AutoWalk => KeyMouse::Key(VirtualKeyCode::Period),
|
GameInput::AutoWalk => KeyMouse::Key(VirtualKeyCode::Period),
|
||||||
GameInput::CycleCamera => KeyMouse::Key(VirtualKeyCode::Key0),
|
GameInput::CycleCamera => KeyMouse::Key(VirtualKeyCode::Key0),
|
||||||
@ -257,7 +255,6 @@ pub mod con_settings {
|
|||||||
pub swimup: Button,
|
pub swimup: Button,
|
||||||
pub swimdown: Button,
|
pub swimdown: Button,
|
||||||
pub sneak: Button,
|
pub sneak: Button,
|
||||||
//pub wall_leap: Button,
|
|
||||||
pub toggle_lantern: Button,
|
pub toggle_lantern: Button,
|
||||||
pub mount: Button,
|
pub mount: Button,
|
||||||
pub map: Button,
|
pub map: Button,
|
||||||
@ -279,7 +276,6 @@ pub mod con_settings {
|
|||||||
pub interact: Button,
|
pub interact: Button,
|
||||||
pub toggle_wield: Button,
|
pub toggle_wield: Button,
|
||||||
pub swap_loadout: Button,
|
pub swap_loadout: Button,
|
||||||
//pub charge: Button,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@ -349,7 +345,6 @@ pub mod con_settings {
|
|||||||
swimup: Button::Simple(GilButton::South),
|
swimup: Button::Simple(GilButton::South),
|
||||||
swimdown: Button::Simple(GilButton::East),
|
swimdown: Button::Simple(GilButton::East),
|
||||||
sneak: Button::Simple(GilButton::East),
|
sneak: Button::Simple(GilButton::East),
|
||||||
//wall_leap: Button::Simple(GilButton::Unknown),
|
|
||||||
toggle_lantern: Button::Simple(GilButton::DPadLeft),
|
toggle_lantern: Button::Simple(GilButton::DPadLeft),
|
||||||
mount: Button::Simple(GilButton::North),
|
mount: Button::Simple(GilButton::North),
|
||||||
map: Button::Simple(GilButton::Select),
|
map: Button::Simple(GilButton::Select),
|
||||||
@ -371,7 +366,6 @@ pub mod con_settings {
|
|||||||
interact: Button::Simple(GilButton::North),
|
interact: Button::Simple(GilButton::North),
|
||||||
toggle_wield: Button::Simple(GilButton::West),
|
toggle_wield: Button::Simple(GilButton::West),
|
||||||
swap_loadout: Button::Simple(GilButton::LeftThumb),
|
swap_loadout: Button::Simple(GilButton::LeftThumb),
|
||||||
//charge: Button::Simple(GilButton::Unknown),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@ pub enum GameInput {
|
|||||||
SwimDown,
|
SwimDown,
|
||||||
Fly,
|
Fly,
|
||||||
Sneak,
|
Sneak,
|
||||||
//WallLeap,
|
|
||||||
ToggleLantern,
|
ToggleLantern,
|
||||||
Mount,
|
Mount,
|
||||||
Chat,
|
Chat,
|
||||||
@ -69,7 +68,6 @@ pub enum GameInput {
|
|||||||
Respawn,
|
Respawn,
|
||||||
Interact,
|
Interact,
|
||||||
ToggleWield,
|
ToggleWield,
|
||||||
//Charge,
|
|
||||||
SwapLoadout,
|
SwapLoadout,
|
||||||
FreeLook,
|
FreeLook,
|
||||||
AutoWalk,
|
AutoWalk,
|
||||||
@ -99,7 +97,6 @@ impl GameInput {
|
|||||||
GameInput::SwimDown => "gameinput.swimdown",
|
GameInput::SwimDown => "gameinput.swimdown",
|
||||||
GameInput::Fly => "gameinput.fly",
|
GameInput::Fly => "gameinput.fly",
|
||||||
GameInput::Sneak => "gameinput.sneak",
|
GameInput::Sneak => "gameinput.sneak",
|
||||||
//GameInput::WallLeap => "gameinput.wallleap",
|
|
||||||
GameInput::ToggleLantern => "gameinput.togglelantern",
|
GameInput::ToggleLantern => "gameinput.togglelantern",
|
||||||
GameInput::Mount => "gameinput.mount",
|
GameInput::Mount => "gameinput.mount",
|
||||||
GameInput::Chat => "gameinput.chat",
|
GameInput::Chat => "gameinput.chat",
|
||||||
@ -123,7 +120,6 @@ impl GameInput {
|
|||||||
GameInput::Respawn => "gameinput.respawn",
|
GameInput::Respawn => "gameinput.respawn",
|
||||||
GameInput::Interact => "gameinput.interact",
|
GameInput::Interact => "gameinput.interact",
|
||||||
GameInput::ToggleWield => "gameinput.togglewield",
|
GameInput::ToggleWield => "gameinput.togglewield",
|
||||||
//GameInput::Charge => "gameinput.charge",
|
|
||||||
GameInput::FreeLook => "gameinput.freelook",
|
GameInput::FreeLook => "gameinput.freelook",
|
||||||
GameInput::AutoWalk => "gameinput.autowalk",
|
GameInput::AutoWalk => "gameinput.autowalk",
|
||||||
GameInput::Slot1 => "gameinput.slot1",
|
GameInput::Slot1 => "gameinput.slot1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user