mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Food now applies buff at end of state.
Rolling and poise states now cancel the potion buff. UseItem character state now checks that the item in the slot has the same item_definition_id as when the entity enters the state. Rolling can no cancel item use. Rolling now checks for move_dir instead of velocity.
This commit is contained in:
parent
37c6fe9ee8
commit
8a9de26132
@ -339,7 +339,7 @@ impl CharacterAbility {
|
||||
match self {
|
||||
CharacterAbility::Roll { energy_cost, .. } => {
|
||||
data.physics.on_ground.is_some()
|
||||
&& data.vel.0.xy().magnitude_squared() > 0.5
|
||||
&& data.inputs.move_dir.magnitude_squared() > 0.25
|
||||
&& update
|
||||
.energy
|
||||
.try_change_by(-(*energy_cost as i32), EnergySource::Ability)
|
||||
|
@ -1,9 +1,10 @@
|
||||
use super::utils::*;
|
||||
use crate::{
|
||||
comp::{
|
||||
buff::{BuffChange, BuffKind},
|
||||
inventory::{
|
||||
item::{ConsumableKind, ItemKind},
|
||||
slot::Slot,
|
||||
slot::{InvSlotId, Slot},
|
||||
},
|
||||
CharacterState, InventoryManip, StateUpdate,
|
||||
},
|
||||
@ -14,7 +15,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Separated out to condense update portions of character state
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct StaticData {
|
||||
/// Buildup to item use
|
||||
pub buildup_duration: Duration,
|
||||
@ -23,7 +24,9 @@ pub struct StaticData {
|
||||
/// Recovery after item use
|
||||
pub recover_duration: Duration,
|
||||
/// Inventory slot to use item from
|
||||
pub inv_slot: Slot,
|
||||
pub inv_slot: InvSlotId,
|
||||
/// Item definition id, used to verify that slot still has the correct item
|
||||
pub item_definition_id: String,
|
||||
/// Kind of item used
|
||||
pub item_kind: ItemUseKind,
|
||||
/// Had weapon wielded
|
||||
@ -32,7 +35,7 @@ pub struct StaticData {
|
||||
pub was_sneak: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Struct containing data that does not change over the course of the
|
||||
/// character state
|
||||
@ -58,48 +61,59 @@ impl CharacterBehavior for Data {
|
||||
},
|
||||
}
|
||||
|
||||
let use_point = match self.static_data.item_kind {
|
||||
ItemUseKind::Consumable(ConsumableKind::Potion) => UsePoint::BuildupUse,
|
||||
ItemUseKind::Consumable(ConsumableKind::Food) => UsePoint::UseRecover,
|
||||
};
|
||||
|
||||
match self.stage_section {
|
||||
StageSection::Buildup => {
|
||||
if self.timer < self.static_data.buildup_duration {
|
||||
// Build up
|
||||
update.character = CharacterState::UseItem(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to use section of stage
|
||||
update.character = CharacterState::UseItem(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Use,
|
||||
..*self
|
||||
});
|
||||
// Create inventory manipulation event
|
||||
let inv_manip = InventoryManip::Use(self.static_data.inv_slot);
|
||||
update
|
||||
.server_events
|
||||
.push_front(ServerEvent::InventoryManip(data.entity, inv_manip));
|
||||
if let UsePoint::BuildupUse = use_point {
|
||||
// Create inventory manipulation event
|
||||
use_item(data, &mut update, self);
|
||||
}
|
||||
}
|
||||
},
|
||||
StageSection::Use => {
|
||||
if self.timer < self.static_data.use_duration {
|
||||
// Item use
|
||||
update.character = CharacterState::UseItem(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to recover section of stage
|
||||
update.character = CharacterState::UseItem(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
if let UsePoint::UseRecover = use_point {
|
||||
// Create inventory manipulation event
|
||||
use_item(data, &mut update, self);
|
||||
}
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
if self.timer < self.static_data.recover_duration {
|
||||
// Recovery
|
||||
update.character = CharacterState::UseItem(Data {
|
||||
static_data: self.static_data.clone(),
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
@ -120,6 +134,17 @@ impl CharacterBehavior for Data {
|
||||
},
|
||||
}
|
||||
|
||||
// At end of state logic so an interrupt isn't overwritten
|
||||
handle_state_interrupt(data, &mut update, false);
|
||||
|
||||
if matches!(update.character, CharacterState::Roll(_)) {
|
||||
// Remove potion effect if left the use item state early by rolling
|
||||
update.server_events.push_front(ServerEvent::Buff {
|
||||
entity: data.entity,
|
||||
buff_change: BuffChange::RemoveByKind(BuffKind::Potion),
|
||||
});
|
||||
}
|
||||
|
||||
update
|
||||
}
|
||||
}
|
||||
@ -138,3 +163,28 @@ impl From<&ItemKind> for Option<ItemUseKind> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to control when the item is used in the state
|
||||
enum UsePoint {
|
||||
/// Between buildup and use
|
||||
BuildupUse,
|
||||
/// Between use and recover
|
||||
UseRecover,
|
||||
}
|
||||
|
||||
fn use_item(data: &JoinData, update: &mut StateUpdate, state: &Data) {
|
||||
// Check if the same item is in the slot
|
||||
let item_is_same = data
|
||||
.inventory
|
||||
.get(state.static_data.inv_slot)
|
||||
.map_or(false, |item| {
|
||||
item.item_definition_id() == state.static_data.item_definition_id
|
||||
});
|
||||
if item_is_same {
|
||||
// Create inventory manipulation event
|
||||
let inv_manip = InventoryManip::Use(Slot::Inventory(state.static_data.inv_slot));
|
||||
update
|
||||
.server_events
|
||||
.push_front(ServerEvent::InventoryManip(data.entity, inv_manip));
|
||||
}
|
||||
}
|
||||
|
@ -576,14 +576,14 @@ pub fn handle_manipulate_loadout(
|
||||
inv_action: InventoryAction,
|
||||
) {
|
||||
use use_item::ItemUseKind;
|
||||
if let InventoryAction::Use(Slot::Inventory(slot)) = inv_action {
|
||||
if let InventoryAction::Use(Slot::Inventory(inv_slot)) = inv_action {
|
||||
// If inventory action is using a slot, and slot is in the inventory
|
||||
// TODO: Do some non lazy way of handling the possibility that items equipped in
|
||||
// the loadout will have effects that are desired to be non-instantaneous
|
||||
if let Some(item_kind) = data
|
||||
if let Some((item_kind, item)) = data
|
||||
.inventory
|
||||
.get(slot)
|
||||
.and_then(|item| Option::<ItemUseKind>::from(item.kind()))
|
||||
.get(inv_slot)
|
||||
.and_then(|item| Option::<ItemUseKind>::from(item.kind()).zip(Some(item)))
|
||||
{
|
||||
// (buildup, use, recover)
|
||||
let durations = match item_kind {
|
||||
@ -604,8 +604,9 @@ pub fn handle_manipulate_loadout(
|
||||
buildup_duration: durations.0,
|
||||
use_duration: durations.1,
|
||||
recover_duration: durations.2,
|
||||
inv_slot: Slot::Inventory(slot),
|
||||
inv_slot,
|
||||
item_kind,
|
||||
item_definition_id: item.item_definition_id().to_string(),
|
||||
was_wielded: matches!(data.character, CharacterState::Wielding),
|
||||
was_sneak: matches!(data.character, CharacterState::Sneak),
|
||||
},
|
||||
|
@ -165,6 +165,14 @@ impl<'a> System<'a> for Sys {
|
||||
let was_wielded = char_state.get_unchecked().is_wield();
|
||||
let poise_state = poise.poise_state();
|
||||
let pos = pos.0;
|
||||
// Remove potion buff if knocked into poise state
|
||||
if !matches!(poise_state, PoiseState::Normal) {
|
||||
use comp::buff::{BuffChange, BuffKind};
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
entity,
|
||||
buff_change: BuffChange::RemoveByKind(BuffKind::Potion),
|
||||
});
|
||||
}
|
||||
match poise_state {
|
||||
PoiseState::Normal => {},
|
||||
PoiseState::Interrupted => {
|
||||
|
Loading…
Reference in New Issue
Block a user