Inventory: Implemented dynamic and better ordering by Category

This commit is contained in:
Matas Minelga 2022-12-31 02:32:41 +02:00
parent 0052af85bc
commit 040c9fe6ee
No known key found for this signature in database
GPG Key ID: 74923483B70D4E9F
5 changed files with 94 additions and 4 deletions

View File

@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved shiny water shaders
- Tweaked armor stats
- Move bag icon to skillbar
- Improved inventory sorting by Category
### Removed

View File

@ -38,4 +38,5 @@ hud-bag-stun_res_desc =
Regenerates like Energy.
hud-bag-sort_by_name = Sort by Name
hud-bag-sort_by_quality = Sort by Quality
hud-bag-sort_by_category = Sort by Category
hud-bag-sort_by_category = Sort by Category
hud-bag-sort_by_tag = Sort by Tag

View File

@ -305,8 +305,34 @@ impl ItemKind {
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Glider | ItemKind::Lantern(_)
)
}
pub fn get_itemkind_string(&self) -> String {
let result = match self {
ItemKind::Tool(tool) => format!("Tool: {:?}", tool),
ItemKind::ModularComponent(modular_component) => {
format!("Modular Component: {:?}", modular_component)
},
ItemKind::Lantern(lantern) => format!("Lantern: {:?}", lantern),
ItemKind::Armor(armor) => format!("Armor: {:?}", armor),
ItemKind::Glider => "Glider:".to_string(),
ItemKind::Consumable { kind, effects } => {
format!("Consumable: {:?}, {:?}", kind, effects)
},
ItemKind::Throwable { kind } => format!("Throwable: {:?}", kind),
ItemKind::Utility { kind } => format!("Utility: {:?}", kind),
ItemKind::Ingredient { descriptor } => format!("Ingredient: {}", descriptor),
ItemKind::TagExamples { item_ids } => format!("TagExamples: {:?}", item_ids),
};
result
}
}
// impl fmt::Display for ItemKind {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// write!(f, "{}", self.to_string())
// }
// }
pub type ItemId = AtomicCell<Option<NonZeroU64>>;
/* /// The only way to access an item id outside this module is to mutably, atomically update it using

View File

@ -1,7 +1,7 @@
use core::ops::Not;
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use std::{convert::TryFrom, mem, ops::Range};
use std::{cmp::Ordering, convert::TryFrom, mem, ops::Range};
use tracing::{debug, trace, warn};
use vek::Vec3;
@ -54,6 +54,7 @@ pub enum Error {
pub enum InventorySortOrder {
Name,
Quality,
Category,
Tag,
}
@ -62,11 +63,20 @@ impl InventorySortOrder {
match self {
InventorySortOrder::Name => InventorySortOrder::Quality,
InventorySortOrder::Quality => InventorySortOrder::Tag,
InventorySortOrder::Tag => InventorySortOrder::Name,
InventorySortOrder::Tag => InventorySortOrder::Category,
InventorySortOrder::Category => InventorySortOrder::Name,
}
}
}
pub enum CustomOrder {
Name,
Quality,
KindPartial,
KindFull,
Tag,
}
/// Represents the Inventory of an entity. The inventory has 18 "built-in"
/// slots, with further slots being provided by items equipped in the Loadout
/// sub-struct. Inventory slots are indexed by `InvSlotId` which is
@ -137,6 +147,49 @@ impl Inventory {
)
}
pub fn order_by_custom(custom_order: &[CustomOrder], a: &Item, b: &Item) -> Ordering {
let mut order = custom_order.iter();
let a_quality = a.quality();
let b_quality = b.quality();
let a_kind = a.kind().get_itemkind_string();
let b_kind = b.kind().get_itemkind_string();
let mut cmp = match order.next() {
Some(CustomOrder::KindFull) => Ord::cmp(&a_kind, &b_kind),
Some(CustomOrder::KindPartial) => Ord::cmp(
&a_kind.split_once(':').unwrap().0,
&b_kind.split_once(':').unwrap().0,
),
Some(CustomOrder::Quality) => Ord::cmp(&b_quality, &a_quality),
Some(CustomOrder::Name) => Ord::cmp(&a.name(), &b.name()),
Some(CustomOrder::Tag) => Ord::cmp(
&a.tags().first().map_or("", |tag| tag.name()),
&b.tags().first().map_or("", |tag| tag.name()),
),
_ => Ordering::Equal,
};
while cmp == Ordering::Equal {
match order.next() {
Some(CustomOrder::KindFull) => cmp = Ord::cmp(&a_kind, &b_kind),
Some(CustomOrder::KindPartial) => {
cmp = Ord::cmp(
&a_kind.split_once(':').unwrap().0,
&b_kind.split_once(':').unwrap().0,
)
},
Some(CustomOrder::Quality) => cmp = Ord::cmp(&b_quality, &a_quality),
Some(CustomOrder::Name) => cmp = Ord::cmp(&a.name(), &b.name()),
Some(CustomOrder::Tag) => {
cmp = Ord::cmp(
&a.tags().first().map_or("", |tag| tag.name()),
&b.tags().first().map_or("", |tag| tag.name()),
)
},
_ => break,
}
}
cmp
}
/// Sorts the inventory using the next sort order
pub fn sort(&mut self) {
let sort_order = self.next_sort_order;
@ -146,6 +199,14 @@ impl Inventory {
InventorySortOrder::Name => Ord::cmp(&a.name(), &b.name()),
// Quality is sorted in reverse since we want high quality items first
InventorySortOrder::Quality => Ord::cmp(&b.quality(), &a.quality()),
InventorySortOrder::Category => {
let order = vec![
CustomOrder::KindPartial,
CustomOrder::Quality,
CustomOrder::Name,
];
Self::order_by_custom(&order, a, b)
},
InventorySortOrder::Tag => Ord::cmp(
&a.tags().first().map_or("", |tag| tag.name()),
&b.tags().first().map_or("", |tag| tag.name()),

View File

@ -824,7 +824,8 @@ impl<'a> Widget for Bag<'a> {
&(match inventory.next_sort_order() {
InventorySortOrder::Name => i18n.get_msg("hud-bag-sort_by_name"),
InventorySortOrder::Quality => i18n.get_msg("hud-bag-sort_by_quality"),
InventorySortOrder::Tag => i18n.get_msg("hud-bag-sort_by_category"),
InventorySortOrder::Category => i18n.get_msg("hud-bag-sort_by_category"),
InventorySortOrder::Tag => i18n.get_msg("hud-bag-sort_by_tag"),
}),
"",
&tooltip,