diff --git a/src/items/all-held-items.ts b/src/items/all-held-items.ts index 396e681a616..6830bcbf7f1 100644 --- a/src/items/all-held-items.ts +++ b/src/items/all-held-items.ts @@ -17,31 +17,17 @@ import { import { type BERRY_PARAMS, BerryHeldItem, berryTypeToHeldItem } from "./held-items/berry"; import { type EXP_BOOST_PARAMS, ExpBoosterHeldItem } from "./held-items/exp-booster"; import { type HIT_HEAL_PARAMS, HitHealHeldItem } from "./held-items/hit-heal"; -import type { RESET_NEGATIVE_STAT_STAGE_PARAMS } from "./held-items/reset-negative-stat-stage"; +import { InstantReviveHeldItem, type INSTANT_REVIVE_PARAMS } from "./held-items/instant-revive"; +import { + ResetNegativeStatStageHeldItem, + type RESET_NEGATIVE_STAT_STAGE_PARAMS, +} from "./held-items/reset-negative-stat-stage"; import type { TURN_END_HEAL_PARAMS } from "./held-items/turn-end-heal"; import { TurnEndHealHeldItem } from "./held-items/turn-end-heal"; export const allHeldItems = {}; export function initHeldItems() { - // SILK_SCARF, BLACK_BELT, etc... - for (const [typeKey, heldItemType] of Object.entries(attackTypeToHeldItem)) { - const pokemonType = Number(typeKey) as PokemonType; - allHeldItems[heldItemType] = new AttackTypeBoosterHeldItem(heldItemType, 99, pokemonType, 0.2); - } - - // vitamins - for (const [statKey, heldItemType] of Object.entries(permanentStatToHeldItem)) { - const stat = Number(statKey) as PermanentStat; - allHeldItems[heldItemType] = new BaseStatBoosterHeldItem(heldItemType, 10, stat); - } - - allHeldItems[HeldItemId.LEFTOVERS] = new TurnEndHealHeldItem(HeldItemId.LEFTOVERS, 4); - allHeldItems[HeldItemId.SHELL_BELL] = new HitHealHeldItem(HeldItemId.SHELL_BELL, 4); - - allHeldItems[HeldItemId.LUCKY_EGG] = new ExpBoosterHeldItem(HeldItemId.LUCKY_EGG, 99, 40); - allHeldItems[HeldItemId.GOLDEN_EGG] = new ExpBoosterHeldItem(HeldItemId.GOLDEN_EGG, 99, 100); - for (const berry of getEnumValues(BerryType)) { let maxStackCount: number; if ([BerryType.LUM, BerryType.LEPPA, BerryType.SITRUS, BerryType.ENIGMA].includes(berry)) { @@ -53,6 +39,27 @@ export function initHeldItems() { allHeldItems[berryId] = new BerryHeldItem(berry, maxStackCount); } console.log(allHeldItems); + + allHeldItems[HeldItemId.REVIVER_SEED] = new InstantReviveHeldItem(HeldItemId.REVIVER_SEED, 1); + allHeldItems[HeldItemId.WHITE_HERB] = new ResetNegativeStatStageHeldItem(HeldItemId.WHITE_HERB, 2); + + // SILK_SCARF, BLACK_BELT, etc... + for (const [typeKey, heldItemType] of Object.entries(attackTypeToHeldItem)) { + const pokemonType = Number(typeKey) as PokemonType; + allHeldItems[heldItemType] = new AttackTypeBoosterHeldItem(heldItemType, 99, pokemonType, 0.2); + } + + allHeldItems[HeldItemId.LUCKY_EGG] = new ExpBoosterHeldItem(HeldItemId.LUCKY_EGG, 99, 40); + allHeldItems[HeldItemId.GOLDEN_EGG] = new ExpBoosterHeldItem(HeldItemId.GOLDEN_EGG, 99, 100); + + allHeldItems[HeldItemId.LEFTOVERS] = new TurnEndHealHeldItem(HeldItemId.LEFTOVERS, 4); + allHeldItems[HeldItemId.SHELL_BELL] = new HitHealHeldItem(HeldItemId.SHELL_BELL, 4); + + // vitamins + for (const [statKey, heldItemType] of Object.entries(permanentStatToHeldItem)) { + const stat = Number(statKey) as PermanentStat; + allHeldItems[heldItemType] = new BaseStatBoosterHeldItem(heldItemType, 10, stat); + } } type APPLY_HELD_ITEMS_PARAMS = { @@ -63,6 +70,7 @@ type APPLY_HELD_ITEMS_PARAMS = { [ITEM_EFFECT.EXP_BOOSTER]: EXP_BOOST_PARAMS; [ITEM_EFFECT.BERRY]: BERRY_PARAMS; [ITEM_EFFECT.BASE_STAT_BOOSTER]: BASE_STAT_BOOSTER_PARAMS; + [ITEM_EFFECT.INSTANT_REVIVE]: INSTANT_REVIVE_PARAMS; }; export function applyHeldItems(effect: T, params: APPLY_HELD_ITEMS_PARAMS[T]) { diff --git a/src/items/held-item.ts b/src/items/held-item.ts index 31d734f686f..b634aecff15 100644 --- a/src/items/held-item.ts +++ b/src/items/held-item.ts @@ -12,6 +12,7 @@ export const ITEM_EFFECT = { // Should we actually distinguish different berry effects? BERRY: 6, BASE_STAT_BOOSTER: 7, + INSTANT_REVIVE: 8, } as const; export type ITEM_EFFECT = (typeof ITEM_EFFECT)[keyof typeof ITEM_EFFECT]; diff --git a/src/items/held-items/instant-revive.ts b/src/items/held-items/instant-revive.ts new file mode 100644 index 00000000000..de395ecd5ff --- /dev/null +++ b/src/items/held-items/instant-revive.ts @@ -0,0 +1,68 @@ +import type Pokemon from "#app/field/pokemon"; +import { globalScene } from "#app/global-scene"; +import i18next from "i18next"; +import { ConsumableHeldItem, ITEM_EFFECT } from "../held-item"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; +import { toDmgValue } from "#app/utils/common"; +import { applyAbAttrs, CommanderAbAttr } from "#app/data/abilities/ability"; + +export interface INSTANT_REVIVE_PARAMS { + /** The pokemon with the item */ + pokemon: Pokemon; +} + +/** + * Modifier used for held items, namely White Herb, that restore adverse stat + * stages in battle. + * @extends PokemonHeldItemModifier + * @see {@linkcode apply} + */ +export class InstantReviveHeldItem extends ConsumableHeldItem { + public effects: ITEM_EFFECT[] = [ITEM_EFFECT.INSTANT_REVIVE]; + + get name(): string { + return i18next.t("modifierType:ModifierType.REVIVER_SEED.name"); + } + + get description(): string { + return i18next.t("modifierType:ModifierType.REVIVER_SEED.description"); + } + + get icon(): string { + return "reviver_seed"; + } + /** + * Goes through the holder's stat stages and, if any are negative, resets that + * stat stage back to 0. + * @param pokemon {@linkcode Pokemon} that holds the item + * @returns `true` if any stat stages were reset, false otherwise + */ + apply(params: INSTANT_REVIVE_PARAMS): boolean { + const pokemon = params.pokemon; + // Restore the Pokemon to half HP + globalScene.unshiftPhase( + new PokemonHealPhase( + pokemon.getBattlerIndex(), + toDmgValue(pokemon.getMaxHp() / 2), + i18next.t("modifier:pokemonInstantReviveApply", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + typeName: this.name, + }), + false, + false, + true, + ), + ); + + // Remove the Pokemon's FAINT status + pokemon.resetStatus(true, false, true, false); + + // Reapply Commander on the Pokemon's side of the field, if applicable + const field = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); + for (const p of field) { + applyAbAttrs(CommanderAbAttr, p, null, false); + } + return true; + } +} diff --git a/src/items/held-items/reset-negative-stat-stage.ts b/src/items/held-items/reset-negative-stat-stage.ts index 9e236a8f458..3dbbf51d404 100644 --- a/src/items/held-items/reset-negative-stat-stage.ts +++ b/src/items/held-items/reset-negative-stat-stage.ts @@ -30,7 +30,7 @@ export class ResetNegativeStatStageHeldItem extends ConsumableHeldItem { } get icon(): string { - return "shell_bell"; + return "white_herb"; } /** * Goes through the holder's stat stages and, if any are negative, resets that