Inputs remain in queue while active, allowing interrupts and queued inputs to be more cleanly handled

This commit is contained in:
Sam 2021-03-14 11:19:22 -04:00
parent b5d501199d
commit be27289a7f
14 changed files with 50 additions and 221 deletions

View File

@ -1120,7 +1120,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
timer: Duration::default(),
stage_section: StageSection::Buildup,
exhausted: false,
end: false,
}),
CharacterAbility::BasicRanged {
buildup_duration,
@ -1145,7 +1144,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
timer: Duration::default(),
stage_section: StageSection::Buildup,
exhausted: false,
end: false,
}),
CharacterAbility::Boost {
movement_duration,
@ -1157,7 +1155,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
ability_info,
},
timer: Duration::default(),
end: false,
}),
CharacterAbility::DashMelee {
energy_cost: _,
@ -1202,7 +1199,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
refresh_distance: 0.0,
stage_section: StageSection::Buildup,
exhausted: false,
end: false,
}),
CharacterAbility::BasicBlock => CharacterState::BasicBlock,
CharacterAbility::Roll {
@ -1251,7 +1247,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
stage: 1,
timer: Duration::default(),
stage_section: StageSection::Buildup,
end: false,
}),
CharacterAbility::LeapMelee {
energy_cost: _,
@ -1320,7 +1315,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
spins_remaining: *num_spins - 1,
stage_section: StageSection::Buildup,
exhausted: false,
end: false,
}),
CharacterAbility::ChargedMelee {
energy_cost,
@ -1361,7 +1355,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
timer: Duration::default(),
exhausted: false,
charge_amount: 0.0,
end: false,
}),
CharacterAbility::ChargedRanged {
energy_cost: _,
@ -1402,7 +1395,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
timer: Duration::default(),
stage_section: StageSection::Buildup,
exhausted: false,
end: false,
}),
CharacterAbility::RepeaterRanged {
energy_cost: _,
@ -1499,7 +1491,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
end: false,
}),
CharacterAbility::BasicAura {
buildup_duration,
@ -1549,7 +1540,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
end: false,
}),
}
}

View File

