pokerogue/src/field/pokemon-held-item-manager.ts

187 lines
5.0 KiB
TypeScript

import { allHeldItems } from "#app/items/all-held-items";
import { isItemInRequested, type HeldItemCategoryId, type HeldItemId } from "#app/enums/held-item-id";
import type { FormChangeItem } from "#enums/form-change-item";
import {
type HeldItemConfiguration,
isHeldItemSpecs,
type HeldItemDataMap,
type HeldItemSpecs,
} from "#app/items/held-item-data-types";
interface FormChangeItemProperties {
active: boolean;
}
export type FormChangeItemPropertyMap = {
[key in FormChangeItem]?: FormChangeItemProperties;
};
export class PokemonItemManager {
public heldItems: HeldItemDataMap;
public formChangeItems: FormChangeItemPropertyMap;
constructor() {
this.heldItems = {};
this.formChangeItems = {};
}
getItemSpecs(id: HeldItemId): HeldItemSpecs | undefined {
const item = this.heldItems[id];
if (item) {
const itemSpecs: HeldItemSpecs = {
...item,
id,
};
return itemSpecs;
}
return undefined;
}
generateHeldItemConfiguration(restrictedIds?: HeldItemId[]): HeldItemConfiguration {
const config: HeldItemConfiguration = [];
for (const [k, item] of Object.entries(this.heldItems)) {
const id = Number(k);
if (item && (!restrictedIds || id in restrictedIds)) {
const specs: HeldItemSpecs = { ...item, id };
config.push({ entry: specs, count: 1 });
}
}
return config;
}
getHeldItems(): number[] {
return Object.keys(this.heldItems).map(k => Number(k));
}
getTransferableHeldItems(): number[] {
return Object.keys(this.heldItems)
.filter(k => allHeldItems[k].isTransferable)
.map(k => Number(k));
}
getStealableHeldItems(): number[] {
return Object.keys(this.heldItems)
.filter(k => allHeldItems[k].isStealable)
.map(k => Number(k));
}
getSuppressableHeldItems(): number[] {
return Object.keys(this.heldItems)
.filter(k => allHeldItems[k].isSuppressable)
.map(k => Number(k));
}
hasItem(itemType: HeldItemId): boolean {
return itemType in this.heldItems;
}
getStack(itemType: HeldItemId): number {
const item = this.heldItems[itemType];
return item ? item.stack : 0;
}
isMaxStack(itemType: HeldItemId): boolean {
const item = this.heldItems[itemType];
return item ? item.stack >= allHeldItems[itemType].getMaxStackCount() : false;
}
overrideItems(newItems: HeldItemDataMap) {
this.heldItems = newItems;
// The following is to allow randomly generated item configs to have stack 0
for (const [item, properties] of Object.entries(this.heldItems)) {
if (!properties || properties.stack <= 0) {
delete this.heldItems[item];
}
}
}
add(itemType: HeldItemId | HeldItemSpecs, addStack = 1): boolean {
if (isHeldItemSpecs(itemType)) {
return this.addItemWithSpecs(itemType);
}
const maxStack = allHeldItems[itemType].getMaxStackCount();
const item = this.heldItems[itemType];
if (item) {
// TODO: We may want an error message of some kind instead
if (item.stack < maxStack) {
item.stack = Math.min(item.stack + addStack, maxStack);
return true;
}
} else {
this.heldItems[itemType] = { stack: Math.min(addStack, maxStack) };
return true;
}
return false;
}
addItemWithSpecs(itemSpecs: HeldItemSpecs): boolean {
const id = itemSpecs.id;
const maxStack = allHeldItems[id].getMaxStackCount();
const item = this.heldItems[id];
const tempStack = item?.stack ?? 0;
this.heldItems[id] = itemSpecs;
this.heldItems[id].stack = Math.min(itemSpecs.stack + tempStack, maxStack);
return true;
}
remove(itemType: HeldItemId, removeStack = 1, all = false) {
const item = this.heldItems[itemType];
if (item) {
item.stack -= removeStack;
if (all || item.stack <= 0) {
delete this.heldItems[itemType];
}
}
}
filterRequestedItems(requestedItems: (HeldItemCategoryId | HeldItemId)[], transferableOnly = true, exclude = false) {
const currentItems = transferableOnly ? this.getTransferableHeldItems() : this.getHeldItems();
return currentItems.filter(it => !exclude && isItemInRequested(it, requestedItems));
}
addFormChangeItem(id: FormChangeItem) {
if (!(id in this.formChangeItems)) {
this.formChangeItems[id] = { active: false };
}
}
hasFormChangeItem(id: FormChangeItem): boolean {
return id in this.formChangeItems;
}
hasActiveFormChangeItem(id: FormChangeItem): boolean {
const item = this.formChangeItems[id];
if (item) {
return item.active;
}
return false;
}
getFormChangeItems(): FormChangeItem[] {
return Object.keys(this.formChangeItems).map(k => Number(k));
}
getActiveFormChangeItems(): FormChangeItem[] {
return this.getFormChangeItems().filter(m => this.formChangeItems[m]?.active);
}
toggleActive(id: FormChangeItem) {
const item = this.formChangeItems[id];
if (item) {
item.active = !item.active;
}
}
clearItems() {
this.heldItems = {};
this.formChangeItems = {};
}
}