use crate::handling::cached_value::CachedValue; use crate::handling::Cacheable; use crate::{cached_value, ExternRef, ExternalReferenceType, StringKey}; use alloc::rc::Rc; /// An item category defines which bag slot items are stored in. #[repr(u8)] #[derive(Clone)] 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. #[repr(u8)] #[derive(Clone)] 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, } struct ItemInner { ptr: ExternRef, name: CachedValue, category: CachedValue, battle_category: CachedValue, price: CachedValue, } /// An item is an object which the player can pick up, keep in their Bag, and use in some manner #[derive(Clone)] pub struct Item { inner: Rc, } impl Item { pub(crate) fn new(ptr: ExternRef) -> Self { Self::from_ref(ptr, &|ptr| Self { inner: Rc::new(ItemInner { ptr, name: cached_value!({ StringKey::new(item_get_name(ptr)) }), category: cached_value!({ item_get_category(ptr) }), battle_category: cached_value!({ item_get_battle_category(ptr) }), price: cached_value!({ item_get_price(ptr) }), }), }) } pub(crate) fn ptr(&self) -> ExternRef { self.inner.ptr } /// The name of the item. pub fn name(&self) -> StringKey { self.inner.name.value() } /// Which bag slot items are stored in. pub fn category(&self) -> ItemCategory { self.inner.category.value() } /// How the item is categorized when in battle. pub fn battle_category(&self) -> BattleItemCategory { self.inner.battle_category.value() } /// The buying value of the item. pub fn price(&self) -> i32 { self.inner.price.value() } pub fn has_flag(&self, flag: &StringKey) -> bool { unsafe { item_has_flag(self.ptr(), flag.ptr()) } } } crate::handling::cacheable::cacheable!(Item); impl ExternalReferenceType for Item { fn from_extern_value(reference: ExternRef) -> Self { Item::new(reference) } } extern "wasm" { fn item_get_name(ptr: ExternRef) -> ExternRef; fn item_get_category(ptr: ExternRef) -> ItemCategory; fn item_get_battle_category(ptr: ExternRef) -> BattleItemCategory; fn item_get_price(ptr: ExternRef) -> i32; fn item_has_flag(ptr: ExternRef, flag: ExternRef) -> bool; }