@ -3,7 +3,7 @@ use crate::{
Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageSource,
GroupTarget,
},
comp::{beam, CharacterState, EnergyChange, EnergySource, InputKind, Ori, Pos, StateUpdate},
comp::{beam, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -56,8 +56,6 @@ pub struct Data {
pub timer: Duration,
/// What section the character stage is in
pub stage_section: StageSection,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -112,7 +110,7 @@ impl CharacterBehavior for Data {
StageSection::Cast => {
if
/* ability_key_is_pressed(data, self.static_data.ability_info.key) */
!self.end
input_is_pressed(data, self.static_data.ability_info)
&& (self.static_data.energy_drain <= f32::EPSILON
|| update.energy.current() > 0)
{
@ -209,19 +207,6 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::BasicBeam(c) = &mut update.character {
c.end = true;
}
}
update
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{CharacterState, InputKind, Melee, StateUpdate},
comp::{CharacterState, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -44,8 +44,6 @@ pub struct Data {
pub stage_section: StageSection,
/// Whether the attack can deal more damage
pub exhausted: bool,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -164,12 +162,10 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if self.end || self.static_data.ability_info.input.is_none() {
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Melee>(data.entity);
} else {
if input_is_pressed(data, self.static_data.ability_info) {
reset_state(self, data, &mut update);
} else {
update.character = CharacterState::Wielding;
}
}
},
@ -183,19 +179,6 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::BasicMelee(c) = &mut update.character {
c.end = true;
}
}
update
}
}
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {

View File

@ -1,7 +1,5 @@
use crate::{
comp::{
Body, CharacterState, Gravity, InputKind, LightEmitter, ProjectileConstructor, StateUpdate,
},
comp::{Body, CharacterState, Gravity, LightEmitter, ProjectileConstructor, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -39,8 +37,6 @@ pub struct Data {
pub stage_section: StageSection,
/// Whether the attack fired already
pub exhausted: bool,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -115,10 +111,10 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if self.end || self.static_data.ability_info.input.is_none() {
update.character = CharacterState::Wielding;
} else {
if input_is_pressed(data, self.static_data.ability_info) {
reset_state(self, data, &mut update);
} else {
update.character = CharacterState::Wielding;
}
}
},
@ -130,19 +126,6 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::BasicRanged(c) = &mut update.character {
c.end = true;
}
}
update
}
}
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {

View File

@ -1,5 +1,5 @@
use crate::{
comp::{CharacterState, InputKind, StateUpdate},
comp::{CharacterState, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -23,8 +23,6 @@ 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 {
@ -49,23 +47,10 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if self.end || self.static_data.ability_info.input.is_none() {
update.character = CharacterState::Wielding;
} else {
if input_is_pressed(data, self.static_data.ability_info) {
reset_state(self, data, &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 {
if let CharacterState::Boost(c) = &mut update.character {
c.end = true;
} else {
update.character = CharacterState::Wielding;
}
}

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{CharacterState, EnergyChange, EnergySource, InputKind, Melee, StateUpdate},
comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::{StageSection, *},
@ -60,8 +60,6 @@ pub struct Data {
pub exhausted: bool,
/// How much the attack charged by
pub charge_amount: f32,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -84,7 +82,7 @@ impl CharacterBehavior for Data {
StageSection::Charge => {
if
/* ability_key_is_pressed(data, self.static_data.ability_info.key) */
!self.end
input_is_pressed(data, self.static_data.ability_info)
&& update.energy.current() as f32 >= self.static_data.energy_cost
&& self.timer < self.static_data.charge_duration
{
@ -113,7 +111,7 @@ impl CharacterBehavior for Data {
});
} else if
/* ability_key_is_pressed(data, self.static_data.ability_info.key) */
!self.end
input_is_pressed(data, self.static_data.ability_info)
&& update.energy.current() as f32 >= self.static_data.energy_cost
{
// Maintains charge
@ -248,17 +246,4 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::ChargedMelee(c) = &mut update.character {
c.end = true;
}
}
update
}
}

View File

@ -4,8 +4,8 @@ use crate::{
DamageSource, GroupTarget, Knockback, KnockbackDir,
},
comp::{
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, InputKind,
LightEmitter, Projectile, StateUpdate,
projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter,
Projectile, StateUpdate,
},
event::ServerEvent,
states::{
@ -60,8 +60,6 @@ pub struct Data {
pub stage_section: StageSection,
/// Whether the attack fired already
pub exhausted: bool,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -103,7 +101,7 @@ impl CharacterBehavior for Data {
StageSection::Charge => {
if
/* \!ability_key_is_pressed(data, self.static_data.ability_info.key) */
self.end && !self.exhausted {
!input_is_pressed(data, self.static_data.ability_info) && !self.exhausted {
let charge_frac = (self.timer.as_secs_f32()
/ self.static_data.charge_duration.as_secs_f32())
.min(1.0);
@ -164,7 +162,7 @@ impl CharacterBehavior for Data {
..*self
});
} else if self.timer < self.static_data.charge_duration
&& /*ability_key_is_pressed(data, self.static_data.ability_info.key)*/ !self.end
&& /*ability_key_is_pressed(data, self.static_data.ability_info.key)*/ input_is_pressed(data, self.static_data.ability_info)
{
// Charges
update.character = CharacterState::ChargedRanged(Data {
@ -186,7 +184,7 @@ impl CharacterBehavior for Data {
});
} else if
/* ability_key_is_pressed(data, self.static_data.ability_info.key) */
!self.end {
input_is_pressed(data, self.static_data.ability_info) {
// Holds charge
update.character = CharacterState::ChargedRanged(Data {
timer: self
@ -231,17 +229,4 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::ChargedRanged(c) = &mut update.character {
c.end = true;
}
}
update
}
}

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{CharacterState, InputKind, Melee, StateUpdate},
comp::{CharacterState, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -113,8 +113,6 @@ pub struct Data {
pub timer: Duration,
/// Checks what section a stage is in
pub stage_section: StageSection,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -271,12 +269,10 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if self.end || self.static_data.ability_info.input.is_none() {
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Melee>(data.entity);
} else {
if input_is_pressed(data, self.static_data.ability_info) {
reset_state(self, data, &mut update);
} else {
update.character = CharacterState::Wielding;
}
}
},
@ -290,19 +286,6 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::ComboMelee(c) = &mut update.character {
c.end = true;
}
}
update
}
}
fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) {

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{CharacterState, EnergyChange, EnergySource, InputKind, Melee, StateUpdate},
comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
@ -66,8 +66,6 @@ pub struct Data {
pub stage_section: StageSection,
/// Whether the state should attempt attacking again
pub exhausted: bool,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -103,7 +101,7 @@ impl CharacterBehavior for Data {
auto_charge: /*\!ability_key_is_pressed(
data,
self.static_data.ability_info.key,
)*/self.end,
)*/input_is_pressed(data, self.static_data.ability_info),
timer: Duration::default(),
stage_section: StageSection::Charge,
..*self
@ -113,7 +111,7 @@ impl CharacterBehavior for Data {
StageSection::Charge => {
if (self.static_data.infinite_charge
|| self.timer < self.static_data.charge_duration)
&& (/* ability_key_is_pressed(data, self.static_data.ability_info.key) */!self.end
&& (/* ability_key_is_pressed(data, self.static_data.ability_info.key) */input_is_pressed(data, self.static_data.ability_info)
|| (self.auto_charge && self.timer < self.static_data.charge_duration))
&& update.energy.current() > 0
{
@ -270,17 +268,4 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::DashMelee(c) = &mut update.character {
c.end = true;
}
}
update
}
}

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackEffect, CombatEffect, CombatRequirement, GroupTarget},
comp::{beam, CharacterState, InputKind, Ori, Pos, StateUpdate},
comp::{beam, CharacterState, Ori, Pos, StateUpdate},
event::ServerEvent,
states::{
behavior::{CharacterBehavior, JoinData},
@ -46,8 +46,6 @@ pub struct Data {
pub timer: Duration,
/// What section the character stage is in
pub stage_section: StageSection,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -95,7 +93,7 @@ impl CharacterBehavior for Data {
StageSection::Cast => {
if
/* ability_key_is_pressed(data, self.static_data.ability_info.key) */
!self.end {
input_is_pressed(data, self.static_data.ability_info) {
let speed =
self.static_data.range / self.static_data.beam_duration.as_secs_f32();
let heal = AttackEffect::new(
@ -168,17 +166,4 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::HealingBeam(c) = &mut update.character {
c.end = true;
}
}
update
}
}

View File

@ -1,8 +1,7 @@
use super::utils::*;
use crate::{
comp::{CharacterState, InputKind, InventoryAction, StateUpdate},
comp::{InventoryAction, StateUpdate},
states::behavior::{CharacterBehavior, JoinData},
uid::Uid,
};
pub struct Data;
@ -20,18 +19,6 @@ impl CharacterBehavior for Data {
update
}
fn handle_input(
&self,
data: &JoinData,
_input: InputKind,
_target: Option<Uid>,
) -> StateUpdate {
let mut update = StateUpdate::from(data);
update.character = CharacterState::Wielding;
update
}
fn wield(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data);
attempt_wield(data, &mut update);

View File

@ -1,6 +1,6 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{CharacterState, EnergyChange, EnergySource, InputKind, Melee, StateUpdate},
comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate},
consts::GRAVITY,
states::{
behavior::{CharacterBehavior, JoinData},
@ -58,8 +58,6 @@ pub struct Data {
pub stage_section: StageSection,
/// Whether the state can deal damage
pub exhausted: bool,
/// Whether or not the state should end
pub end: bool,
}
impl CharacterBehavior for Data {
@ -181,7 +179,7 @@ impl CharacterBehavior for Data {
} else if update.energy.current() as f32 >= self.static_data.energy_cost
&& (self.spins_remaining != 0
|| (self.static_data.is_infinite
&& /*ability_key_is_pressed(data, self.static_data.ability_info.key)*/ !self.end))
&& /*ability_key_is_pressed(data, self.static_data.ability_info.key)*/ input_is_pressed(data, self.static_data.ability_info)))
{
let new_spins_remaining = if self.static_data.is_infinite {
self.spins_remaining
@ -235,19 +233,6 @@ impl CharacterBehavior for Data {
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 {
if let CharacterState::SpinMelee(c) = &mut update.character {
c.end = true;
}
}
update
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -506,6 +506,13 @@ pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind)
}
}
pub fn attempt_input(data: &JoinData, update: &mut StateUpdate) {
// TODO: look into using first() when it becomes stable
if let Some(input) = data.controller.queued_inputs.iter().next() {
handle_input(data, update, *input);
}
}
/*pub fn handle_ability1_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.primary.is_pressed() {
handle_ability_pressed(data, update, AbilityKey::Mouse1);
@ -620,6 +627,13 @@ pub fn handle_interrupt(data: &JoinData, update: &mut StateUpdate, attacks_inter
handle_dodge_input(data, update);
}
pub fn input_is_pressed(data: &JoinData, ability_info: AbilityInfo) -> bool {
//data.controller.queued_inputs.contains(ability_info.input)
ability_info
.input
.map_or(false, |i| data.controller.queued_inputs.contains(&i))
}
pub fn ability_key_is_pressed(data: &JoinData, ability_key: AbilityKey) -> bool {
match ability_key {
AbilityKey::Mouse1 =>

View File

@ -2,10 +2,9 @@ use super::utils::*;
use crate::{
comp::{
slot::{EquipSlot, Slot},
CharacterState, InputKind, InventoryAction, StateUpdate,
CharacterState, InventoryAction, StateUpdate,
},
states::behavior::{CharacterBehavior, JoinData},
uid::Uid,
};
pub struct Data;
@ -23,12 +22,7 @@ impl CharacterBehavior for Data {
handle_ability4_input(&data, &mut update);
handle_dodge_input(&data, &mut update);
update
}
fn handle_input(&self, data: &JoinData, input: InputKind, _target: Option<Uid>) -> StateUpdate {
let mut update = StateUpdate::from(data);
handle_input(&data, &mut update, input);
attempt_input(&data, &mut update);
update
}