diff --git a/src/items/all-held-items.ts b/src/items/all-held-items.ts index 7464a2e3a93..de745f65004 100644 --- a/src/items/all-held-items.ts +++ b/src/items/all-held-items.ts @@ -1,6 +1,7 @@ import { HeldItems } from "#enums/held-items"; import type { PokemonType } from "#enums/pokemon-type"; import { AttackTypeBoosterHeldItem, attackTypeToHeldItem } from "./held-items/attack-type-booster"; +import { HitHealHeldItem } from "./held-items/hit-heal"; import { TurnHealHeldItem } from "./held-items/turn-heal"; export const allHeldItems = {}; @@ -12,5 +13,6 @@ export function initHeldItems() { allHeldItems[heldItemType] = new AttackTypeBoosterHeldItem(heldItemType, 99, pokemonType, 0.2); } allHeldItems[HeldItems.LEFTOVERS] = new TurnHealHeldItem(HeldItems.LEFTOVERS, 4); + allHeldItems[HeldItems.SHELL_BELL] = new HitHealHeldItem(HeldItems.LEFTOVERS, 4); console.log(allHeldItems); } diff --git a/src/items/held-items/hit-heal.ts b/src/items/held-items/hit-heal.ts new file mode 100644 index 00000000000..8e710f3359c --- /dev/null +++ b/src/items/held-items/hit-heal.ts @@ -0,0 +1,55 @@ +import type Pokemon from "#app/field/pokemon"; +import { globalScene } from "#app/global-scene"; +import i18next from "i18next"; +import { HeldItem } from "#app/items/held-item"; +import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; +import { toDmgValue } from "#app/utils/common"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { allHeldItems } from "../all-held-items"; + +export class HitHealHeldItem extends HeldItem { + get name(): string { + return i18next.t("modifierType:ModifierType.SHELL_BELL.name"); + } + + get description(): string { + return i18next.t("modifierType:ModifierType.SHELL_BELL.description"); + } + + get icon(): string { + return "shell_bell"; + } + + /** + * Applies {@linkcode HitHealModifier} + * @param pokemon The {@linkcode Pokemon} that holds the item + * @returns `true` if the {@linkcode Pokemon} was healed + */ + apply(stackCount: number, pokemon: Pokemon): boolean { + if (pokemon.turnData.totalDamageDealt && !pokemon.isFullHp()) { + // TODO: this shouldn't be undefined AFAIK + globalScene.unshiftPhase( + new PokemonHealPhase( + pokemon.getBattlerIndex(), + toDmgValue(pokemon.turnData.totalDamageDealt / 8) * stackCount, + i18next.t("modifier:hitHealApply", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + typeName: this.name, + }), + true, + ), + ); + } + return true; + } +} + +export function applyHitHealHeldItem(pokemon: Pokemon) { + if (pokemon) { + for (const [item, props] of Object.entries(pokemon.heldItemManager.getHeldItems())) { + if (allHeldItems[item] instanceof HitHealHeldItem) { + allHeldItems[item].apply(props.stack, pokemon); + } + } + } +} diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index dcd692462eb..c32364f99ba 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2363,6 +2363,9 @@ export const modifierTypes = { LEFTOVERS_REWARD: () => new PokemonHeldItemReward(HeldItems.LEFTOVERS, (type, args) => new TurnHealModifier(type, (args[0] as Pokemon).id)), + SHELL_BELL_REWARD: () => + new PokemonHeldItemReward(HeldItems.SHELL_BELL, (type, args) => new HitHealModifier(type, (args[0] as Pokemon).id)), + LEFTOVERS: () => new PokemonHeldItemModifierType( "modifierType:ModifierType.LEFTOVERS", @@ -3051,7 +3054,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.ROGUE_BALL, () => (hasMaximumBalls(PokeballType.ROGUE_BALL) ? 0 : 16), 16), new WeightedModifierType(modifierTypes.RELIC_GOLD, skipInLastClassicWaveOrDefault(2)), new WeightedModifierType(modifierTypes.LEFTOVERS_REWARD, 3), - new WeightedModifierType(modifierTypes.SHELL_BELL, 3), + new WeightedModifierType(modifierTypes.SHELL_BELL_REWARD, 3), new WeightedModifierType(modifierTypes.BERRY_POUCH, 4), new WeightedModifierType(modifierTypes.GRIP_CLAW, 5), new WeightedModifierType(modifierTypes.SCOPE_LENS, 4), @@ -3675,6 +3678,27 @@ export function getEnemyModifierTypesForWave( return ret; } +export function getEnemyHeldItemsForWave( + waveIndex: number, + count: number, + party: EnemyPokemon[], + poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER, + upgradeChance = 0, +): PokemonHeldItemReward[] { + const ret = new Array(count) + .fill(0) + .map( + () => + getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0) + ?.type as PokemonHeldItemReward, + ); + if (!(waveIndex % 1000)) { + // TODO: Change this line with the actual held item when implemented + ret.push(getModifierType(modifierTypes.MINI_BLACK_HOLE) as PokemonHeldItemReward); + } + return ret; +} + export function getDailyRunStarterModifiers(party: PlayerPokemon[]): PokemonHeldItemModifier[] { const ret: PokemonHeldItemModifier[] = []; for (const p of party) { diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index e3773952214..15df6e35355 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -78,6 +78,7 @@ import type Move from "#app/data/moves/move"; import { isFieldTargeted } from "#app/data/moves/move-utils"; import { FaintPhase } from "./faint-phase"; import { DamageAchv } from "#app/system/achv"; +import { applyHitHealHeldItem } from "#app/items/held-items/hit-heal"; type HitCheckEntry = [HitCheckResult, TypeDamageMultiplier]; @@ -416,7 +417,7 @@ export class MoveEffectPhase extends PokemonPhase { // If there are multiple hits, or if there are hits of the multi-hit move left globalScene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal })); } - globalScene.applyModifiers(HitHealModifier, this.player, user); + applyHitHealHeldItem(user); this.getTargets().forEach(target => (target.turnData.moveEffectiveness = null)); } }