Made combo melee more ergonomic to use when it is a stance

This commit is contained in:
Sam 2022-09-11 21:49:31 -04:00
parent 21aabb5663
commit 8d3567b6b2
23 changed files with 257 additions and 119 deletions

View File

@ -1379,37 +1379,40 @@ impl CharacterAbility {
#[must_use]
pub fn contextualize(mut self, data: &JoinData) -> Self {
if let Some(ability_info) = data.character.ability_info() {
if let Some(AbilityKind::Sword(old_stance)) = ability_info.ability_meta.kind {
if let Some(AbilityKind::Sword(new_stance)) = self.ability_meta().kind {
let energy_reduction = if old_stance == new_stance {
0.75
} else if old_stance == SwordStance::Balanced {
1.0
} else {
1.5
};
use CharacterAbility::*;
match &mut self {
BasicMelee { energy_cost, .. }
| ComboMelee2 {
energy_cost_per_strike: energy_cost,
..
}
| FinisherMelee { energy_cost, .. }
| DashMelee { energy_cost, .. }
| SpinMelee { energy_cost, .. }
| ChargedMelee { energy_cost, .. }
| Shockwave { energy_cost, .. }
| BasicBlock { energy_cost, .. }
| SelfBuff { energy_cost, .. }
| DiveMelee { energy_cost, .. }
| RiposteMelee { energy_cost, .. }
| RapidMelee { energy_cost, .. } => {
*energy_cost *= energy_reduction;
},
_ => {},
if let Some(AbilityKind::Sword(old_stance)) = data
.character
.ability_info()
.and_then(|info| info.ability_meta)
.and_then(|meta| meta.kind)
{
if let Some(AbilityKind::Sword(new_stance)) = self.ability_meta().kind {
let energy_reduction = if old_stance == new_stance {
0.75
} else if old_stance == SwordStance::Balanced {
1.0
} else {
1.5
};
use CharacterAbility::*;
match &mut self {
BasicMelee { energy_cost, .. }
| ComboMelee2 {
energy_cost_per_strike: energy_cost,
..
}
| FinisherMelee { energy_cost, .. }
| DashMelee { energy_cost, .. }
| SpinMelee { energy_cost, .. }
| ChargedMelee { energy_cost, .. }
| Shockwave { energy_cost, .. }
| BasicBlock { energy_cost, .. }
| SelfBuff { energy_cost, .. }
| DiveMelee { energy_cost, .. }
| RiposteMelee { energy_cost, .. }
| RapidMelee { energy_cost, .. } => {
*energy_cost *= energy_reduction;
},
_ => {},
}
}
}

View File

@ -281,13 +281,16 @@ impl CharacterState {
}
pub fn is_parry(&self) -> bool {
let from_capability =
if let Some(capabilities) = self.ability_info().map(|a| a.ability_meta.capabilities) {
capabilities.contains(Capability::BUILDUP_PARRIES)
&& matches!(self.stage_section(), Some(StageSection::Buildup))
} else {
false
};
let from_capability = if let Some(capabilities) = self
.ability_info()
.and_then(|a| a.ability_meta)
.map(|m| m.capabilities)
{
capabilities.contains(Capability::BUILDUP_PARRIES)
&& matches!(self.stage_section(), Some(StageSection::Buildup))
} else {
false
};
let from_state = match self {
CharacterState::BasicBlock(c) => c.is_parry(),
CharacterState::RiposteMelee(c) => matches!(c.stage_section, StageSection::Buildup),
@ -503,7 +506,7 @@ impl CharacterState {
CharacterState::Skate(_) => None,
CharacterState::Glide(_) => None,
CharacterState::GlideWield(_) => None,
CharacterState::Stunned(_) => None,
CharacterState::Stunned(data) => Some(data.static_data.ability_info),
CharacterState::Sit => None,
CharacterState::Dance => None,
CharacterState::BasicBlock(data) => Some(data.static_data.ability_info),
@ -528,8 +531,8 @@ impl CharacterState {
CharacterState::BasicSummon(data) => Some(data.static_data.ability_info),
CharacterState::SelfBuff(data) => Some(data.static_data.ability_info),
CharacterState::SpriteSummon(data) => Some(data.static_data.ability_info),
CharacterState::UseItem(_) => None,
CharacterState::SpriteInteract(_) => None,
CharacterState::UseItem(data) => Some(data.static_data.ability_info),
CharacterState::SpriteInteract(data) => Some(data.static_data.ability_info),
CharacterState::FinisherMelee(data) => Some(data.static_data.ability_info),
CharacterState::Music(data) => Some(data.static_data.ability_info),
CharacterState::DiveMelee(data) => Some(data.static_data.ability_info),

View File

@ -78,7 +78,11 @@ pub enum PoiseState {
impl PoiseState {
/// Returns the optional stunned character state and duration of stun, and
/// optional impulse strength corresponding to a particular poise state
pub fn poise_effect(&self, was_wielded: bool) -> (Option<(CharacterState, f64)>, Option<f32>) {
pub fn poise_effect(
&self,
was_wielded: bool,
ability_info: states::utils::AbilityInfo,
) -> (Option<(CharacterState, f64)>, Option<f32>) {
use states::{
stunned::{Data, StaticData},
utils::StageSection,
@ -113,6 +117,7 @@ impl PoiseState {
recover_duration,
movement_speed,
poise_state: *self,
ability_info,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
@ -262,10 +267,9 @@ impl Poise {
let from_char = {
let resistant = char_state
.and_then(|cs| cs.ability_info())
.and_then(|a| a.ability_meta)
.map_or(false, |a| {
a.ability_meta
.capabilities
.contains(Capability::POISE_RESISTANT)
a.capabilities.contains(Capability::POISE_RESISTANT)
});
if resistant { 0.5 } else { 0.0 }
};

View File

@ -96,7 +96,7 @@ impl CharacterBehavior for Data {
}
},
StageSection::Action => {
if input_is_pressed(data, self.static_data.ability_info.input)
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
&& (self.static_data.energy_drain <= f32::EPSILON
|| update.energy.current() > 0.0)
{

View File

@ -76,7 +76,7 @@ impl CharacterBehavior for Data {
},
StageSection::Action => {
if self.static_data.can_hold
&& input_is_pressed(data, self.static_data.ability_info.input)
&& self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
{
// Block
update.character = CharacterState::BasicBlock(Data {

View File

@ -118,7 +118,7 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if input_is_pressed(data, self.static_data.ability_info.input) {
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
reset_state(self, data, output_events, &mut update);
} else {
end_ability(data, &mut update);
@ -146,10 +146,12 @@ fn reset_state(
output_events: &mut OutputEvents,
update: &mut StateUpdate,
) {
handle_input(
join,
output_events,
update,
data.static_data.ability_info.input,
);
if let Some(input) = data.static_data.ability_info.input {
handle_input(
join,
output_events,
update,
input,
);
}
}

View File

@ -123,7 +123,7 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if input_is_pressed(data, self.static_data.ability_info.input) {
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
reset_state(self, data, output_events, &mut update);
} else {
end_ability(data, &mut update);
@ -149,10 +149,12 @@ fn reset_state(
output_events: &mut OutputEvents,
update: &mut StateUpdate,
) {
handle_input(
join,
output_events,
update,
data.static_data.ability_info.input,
);
if let Some(input) = data.static_data.ability_info.input {
handle_input(
join,
output_events,
update,
input,
);
}
}

View File

@ -46,7 +46,7 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if input_is_pressed(data, self.static_data.ability_info.input) {
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
reset_state(self, data, output_events, &mut update);
} else {
update.vel.0 = update.vel.0.try_normalized().unwrap_or_default()
@ -69,10 +69,12 @@ fn reset_state(
output_events: &mut OutputEvents,
update: &mut StateUpdate,
) {
handle_input(
join,
output_events,
update,
data.static_data.ability_info.input,
);
if let Some(input) = data.static_data.ability_info.input {
handle_input(
join,
output_events,
update,
input,
);
}
}

View File

@ -58,7 +58,7 @@ impl CharacterBehavior for Data {
match self.stage_section {
StageSection::Charge => {
if input_is_pressed(data, self.static_data.ability_info.input)
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
&& update.energy.current() >= self.static_data.energy_cost
&& self.timer < self.static_data.charge_duration
{
@ -77,7 +77,7 @@ impl CharacterBehavior for Data {
update
.energy
.change_by(-self.static_data.energy_drain * data.dt.0);
} else if input_is_pressed(data, self.static_data.ability_info.input)
} else if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
&& update.energy.current() >= self.static_data.energy_cost
{
// Maintains charge

View File

@ -96,7 +96,7 @@ impl CharacterBehavior for Data {
}
},
StageSection::Charge => {
if !input_is_pressed(data, self.static_data.ability_info.input) && !self.exhausted {
if !self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) && !self.exhausted {
let charge_frac = self.charge_frac();
let arrow = ProjectileConstructor::Arrow {
damage: self.static_data.initial_damage as f32
@ -138,7 +138,7 @@ impl CharacterBehavior for Data {
..*self
});
} else if self.timer < self.static_data.charge_duration
&& input_is_pressed(data, self.static_data.ability_info.input)
&& self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
{
// Charges
update.character = CharacterState::ChargedRanged(Data {
@ -150,7 +150,7 @@ impl CharacterBehavior for Data {
update
.energy
.change_by(-self.static_data.energy_drain * data.dt.0);
} else if input_is_pressed(data, self.static_data.ability_info.input) {
} else if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
// Holds charge
update.character = CharacterState::ChargedRanged(Data {
timer: tick_attack_or_default(data, self.timer, None),

View File

@ -341,7 +341,7 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if input_is_pressed(data, self.static_data.ability_info.input) {
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
reset_state(self, data, output_events, &mut update);
} else {
end_ability(data, &mut update);
@ -382,14 +382,16 @@ fn reset_state(
output_events: &mut OutputEvents,
update: &mut StateUpdate,
) {
handle_input(
join,
output_events,
update,
data.static_data.ability_info.input,
);
if let Some(input) = data.static_data.ability_info.input {
handle_input(
join,
output_events,
update,
input,
);
if let CharacterState::ComboMelee(c) = &mut update.character {
c.stage = (data.stage % data.static_data.num_stages) + 1;
if let CharacterState::ComboMelee(c) = &mut update.character {
c.stage = (data.stage % data.static_data.num_stages) + 1;
}
}
}

View File

@ -1,11 +1,11 @@
use crate::{
comp::{
character_state::OutputEvents, tool::Stats, CharacterState, InputKind, Melee,
MeleeConstructor, StateUpdate, InputAttr
MeleeConstructor, StateUpdate, InputAttr, InventoryAction, slot::{Slot, EquipSlot},
},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
utils::*, idle, wielding,
},
uid::Uid,
};
@ -116,7 +116,7 @@ impl CharacterBehavior for Data {
let ability_input = if self.static_data.is_stance {
InputKind::Primary
} else {
self.static_data.ability_info.input
self.static_data.ability_info.input.unwrap_or(InputKind::Primary)
};
handle_orientation(data, &mut update, 1.0, None);
@ -237,7 +237,7 @@ impl CharacterBehavior for Data {
if input_is_pressed(data, ability_input) {
next_strike(&mut update)
} else if !input_is_pressed(data, self.static_data.ability_info.input) {
} else if !self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
attempt_input(data, output_events, &mut update);
}
},
@ -255,7 +255,7 @@ impl CharacterBehavior for Data {
) -> StateUpdate {
let mut update = StateUpdate::from(data);
if matches!(data.character, CharacterState::ComboMelee2(data) if data.static_data.ability_info.input == input && input != InputKind::Primary && data.stage_section.is_none()) {
if matches!(data.character, CharacterState::ComboMelee2(data) if data.static_data.ability_info.input == Some(input) && input != InputKind::Primary && data.stage_section.is_none()) {
end_ability(data, &mut update);
} else {
update.queued_inputs.insert(input, InputAttr {
@ -265,6 +265,97 @@ impl CharacterBehavior for Data {
}
update
}
fn swap_equipped_weapons(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
update.character =
CharacterState::Wielding(wielding::Data { is_sneaking: data.character.is_stealthy() });
attempt_swap_equipped_weapons(data, &mut update);
}
}
update
}
fn unwield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
update.character = CharacterState::Idle(idle::Data {
is_sneaking: data.character.is_stealthy(),
footwear: None,
});
}
}
update
}
fn manipulate_loadout(
&self,
data: &JoinData,
output_events: &mut OutputEvents,
inv_action: InventoryAction,
) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
match inv_action {
InventoryAction::Drop(slot)
| InventoryAction::Swap(slot, _)
| InventoryAction::Swap(_, Slot::Equip(slot)) if matches!(slot, EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand) => {
update.character = CharacterState::Idle(idle::Data {
is_sneaking: data.character.is_stealthy(),
footwear: None,
});
},
_ => (),
}
handle_manipulate_loadout(data, output_events, &mut update, inv_action);
}
}
update
}
fn glide_wield(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
attempt_glide_wield(data, &mut update, output_events);
}
}
update
}
fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
attempt_sit(data, &mut update);
}
}
update
}
fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() {
attempt_dance(data, &mut update);
}
}
update
}
fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let CharacterState::ComboMelee2(c) = data.character {
if c.stage_section.is_none() && data.physics.on_ground.is_some() && data.body.is_humanoid() {
update.character = CharacterState::Wielding(wielding::Data { is_sneaking: true });
}
}
update
}
}
impl Data {

View File

@ -81,7 +81,7 @@ impl CharacterBehavior for Data {
} else {
// Transitions to charge section of stage
update.character = CharacterState::DashMelee(Data {
auto_charge: !input_is_pressed(data, self.static_data.ability_info.input),
auto_charge: !self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)),
timer: Duration::default(),
stage_section: StageSection::Charge,
..*self
@ -90,7 +90,7 @@ impl CharacterBehavior for Data {
},
StageSection::Charge => {
if self.timer < self.charge_end_timer
&& (input_is_pressed(data, self.static_data.ability_info.input)
&& (self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
|| (self.auto_charge && self.timer < self.static_data.charge_duration))
&& update.energy.current() > 0.0
{

View File

@ -56,7 +56,7 @@ impl CharacterBehavior for Data {
});
} else {
// Done
if input_is_pressed(data, self.static_data.ability_info.input) {
if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
reset_state(self, data, output_events, &mut update);
} else {
end_ability(data, &mut update);
@ -72,7 +72,7 @@ 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) {
if !self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input)) {
handle_dodge_input(data, &mut update);
}
@ -86,10 +86,12 @@ fn reset_state(
output_events: &mut OutputEvents,
update: &mut StateUpdate,
) {
handle_input(
join,
output_events,
update,
data.static_data.ability_info.input,
);
if let Some(input) = data.static_data.ability_info.input {
handle_input(
join,
output_events,
update,
input,
);
}
}

View File

@ -84,7 +84,7 @@ impl CharacterBehavior for Data {
.unwrap_or_default(),
..*self
});
} else if input_is_pressed(data, self.static_data.ability_info.input)
} else if self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))
&& update.energy.current() >= self.static_data.energy_cost
{
// Fire if input is pressed still

View File

@ -121,7 +121,7 @@ impl CharacterBehavior for Data {
} else if update.energy.current() as f32 >= self.static_data.energy_cost
&& (self.consecutive_spins < self.static_data.num_spins
|| (self.static_data.is_infinite
&& input_is_pressed(data, self.static_data.ability_info.input)))
&& self.static_data.ability_info.input.map_or(false, |input| input_is_pressed(data, input))))
{
update.character = CharacterState::SpinMelee(Data {
timer: Duration::default(),

View File

@ -29,6 +29,8 @@ pub struct StaticData {
pub was_wielded: bool,
/// Was sneaking
pub was_sneak: bool,
/// Miscellaneous information about the ability
pub ability_info: AbilityInfo,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -19,6 +19,8 @@ pub struct StaticData {
pub movement_speed: f32,
/// Poise state (used for determining animation in the client)
pub poise_state: PoiseState,
/// Miscellaneous information about the ability
pub ability_info: AbilityInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -36,6 +36,8 @@ pub struct StaticData {
pub was_wielded: bool,
/// Was sneaking
pub was_sneak: bool,
/// Miscellaneous information about the ability
pub ability_info: AbilityInfo,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -806,8 +806,9 @@ pub fn handle_manipulate_loadout(
inv_slot,
item_kind,
item_hash: item.item_hash(),
was_wielded: matches!(data.character, CharacterState::Wielding(_)),
was_wielded: data.character.is_wield(),
was_sneak: data.character.is_stealthy(),
ability_info: AbilityInfo::from_forced_state_change(data.character),
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
@ -910,8 +911,9 @@ pub fn handle_manipulate_loadout(
recover_duration,
sprite_pos,
sprite_kind: sprite_interact,
was_wielded: matches!(data.character, CharacterState::Wielding(_)),
was_wielded: data.character.is_wield(),
was_sneak: data.character.is_stealthy(),
ability_info: AbilityInfo::from_forced_state_change(data.character),
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
@ -1060,7 +1062,7 @@ pub fn handle_dodge_input(data: &JoinData<'_>, update: &mut StateUpdate) {
));
if let CharacterState::Roll(roll) = &mut update.character {
if let CharacterState::ComboMelee(c) = data.character {
roll.was_combo = Some((c.static_data.ability_info.input, c.stage));
roll.was_combo = c.static_data.ability_info.input.map(|input| (input, c.stage));
roll.was_wielded = true;
} else {
if data.character.is_wield() {
@ -1085,7 +1087,7 @@ pub fn handle_interrupts(
// Check that the input used to enter current character state (if there was one)
// is not pressed
if input_override
.or_else(|| data.character.ability_info().map(|a| a.input))
.or_else(|| data.character.ability_info().and_then(|a| a.input))
.map_or(true, |input| !input_is_pressed(data, input))
{
let can_dodge = {
@ -1095,16 +1097,14 @@ pub fn handle_interrupts(
.map_or(true, |stage_section| {
matches!(stage_section, StageSection::Buildup)
});
let interruptible = data.character.ability_info().map_or(false, |info| {
info.ability_meta
.capabilities
let interruptible = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| {
meta.capabilities
.contains(Capability::ROLL_INTERRUPT)
});
in_buildup || interruptible
};
let can_block = data.character.ability_info().map_or(false, |info| {
info.ability_meta
.capabilities
let can_block = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| {
meta.capabilities
.contains(Capability::BLOCK_INTERRUPT)
});
if can_dodge {
@ -1281,12 +1281,13 @@ impl MovementDirection {
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct AbilityInfo {
pub tool: Option<ToolKind>,
pub hand: Option<HandInfo>,
pub input: InputKind,
pub input: Option<InputKind>,
pub input_attr: Option<InputAttr>,
pub ability_meta: AbilityMeta,
pub ability_meta: Option<AbilityMeta>,
pub ability: Option<Ability>,
pub return_ability: Option<InputKind>,
}
@ -1314,7 +1315,7 @@ impl AbilityInfo {
.map(|(i, a)| a.get_ability(i, data.inventory, Some(data.skill_set)));
let return_ability = if data.character.should_be_returned_to() {
data.character.ability_info().map(|info| info.input)
data.character.ability_info().and_then(|info| info.input)
} else {
None
};
@ -1322,13 +1323,31 @@ impl AbilityInfo {
Self {
tool,
hand,
input,
input: Some(input),
input_attr: data.controller.queued_inputs.get(&input).copied(),
ability_meta,
ability_meta: Some(ability_meta),
ability,
return_ability,
}
}
pub fn from_forced_state_change(char_state: &CharacterState) -> Self {
let return_ability = if char_state.should_be_returned_to() {
char_state.ability_info().and_then(|info| info.input)
} else {
None
};
Self {
tool: None,
hand: None,
input: None,
input_attr: None,
ability_meta: None,
ability: None,
return_ability,
}
}
}
pub fn end_ability(data: &JoinData<'_>, update: &mut StateUpdate) {

View File

@ -17,7 +17,7 @@ use common::{
resources::{DeltaTime, Time},
states::{
behavior::{JoinData, JoinStruct},
idle,
idle, utils,
},
terrain::TerrainGrid,
uid::Uid,
@ -148,10 +148,11 @@ impl<'a> System<'a> for Sys {
// Enter stunned state if poise damage is enough
if let Some(mut poise) = poises.get_mut(entity) {
let was_wielded = char_state.is_wield();
let ability_info = utils::AbilityInfo::from_forced_state_change(&char_state);
let poise_state = poise.poise_state();
let pos = pos.0;
if let (Some((stunned_state, stunned_duration)), impulse_strength) =
poise_state.poise_effect(was_wielded)
poise_state.poise_effect(was_wielded, ability_info)
{
// Reset poise if there is some stunned state to apply
poise.reset(*read_data.time, stunned_duration);

View File

@ -26,7 +26,7 @@ use common::{
outcome::{HealthChangeInfo, Outcome},
resources::Time,
rtsim::RtSimEntity,
states::utils::StageSection,
states::utils::{AbilityInfo, StageSection},
terrain::{Block, BlockKind, TerrainGrid},
uid::{Uid, UidAllocator},
util::Dir,
@ -1324,8 +1324,9 @@ pub fn handle_entity_attacked_hook(server: &Server, entity: EcsEntity) {
) {
let poise_state = comp::poise::PoiseState::Interrupted;
let was_wielded = char_state.is_wield();
let ability_info = AbilityInfo::from_forced_state_change(&char_state);
if let (Some((stunned_state, stunned_duration)), impulse_strength) =
poise_state.poise_effect(was_wielded)
poise_state.poise_effect(was_wielded, ability_info)
{
// Reset poise if there is some stunned state to apply
poise.reset(*time, stunned_duration);

View File

@ -250,7 +250,7 @@ impl<'a> Widget for BuffsBar<'a> {
{
match buff.kind {
BuffIconKind::Buff { kind, .. } => event.push(Event::RemoveBuff(kind)),
BuffIconKind::Ability { .. } => todo!(),
BuffIconKind::Ability { .. } => {},
}
};
});
@ -413,7 +413,7 @@ impl<'a> Widget for BuffsBar<'a> {
{
match buff.kind {
BuffIconKind::Buff { kind, .. } => event.push(Event::RemoveBuff(kind)),
BuffIconKind::Ability { .. } => todo!(),
BuffIconKind::Ability { .. } => {},
}
}
Text::new(&remaining_time)