mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Enable unequipping as well as equipping to specific slots
This commit is contained in:
parent
66b4c0d529
commit
c1c09dce1b
@ -54,6 +54,13 @@
|
||||
"voxel.weapon.shield.wood-0",
|
||||
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 2.4,
|
||||
),
|
||||
// Lanterns
|
||||
Lantern(Black0): Png(
|
||||
"element.icons.lantern_black-0",
|
||||
),
|
||||
Lantern(Green0): Png(
|
||||
"element.icons.lantern_green-0",
|
||||
),
|
||||
// Other
|
||||
Utility(Collar): Png(
|
||||
"element.icons.collar",
|
||||
@ -251,13 +258,6 @@
|
||||
Armor(Neck(Neck0)): Png(
|
||||
"element.icons.neck-0",
|
||||
),
|
||||
// Lanterns
|
||||
Armor(Lantern(Black0)): Png(
|
||||
"element.icons.lantern_black-0",
|
||||
),
|
||||
Armor(Lantern(Green0)): Png(
|
||||
"element.icons.lantern_green-0",
|
||||
),
|
||||
// Tabards
|
||||
Armor(Tabard(Admin)): Png(
|
||||
"element.icons.tabard_admin",
|
||||
|
@ -244,21 +244,21 @@ impl Client {
|
||||
// Can't fail
|
||||
}
|
||||
|
||||
pub fn use_inventory_slot(&mut self, slot: usize) {
|
||||
pub fn use_slot(&mut self, slot: comp::slot::Slot) {
|
||||
self.postbox
|
||||
.send_message(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Use(slot),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn swap_inventory_slots(&mut self, a: usize, b: usize) {
|
||||
pub fn swap_slots(&mut self, a: comp::slot::Slot, b: comp::slot::Slot) {
|
||||
self.postbox
|
||||
.send_message(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Swap(a, b),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn drop_inventory_slot(&mut self, slot: usize) {
|
||||
pub fn drop_slot(&mut self, slot: comp::slot::Slot) {
|
||||
self.postbox
|
||||
.send_message(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Drop(slot),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{sync::Uid, util::Dir};
|
||||
use crate::{comp::inventory::slot::Slot, sync::Uid, util::Dir};
|
||||
use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
use std::time::Duration;
|
||||
@ -11,9 +11,9 @@ pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
|
||||
pub enum InventoryManip {
|
||||
Pickup(Uid),
|
||||
Collect(Vec3<i32>),
|
||||
Use(usize),
|
||||
Swap(usize, usize),
|
||||
Drop(usize),
|
||||
Use(Slot),
|
||||
Swap(Slot, Slot),
|
||||
Drop(Slot),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -188,13 +188,6 @@ pub enum Neck {
|
||||
pub const ALL_NECKS: [Neck; 1] = [Neck::Neck0];
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Lantern {
|
||||
Black0 = 1,
|
||||
Green0 = 2,
|
||||
}
|
||||
pub const ALL_LANTERNS: [Lantern; 2] = [Lantern::Black0, Lantern::Green0];
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Leather0 = 1,
|
||||
AssaMask0 = 2,
|
||||
@ -218,7 +211,6 @@ pub enum Armor {
|
||||
Back(Back),
|
||||
Ring(Ring),
|
||||
Neck(Neck),
|
||||
Lantern(Lantern),
|
||||
Head(Head),
|
||||
Tabard(Tabard),
|
||||
}
|
||||
|
@ -36,12 +36,21 @@ pub enum Ingredient {
|
||||
Grass,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Lantern {
|
||||
Black0 = 1,
|
||||
Green0 = 2,
|
||||
}
|
||||
pub const ALL_LANTERNS: [Lantern; 2] = [Lantern::Black0, Lantern::Green0];
|
||||
|
||||
fn default_amount() -> u32 { 1 }
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum ItemKind {
|
||||
/// Something wieldable
|
||||
Tool(tool::Tool),
|
||||
Lantern(Lantern),
|
||||
Armor {
|
||||
kind: armor::Armor,
|
||||
stats: armor::Stats,
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod item;
|
||||
pub mod slot;
|
||||
|
||||
use crate::assets;
|
||||
use item::{Consumable, Item, ItemKind};
|
||||
@ -36,7 +37,9 @@ impl Inventory {
|
||||
/// new group. Returns the item again if no space was found.
|
||||
pub fn push(&mut self, item: Item) -> Option<Item> {
|
||||
let item = match item.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } => self.add_to_first_empty(item),
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => {
|
||||
self.add_to_first_empty(item)
|
||||
},
|
||||
ItemKind::Utility {
|
||||
kind: item_kind,
|
||||
amount: new_amount,
|
||||
@ -239,7 +242,9 @@ impl Inventory {
|
||||
if let Some(Some(item)) = self.slots.get_mut(cell) {
|
||||
let mut return_item = item.clone();
|
||||
match &mut item.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } => self.remove(cell),
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => {
|
||||
self.remove(cell)
|
||||
},
|
||||
ItemKind::Utility { kind, amount } => {
|
||||
if *amount <= 1 {
|
||||
self.remove(cell)
|
||||
|
250
common/src/comp/inventory/slot.rs
Normal file
250
common/src/comp/inventory/slot.rs
Normal file
@ -0,0 +1,250 @@
|
||||
use crate::{comp, comp::item};
|
||||
use comp::{Inventory, Loadout};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum Slot {
|
||||
Inventory(usize),
|
||||
Equip(EquipSlot),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum EquipSlot {
|
||||
Armor(ArmorSlot),
|
||||
Mainhand,
|
||||
Offhand,
|
||||
Lantern,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum ArmorSlot {
|
||||
Head,
|
||||
Neck,
|
||||
Shoulders,
|
||||
Chest,
|
||||
Hands,
|
||||
Ring,
|
||||
Back,
|
||||
Belt,
|
||||
Legs,
|
||||
Feet,
|
||||
Tabard,
|
||||
}
|
||||
|
||||
//const ALL_ARMOR_SLOTS: [ArmorSlot; 11] = [
|
||||
// Head, Neck, Shoulders, Chest, Hands, Ring, Back, Belt, Legs, Feet, Tabard,
|
||||
//];
|
||||
|
||||
impl Slot {
|
||||
pub fn can_hold(self, item_kind: &item::ItemKind) -> bool {
|
||||
match (self, item_kind) {
|
||||
(Self::Inventory(_), _) => true,
|
||||
(Self::Equip(slot), item_kind) => slot.can_hold(item_kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EquipSlot {
|
||||
fn can_hold(self, item_kind: &item::ItemKind) -> bool {
|
||||
use item::ItemKind;
|
||||
match (self, item_kind) {
|
||||
(Self::Armor(slot), ItemKind::Armor { kind, .. }) => slot.can_hold(kind),
|
||||
(Self::Mainhand, ItemKind::Tool(_)) => true,
|
||||
(Self::Offhand, ItemKind::Tool(_)) => true,
|
||||
(Self::Lantern, ItemKind::Lantern(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ArmorSlot {
|
||||
fn can_hold(self, armor: &item::armor::Armor) -> bool {
|
||||
use item::armor::Armor;
|
||||
match (self, armor) {
|
||||
(Self::Head, Armor::Head(_)) => true,
|
||||
(Self::Neck, Armor::Neck(_)) => true,
|
||||
(Self::Shoulders, Armor::Shoulder(_)) => true,
|
||||
(Self::Chest, Armor::Chest(_)) => true,
|
||||
(Self::Hands, Armor::Hand(_)) => true,
|
||||
(Self::Ring, Armor::Ring(_)) => true,
|
||||
(Self::Back, Armor::Back(_)) => true,
|
||||
(Self::Belt, Armor::Belt(_)) => true,
|
||||
(Self::Legs, Armor::Pants(_)) => true,
|
||||
(Self::Feet, Armor::Foot(_)) => true,
|
||||
(Self::Tabard, Armor::Tabard(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: shouldn't need this
|
||||
fn item_config(item: item::Item) -> comp::ItemConfig {
|
||||
let mut abilities = if let item::ItemKind::Tool(tool) = &item.kind {
|
||||
tool.get_abilities()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
.into_iter();
|
||||
|
||||
comp::ItemConfig {
|
||||
item,
|
||||
ability1: abilities.next(),
|
||||
ability2: abilities.next(),
|
||||
ability3: abilities.next(),
|
||||
block_ability: Some(comp::CharacterAbility::BasicBlock),
|
||||
dodge_ability: Some(comp::CharacterAbility::Roll),
|
||||
}
|
||||
}
|
||||
|
||||
fn loadout_replace(
|
||||
equip_slot: EquipSlot,
|
||||
item: Option<item::Item>,
|
||||
loadout: &mut Loadout,
|
||||
) -> Option<item::Item> {
|
||||
use std::mem::replace;
|
||||
match equip_slot {
|
||||
EquipSlot::Armor(ArmorSlot::Head) => replace(&mut loadout.head, item),
|
||||
EquipSlot::Armor(ArmorSlot::Neck) => replace(&mut loadout.neck, item),
|
||||
EquipSlot::Armor(ArmorSlot::Shoulders) => replace(&mut loadout.shoulder, item),
|
||||
EquipSlot::Armor(ArmorSlot::Chest) => replace(&mut loadout.chest, item),
|
||||
EquipSlot::Armor(ArmorSlot::Hands) => replace(&mut loadout.hand, item),
|
||||
EquipSlot::Armor(ArmorSlot::Ring) => replace(&mut loadout.ring, item),
|
||||
EquipSlot::Armor(ArmorSlot::Back) => replace(&mut loadout.back, item),
|
||||
EquipSlot::Armor(ArmorSlot::Belt) => replace(&mut loadout.belt, item),
|
||||
EquipSlot::Armor(ArmorSlot::Legs) => replace(&mut loadout.pants, item),
|
||||
EquipSlot::Armor(ArmorSlot::Feet) => replace(&mut loadout.foot, item),
|
||||
EquipSlot::Armor(ArmorSlot::Tabard) => replace(&mut loadout.tabard, item),
|
||||
EquipSlot::Lantern => replace(&mut loadout.lantern, item),
|
||||
EquipSlot::Mainhand => {
|
||||
replace(&mut loadout.active_item, item.map(item_config)).map(|i| i.item)
|
||||
},
|
||||
EquipSlot::Offhand => {
|
||||
replace(&mut loadout.second_item, item.map(item_config)).map(|i| i.item)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn loadout_insert(
|
||||
equip_slot: EquipSlot,
|
||||
item: item::Item,
|
||||
loadout: &mut Loadout,
|
||||
) -> Option<item::Item> {
|
||||
loadout_replace(equip_slot, Some(item), loadout)
|
||||
}
|
||||
|
||||
pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout) -> Option<item::Item> {
|
||||
loadout_replace(equip_slot, None, loadout)
|
||||
}
|
||||
|
||||
fn swap_inventory_loadout(
|
||||
inventory_slot: usize,
|
||||
equip_slot: EquipSlot,
|
||||
inventory: &mut Inventory,
|
||||
loadout: &mut Loadout,
|
||||
) {
|
||||
// Check if loadout slot can hold item
|
||||
if inventory
|
||||
.get(inventory_slot)
|
||||
.map_or(true, |item| equip_slot.can_hold(&item.kind))
|
||||
{
|
||||
// Take item from loadout
|
||||
let from_equip = loadout_remove(equip_slot, loadout);
|
||||
// Swap with item in the inventory
|
||||
let from_inv = if let Some(item) = from_equip {
|
||||
// If this fails and we get item back as an err it will just be put back in the
|
||||
// loadout
|
||||
inventory
|
||||
.insert(inventory_slot, item)
|
||||
.unwrap_or_else(|i| Some(i))
|
||||
} else {
|
||||
inventory.remove(inventory_slot)
|
||||
};
|
||||
// Put item from the inventory in loadout
|
||||
if let Some(item) = from_inv {
|
||||
loadout_insert(equip_slot, item, loadout).unwrap_none(); // Can never fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) {
|
||||
// Get items from the slots
|
||||
let item_a = loadout_remove(slot_a, loadout);
|
||||
let item_b = loadout_remove(slot_b, loadout);
|
||||
// Check if items can go in the other slots
|
||||
if item_a.as_ref().map_or(true, |i| slot_b.can_hold(&i.kind))
|
||||
&& item_b.as_ref().map_or(true, |i| slot_a.can_hold(&i.kind))
|
||||
{
|
||||
// Swap
|
||||
loadout_replace(slot_b, item_a, loadout).unwrap_none();
|
||||
loadout_replace(slot_a, item_b, loadout).unwrap_none();
|
||||
} else {
|
||||
// Otherwise put the items back
|
||||
loadout_replace(slot_a, item_a, loadout).unwrap_none();
|
||||
loadout_replace(slot_b, item_b, loadout).unwrap_none();
|
||||
}
|
||||
}
|
||||
|
||||
// Should this report if a change actually occurred? (might be useful when
|
||||
// minimizing network use)
|
||||
pub fn swap(
|
||||
slot_a: Slot,
|
||||
slot_b: Slot,
|
||||
inventory: Option<&mut Inventory>,
|
||||
loadout: Option<&mut Loadout>,
|
||||
) {
|
||||
match (slot_a, slot_b) {
|
||||
(Slot::Inventory(slot_a), Slot::Inventory(slot_b)) => {
|
||||
inventory.map(|i| i.swap_slots(slot_a, slot_b));
|
||||
},
|
||||
(Slot::Inventory(inv_slot), Slot::Equip(equip_slot))
|
||||
| (Slot::Equip(equip_slot), Slot::Inventory(inv_slot)) => {
|
||||
if let Some((inventory, loadout)) = loadout.and_then(|l| inventory.map(|i| (i, l))) {
|
||||
swap_inventory_loadout(inv_slot, equip_slot, inventory, loadout);
|
||||
}
|
||||
},
|
||||
|
||||
(Slot::Equip(slot_a), Slot::Equip(slot_b)) => {
|
||||
loadout.map(|l| swap_loadout(slot_a, slot_b, l));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
use item::{armor::Armor, ItemKind};
|
||||
|
||||
let equip_slot = inventory.get(slot).and_then(|i| match &i.kind {
|
||||
ItemKind::Tool(_) => Some(EquipSlot::Mainhand),
|
||||
ItemKind::Armor { kind, .. } => Some(EquipSlot::Armor(match kind {
|
||||
Armor::Head(_) => ArmorSlot::Head,
|
||||
Armor::Neck(_) => ArmorSlot::Neck,
|
||||
Armor::Shoulder(_) => ArmorSlot::Shoulders,
|
||||
Armor::Chest(_) => ArmorSlot::Chest,
|
||||
Armor::Hand(_) => ArmorSlot::Hands,
|
||||
Armor::Ring(_) => ArmorSlot::Ring,
|
||||
Armor::Back(_) => ArmorSlot::Back,
|
||||
Armor::Belt(_) => ArmorSlot::Belt,
|
||||
Armor::Pants(_) => ArmorSlot::Legs,
|
||||
Armor::Foot(_) => ArmorSlot::Feet,
|
||||
Armor::Tabard(_) => ArmorSlot::Tabard,
|
||||
})),
|
||||
ItemKind::Lantern(_) => Some(EquipSlot::Lantern),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
if let Some(equip_slot) = equip_slot {
|
||||
// If item is going to mainhand, put mainhand in offhand and place offhand in
|
||||
// inventory
|
||||
if let EquipSlot::Mainhand = equip_slot {
|
||||
swap_loadout(EquipSlot::Mainhand, EquipSlot::Offhand, loadout);
|
||||
}
|
||||
|
||||
swap_inventory_loadout(slot, equip_slot, inventory, loadout);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
loadout_remove(slot, loadout) // Remove item from loadout
|
||||
.and_then(|i| inventory.push(i)) // Insert into inventory
|
||||
.and_then(|i| loadout_insert(slot, i, loadout)) // If that fails put back in loadout
|
||||
.unwrap(); // Never fails
|
||||
}
|
@ -31,7 +31,7 @@ pub use controller::{
|
||||
pub use energy::{Energy, EnergySource};
|
||||
pub use inputs::CanBuild;
|
||||
pub use inventory::{
|
||||
item, item::Item, Inventory, InventoryUpdate, InventoryUpdateEvent, MAX_PICKUP_RANGE_SQR,
|
||||
item, item::Item, slot, Inventory, InventoryUpdate, InventoryUpdateEvent, MAX_PICKUP_RANGE_SQR,
|
||||
};
|
||||
pub use last::Last;
|
||||
pub use location::{Waypoint, WaypointArea};
|
||||
|
@ -2,6 +2,7 @@
|
||||
#![type_length_limit = "1664759"]
|
||||
#![feature(
|
||||
arbitrary_enum_discriminant,
|
||||
option_unwrap_none,
|
||||
bool_to_option,
|
||||
label_break_value,
|
||||
trait_alias,
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{Server, StateExt};
|
||||
use common::{
|
||||
comp::{self, item, Pos, MAX_PICKUP_RANGE_SQR},
|
||||
comp::{
|
||||
self, item,
|
||||
slot::{self, Slot},
|
||||
Pos, MAX_PICKUP_RANGE_SQR,
|
||||
},
|
||||
sync::WorldSyncExt,
|
||||
terrain::block::Block,
|
||||
vol::{ReadVol, Vox},
|
||||
@ -83,162 +87,145 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
}
|
||||
},
|
||||
|
||||
comp::InventoryManip::Use(slot_idx) => {
|
||||
let item_opt = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.and_then(|inv| inv.take(slot_idx));
|
||||
comp::InventoryManip::Use(slot) => {
|
||||
let mut inventories = state.ecs().write_storage::<comp::Inventory>();
|
||||
let inventory = if let Some(inventory) = inventories.get_mut(entity) {
|
||||
inventory
|
||||
} else {
|
||||
error!("Can't manipulate inventory, entity doesn't have one");
|
||||
return;
|
||||
};
|
||||
|
||||
let mut event = comp::InventoryUpdateEvent::Used;
|
||||
let mut maybe_effect = None;
|
||||
|
||||
if let Some(item) = item_opt {
|
||||
match &item.kind {
|
||||
item::ItemKind::Tool(tool) => {
|
||||
if let Some(loadout) =
|
||||
state.ecs().write_storage::<comp::Loadout>().get_mut(entity)
|
||||
{
|
||||
// Insert old item into inventory
|
||||
if let Some(old_item) = loadout.active_item.take() {
|
||||
state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.insert(slot_idx, old_item.item));
|
||||
}
|
||||
|
||||
let mut abilities = tool.get_abilities();
|
||||
let mut ability_drain = abilities.drain(..);
|
||||
let active_item = comp::ItemConfig {
|
||||
item,
|
||||
ability1: ability_drain.next(),
|
||||
ability2: ability_drain.next(),
|
||||
ability3: ability_drain.next(),
|
||||
block_ability: Some(comp::CharacterAbility::BasicBlock),
|
||||
dodge_ability: Some(comp::CharacterAbility::Roll),
|
||||
};
|
||||
loadout.active_item = Some(active_item);
|
||||
let event = match slot {
|
||||
Slot::Inventory(slot) => {
|
||||
use item::ItemKind;
|
||||
// Check if item is equipable
|
||||
if inventory.get(slot).map_or(false, |i| match &i.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => true,
|
||||
_ => false,
|
||||
}) {
|
||||
if let Some(loadout) = state.ecs().write_storage().get_mut(entity) {
|
||||
slot::equip(slot, inventory, loadout);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
|
||||
item::ItemKind::Consumable { kind, effect, .. } => {
|
||||
event = comp::InventoryUpdateEvent::Consumed(*kind);
|
||||
state.apply_effect(entity, *effect);
|
||||
},
|
||||
|
||||
item::ItemKind::Armor { kind, .. } => {
|
||||
if let Some(loadout) =
|
||||
state.ecs().write_storage::<comp::Loadout>().get_mut(entity)
|
||||
{
|
||||
use comp::item::armor::Armor::*;
|
||||
let slot = match kind.clone() {
|
||||
Shoulder(_) => &mut loadout.shoulder,
|
||||
Chest(_) => &mut loadout.chest,
|
||||
Belt(_) => &mut loadout.belt,
|
||||
Hand(_) => &mut loadout.hand,
|
||||
Pants(_) => &mut loadout.pants,
|
||||
Foot(_) => &mut loadout.foot,
|
||||
Back(_) => &mut loadout.back,
|
||||
Ring(_) => &mut loadout.ring,
|
||||
Neck(_) => &mut loadout.neck,
|
||||
Lantern(_) => &mut loadout.lantern,
|
||||
Head(_) => &mut loadout.head,
|
||||
Tabard(_) => &mut loadout.tabard,
|
||||
};
|
||||
|
||||
// Insert old item into inventory
|
||||
if let Some(old_item) = slot.take() {
|
||||
state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.insert(slot_idx, old_item));
|
||||
}
|
||||
|
||||
*slot = Some(item);
|
||||
}
|
||||
},
|
||||
|
||||
item::ItemKind::Utility { kind, .. } => match kind {
|
||||
comp::item::Utility::Collar => {
|
||||
let reinsert = if let Some(pos) =
|
||||
state.read_storage::<comp::Pos>().get(entity)
|
||||
{
|
||||
if (
|
||||
&state.read_storage::<comp::Alignment>(),
|
||||
&state.read_storage::<comp::Agent>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(alignment, _)| {
|
||||
alignment == &&comp::Alignment::Owned(entity)
|
||||
})
|
||||
.count()
|
||||
>= 3
|
||||
} else if let Some(item) = inventory.take(slot) {
|
||||
match &item.kind {
|
||||
ItemKind::Consumable { kind, effect, .. } => {
|
||||
maybe_effect = Some(*effect);
|
||||
Some(comp::InventoryUpdateEvent::Consumed(*kind))
|
||||
},
|
||||
ItemKind::Utility {
|
||||
kind: comp::item::Utility::Collar,
|
||||
..
|
||||
} => {
|
||||
let reinsert = if let Some(pos) =
|
||||
state.read_storage::<comp::Pos>().get(entity)
|
||||
{
|
||||
true
|
||||
} else if let Some(tameable_entity) = {
|
||||
let nearest_tameable = (
|
||||
&state.ecs().entities(),
|
||||
&state.ecs().read_storage::<comp::Pos>(),
|
||||
&state.ecs().read_storage::<comp::Alignment>(),
|
||||
if (
|
||||
&state.read_storage::<comp::Alignment>(),
|
||||
&state.read_storage::<comp::Agent>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, wild_pos, _)| {
|
||||
wild_pos.0.distance_squared(pos.0) < 5.0f32.powf(2.0)
|
||||
.filter(|(alignment, _)| {
|
||||
alignment == &&comp::Alignment::Owned(entity)
|
||||
})
|
||||
.filter(|(_, _, alignment)| {
|
||||
alignment == &&comp::Alignment::Wild
|
||||
})
|
||||
.min_by_key(|(_, wild_pos, _)| {
|
||||
(wild_pos.0.distance_squared(pos.0) * 100.0) as i32
|
||||
})
|
||||
.map(|(entity, _, _)| entity);
|
||||
nearest_tameable
|
||||
} {
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(tameable_entity, comp::Alignment::Owned(entity));
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(tameable_entity, comp::Agent::default());
|
||||
false
|
||||
.count()
|
||||
>= 3
|
||||
{
|
||||
true
|
||||
} else if let Some(tameable_entity) = {
|
||||
let nearest_tameable = (
|
||||
&state.ecs().entities(),
|
||||
&state.ecs().read_storage::<comp::Pos>(),
|
||||
&state.ecs().read_storage::<comp::Alignment>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, wild_pos, _)| {
|
||||
wild_pos.0.distance_squared(pos.0)
|
||||
< 5.0f32.powf(2.0)
|
||||
})
|
||||
.filter(|(_, _, alignment)| {
|
||||
alignment == &&comp::Alignment::Wild
|
||||
})
|
||||
.min_by_key(|(_, wild_pos, _)| {
|
||||
(wild_pos.0.distance_squared(pos.0) * 100.0) as i32
|
||||
})
|
||||
.map(|(entity, _, _)| entity);
|
||||
nearest_tameable
|
||||
} {
|
||||
let _ = state.ecs().write_storage().insert(
|
||||
tameable_entity,
|
||||
comp::Alignment::Owned(entity),
|
||||
);
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(tameable_entity, comp::Agent::default());
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if reinsert {
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.insert(slot, item));
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if reinsert {
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.insert(slot_idx, item));
|
||||
}
|
||||
},
|
||||
},
|
||||
_ => {
|
||||
let _ = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.insert(slot_idx, item));
|
||||
},
|
||||
}
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
},
|
||||
_ => {
|
||||
// TODO: this doesn't work for stackable items
|
||||
inventory.insert(slot, item).unwrap();
|
||||
None
|
||||
},
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
Slot::Equip(slot) => {
|
||||
if let Some(loadout) = state.ecs().write_storage().get_mut(entity) {
|
||||
slot::unequip(slot, inventory, loadout);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
error!("Entity doesn't have a loadout, can't unequip...");
|
||||
None
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
drop(inventories);
|
||||
if let Some(effect) = maybe_effect {
|
||||
state.apply_effect(entity, effect);
|
||||
}
|
||||
if let Some(event) = event {
|
||||
state.write_component(entity, comp::InventoryUpdate::new(event));
|
||||
}
|
||||
|
||||
state.write_component(entity, comp::InventoryUpdate::new(event));
|
||||
},
|
||||
|
||||
comp::InventoryManip::Swap(a, b) => {
|
||||
state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.swap_slots(a, b));
|
||||
let ecs = state.ecs();
|
||||
let mut inventories = ecs.write_storage();
|
||||
let mut loadouts = ecs.write_storage();
|
||||
let inventory = inventories.get_mut(entity);
|
||||
let loadout = loadouts.get_mut(entity);
|
||||
|
||||
slot::swap(a, b, inventory, loadout);
|
||||
|
||||
// :/
|
||||
drop(loadouts);
|
||||
drop(inventories);
|
||||
|
||||
state.write_component(
|
||||
entity,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Swapped),
|
||||
@ -246,11 +233,18 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
},
|
||||
|
||||
comp::InventoryManip::Drop(slot) => {
|
||||
let item = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.and_then(|inv| inv.remove(slot));
|
||||
let item = match slot {
|
||||
Slot::Inventory(slot) => state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.and_then(|inv| inv.remove(slot)),
|
||||
Slot::Equip(slot) => state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.get_mut(entity)
|
||||
.and_then(|ldt| slot::loadout_remove(slot, ldt)),
|
||||
};
|
||||
|
||||
if let (Some(item), Some(pos)) =
|
||||
(item, state.ecs().read_storage::<comp::Pos>().get(entity))
|
||||
|
@ -1,9 +1,8 @@
|
||||
use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::ItemImgs,
|
||||
slots::{ArmorSlot, InventorySlot, SlotManager},
|
||||
Event as HudEvent, Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
XP_COLOR,
|
||||
slots::{ArmorSlot, EquipSlot, InventorySlot, SlotManager},
|
||||
Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
i18n::VoxygenLocalization,
|
||||
@ -135,7 +134,6 @@ pub struct State {
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
HudEvent(HudEvent),
|
||||
Stats,
|
||||
Close,
|
||||
}
|
||||
@ -350,7 +348,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Head, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Head), [45.0; 2])
|
||||
.mid_top_with_margin_on(state.ids.bg_frame, 60.0)
|
||||
.with_icon(self.imgs.head_bg, Vec2::new(32.0, 40.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -363,7 +361,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Neck, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Neck), [45.0; 2])
|
||||
.mid_bottom_with_margin_on(state.ids.head_slot, -55.0)
|
||||
.with_icon(self.imgs.necklace_bg, Vec2::new(40.0, 31.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -377,7 +375,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Chest, [85.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Chest), [85.0; 2])
|
||||
.mid_bottom_with_margin_on(state.ids.neck_slot, -95.0)
|
||||
.with_icon(self.imgs.chest_bg, Vec2::new(64.0, 42.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -388,7 +386,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
|item| (item.name(), item.description()),
|
||||
);
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Shoulders, [70.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Shoulders), [70.0; 2])
|
||||
.bottom_left_with_margins_on(state.ids.chest_slot, 0.0, -80.0)
|
||||
.with_icon(self.imgs.shoulders_bg, Vec2::new(60.0, 36.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -401,7 +399,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Hands, [70.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Hands), [70.0; 2])
|
||||
.bottom_right_with_margins_on(state.ids.chest_slot, 0.0, -80.0)
|
||||
.with_icon(self.imgs.hands_bg, Vec2::new(55.0, 60.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -414,7 +412,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Belt, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Belt), [45.0; 2])
|
||||
.mid_bottom_with_margin_on(state.ids.chest_slot, -55.0)
|
||||
.with_icon(self.imgs.belt_bg, Vec2::new(40.0, 23.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -427,7 +425,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Legs, [85.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Legs), [85.0; 2])
|
||||
.mid_bottom_with_margin_on(state.ids.belt_slot, -95.0)
|
||||
.with_icon(self.imgs.legs_bg, Vec2::new(48.0, 70.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -438,7 +436,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
|item| (item.name(), item.description()),
|
||||
);
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Lantern, [45.0; 2])
|
||||
.fabricate(EquipSlot::Lantern, [45.0; 2])
|
||||
.bottom_right_with_margins_on(state.ids.shoulders_slot, -55.0, 0.0)
|
||||
.with_icon(self.imgs.lantern_bg, Vec2::new(24.0, 38.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -451,7 +449,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Ring, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Ring), [45.0; 2])
|
||||
.bottom_left_with_margins_on(state.ids.hands_slot, -55.0, 0.0)
|
||||
.with_icon(self.imgs.ring_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -464,7 +462,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Back, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Back), [45.0; 2])
|
||||
.down_from(state.ids.lantern_slot, 10.0)
|
||||
.with_icon(self.imgs.back_bg, Vec2::new(33.0, 40.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -477,7 +475,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Feet, [45.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Feet), [45.0; 2])
|
||||
.down_from(state.ids.ring_slot, 10.0)
|
||||
.with_icon(self.imgs.feet_bg, Vec2::new(32.0, 40.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -490,7 +488,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
(item.name(), item.description())
|
||||
});
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Tabard, [70.0; 2])
|
||||
.fabricate(EquipSlot::Armor(ArmorSlot::Tabard), [70.0; 2])
|
||||
.top_right_with_margins_on(state.ids.bg_frame, 80.5, 53.0)
|
||||
.with_icon(self.imgs.tabard_bg, Vec2::new(60.0, 60.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -501,7 +499,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
|item| (item.name(), item.description()),
|
||||
);
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Mainhand, [85.0; 2])
|
||||
.fabricate(EquipSlot::Mainhand, [85.0; 2])
|
||||
.bottom_right_with_margins_on(state.ids.back_slot, -95.0, 0.0)
|
||||
.with_icon(self.imgs.mainhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -512,7 +510,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
|item| (item.name(), item.description()),
|
||||
);
|
||||
slot_maker
|
||||
.fabricate(ArmorSlot::Offhand, [85.0; 2])
|
||||
.fabricate(EquipSlot::Offhand, [85.0; 2])
|
||||
.bottom_left_with_margins_on(state.ids.feet_slot, -95.0, 0.0)
|
||||
.with_icon(self.imgs.offhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN))
|
||||
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
|
||||
@ -681,9 +679,6 @@ impl<'a> Widget for Bag<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Drop selected item
|
||||
// if ui.widget_input(ui.window).clicks().left().next().is_some() {
|
||||
|
||||
// Stats Button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(92.0, 22.0)
|
||||
|
@ -4,7 +4,7 @@ use common::{
|
||||
comp::item::{
|
||||
armor::Armor,
|
||||
tool::{Tool, ToolKind},
|
||||
Consumable, Ingredient, Item, ItemKind, Utility,
|
||||
Consumable, Ingredient, Item, ItemKind, Lantern, Utility,
|
||||
},
|
||||
figure::Segment,
|
||||
};
|
||||
@ -20,6 +20,7 @@ use vek::*;
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum ItemKey {
|
||||
Tool(ToolKind),
|
||||
Lantern(Lantern),
|
||||
Armor(Armor),
|
||||
Utility(Utility),
|
||||
Consumable(Consumable),
|
||||
@ -30,6 +31,7 @@ impl From<&Item> for ItemKey {
|
||||
fn from(item: &Item) -> Self {
|
||||
match &item.kind {
|
||||
ItemKind::Tool(Tool { kind, .. }) => ItemKey::Tool(kind.clone()),
|
||||
ItemKind::Lantern(kind) => ItemKey::Lantern(kind.clone()),
|
||||
ItemKind::Armor { kind, .. } => ItemKey::Armor(kind.clone()),
|
||||
ItemKind::Utility { kind, .. } => ItemKey::Utility(kind.clone()),
|
||||
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),
|
||||
|
@ -232,11 +232,9 @@ pub enum Event {
|
||||
ToggleDebug(bool),
|
||||
UiScale(ScaleChange),
|
||||
CharacterSelection,
|
||||
UseInventorySlot(usize),
|
||||
SwapInventorySlots(usize, usize),
|
||||
SwapInventoryArmor(usize, slots::ArmorSlot),
|
||||
SwapArmorSlots(slots::ArmorSlot, slots::ArmorSlot),
|
||||
DropInventorySlot(usize),
|
||||
UseSlot(comp::slot::Slot),
|
||||
SwapSlots(comp::slot::Slot, comp::slot::Slot),
|
||||
DropSlot(comp::slot::Slot),
|
||||
Logout,
|
||||
Quit,
|
||||
ChangeLanguage(LanguageMetadata),
|
||||
@ -1660,7 +1658,6 @@ impl Hud {
|
||||
)
|
||||
.set(self.ids.bag, ui_widgets)
|
||||
{
|
||||
Some(bag::Event::HudEvent(event)) => events.push(event),
|
||||
Some(bag::Event::Stats) => self.show.stats = !self.show.stats,
|
||||
Some(bag::Event::Close) => {
|
||||
self.show.bag(false);
|
||||
@ -1961,30 +1958,32 @@ impl Hud {
|
||||
|
||||
// Maintain slot manager
|
||||
for event in self.slot_manager.maintain(ui_widgets) {
|
||||
use comp::slot::Slot;
|
||||
use slots::SlotKind;
|
||||
let to_slot = |slot_kind| match slot_kind {
|
||||
SlotKind::Inventory(i) => Some(Slot::Inventory(i.0)),
|
||||
SlotKind::Equip(e) => Some(Slot::Equip(e)),
|
||||
//SlotKind::Hotbar(h) => None,
|
||||
};
|
||||
match event {
|
||||
slot::Event::Dragged(SlotKind::Inventory(from), SlotKind::Inventory(to)) => {
|
||||
// Swap between inventory slots
|
||||
events.push(Event::SwapInventorySlots(from.0, to.0));
|
||||
slot::Event::Dragged(a, b) => {
|
||||
// Swap between slots
|
||||
if let (Some(a), Some(b)) = (to_slot(a), to_slot(b)) {
|
||||
events.push(Event::SwapSlots(a, b));
|
||||
}
|
||||
},
|
||||
slot::Event::Dragged(SlotKind::Armor(from), SlotKind::Armor(to)) => {
|
||||
// Swap between two armor slots
|
||||
events.push(Event::SwapArmorSlots(from, to));
|
||||
slot::Event::Dropped(from) => {
|
||||
// Drop item
|
||||
if let Some(from) = to_slot(from) {
|
||||
events.push(Event::DropSlot(from));
|
||||
}
|
||||
},
|
||||
slot::Event::Dragged(SlotKind::Inventory(inv), SlotKind::Armor(arm))
|
||||
| slot::Event::Dragged(SlotKind::Armor(arm), SlotKind::Inventory(inv)) => {
|
||||
// Swap between inventory and armor slot
|
||||
events.push(Event::SwapInventoryArmor(inv.0, arm));
|
||||
slot::Event::Used(from) => {
|
||||
// Item used (selected and then clicked again)
|
||||
if let Some(from) = to_slot(from) {
|
||||
events.push(Event::UseSlot(from));
|
||||
}
|
||||
},
|
||||
slot::Event::Dropped(SlotKind::Inventory(from)) => {
|
||||
// Drop item from inventory
|
||||
events.push(Event::DropInventorySlot(from.0));
|
||||
},
|
||||
slot::Event::Used(SlotKind::Inventory(inv)) => {
|
||||
// Item in inventory used (selected and then clicked again)
|
||||
events.push(Event::UseInventorySlot(inv.0));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,12 @@ use crate::ui::slot::{self, SlotKey, SumSlot};
|
||||
use common::comp::{item::ItemKind, Inventory, Loadout};
|
||||
use conrod_core::image;
|
||||
|
||||
pub use common::comp::slot::{ArmorSlot, EquipSlot};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum SlotKind {
|
||||
Inventory(InventorySlot),
|
||||
Armor(ArmorSlot),
|
||||
Equip(EquipSlot),
|
||||
/*Hotbar(HotbarSlot),
|
||||
*Spellbook(SpellbookSlot), TODO */
|
||||
}
|
||||
@ -16,24 +18,6 @@ pub type SlotManager = slot::SlotManager<SlotKind>;
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct InventorySlot(pub usize);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum ArmorSlot {
|
||||
Head,
|
||||
Neck,
|
||||
Shoulders,
|
||||
Chest,
|
||||
Hands,
|
||||
Ring,
|
||||
Lantern,
|
||||
Back,
|
||||
Belt,
|
||||
Legs,
|
||||
Feet,
|
||||
Mainhand,
|
||||
Offhand,
|
||||
Tabard,
|
||||
}
|
||||
|
||||
/*#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum HotbarSlot {
|
||||
One,
|
||||
@ -59,7 +43,7 @@ impl SlotKey<Inventory, ItemImgs> for InventorySlot {
|
||||
source
|
||||
.get(self.0)
|
||||
.and_then(|item| match item.kind {
|
||||
ItemKind::Tool { .. } | ItemKind::Armor { .. } => None,
|
||||
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
||||
ItemKind::Utility { amount, .. }
|
||||
| ItemKind::Consumable { amount, .. }
|
||||
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
||||
@ -72,26 +56,25 @@ impl SlotKey<Inventory, ItemImgs> for InventorySlot {
|
||||
}
|
||||
}
|
||||
|
||||
impl SlotKey<Loadout, ItemImgs> for ArmorSlot {
|
||||
impl SlotKey<Loadout, ItemImgs> for EquipSlot {
|
||||
type ImageKey = ItemKey;
|
||||
|
||||
fn image_key(&self, source: &Loadout) -> Option<Self::ImageKey> {
|
||||
let item = match self {
|
||||
ArmorSlot::Shoulders => source.shoulder.as_ref(),
|
||||
ArmorSlot::Chest => source.chest.as_ref(),
|
||||
ArmorSlot::Belt => source.belt.as_ref(),
|
||||
ArmorSlot::Hands => source.hand.as_ref(),
|
||||
ArmorSlot::Legs => source.pants.as_ref(),
|
||||
ArmorSlot::Feet => source.foot.as_ref(),
|
||||
ArmorSlot::Back => source.back.as_ref(),
|
||||
ArmorSlot::Ring => source.ring.as_ref(),
|
||||
ArmorSlot::Neck => source.neck.as_ref(),
|
||||
ArmorSlot::Head => source.head.as_ref(),
|
||||
ArmorSlot::Lantern => source.lantern.as_ref(),
|
||||
ArmorSlot::Tabard => source.tabard.as_ref(),
|
||||
ArmorSlot::Mainhand => source.active_item.as_ref().map(|i| &i.item),
|
||||
ArmorSlot::Offhand => source.second_item.as_ref().map(|i| &i.item),
|
||||
_ => None,
|
||||
EquipSlot::Armor(ArmorSlot::Shoulders) => source.shoulder.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Chest) => source.chest.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Belt) => source.belt.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Hands) => source.hand.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Legs) => source.pants.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Feet) => source.foot.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Back) => source.back.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Ring) => source.ring.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Neck) => source.neck.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Head) => source.head.as_ref(),
|
||||
EquipSlot::Armor(ArmorSlot::Tabard) => source.tabard.as_ref(),
|
||||
EquipSlot::Mainhand => source.active_item.as_ref().map(|i| &i.item),
|
||||
EquipSlot::Offhand => source.second_item.as_ref().map(|i| &i.item),
|
||||
EquipSlot::Lantern => source.lantern.as_ref(),
|
||||
};
|
||||
|
||||
item.map(Into::into)
|
||||
@ -132,8 +115,8 @@ impl From<InventorySlot> for SlotKind {
|
||||
fn from(inventory: InventorySlot) -> Self { Self::Inventory(inventory) }
|
||||
}
|
||||
|
||||
impl From<ArmorSlot> for SlotKind {
|
||||
fn from(armor: ArmorSlot) -> Self { Self::Armor(armor) }
|
||||
impl From<EquipSlot> for SlotKind {
|
||||
fn from(equip: EquipSlot) -> Self { Self::Equip(equip) }
|
||||
}
|
||||
|
||||
//impl From<HotbarSlot> for SlotKind {
|
||||
|
@ -12,9 +12,9 @@ use common::{
|
||||
dragon, fish_medium, fish_small,
|
||||
humanoid::{Body, BodyType, EyeColor, Eyebrows, Race, Skin},
|
||||
item::{
|
||||
armor::{Armor, Back, Belt, Chest, Foot, Hand, Head, Lantern, Pants, Shoulder, Tabard},
|
||||
armor::{Armor, Back, Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Tabard},
|
||||
tool::{Tool, ToolKind},
|
||||
ItemKind,
|
||||
ItemKind, Lantern,
|
||||
},
|
||||
object,
|
||||
quadruped_medium::{BodyType as QMBodyType, Species as QMSpecies},
|
||||
@ -701,21 +701,18 @@ impl HumArmorLanternSpec {
|
||||
}
|
||||
|
||||
pub fn mesh_lantern(&self, body: &Body, loadout: &Loadout) -> Mesh<FigurePipeline> {
|
||||
let spec = if let Some(ItemKind::Armor {
|
||||
kind: Armor::Lantern(lantern),
|
||||
..
|
||||
}) = loadout.lantern.as_ref().map(|i| &i.kind)
|
||||
{
|
||||
match self.0.map.get(&lantern) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!("No lantern specification exists for {:?}", lantern);
|
||||
return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
&self.0.default
|
||||
};
|
||||
let spec =
|
||||
if let Some(ItemKind::Lantern(lantern)) = loadout.lantern.as_ref().map(|i| &i.kind) {
|
||||
match self.0.map.get(&lantern) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!("No lantern specification exists for {:?}", lantern);
|
||||
return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
&self.0.default
|
||||
};
|
||||
|
||||
let lantern_segment = color_segment(
|
||||
graceful_load_mat_segment(&spec.vox_spec.0),
|
||||
|
@ -643,22 +643,9 @@ impl PlayState for SessionState {
|
||||
global_state.settings.graphics.max_fps = fps;
|
||||
global_state.settings.save_to_file_warn();
|
||||
},
|
||||
HudEvent::UseInventorySlot(x) => self.client.borrow_mut().use_inventory_slot(x),
|
||||
HudEvent::SwapInventorySlots(a, b) => {
|
||||
self.client.borrow_mut().swap_inventory_slots(a, b)
|
||||
},
|
||||
HudEvent::SwapInventoryArmor(inv_slot, armor_slot) => {
|
||||
// Swapping between inventory and armor slot
|
||||
// TODO: don't do this
|
||||
self.client.borrow_mut().use_inventory_slot(inv_slot)
|
||||
},
|
||||
HudEvent::SwapArmorSlots(from, to) => {
|
||||
// Only works with rings currently
|
||||
// TODO: implement
|
||||
},
|
||||
HudEvent::DropInventorySlot(x) => {
|
||||
self.client.borrow_mut().drop_inventory_slot(x)
|
||||
},
|
||||
HudEvent::UseSlot(x) => self.client.borrow_mut().use_slot(x),
|
||||
HudEvent::SwapSlots(a, b) => self.client.borrow_mut().swap_slots(a, b),
|
||||
HudEvent::DropSlot(x) => self.client.borrow_mut().drop_slot(x),
|
||||
HudEvent::ChangeFOV(new_fov) => {
|
||||
global_state.settings.graphics.fov = new_fov;
|
||||
global_state.settings.save_to_file_warn();
|
||||
|
@ -153,9 +153,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// If dragging and mouse if released check if there is a slot widget under the
|
||||
// If dragging and mouse is released check if there is a slot widget under the
|
||||
// mouse
|
||||
if let ManagerState::Dragging(id, slot, content_img) = &self.state {
|
||||
if let ManagerState::Dragging(_, slot, content_img) = &self.state {
|
||||
let content_img = *content_img;
|
||||
let input = &ui.global_input().current;
|
||||
if let mouse::ButtonPosition::Up = input.mouse.buttons.left() {
|
||||
|
Loading…
Reference in New Issue
Block a user