Gen7ScriptsRs/pkmn_lib_interface/src/app_interface/static_data/item.rs

144 lines
4.7 KiB
Rust
Executable File

use crate::app_interface::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,
}
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait ItemTrait {
fn reference(&self) -> u32;
/// 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;
fn has_flag(&self, flag: &StringKey) -> bool;
}
pub type Item = Rc<dyn ItemTrait>;
#[cfg(feature = "mock_data")]
pub type MockItem = MockItemTrait;
#[cfg(not(feature = "mock_data"))]
mod implementation {
use crate::app_interface::{BattleItemCategory, ItemCategory, ItemTrait, StringKey};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters};
use alloc::rc::Rc;
struct ItemInner {
reference: ExternRef<ItemImpl>,
name: CachedValue<StringKey>,
category: CachedValue<ItemCategory>,
battle_category: CachedValue<BattleItemCategory>,
price: CachedValue<i32>,
}
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
#[derive(Clone)]
pub struct ItemImpl {
inner: Rc<ItemInner>,
}
#[cfg(not(feature = "mock_data"))]
impl ItemImpl {
pub(crate) fn new(reference: ExternRef<Self>) -> Self {
Self::from_ref(reference, &|reference| Self {
inner: Rc::new(ItemInner {
reference,
name: cached_value!({ StringKey::new(item_get_name(reference)) }),
category: cached_value!({ item_get_category(reference) }),
battle_category: cached_value!({ item_get_battle_category(reference) }),
price: cached_value!({ item_get_price(reference) }),
}),
})
}
pub(crate) fn reference(&self) -> ExternRef<Self> {
self.inner.reference
}
}
#[cfg(not(feature = "mock_data"))]
impl ItemTrait for ItemImpl {
fn reference(&self) -> u32 {
self.inner.reference.get_internal_index()
}
cached_value_getters! {
/// 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;
}
fn has_flag(&self, flag: &StringKey) -> bool {
unsafe { item_has_flag(self.inner.reference, flag.ptr()) }
}
}
crate::handling::cacheable::cacheable!(ItemImpl);
#[cfg(not(feature = "mock_data"))]
impl ExternalReferenceType for ItemImpl {
fn from_extern_value(reference: ExternRef<Self>) -> Self {
ItemImpl::new(reference)
}
}
extern "wasm" {
fn item_get_name(ptr: ExternRef<ItemImpl>) -> ExternRef<StringKey>;
fn item_get_category(ptr: ExternRef<ItemImpl>) -> ItemCategory;
fn item_get_battle_category(ptr: ExternRef<ItemImpl>) -> BattleItemCategory;
fn item_get_price(ptr: ExternRef<ItemImpl>) -> i32;
fn item_has_flag(ptr: ExternRef<ItemImpl>, flag: ExternRef<StringKey>) -> bool;
}
}
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;