From 2257d8d2f286d1e6c45236122388b368c242f4d6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 8 Nov 2023 17:30:07 -0500 Subject: [PATCH] Add memory mushroom item for remembering moves --- src/battle-phases.ts | 11 +++++++--- src/modifier/modifier-type.ts | 16 +++++++++++++- src/modifier/modifier.ts | 18 ++++++++++++++++ src/pokemon.ts | 7 ++++++- src/ui/party-ui-handler.ts | 39 ++++++++++++++++++++++++++++------- 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/battle-phases.ts b/src/battle-phases.ts index c62d6cf1254..f3b5a0f4e06 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -16,7 +16,7 @@ import { EvolutionPhase } from "./evolution-phase"; import { BattlePhase } from "./battle-phase"; import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat"; import { Biome, biomeLinks } from "./data/biome"; -import { FusePokemonModifierType, ModifierPoolType, ModifierTier, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; +import { FusePokemonModifierType, ModifierPoolType, ModifierTier, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag"; import { getPokemonMessage } from "./messages"; @@ -2923,8 +2923,11 @@ export class SelectModifierPhase extends BattlePhase { const pokemonModifierType = modifierType as PokemonModifierType; const isMoveModifier = modifierType instanceof PokemonMoveModifierType; const isTmModifier = modifierType instanceof TmModifierType; + const isRememberMoveModifier = modifierType instanceof RememberMoveModifierType; const partyUiMode = isMoveModifier ? PartyUiMode.MOVE_MODIFIER - : isTmModifier ? PartyUiMode.TM_MODIFIER : PartyUiMode.MODIFIER; + : isTmModifier ? PartyUiMode.TM_MODIFIER + : isRememberMoveModifier ? PartyUiMode.REMEMBER_MOVE_MODIFIER + : PartyUiMode.MODIFIER; const tmMoveId = isTmModifier ? (modifierType as TmModifierType).moveId : undefined; @@ -2933,7 +2936,9 @@ export class SelectModifierPhase extends BattlePhase { this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => { const modifierType = typeOptions[cursor].type; const modifier = !isMoveModifier - ? modifierType.newModifier(party[slotIndex]) + ? !isRememberMoveModifier + ? modifierType.newModifier(party[slotIndex]) + : modifierType.newModifier(party[slotIndex], option as integer) : modifierType.newModifier(party[slotIndex], option - PartyOption.MOVE_1); this.scene.ui.clearText(); this.scene.ui.setMode(Mode.MESSAGE); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index a4136ed2a0e..bee082d83bf 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -6,7 +6,7 @@ import { EvolutionItem, pokemonEvolutions } from '../data/pokemon-evolutions'; import { Stat, getStatName } from '../data/pokemon-stat'; import { tmPoolTiers, tmSpecies } from '../data/tms'; import { Type } from '../data/type'; -import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from '../ui/party-ui-handler'; +import PartyUiHandler, { PokemonMoveSelectFilter, PokemonRememberMoveSelectFilter, PokemonSelectFilter } from '../ui/party-ui-handler'; import * as Utils from '../utils'; import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat'; import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry'; @@ -205,6 +205,17 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { } } +export class RememberMoveModifierType extends PokemonModifierType { + constructor(name: string, description: string, iconImage?: string, group?: string) { + super(name, description, (type, args) => new Modifiers.RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)), + (pokemon: PlayerPokemon) => { + if (!pokemon.getLearnableLevelMoves().length) + return PartyUiHandler.NoEffectMessage; + return null; + }, iconImage, group); + } +} + export class DoubleBattleChanceBoosterModifierType extends ModifierType { public battleCount: integer; @@ -653,6 +664,8 @@ export const modifierTypes = { TM_GREAT: () => new TmModifierTypeGenerator(ModifierTier.GREAT), TM_ULTRA: () => new TmModifierTypeGenerator(ModifierTier.ULTRA), + MEMORY_MUSHROOM: () => new RememberMoveModifierType('Memory Mushroom', 'Recall one Pokémon\'s forgotten move', 'big_mushroom'), + EXP_SHARE: () => new ModifierType('EXP. All', 'Non-participants receive 20% of a single participant\'s EXP. Points', (type, _args) => new Modifiers.ExpShareModifier(type), 'exp_share'), EXP_BALANCE: () => new ModifierType('EXP. Balance', 'All EXP. Points received from battles are split between the lower leveled party members', @@ -786,6 +799,7 @@ const modifierPool = { new WeightedModifierType(modifierTypes.MAX_LURE, 4), new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 4), new WeightedModifierType(modifierTypes.TM_ULTRA, 5), + new WeightedModifierType(modifierTypes.MEMORY_MUSHROOM, (party: Pokemon[]) => party.filter(p => p.getLearnableLevelMoves().length).length ? 4 : 0), new WeightedModifierType(modifierTypes.REVIVER_SEED, 3), new WeightedModifierType(modifierTypes.CANDY_JAR, 3), new WeightedModifierType(modifierTypes.GRIP_CLAW, 2), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 11e902ba39e..38d95174497 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -888,6 +888,24 @@ export class TmModifier extends ConsumablePokemonModifier { } } +export class RememberMoveModifier extends ConsumablePokemonModifier { + public levelMoveIndex: integer; + + constructor(type: ModifierTypes.ModifierType, pokemonId: integer, levelMoveIndex: integer) { + super(type, pokemonId); + + this.levelMoveIndex = levelMoveIndex; + } + + apply(args: any[]): boolean { + const pokemon = args[0] as PlayerPokemon; + + pokemon.scene.unshiftPhase(new LearnMovePhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.getLearnableLevelMoves()[this.levelMoveIndex])); + + return true; + } +} + export class EvolutionItemModifier extends ConsumablePokemonModifier { constructor(type: ModifierTypes.EvolutionItemModifierType, pokemonId: integer) { super(type, pokemonId); diff --git a/src/pokemon.ts b/src/pokemon.ts index fc4559ba423..990a0000940 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -29,6 +29,7 @@ import { Mode } from './ui/ui'; import PartyUiHandler, { PartyOption, PartyUiMode } from './ui/party-ui-handler'; import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import { GameMode } from './game-mode'; +import { pokemonFormLevelMoves } from './data/pokemon-level-moves'; export enum FieldPosition { CENTER, @@ -471,6 +472,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.moveset; } + getLearnableLevelMoves(): Moves[] { + return this.getLevelMoves(1).filter(lm => !this.moveset.filter(m => m.moveId === lm).length); + } + getTypes(ignoreOverride?: boolean): Type[] { const types = []; @@ -548,7 +553,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getLevelMoves(startingLevel?: integer): Moves[] { const ret: Moves[] = []; - const levelMoves = this.getSpeciesForm().getLevelMoves();; + const levelMoves = this.getSpeciesForm().getLevelMoves(); if (levelMoves) { if (!startingLevel) startingLevel = this.level; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index d4af49cb009..729cebc290a 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -7,7 +7,7 @@ import MessageUiHandler from "./message-ui-handler"; import { Mode } from "./ui"; import * as Utils from "../utils"; import { PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier"; -import { Moves } from "../data/move"; +import { Moves, allMoves } from "../data/move"; import { getGenderColor, getGenderSymbol } from "../data/gender"; import { StatusEffect } from "../data/status-effect"; @@ -20,6 +20,7 @@ export enum PartyUiMode { MODIFIER, MOVE_MODIFIER, TM_MODIFIER, + REMEMBER_MOVE_MODIFIER, MODIFIER_TRANSFER, SPLICE, RELEASE @@ -205,6 +206,16 @@ export default class PartyUiHandler extends MessageUiHandler { this.startTransfer(); this.clearOptions(); ui.playSelect(); + } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) { + let filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon); + if (filterResult === null) { + this.selectCallback(this.cursor, option); + this.clearOptions(); + } else { + this.clearOptions(); + this.showText(filterResult as string, null, () => this.showText(null, 0), null, true); + } + ui.playSelect(); } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL) || (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) { let filterResult: string; @@ -271,8 +282,7 @@ export default class PartyUiHandler extends MessageUiHandler { } else if (button === Button.CANCEL) { this.clearOptions(); ui.playSelect(); - } - else { + } else { switch (button) { case Button.UP: success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); @@ -464,6 +474,10 @@ export default class PartyUiHandler extends MessageUiHandler { const pokemon = this.scene.getParty()[this.cursor]; + const learnableLevelMoves = this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER + ? pokemon.getLearnableLevelMoves() + : null; + const itemModifiers = this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER ? this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[] @@ -475,7 +489,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.eraseOptionsCursor(); } - if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { + if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { switch (this.partyUiMode) { case PartyUiMode.SWITCH: case PartyUiMode.FAINT_SWITCH: @@ -516,6 +530,10 @@ export default class PartyUiHandler extends MessageUiHandler { } else if (this.partyUiMode === PartyUiMode.MOVE_MODIFIER) { for (let m = 0; m < pokemon.moveset.length; m++) this.options.push(PartyOption.MOVE_1 + m); + } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { + const learnableMoves = pokemon.getLearnableLevelMoves(); + for (let m = 0; m < learnableMoves.length; m++) + this.options.push(m); } else { for (let im = 0; im < itemModifiers.length; im++) this.options.push(im); @@ -549,7 +567,7 @@ export default class PartyUiHandler extends MessageUiHandler { for (let o = optionStartIndex; o < optionEndIndex; o++) { const option = this.options[this.options.length - (o + 1)]; let optionName: string; - if (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode || option === PartyOption.CANCEL) { + if ((this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode)) || option === PartyOption.CANCEL) { switch (option) { case PartyOption.MOVE_1: case PartyOption.MOVE_2: @@ -565,7 +583,10 @@ export default class PartyUiHandler extends MessageUiHandler { optionName = '↑'; else if (option === PartyOption.SCROLL_DOWN) optionName = '↓'; - else { + else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { + const move = learnableLevelMoves[option]; + optionName = allMoves[move].name; + } else { const itemModifier = itemModifiers[option]; optionName = itemModifier.type.name; if (itemModifier.stackCount > 1) @@ -583,7 +604,7 @@ export default class PartyUiHandler extends MessageUiHandler { startTransfer(): void { this.transferMode = true; this.transferCursor = this.cursor; - this.transferOptionCursor = this.optionsCursor + this.optionsScrollCursor + (this.options[0] === PartyOption.SCROLL_UP ? -1 : 0); + this.transferOptionCursor = this.getOptionsCursorWithScroll(); this.partySlots[this.transferCursor].setTransfer(true); } @@ -635,6 +656,10 @@ export default class PartyUiHandler extends MessageUiHandler { return `Smell ya later, ${pokemonName}!`; } + getOptionsCursorWithScroll(): integer { + return this.optionsCursor + this.optionsScrollCursor + (this.options && this.options[0] === PartyOption.SCROLL_UP ? -1 : 0); + } + clearOptions() { this.optionsMode = false; this.optionsScroll = false;