using System.Collections.Immutable; using PkmnLib.Static.Moves; using PkmnLib.Static.Utils; namespace PkmnLib.Static; /// /// An item category defines which bag slot items are stored in. /// public enum ItemCategory { /// /// This is where most items should go. /// MiscItem, /// /// Pokeballs are used for capturing Pokémons. /// 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. /// public enum BattleItemCategory { /// /// This item can't be used in battle. /// None, /// /// This item is used for healing Pokémon. /// Healing, /// /// This item is used for healing Pokémon from a status. /// StatusHealing, /// /// This item is used for capturing Pokémon. /// 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. /// public interface IItem : INamedValue { /// /// Which bag slot items are stored in. /// ItemCategory Category { get; } /// /// How the item is categorized when in battle. /// BattleItemCategory BattleCategory { get; } /// /// The buying value of the item. /// int Price { get; } /// /// A set of arbitrary flags that can be set on the item. /// ImmutableHashSet Flags { get; } /// /// The effect of the item when used outside of battle. /// ISecondaryEffect? Effect { get; } /// /// The effect of the item when used in battle. /// ISecondaryEffect? BattleEffect { get; } /// /// A set of arbitrary data that can be set on the item. /// IReadOnlyDictionary AdditionalData { get; } /// /// Tries to get additional data from the item. If the data is not present, the value will be null. /// If the data is present, but cannot be converted to the requested type, the value will be null. /// bool TryGetAdditionalData(StringKey key, out T? value); /// /// Checks whether the item has a specific flag. /// /// The flag to check for. /// True if the item has the flag, false otherwise. bool HasFlag(string key); } /// public class ItemImpl : IItem { /// public ItemImpl(StringKey name, ItemCategory category, BattleItemCategory battleCategory, int price, IEnumerable flags, ISecondaryEffect? effect, ISecondaryEffect? battleTriggerEffect, Dictionary additionalData) { Name = name; Category = category; BattleCategory = battleCategory; Price = price; Effect = effect; BattleEffect = battleTriggerEffect; AdditionalData = additionalData; Flags = [..flags]; } /// public StringKey Name { get; } /// public ItemCategory Category { get; } /// public BattleItemCategory BattleCategory { get; } /// public int Price { get; } /// public ImmutableHashSet Flags { get; } /// public ISecondaryEffect? Effect { get; } /// public ISecondaryEffect? BattleEffect { get; } /// public IReadOnlyDictionary AdditionalData { get; } /// public bool TryGetAdditionalData(StringKey key, out T? value) { if (AdditionalData.TryGetValue(key, out var obj)) { switch (obj) { case T t: value = t; return true; case IConvertible convertible: try { value = (T)convertible.ToType(typeof(T), null); return true; } catch (InvalidCastException) { // Ignore } break; } } value = default; return false; } /// public bool HasFlag(string key) => Flags.Contains(key); }