use hashbrown::HashSet; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::any::Any; use std::fmt::Debug; use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// An item category defines which bag slot items are stored in. #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum ItemCategory { /// This is where most items should go. MiscItem, /// Pokeballs are used for capturing Pokemons. Pokeball, /// Medicine is used for healing HP, PP, and status effects Medicine, /// Berry is used for all berries. Berry, /// TMHM is used for Technical and Hidden Machines. TMHM, /// Form Changer is used for items that change forms, such as mega stones. FormChanger, /// Key Items are single stored items, generally used for story progression. KeyItem, /// Mail is used for mail items. Mail, } /// A battle item category defines how the item is categorized when in battle. #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum BattleItemCategory { /// This item can't be used in battle. None, /// This item is used for healing Pokemon. Healing, /// This item is used for healing Pokemon from a status. StatusHealing, /// This item is used for capturing Pokemon. Pokeball, /// This item does not belong in above categories, but is still a battle item. MiscBattleItem, } /// An item is an object which the player can pick up, keep in their Bag, and use in some manner pub trait Item: ValueIdentifiable + Debug + Any { /// The name of the item. fn name(&self) -> &StringKey; /// Which bag slot items are stored in. fn category(&self) -> ItemCategory; /// How the item is categorized when in battle. fn battle_category(&self) -> BattleItemCategory; /// The buying value of the item. fn price(&self) -> i32; /// A set of arbitrary flags that can be set on the item. fn flags(&self) -> &HashSet; /// Checks whether the item has a specific flag. fn has_flag(&self, key: &StringKey) -> bool; } /// An item is an object which the player can pick up, keep in their Bag, and use in some manner #[derive(Debug)] pub struct ItemImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The name of the item. name: StringKey, /// Which bag slot items are stored in. category: ItemCategory, /// How the item is categorized when in battle. battle_category: BattleItemCategory, /// The buying value of the item. price: i32, /// A set of arbitrary flags that can be set on the item. flags: HashSet, } impl ItemImpl { /// Instantiates an item. pub fn new( name: &StringKey, category: ItemCategory, battle_category: BattleItemCategory, price: i32, flags: HashSet, ) -> ItemImpl { ItemImpl { identifier: Default::default(), name: name.clone(), category, battle_category, price, flags, } } } impl Item for ItemImpl { /// The name of the item. fn name(&self) -> &StringKey { &self.name } /// Which bag slot items are stored in. fn category(&self) -> ItemCategory { self.category } /// How the item is categorized when in battle. fn battle_category(&self) -> BattleItemCategory { self.battle_category } /// The buying value of the item. fn price(&self) -> i32 { self.price } /// A set of arbitrary flags that can be set on the item. fn flags(&self) -> &HashSet { &self.flags } /// Checks whether the item has a specific flag. fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } } impl ValueIdentifiable for ItemImpl { fn value_identifier(&self) -> ValueIdentifier { self.identifier } }