mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Sprites now go through a character state to be picked up.
This commit is contained in:
parent
171e329609
commit
538cb56b87
@ -1369,8 +1369,8 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn collect_block(&mut self, pos: Vec3<i32>) {
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent(
|
||||
InventoryEvent::Collect(pos),
|
||||
self.control_action(ControlAction::InventoryAction(InventoryAction::Collect(
|
||||
pos,
|
||||
)));
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,9 @@ pub enum CharacterState {
|
||||
SpriteSummon(sprite_summon::Data),
|
||||
/// Handles logic for using an item so it is not simply instant
|
||||
UseItem(use_item::Data),
|
||||
/// Handles logic for interacting with a sprite, e.g. using a chest or
|
||||
/// picking a plant
|
||||
SpriteInteract(sprite_interact::Data),
|
||||
}
|
||||
|
||||
impl CharacterState {
|
||||
@ -255,6 +258,7 @@ impl CharacterState {
|
||||
CharacterState::SelfBuff(data) => data.behavior(j),
|
||||
CharacterState::SpriteSummon(data) => data.behavior(j),
|
||||
CharacterState::UseItem(data) => data.behavior(j),
|
||||
CharacterState::SpriteInteract(data) => data.behavior(j),
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,6 +299,7 @@ impl CharacterState {
|
||||
CharacterState::SelfBuff(data) => data.handle_event(j, action),
|
||||
CharacterState::SpriteSummon(data) => data.handle_event(j, action),
|
||||
CharacterState::UseItem(data) => data.handle_event(j, action),
|
||||
CharacterState::SpriteInteract(data) => data.handle_event(j, action),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use vek::*;
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum InventoryEvent {
|
||||
Pickup(Uid),
|
||||
Collect(Vec3<i32>),
|
||||
Swap(InvSlotId, InvSlotId),
|
||||
SplitSwap(InvSlotId, InvSlotId),
|
||||
Drop(InvSlotId),
|
||||
@ -35,6 +34,7 @@ pub enum InventoryAction {
|
||||
Drop(EquipSlot),
|
||||
Use(Slot),
|
||||
Sort,
|
||||
Collect(Vec3<i32>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -61,6 +61,7 @@ impl From<InventoryAction> for InventoryManip {
|
||||
InventoryAction::Swap(equip, slot) => Self::Swap(Slot::Equip(equip), slot),
|
||||
InventoryAction::Drop(equip) => Self::Drop(Slot::Equip(equip)),
|
||||
InventoryAction::Sort => Self::Sort,
|
||||
InventoryAction::Collect(collect) => Self::Collect(collect),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,7 +70,6 @@ impl From<InventoryEvent> for InventoryManip {
|
||||
fn from(inv_event: InventoryEvent) -> Self {
|
||||
match inv_event {
|
||||
InventoryEvent::Pickup(pickup) => Self::Pickup(pickup),
|
||||
InventoryEvent::Collect(collect) => Self::Collect(collect),
|
||||
InventoryEvent::Swap(inv1, inv2) => {
|
||||
Self::Swap(Slot::Inventory(inv1), Slot::Inventory(inv2))
|
||||
},
|
||||
|
@ -25,6 +25,7 @@ pub mod shockwave;
|
||||
pub mod sit;
|
||||
pub mod sneak;
|
||||
pub mod spin_melee;
|
||||
pub mod sprite_interact;
|
||||
pub mod sprite_summon;
|
||||
pub mod stunned;
|
||||
pub mod talk;
|
||||
|
184
common/src/states/sprite_interact.rs
Normal file
184
common/src/states/sprite_interact.rs
Normal file
@ -0,0 +1,184 @@
|
||||
use super::utils::*;
|
||||
use crate::{
|
||||
comp::{CharacterState, InventoryManip, StateUpdate},
|
||||
event::ServerEvent,
|
||||
states::behavior::{CharacterBehavior, JoinData},
|
||||
terrain::SpriteKind,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use vek::Vec3;
|
||||
|
||||
/// Separated out to condense update portions of character state
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct StaticData {
|
||||
/// Buildup to item use
|
||||
pub buildup_duration: Duration,
|
||||
/// Duration of item use
|
||||
pub use_duration: Duration,
|
||||
/// Recovery after item use
|
||||
pub recover_duration: Duration,
|
||||
/// Position sprite is located at
|
||||
pub sprite_pos: Vec3<i32>,
|
||||
/// Kind of sprite interacted with
|
||||
pub sprite_kind: SpriteInteractKind,
|
||||
/// Had weapon wielded
|
||||
pub was_wielded: bool,
|
||||
/// Was sneaking
|
||||
pub was_sneak: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Struct containing data that does not change over the course of the
|
||||
/// character state
|
||||
pub static_data: StaticData,
|
||||
/// Timer for each stage
|
||||
pub timer: Duration,
|
||||
/// What section the character stage is in
|
||||
pub stage_section: StageSection,
|
||||
}
|
||||
|
||||
impl CharacterBehavior for Data {
|
||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||
let mut update = StateUpdate::from(data);
|
||||
|
||||
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 {
|
||||
// Build up
|
||||
update.character = CharacterState::SpriteInteract(Data {
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to use section of stage
|
||||
update.character = CharacterState::SpriteInteract(Data {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Action,
|
||||
..*self
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Action => {
|
||||
if self.timer < self.static_data.use_duration {
|
||||
// Item use
|
||||
update.character = CharacterState::SpriteInteract(Data {
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Transitions to recover section of stage
|
||||
update.character = CharacterState::SpriteInteract(Data {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Recover,
|
||||
..*self
|
||||
});
|
||||
}
|
||||
},
|
||||
StageSection::Recover => {
|
||||
if self.timer < self.static_data.recover_duration {
|
||||
// Recovery
|
||||
update.character = CharacterState::SpriteInteract(Data {
|
||||
timer: tick_attack_or_default(data, self.timer, None),
|
||||
..*self
|
||||
});
|
||||
} else {
|
||||
// Create inventory manipulation event
|
||||
let inv_manip = InventoryManip::Collect(self.static_data.sprite_pos);
|
||||
update
|
||||
.server_events
|
||||
.push_front(ServerEvent::InventoryManip(data.entity, inv_manip));
|
||||
// Done
|
||||
if self.static_data.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else if self.static_data.was_sneak {
|
||||
update.character = CharacterState::Sneak;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If it somehow ends up in an incorrect stage section
|
||||
update.character = CharacterState::Idle;
|
||||
},
|
||||
}
|
||||
|
||||
// At end of state logic so an interrupt isn't overwritten
|
||||
handle_state_interrupt(data, &mut update, false);
|
||||
|
||||
update
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to control effects based off of the type of item used
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum SpriteInteractKind {
|
||||
Chest,
|
||||
Harvestable,
|
||||
Collectible,
|
||||
}
|
||||
|
||||
impl From<SpriteKind> for Option<SpriteInteractKind> {
|
||||
fn from(sprite_kind: SpriteKind) -> Self {
|
||||
match sprite_kind {
|
||||
SpriteKind::Apple
|
||||
| SpriteKind::Mushroom
|
||||
| SpriteKind::RedFlower
|
||||
| SpriteKind::Sunflower
|
||||
| SpriteKind::Coconut
|
||||
| SpriteKind::Beehive
|
||||
| SpriteKind::Cotton
|
||||
| SpriteKind::Moonbell
|
||||
| SpriteKind::Pyrebloom
|
||||
| SpriteKind::WildFlax
|
||||
| SpriteKind::RoundCactus
|
||||
| SpriteKind::ShortFlatCactus
|
||||
| SpriteKind::MedFlatCactus => Some(SpriteInteractKind::Harvestable),
|
||||
SpriteKind::Stones
|
||||
| SpriteKind::Twigs
|
||||
| SpriteKind::VialEmpty
|
||||
| SpriteKind::Bowl
|
||||
| SpriteKind::PotionMinor
|
||||
| SpriteKind::Seashells => Some(SpriteInteractKind::Collectible),
|
||||
SpriteKind::DungeonChest0
|
||||
| SpriteKind::DungeonChest1
|
||||
| SpriteKind::DungeonChest2
|
||||
| SpriteKind::DungeonChest3
|
||||
| SpriteKind::DungeonChest4
|
||||
| SpriteKind::DungeonChest5
|
||||
| SpriteKind::Chest
|
||||
| SpriteKind::ChestBuried
|
||||
| SpriteKind::Mud
|
||||
| SpriteKind::Crate => Some(SpriteInteractKind::Chest),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpriteInteractKind {
|
||||
/// Returns (buildup, use, recover)
|
||||
pub fn durations(&self) -> (Duration, Duration, Duration) {
|
||||
match self {
|
||||
Self::Chest => (
|
||||
Duration::from_secs_f32(0.5),
|
||||
Duration::from_secs_f32(2.0),
|
||||
Duration::from_secs_f32(0.5),
|
||||
),
|
||||
Self::Collectible => (
|
||||
Duration::from_secs_f32(0.1),
|
||||
Duration::from_secs_f32(0.3),
|
||||
Duration::from_secs_f32(0.1),
|
||||
),
|
||||
Self::Harvestable => (
|
||||
Duration::from_secs_f32(0.3),
|
||||
Duration::from_secs_f32(0.5),
|
||||
Duration::from_secs_f32(0.2),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ use crate::{
|
||||
event::{LocalEvent, ServerEvent},
|
||||
states::{behavior::JoinData, *},
|
||||
util::Dir,
|
||||
vol::ReadVol,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
@ -584,11 +585,12 @@ pub fn handle_manipulate_loadout(
|
||||
update: &mut StateUpdate,
|
||||
inv_action: InventoryAction,
|
||||
) {
|
||||
use use_item::ItemUseKind;
|
||||
if let InventoryAction::Use(Slot::Inventory(inv_slot)) = inv_action {
|
||||
match inv_action {
|
||||
InventoryAction::Use(Slot::Inventory(inv_slot)) => {
|
||||
// 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
|
||||
use use_item::ItemUseKind;
|
||||
if let Some((item_kind, item)) = data
|
||||
.inventory
|
||||
.and_then(|inv| inv.get(inv_slot))
|
||||
@ -616,13 +618,55 @@ pub fn handle_manipulate_loadout(
|
||||
.server_events
|
||||
.push_front(ServerEvent::InventoryManip(data.entity, inv_action.into()));
|
||||
}
|
||||
},
|
||||
InventoryAction::Collect(pos) => {
|
||||
// First, get sprite data for position, if there is a sprite
|
||||
use sprite_interact::SpriteInteractKind;
|
||||
let sprite_at_pos = data
|
||||
.terrain
|
||||
.get(pos)
|
||||
.ok()
|
||||
.copied()
|
||||
.and_then(|b| b.get_sprite());
|
||||
|
||||
// Checks if position has a collectible sprite as wella s what sprite is at the
|
||||
// position
|
||||
let sprite_interact = sprite_at_pos.and_then(Option::<SpriteInteractKind>::from);
|
||||
|
||||
if let Some(sprite_interact) = sprite_interact {
|
||||
// If the sprite is collectible, enter the sprite interaction character state
|
||||
// TODO: Handle cases for sprite being interactible, but not collectible (none
|
||||
// currently exist)
|
||||
let (buildup_duration, use_duration, recover_duration) =
|
||||
sprite_interact.durations();
|
||||
|
||||
update.character = CharacterState::SpriteInteract(sprite_interact::Data {
|
||||
static_data: sprite_interact::StaticData {
|
||||
buildup_duration,
|
||||
use_duration,
|
||||
recover_duration,
|
||||
sprite_pos: pos,
|
||||
sprite_kind: sprite_interact,
|
||||
was_wielded: matches!(data.character, CharacterState::Wielding),
|
||||
was_sneak: matches!(data.character, CharacterState::Sneak),
|
||||
},
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Buildup,
|
||||
})
|
||||
} else {
|
||||
// Else if inventory action is not item use, or if slot is in loadout, just do
|
||||
// event instantaneously
|
||||
// Otherwise send server event immediately
|
||||
update
|
||||
.server_events
|
||||
.push_front(ServerEvent::InventoryManip(data.entity, inv_action.into()));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// Else 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
|
||||
|
@ -261,7 +261,8 @@ impl<'a> System<'a> for Sys {
|
||||
| CharacterState::Climb { .. }
|
||||
| CharacterState::Stunned { .. }
|
||||
| CharacterState::BasicBlock { .. }
|
||||
| CharacterState::UseItem { .. } => {},
|
||||
| CharacterState::UseItem { .. }
|
||||
| CharacterState::SpriteInteract { .. } => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user