diff --git a/common/src/states/use_item.rs b/common/src/states/use_item.rs index 951f69a5d2..342369307d 100644 --- a/common/src/states/use_item.rs +++ b/common/src/states/use_item.rs @@ -5,8 +5,9 @@ use crate::{ item::{ConsumableKind, ItemKind}, slot::Slot, }, - CharacterState, StateUpdate, + CharacterState, InventoryManip, StateUpdate, }, + event::ServerEvent, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -25,6 +26,10 @@ pub struct StaticData { pub inv_slot: Slot, /// Kind of item used pub item_kind: ItemUseKind, + /// Had weapon wielded + pub was_wielded: bool, + /// Was sneaking + pub was_sneak: bool, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -36,16 +41,23 @@ pub struct Data { pub timer: Duration, /// What section the character stage is in pub stage_section: StageSection, - /// Had weapon - pub was_wielded: bool, - /// Was sneaking - pub was_sneak: bool, } impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); + match self.static_data.item_kind { + ItemUseKind::Consumable(ConsumableKind::Potion) => { + handle_orientation(data, &mut update, 1.0); + handle_move(data, &mut update, 1.0); + }, + ItemUseKind::Consumable(ConsumableKind::Food) => { + handle_orientation(data, &mut update, 0.0); + handle_move(data, &mut update, 0.0); + }, + } + match self.stage_section { StageSection::Buildup => { if self.timer < self.static_data.buildup_duration { @@ -61,6 +73,11 @@ impl CharacterBehavior for Data { 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)); } }, StageSection::Use => { @@ -88,9 +105,9 @@ impl CharacterBehavior for Data { }); } else { // Done - if self.was_wielded { + if self.static_data.was_wielded { update.character = CharacterState::Wielding; - } else if self.was_sneak { + } else if self.static_data.was_sneak { update.character = CharacterState::Sneak; } else { update.character = CharacterState::Idle; diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index dadb6b4c8d..2032cc8080 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -2,8 +2,8 @@ use crate::{ combat, comp::{ biped_large, biped_small, - inventory::slot::EquipSlot, - item::{Hands, ItemKind, Tool, ToolKind}, + inventory::slot::{EquipSlot, Slot}, + item::{ConsumableKind, Hands, ItemKind, Tool, ToolKind}, quadruped_low, quadruped_medium, quadruped_small, skills::{Skill, SwimSkill}, theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind, @@ -575,9 +575,56 @@ pub fn handle_manipulate_loadout( update: &mut StateUpdate, inv_action: InventoryAction, ) { - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + use use_item::ItemUseKind; + if let InventoryAction::Use(Slot::Inventory(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 + .inventory + .get(slot) + .and_then(|item| Option::::from(item.kind())) + { + // (buildup, use, recover) + let durations = match item_kind { + ItemUseKind::Consumable(ConsumableKind::Potion) => ( + Duration::from_secs_f32(0.25), + Duration::from_secs_f32(1.0), + Duration::from_secs_f32(0.25), + ), + ItemUseKind::Consumable(ConsumableKind::Food) => ( + Duration::from_secs_f32(1.0), + Duration::from_secs_f32(5.0), + Duration::from_secs_f32(1.0), + ), + }; + // If item returns a valid kind for item use, do into use item character state + update.character = CharacterState::UseItem(use_item::Data { + static_data: use_item::StaticData { + buildup_duration: durations.0, + use_duration: durations.1, + recover_duration: durations.2, + inv_slot: Slot::Inventory(slot), + item_kind, + was_wielded: matches!(data.character, CharacterState::Wielding), + was_sneak: matches!(data.character, CharacterState::Sneak), + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, + }); + } else { + // Else emit inventory action instantnaneously + update + .server_events + .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + } + } else { + // Else if inventory action is not item use, or if slot is in loadout, just do + // event instantaneously + update + .server_events + .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + } } /// Checks that player can wield the glider and updates `CharacterState` if so