Support for canceling an input. Boost state hooked up to system.

This commit is contained in:
Sam 2021-03-11 23:53:25 -05:00
parent c6d8daaae3
commit 19c81f1528
9 changed files with 87 additions and 24 deletions

View File

@ -998,7 +998,7 @@ impl Client {
target: None,
});
} else {
self.control_action(ControlAction::CancelInput);
self.control_action(ControlAction::CancelInput(input));
}
}

View File

@ -1156,8 +1156,10 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
static_data: boost::StaticData {
movement_duration: Duration::from_secs_f32(*movement_duration),
only_up: *only_up,
ability_info,
},
timer: Duration::default(),
end: false,
}),
CharacterAbility::DashMelee {
energy_cost: _,

View File

@ -18,6 +18,7 @@ pub struct StateUpdate {
pub energy: Energy,
pub swap_equipped_weapons: bool,
pub queued_inputs: BTreeSet<InputKind>,
pub removed_inputs: Vec<InputKind>,
pub local_events: VecDeque<LocalEvent>,
pub server_events: VecDeque<ServerEvent>,
}
@ -32,6 +33,7 @@ impl From<&JoinData<'_>> for StateUpdate {
swap_equipped_weapons: false,
character: data.character.clone(),
queued_inputs: BTreeSet::new(),
removed_inputs: Vec::new(),
local_events: VecDeque::new(),
server_events: VecDeque::new(),
}

View File

@ -115,7 +115,7 @@ pub enum ControlAction {
ability: InputKind,
target: Option<Uid>,
},
CancelInput,
CancelInput(InputKind),
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)]

View File

@ -34,7 +34,11 @@ pub trait CharacterBehavior {
update.queued_inputs.insert(input);
update
}
fn cancel_input(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) }
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 {
match event {
ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data),
@ -50,7 +54,7 @@ pub trait CharacterBehavior {
ControlAction::StartInput { ability, target } => {
self.handle_input(data, ability, target)
},
ControlAction::CancelInput => self.cancel_input(data),
ControlAction::CancelInput(input) => self.cancel_input(data, input),
}
}
// fn init(data: &JoinData) -> CharacterState;

View File

@ -1,5 +1,5 @@
use crate::{
comp::{CharacterState, StateUpdate},
comp::{CharacterState, InputKind, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -13,6 +13,7 @@ use std::time::Duration;
pub struct StaticData {
pub movement_duration: Duration,
pub only_up: bool,
pub ability_info: AbilityInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -22,6 +23,8 @@ pub struct Data {
pub static_data: StaticData,
/// Timer for each stage
pub timer: Duration,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -46,9 +49,31 @@ impl CharacterBehavior for Data {
});
} else {
// Done
update.character = CharacterState::Wielding;
if self.end || self.static_data.ability_info.input.is_none() {
update.character = CharacterState::Wielding;
} else {
reset_state(self, &mut update);
}
}
update
}
fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
let mut update = StateUpdate::from(data);
update.removed_inputs.push(input);
if Some(input) == self.static_data.ability_info.input {
update.character = CharacterState::Boost(Data { end: true, ..*self });
}
update
}
}
fn reset_state(data: &Data, update: &mut StateUpdate) {
update.character = CharacterState::Boost(Data {
timer: Duration::default(),
..*data
})
}

View File

