diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 7a55a7ed571..40818a8eaaf 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -30,7 +30,6 @@ import { HealingBoosterModifier, MultipleParticipantExpBonusModifier, PersistentModifier, - PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, @@ -186,6 +185,8 @@ import { timedEventManager } from "./global-event-manager"; import { starterColors } from "./global-vars/starter-colors"; import { startingWave } from "./starting-wave"; import { ModifierBar } from "./modifier/modifier-bar"; +import { applyHeldItems } from "./items/all-held-items"; +import { ITEM_EFFECT } from "./items/held-item"; const DEBUG_RNG = false; @@ -3722,7 +3723,7 @@ export default class BattleScene extends SceneBase { expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE; } const pokemonExp = new NumberHolder(expValue * expMultiplier); - this.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp); + applyHeldItems(ITEM_EFFECT.EXP_BOOSTER, { pokemon: partyMember, expAmount: pokemonExp }); partyMemberExp.push(Math.floor(pokemonExp.value)); } diff --git a/src/items/all-held-items.ts b/src/items/all-held-items.ts index 4b382f2992d..ec054f493a5 100644 --- a/src/items/all-held-items.ts +++ b/src/items/all-held-items.ts @@ -6,6 +6,7 @@ import { AttackTypeBoosterHeldItem, attackTypeToHeldItem, } from "./held-items/attack-type-booster"; +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 type { TURN_END_HEAL_PARAMS } from "./held-items/turn-end-heal"; @@ -20,7 +21,11 @@ export function initHeldItems() { allHeldItems[heldItemType] = new AttackTypeBoosterHeldItem(heldItemType, 99, pokemonType, 0.2); } allHeldItems[HeldItems.LEFTOVERS] = new TurnEndHealHeldItem(HeldItems.LEFTOVERS, 4); - allHeldItems[HeldItems.SHELL_BELL] = new HitHealHeldItem(HeldItems.LEFTOVERS, 4); + allHeldItems[HeldItems.SHELL_BELL] = new HitHealHeldItem(HeldItems.SHELL_BELL, 4); + + allHeldItems[HeldItems.LUCKY_EGG] = new ExpBoosterHeldItem(HeldItems.LUCKY_EGG, 99, 40); + allHeldItems[HeldItems.GOLDEN_EGG] = new ExpBoosterHeldItem(HeldItems.GOLDEN_EGG, 99, 100); + console.log(allHeldItems); } @@ -29,6 +34,7 @@ type APPLY_HELD_ITEMS_PARAMS = { [ITEM_EFFECT.TURN_END_HEAL]: TURN_END_HEAL_PARAMS; [ITEM_EFFECT.HIT_HEAL]: HIT_HEAL_PARAMS; [ITEM_EFFECT.RESET_NEGATIVE_STAT_STAGE]: RESET_NEGATIVE_STAT_STAGE_PARAMS; + [ITEM_EFFECT.EXP_BOOSTER]: EXP_BOOST_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 c2b5d10bb25..013593a738b 100644 --- a/src/items/held-item.ts +++ b/src/items/held-item.ts @@ -7,6 +7,7 @@ export const ITEM_EFFECT = { TURN_END_HEAL: 2, HIT_HEAL: 3, RESET_NEGATIVE_STAT_STAGE: 4, + EXP_BOOSTER: 5, } as const; export type ITEM_EFFECT = (typeof ITEM_EFFECT)[keyof typeof ITEM_EFFECT]; diff --git a/src/items/held-items/exp-booster.ts b/src/items/held-items/exp-booster.ts new file mode 100644 index 00000000000..e9b5090f972 --- /dev/null +++ b/src/items/held-items/exp-booster.ts @@ -0,0 +1,64 @@ +import type Pokemon from "#app/field/pokemon"; +import type { NumberHolder } from "#app/utils/common"; +import { HeldItems } from "#enums/held-items"; +import i18next from "i18next"; +import { HeldItem, ITEM_EFFECT } from "../held-item"; + +export interface EXP_BOOST_PARAMS { + /** The pokemon with the item */ + pokemon: Pokemon; + /** The amount of exp to gain */ + expAmount: NumberHolder; +} + +export class ExpBoosterHeldItem extends HeldItem { + public effects: ITEM_EFFECT[] = [ITEM_EFFECT.EXP_BOOSTER]; + private boostMultiplier: number; + + constructor(type: HeldItems, maxStackCount = 1, boostPercent: number) { + super(type, maxStackCount); + this.boostMultiplier = boostPercent * 0.01; + } + + get name(): string { + return this.type === HeldItems.LUCKY_EGG + ? i18next.t("modifierType:ModifierType.LUCKY_EGG.name") + : i18next.t("modifierType:ModifierType.GOLDEN_EGG.name"); + } + + get description(): string { + return this.type === HeldItems.LUCKY_EGG + ? i18next.t("modifierType:ModifierType.LUCKY_EGG.description") + : i18next.t("modifierType:ModifierType.GOLDEN_EGG.description"); + } + + get icon(): string { + return this.type === HeldItems.LUCKY_EGG ? "lucky_egg" : "golden_egg"; + } + + // TODO: What do we do with this? Need to look up all the shouldApply + /** + * Checks if {@linkcode PokemonExpBoosterModifier} should be applied + * @param pokemon The {@linkcode Pokemon} to apply the exp boost to + * @param boost {@linkcode NumberHolder} holding the exp boost value + * @returns `true` if {@linkcode PokemonExpBoosterModifier} should be applied + */ + // override shouldApply(pokemon: Pokemon, boost: NumberHolder): boolean { + // return super.shouldApply(pokemon, boost) && !!boost; + // } + + /** + * Applies {@linkcode PokemonExpBoosterModifier} + * @param _pokemon The {@linkcode Pokemon} to apply the exp boost to + * @param boost {@linkcode NumberHolder} holding the exp boost value + * @returns always `true` + */ + apply(params: EXP_BOOST_PARAMS): boolean { + const pokemon = params.pokemon; + const expAmount = params.expAmount; + const stackCount = pokemon.heldItemManager.getStack(this.type); + expAmount.value = Math.floor(expAmount.value * (1 + stackCount * this.boostMultiplier)); + + return true; + } +} diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 8274ef1f31f..2ee938d7f96 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2236,6 +2236,18 @@ export const modifierTypes = { GOLDEN_EXP_CHARM: () => new ExpBoosterModifierType("modifierType:ModifierType.GOLDEN_EXP_CHARM", "golden_exp_charm", 100), + LUCKY_EGG_REWARD: () => + new PokemonHeldItemReward( + HeldItems.LUCKY_EGG, + (type, args) => new ExpBoosterModifier(type, (args[0] as Pokemon).id), + ), + GOLDEN_EGG_REWARD: () => + new PokemonHeldItemReward( + HeldItems.GOLDEN_EGG, + (type, args) => new ExpBoosterModifier(type, (args[0] as Pokemon).id), + ), + + // TODO: Remove these when refactor is done LUCKY_EGG: () => new PokemonExpBoosterModifierType("modifierType:ModifierType.LUCKY_EGG", "lucky_egg", 40), GOLDEN_EGG: () => new PokemonExpBoosterModifierType("modifierType:ModifierType.GOLDEN_EGG", "golden_egg", 100), @@ -3147,17 +3159,17 @@ const wildModifierPool: ModifierPool = { return m; }), [ModifierTier.ULTRA]: [ - new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), + new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER_REWARD, 10), new WeightedModifierType(modifierTypes.WHITE_HERB_REWARD, 0), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), - [ModifierTier.ROGUE]: [new WeightedModifierType(modifierTypes.LUCKY_EGG, 4)].map(m => { + [ModifierTier.ROGUE]: [new WeightedModifierType(modifierTypes.LUCKY_EGG_REWARD, 4)].map(m => { m.setTier(ModifierTier.ROGUE); return m; }), - [ModifierTier.MASTER]: [new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1)].map(m => { + [ModifierTier.MASTER]: [new WeightedModifierType(modifierTypes.GOLDEN_EGG_REWARD, 1)].map(m => { m.setTier(ModifierTier.MASTER); return m; }),