@ -434,7 +434,12 @@ pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
}
}
fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key: AbilityKey) {
fn handle_ability_pressed(
data: &JoinData,
update: &mut StateUpdate,
ability_key: AbilityKey,
input: Option<InputKind>,
) {
let hands = |equip_slot| match data.inventory.equipped(equip_slot).map(|i| i.kind()) {
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
@ -484,7 +489,12 @@ fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key
{
update.character = (
&ability,
AbilityInfo::from_key(data, ability_key, matches!(equip_slot, EquipSlot::Offhand)),
AbilityInfo::from_key(
data,
ability_key,
matches!(equip_slot, EquipSlot::Offhand),
input,
),
)
.into();
}
@ -493,7 +503,7 @@ fn handle_ability_pressed(data: &JoinData, update: &mut StateUpdate, ability_key
pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
match input {
InputKind::Primary => handle_ability_pressed(data, update, AbilityKey::Mouse1),
InputKind::Primary => handle_ability_pressed(data, update, AbilityKey::Mouse1, Some(input)),
}
}
@ -505,19 +515,19 @@ pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind)
pub fn handle_ability2_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.secondary.is_pressed() {
handle_ability_pressed(data, update, AbilityKey::Mouse2);
handle_ability_pressed(data, update, AbilityKey::Mouse2, None);
}
}
pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.ability3.is_pressed() {
handle_ability_pressed(data, update, AbilityKey::Skill1);
handle_ability_pressed(data, update, AbilityKey::Skill1, None);
}
}
pub fn handle_ability4_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.ability4.is_pressed() {
handle_ability_pressed(data, update, AbilityKey::Skill2);
handle_ability_pressed(data, update, AbilityKey::Skill2, None);
}
}
@ -539,7 +549,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
if let CharacterState::ComboMelee(c) = data.character {
update.character = (
&ability,
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
AbilityInfo::from_key(data, AbilityKey::Dodge, false, None),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character {
@ -549,7 +559,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
} else if data.character.is_wield() {
update.character = (
&ability,
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
AbilityInfo::from_key(data, AbilityKey::Dodge, false, None),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character {
@ -558,7 +568,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
} else if data.character.is_stealthy() {
update.character = (
&ability,
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
AbilityInfo::from_key(data, AbilityKey::Dodge, false, None),
)
.into();
if let CharacterState::Roll(roll) = &mut update.character {
@ -567,7 +577,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
} else {
update.character = (
&ability,
AbilityInfo::from_key(data, AbilityKey::Dodge, false),
AbilityInfo::from_key(data, AbilityKey::Dodge, false, None),
)
.into();
}
@ -687,10 +697,16 @@ pub struct AbilityInfo {
pub tool: Option<ToolKind>,
pub hand: Option<HandInfo>,
pub key: AbilityKey,
pub input: Option<InputKind>,
}
impl AbilityInfo {
pub fn from_key(data: &JoinData, key: AbilityKey, from_offhand: bool) -> Self {
pub fn from_key(
data: &JoinData,
key: AbilityKey,
from_offhand: bool,
input: Option<InputKind>,
) -> Self {
let tool_data = if from_offhand {
unwrap_tool_data(data, EquipSlot::Offhand)
} else {
@ -705,7 +721,12 @@ impl AbilityInfo {
)
};
Self { tool, hand, key }
Self {
tool,
hand,
key,
input,
}
}
}

View File

@ -23,7 +23,7 @@ use common::{
use common_ecs::{Job, Origin, Phase, System};
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
if join.char_state.get_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 {
*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 {
let mut inventory = join.inventory.get_mut_unchecked();
let inventory = &mut *inventory;
@ -350,10 +356,11 @@ impl<'a> System<'a> for Sys {
local_emitter.append(&mut state_update.local_events);
server_emitter.append(&mut state_update.server_events);
join_struct
.controller
.queued_inputs
.append(&mut state_update.queued_inputs);
// join_struct
// .controller
// .queued_inputs
// .append(&mut state_update.queued_inputs);
// join_struct.controller.queued_inputs.
incorporate_update(&mut join_struct, state_update);
}
}

View File

@ -1638,7 +1638,9 @@ impl<'a> AgentData<'a> {
Tactic::TailSlap => {
if dist_sqrd < (1.5 * min_attack_dist * self.scale).powi(2) {
if agent.action_timer > 4.0 {
controller.actions.push(ControlAction::CancelInput);
controller
.actions
.push(ControlAction::CancelInput(InputKind::Primary));
//controller.inputs.primary.set_state(false);
agent.action_timer = 0.0;
} else if agent.action_timer > 1.0 {