diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 180c7af1240..8c724cda762 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: patapancakes +github: pagefaultgames diff --git a/src/battle-scene.ts b/src/battle-scene.ts index ff0ca47bcac..8e299dd8e06 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -3091,11 +3091,6 @@ export default class BattleScene extends SceneBase { private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean { const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves(); if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) { - // If ME type is already defined in session data, no need to roll RNG check - if (!isNullOrUndefined(sessionDataEncounterType)) { - return true; - } - // Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance; const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents; diff --git a/src/data/egg-moves.ts b/src/data/egg-moves.ts index 813ade94020..741b707af2f 100644 --- a/src/data/egg-moves.ts +++ b/src/data/egg-moves.ts @@ -81,7 +81,7 @@ export const speciesEggMoves = { [Species.LEDYBA]: [ Moves.POLLEN_PUFF, Moves.THIEF, Moves.PARTING_SHOT, Moves.SPORE ], [Species.SPINARAK]: [ Moves.PARTING_SHOT, Moves.ATTACK_ORDER, Moves.GASTRO_ACID, Moves.STRENGTH_SAP ], [Species.CHINCHOU]: [ Moves.THUNDERCLAP, Moves.BOUNCY_BUBBLE, Moves.THUNDER_CAGE, Moves.TAIL_GLOW ], - [Species.PICHU]: [ Moves.MOONBLAST, Moves.WAVE_CRASH, Moves.AIR_SLASH, Moves.AURA_WHEEL ], + [Species.PICHU]: [ Moves.MOONBLAST, Moves.TRIPLE_AXEL, Moves.FIERY_DANCE, Moves.AURA_WHEEL ], [Species.CLEFFA]: [ Moves.CALM_MIND, Moves.EARTH_POWER, Moves.WISH, Moves.LIGHT_OF_RUIN ], [Species.IGGLYBUFF]: [ Moves.DRAIN_PUNCH, Moves.GRAV_APPLE, Moves.SOFT_BOILED, Moves.EXTREME_SPEED ], [Species.TOGEPI]: [ Moves.SCORCHING_SANDS, Moves.ROOST, Moves.RELIC_SONG, Moves.FIERY_DANCE ], @@ -195,7 +195,7 @@ export const speciesEggMoves = { [Species.REGISTEEL]: [ Moves.BODY_PRESS, Moves.SIZZLY_SLIDE, Moves.RECOVER, Moves.GIGATON_HAMMER ], [Species.LATIAS]: [ Moves.CORE_ENFORCER, Moves.FUSION_FLARE, Moves.SPARKLY_SWIRL, Moves.MYSTICAL_POWER ], [Species.LATIOS]: [ Moves.CORE_ENFORCER, Moves.BLUE_FLARE, Moves.NASTY_PLOT, Moves.TACHYON_CUTTER ], - [Species.KYOGRE]: [ Moves.RECOVER, Moves.HURRICANE, Moves.FLIP_TURN, Moves.WILDBOLT_STORM ], + [Species.KYOGRE]: [ Moves.RECOVER, Moves.HURRICANE, Moves.FREEZY_FROST, Moves.WILDBOLT_STORM ], [Species.GROUDON]: [ Moves.STONE_AXE, Moves.SOLAR_BLADE, Moves.MORNING_SUN, Moves.SACRED_FIRE ], [Species.RAYQUAZA]: [ Moves.V_CREATE, Moves.DRAGON_DARTS, Moves.CORE_ENFORCER, Moves.OBLIVION_WING ], [Species.JIRACHI]: [ Moves.TACHYON_CUTTER, Moves.TRIPLE_ARROWS, Moves.ROCK_SLIDE, Moves.SHELL_SMASH ], diff --git a/src/data/move.ts b/src/data/move.ts index 74ecead73fa..e3cb5d935d5 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5226,6 +5226,9 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { */ const switchOutTarget = this.selfSwitch ? user : target; if (switchOutTarget instanceof PlayerPokemon) { + if (switchOutTarget.scene.getParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) { + return false; + } switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); if (switchOutTarget.hp > 0) { @@ -5234,6 +5237,9 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { } return false; } else if (user.scene.currentBattle.battleType !== BattleType.WILD) { + if (switchOutTarget.scene.getEnemyParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) { + return false; + } // Switch out logic for trainer battles switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); @@ -5244,6 +5250,9 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { false, false), MoveEndPhase); } } else { + if (user.scene.currentBattle.waveIndex % 10 === 0) { + return false; + } // Switch out logic for everything else (eg: WILD battles) switchOutTarget.leaveField(false); diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index f3765c9acba..6d6b5d9f71e 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -159,7 +159,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = return true; }, onHover: () => { - const formName = tradePokemon.species.forms && tradePokemon.species.forms.length > tradePokemon.formIndex ? tradePokemon.species.forms[pokemon.formIndex].formName : null; + const formName = tradePokemon.species.forms && tradePokemon.species.forms.length > tradePokemon.formIndex ? tradePokemon.species.forms[tradePokemon.formIndex].formName : null; const line1 = i18next.t("pokemonInfoContainer:ability") + " " + tradePokemon.getAbility().name + (tradePokemon.getGender() !== Gender.GENDERLESS ? " | " + i18next.t("pokemonInfoContainer:gender") + " " + getGenderSymbol(tradePokemon.getGender()) : ""); const line2 = i18next.t("pokemonInfoContainer:nature") + " " + getNatureName(tradePokemon.getNature()) + (formName ? " | " + i18next.t("pokemonInfoContainer:form") + " " + formName : ""); showEncounterText(scene, `${line1}\n${line2}`, 0, 0, false); diff --git a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts index e41b3ab03ef..e75e7e9f580 100644 --- a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts @@ -558,6 +558,10 @@ function onGameOver(scene: BattleScene) { // Revert BGM scene.playBgm(scene.arena.bgm); + // Clear any leftover battle phases + scene.clearPhaseQueue(); + scene.clearPhaseQueueSplice(); + // Return enemy Pokemon const pokemon = scene.getEnemyPokemon(); if (pokemon) { diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index c9b30415299..fb67305c78d 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -224,7 +224,7 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu // If no filtered mons exist at specified starter tiers, will expand starter search range until there are // Starts by decrementing starter tier min until it is 0, then increments tier max up to 10 let tryFilterStarterTiers: [PokemonSpecies, number][] = filteredSpecies.filter(s => (s[1] >= min && s[1] <= max)); - while (tryFilterStarterTiers.length === 0 && (min !== 0 && max !== 10)) { + while (tryFilterStarterTiers.length === 0 && !(min === 0 && max === 10)) { if (min > 0) { min--; } else { diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index f9602d1386a..698bbb8e9c9 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -11,6 +11,7 @@ import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; +import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier } from "#app/modifier/modifier"; export enum SpeciesWildEvolutionDelay { NONE, @@ -1647,8 +1648,14 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.FROSMOTH, 1, null, new SpeciesFriendshipEvolutionCondition(90, p => p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.GIMMIGHOUL]: [ - new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition( p => p.evoCounter > 9 ), SpeciesWildEvolutionDelay.VERY_LONG), - new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition( p => p.evoCounter > 9 ), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter + + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + + p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier + || m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG), + new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter + + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + + p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier + || m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG) ] }; diff --git a/src/locales/en/move-trigger.json b/src/locales/en/move-trigger.json index 93d25e506ba..7ea5fe82fc2 100644 --- a/src/locales/en/move-trigger.json +++ b/src/locales/en/move-trigger.json @@ -71,5 +71,5 @@ "safeguard": "{{targetName}} is protected by Safeguard!", "substituteOnOverlap": "{{pokemonName}} already\nhas a substitute!", "substituteNotEnoughHp": "But it does not have enough HP\nleft to make a substitute!", - "afterYou": "{{pokemonName}} took the kind offer!" + "afterYou": "{{targetName}} took the kind offer!" } \ No newline at end of file diff --git a/src/locales/es/move-trigger.json b/src/locales/es/move-trigger.json index b49a64ac42a..2e394dd72a7 100644 --- a/src/locales/es/move-trigger.json +++ b/src/locales/es/move-trigger.json @@ -67,5 +67,5 @@ "swapArenaTags": "¡{{pokemonName}} ha intercambiado los efectos del terreno de combate!", "exposedMove": "¡{{pokemonName}} ha identificado\n{{targetPokemonName}}!", "safeguard": "¡{{targetName}} está protegido por Velo Sagrado!", - "afterYou": "¡{{pokemonName}} ha decidido aprovechar la oportunidad!" + "afterYou": "¡{{targetName}} ha decidido aprovechar la oportunidad!" } diff --git a/src/locales/fr/move-trigger.json b/src/locales/fr/move-trigger.json index 7564718e7ce..458b7ed8c4f 100644 --- a/src/locales/fr/move-trigger.json +++ b/src/locales/fr/move-trigger.json @@ -71,5 +71,5 @@ "safeguard": "{{targetName}} est protégé\npar la capacité Rune Protect !", "substituteOnOverlap": "{{pokemonName}} a déjà\nun clone !", "substituteNotEnoughHp": "Mais il est trop faible\npour créer un clone !", - "afterYou": "{{pokemonName}} accepte\navec joie !" + "afterYou": "{{targetName}} accepte\navec joie !" } diff --git a/src/locales/fr/mystery-encounters/bug-type-superfan-dialogue.json b/src/locales/fr/mystery-encounters/bug-type-superfan-dialogue.json index 63195e37062..7e81b99c739 100644 --- a/src/locales/fr/mystery-encounters/bug-type-superfan-dialogue.json +++ b/src/locales/fr/mystery-encounters/bug-type-superfan-dialogue.json @@ -28,7 +28,7 @@ "select_prompt": "Choisissez un objet à donner.", "invalid_selection": "Ce Pokémon ne porte pas ce genre d’objet.", "selected": "Vous remettez l’objet {{selectedItem}} au Dresseur.", - "selected_dialogue": "Sérieux ? {{selectedItem}}, comme ça en cadeau ?\nC’est très générieux !$En guise de ma reconnaissance, laisse-moi\nte faire un cadeau un peu spécial !$Il est dans ma famille depusi des générations, et ça me ferait plaisir de te l’offrir !" + "selected_dialogue": "Sérieux ? {{selectedItem}}, comme ça en cadeau ?\nC’est très générieux !$En guise de ma reconnaissance, laisse-moi\nte faire un cadeau un peu spécial !$Il est dans ma famille depuis des générations, et ça me ferait plaisir de te l’offrir !" } }, "battle_won": "Tes connaissances et tes capacités ont totalement exploité nos faiblesses !$En remerciement de cette leçon, permets-moi\nd’apprendre une capacité Insecte à un de tes Pokémon !", diff --git a/src/locales/fr/mystery-encounters/training-session-dialogue.json b/src/locales/fr/mystery-encounters/training-session-dialogue.json index 9b06651eb59..9de246d3b6f 100644 --- a/src/locales/fr/mystery-encounters/training-session-dialogue.json +++ b/src/locales/fr/mystery-encounters/training-session-dialogue.json @@ -1,7 +1,7 @@ { "intro": "Vous tombez sur du matériel d’entrainement.", "title": "Session d’entrainement", - "description": "Ce matériel semble pouvoir être utilisé pour entrainer un membre de votre équipe ! Il existe plusieurs moyens avec lesquels vous pourriez entrainer un Pokémon, comme @[TOOLTIP_TITLE]{en le faisant combattre et vaincre le reste de votre équipe}.", + "description": "Ce matériel semble pouvoir être utilisé pour entrainer un membre de votre équipe ! Il existe plusieurs moyens avec lesquels vous pourriez entrainer un Pokémon, comme @[TOOLTIP_TITLE]{en le combattant et le vainquant avec le reste de votre équipe}.", "query": "Quel entrainement choisir ?", "invalid_selection": "Le Pokémon doit être en bonne santé.", "option": { diff --git a/src/locales/fr/mystery-encounters/uncommon-breed-dialogue.json b/src/locales/fr/mystery-encounters/uncommon-breed-dialogue.json index d5f5e7e336f..9d70d532f0a 100644 --- a/src/locales/fr/mystery-encounters/uncommon-breed-dialogue.json +++ b/src/locales/fr/mystery-encounters/uncommon-breed-dialogue.json @@ -14,13 +14,13 @@ "label": "Le nourrir", "disabled_tooltip": "Vous avez besoin de 4 Baies pour choisir cette option", "tooltip": "(-) Donner 4 Baies\n(+) Le {{enemyPokemon}} vous apprécie", - "selected": "Vous lancer quelques Baies\nau {{enemyPokemon}} !$Il les engloutit avec joie !$Le {{enemyPokemon}} veut se joindre\nà votre équipe !" + "selected": "Vous lancez quelques Baies\nau {{enemyPokemon}} !$Il les engloutit avec joie !$Le {{enemyPokemon}} veut se joindre\nà votre équipe !" }, "3": { "label": "Devenir amis", "disabled_tooltip": "Votre Pokémon doit connaitre certaines capacités pour choisir cette option", "tooltip": "(+) {{option3PrimaryName}} utilise {{option3PrimaryMove}}\n(+) Le {{enemyPokemon}} vous apprécie", - "selected": "Votre {{option3PrimaryName}} utilise {{option3PrimaryMove}} pour charmer le {{enemyPokemon}} !$The {{enemyPokemon}} veut se joindre\nà votre équipe !" + "selected": "Votre {{option3PrimaryName}} utilise {{option3PrimaryMove}} pour charmer le {{enemyPokemon}} !$Le {{enemyPokemon}} veut se joindre\nà votre équipe !" } } } diff --git a/src/locales/fr/settings.json b/src/locales/fr/settings.json index e310f5d5733..2dd150eed13 100644 --- a/src/locales/fr/settings.json +++ b/src/locales/fr/settings.json @@ -11,7 +11,7 @@ "expGainsSpeed": "Vit. barre d’Exp", "expPartyDisplay": "Afficher Exp équipe", "skipSeenDialogues": "Passer dialogues connus", - "eggSkip": "Animation d’éclosion", + "eggSkip": "Passer les éclosions", "never": "Jamais", "always": "Toujours", "ask": "Demander", diff --git a/src/locales/it/move-trigger.json b/src/locales/it/move-trigger.json index fba671a6813..04870015f2b 100644 --- a/src/locales/it/move-trigger.json +++ b/src/locales/it/move-trigger.json @@ -68,5 +68,5 @@ "exposedMove": "{{pokemonName}} ha identificato\n{{targetPokemonName}}!", "chillyReception": "{{pokemonName}} sta per fare una battuta!", "safeguard": "Salvaguardia protegge {{targetName}}!", - "afterYou": "{{pokemonName}} approfitta della cortesia!" + "afterYou": "{{targetName}} approfitta della cortesia!" } diff --git a/src/locales/ja/move-trigger.json b/src/locales/ja/move-trigger.json index afede7edfb3..4c3d19240f6 100644 --- a/src/locales/ja/move-trigger.json +++ b/src/locales/ja/move-trigger.json @@ -68,5 +68,5 @@ "chillyReception": "{{pokemonName}}は\n寒い ギャグを かました!", "swapArenaTags": "{{pokemonName}}は\nお互いの 場の 効果を 入れ替えた!", "exposedMove": "{{pokemonName}}は {{targetPokemonName}}の\n正体を 見破った!", - "afterYou": "{{pokemonName}}は\nお言葉に 甘えることにした!" + "afterYou": "{{targetName}}は\nお言葉に 甘えることにした!" } diff --git a/src/locales/ko/move-trigger.json b/src/locales/ko/move-trigger.json index 12a126baf9d..4b994f315bf 100644 --- a/src/locales/ko/move-trigger.json +++ b/src/locales/ko/move-trigger.json @@ -69,5 +69,5 @@ "chillyReception": "{{pokemonName}}[[는]] 썰렁한 개그를 선보였다!", "exposedMove": "{{pokemonName}}[[는]]\n{{targetPokemonName}}의 정체를 꿰뚫어 보았다!", "safeguard": "{{targetName}}[[는]] 신비의 베일이 지켜 주고 있다!", - "afterYou": "{{pokemonName}}[[는]]\n배려를 받아들이기로 했다!" + "afterYou": "{{targetName}}[[는]]\n배려를 받아들이기로 했다!" } diff --git a/src/locales/pt_BR/move-trigger.json b/src/locales/pt_BR/move-trigger.json index 307364e1b55..9a4d0b9e8b1 100644 --- a/src/locales/pt_BR/move-trigger.json +++ b/src/locales/pt_BR/move-trigger.json @@ -64,5 +64,5 @@ "chillyReception": "{{pokemonName}} está prestes a contar uma piada gelada!", "exposedMove": "{{pokemonName}} identificou\n{{targetPokemonName}}!", "safeguard": "{{targetName}} está protegido por Safeguard!", - "afterYou": "{{pokemonName}} aceitou a gentil oferta!" + "afterYou": "{{targetName}} aceitou a gentil oferta!" } diff --git a/src/locales/zh_CN/modifier-type.json b/src/locales/zh_CN/modifier-type.json index b02d74eadb5..eb394baf577 100644 --- a/src/locales/zh_CN/modifier-type.json +++ b/src/locales/zh_CN/modifier-type.json @@ -360,7 +360,7 @@ }, "EVOLUTION_TRACKER_GIMMIGHOUL": { "name": "金子宝物", - "description": "这个小精靈爱金子! 继续挑金子然后谁知道什么会发生!" + "description": "这个宝可梦最爱金币!多收集点金币的话会发生什么呢?" }, "BATON": { "name": "接力棒", diff --git a/src/locales/zh_CN/move-trigger.json b/src/locales/zh_CN/move-trigger.json index 60de3591915..32a4d0b4a7d 100644 --- a/src/locales/zh_CN/move-trigger.json +++ b/src/locales/zh_CN/move-trigger.json @@ -68,5 +68,5 @@ "chillyReception": "{{pokemonName}}\n说出了冷笑话!", "exposedMove": "{{pokemonName}}识破了\n{{targetPokemonName}}的原型!", "safeguard": "{{targetName}}\n正受到神秘之幕的保护!", - "afterYou": "{{pokemonName}}\n接受了对手的好意!" + "afterYou": "{{targetName}}\n接受了对手的好意!" } diff --git a/src/locales/zh_TW/move-trigger.json b/src/locales/zh_TW/move-trigger.json index 2cd33a3a416..6b80196f166 100644 --- a/src/locales/zh_TW/move-trigger.json +++ b/src/locales/zh_TW/move-trigger.json @@ -68,5 +68,5 @@ "chillyReception": "{{pokemonName}}\n說了冷笑話!", "exposedMove": "{{pokemonName}}識破了\n{{targetPokemonName}}的原形!", "safeguard": "{{targetName}}\n正受到神秘之幕的保護!", - "afterYou": "{{pokemonName}}\n接受了對手的好意!" + "afterYou": "{{targetName}}\n接受了對手的好意!" } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 9ce555a617e..fb69a96448a 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1387,7 +1387,8 @@ export const modifierTypes = { FORM_CHANGE_ITEM: () => new FormChangeItemModifierTypeGenerator(false), RARE_FORM_CHANGE_ITEM: () => new FormChangeItemModifierTypeGenerator(true), - EVOLUTION_TRACKER_GIMMIGHOUL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVOLUTION_TRACKER_GIMMIGHOUL", "relic_gold", (type, _args) => new Modifiers.EvoTrackerModifier(type, (_args[0] as Pokemon).id, Species.GIMMIGHOUL, 10)), + EVOLUTION_TRACKER_GIMMIGHOUL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVOLUTION_TRACKER_GIMMIGHOUL", "relic_gold", + (type, args) => new Modifiers.EvoTrackerModifier(type, (args[0] as Pokemon).id, Species.GIMMIGHOUL, 10)), MEGA_BRACELET: () => new ModifierType("modifierType:ModifierType.MEGA_BRACELET", "mega_bracelet", (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)), DYNAMAX_BAND: () => new ModifierType("modifierType:ModifierType.DYNAMAX_BAND", "dynamax_band", (type, _args) => new Modifiers.GigantamaxAccessModifier(type)), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index cf9cf78225e..537e2327a21 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1,5 +1,5 @@ import * as ModifierTypes from "./modifier-type"; -import { ModifierType, modifierTypes } from "./modifier-type"; +import { getModifierType, ModifierType, modifierTypes } from "./modifier-type"; import BattleScene from "../battle-scene"; import { getLevelTotalExp } from "../data/exp"; import { MAX_PER_TYPE_POKEBALLS, PokeballType } from "../data/pokeball"; @@ -852,26 +852,47 @@ export class EvoTrackerModifier extends PokemonHeldItemModifier { } matchType(modifier: Modifier): boolean { - if (modifier instanceof EvoTrackerModifier) { - return (modifier as EvoTrackerModifier).species === this.species; - } - return false; + return modifier instanceof EvoTrackerModifier && modifier.species === this.species && modifier.required === this.required; } clone(): PersistentModifier { - return new EvoTrackerModifier(this.type, this.pokemonId, this.species, this.stackCount); + return new EvoTrackerModifier(this.type, this.pokemonId, this.species, this.required, this.stackCount); } getArgs(): any[] { - return super.getArgs().concat(this.species); + return super.getArgs().concat([this.species, this.required]); } apply(args: any[]): boolean { return true; } - getMaxHeldItemCount(_pokemon: Pokemon): integer { - return this.required; + getIconStackText(scene: BattleScene, virtual?: boolean): Phaser.GameObjects.BitmapText | null { + if (this.getMaxStackCount(scene) === 1 || (virtual && !this.virtualStackCount)) { + return null; + } + + const pokemon = scene.getPokemonById(this.pokemonId); + + this.stackCount = pokemon + ? pokemon.evoCounter + pokemon.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier).length + : this.stackCount; + + const text = scene.add.bitmapText(10, 15, "item-count", this.stackCount.toString(), 11); + text.letterSpacing = -0.5; + if (this.getStackCount() >= this.required) { + text.setTint(0xf89890); + } + text.setOrigin(0, 0); + + return text; + } + + getMaxHeldItemCount(pokemon: Pokemon): integer { + this.stackCount = pokemon.evoCounter + pokemon.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + + pokemon.scene.findModifiers(m => m instanceof MoneyMultiplierModifier || m instanceof ExtraModifierModifier).length; + return 999; } } @@ -2414,9 +2435,8 @@ export class MoneyRewardModifier extends ConsumableModifier { scene.getParty().map(p => { if (p.species?.speciesId === Species.GIMMIGHOUL || p.fusionSpecies?.speciesId === Species.GIMMIGHOUL) { - p.evoCounter++; - const modifierType: ModifierType = modifierTypes.EVOLUTION_TRACKER_GIMMIGHOUL(); - const modifier = modifierType!.newModifier(p); + p.evoCounter ? p.evoCounter++ : p.evoCounter = 1; + const modifier = getModifierType(modifierTypes.EVOLUTION_TRACKER_GIMMIGHOUL).newModifier(p) as EvoTrackerModifier; scene.addModifier(modifier); } }); @@ -2586,7 +2606,7 @@ export class HealShopCostModifier extends PersistentModifier { constructor(type: ModifierType, shopMultiplier: number, stackCount?: integer) { super(type, stackCount); - this.shopMultiplier = shopMultiplier; + this.shopMultiplier = shopMultiplier ?? 2.5; } match(modifier: Modifier): boolean { @@ -2598,11 +2618,16 @@ export class HealShopCostModifier extends PersistentModifier { } apply(args: any[]): boolean { - (args[0] as Utils.IntegerHolder).value *= this.shopMultiplier; + const moneyCost = args[0] as Utils.NumberHolder; + moneyCost.value = Math.floor(moneyCost.value * this.shopMultiplier); return true; } + getArgs(): any[] { + return super.getArgs().concat(this.shopMultiplier); + } + getMaxStackCount(scene: BattleScene): integer { return 1; } diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index b0cfa5c55e2..8ecf1478b99 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -238,7 +238,7 @@ export class GameOverPhase extends BattlePhase { enemyModifiers: this.scene.findModifiers(() => true, false).map(m => new PersistentModifierData(m, false)), arena: new ArenaData(this.scene.arena), pokeballCounts: this.scene.pokeballCounts, - money: this.scene.money, + money: Math.floor(this.scene.money), score: this.scene.score, waveIndex: this.scene.currentBattle.waveIndex, battleType: this.scene.currentBattle.battleType, diff --git a/src/phases/mystery-encounter-phases.ts b/src/phases/mystery-encounter-phases.ts index 60755095cca..0efaf1bf4ca 100644 --- a/src/phases/mystery-encounter-phases.ts +++ b/src/phases/mystery-encounter-phases.ts @@ -25,6 +25,7 @@ import { GameOverPhase } from "#app/phases/game-over-phase"; import { SwitchPhase } from "#app/phases/switch-phase"; import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; import { SwitchType } from "#enums/switch-type"; +import { BattlerTagType } from "#enums/battler-tag-type"; /** * Will handle (in order): @@ -218,9 +219,17 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase { start() { super.start(); + // Lapse any residual flinches/endures but ignore all other turn-end battle tags + const includedLapseTags = [BattlerTagType.FLINCHED, BattlerTagType.ENDURING]; const field = this.scene.getField(true).filter(p => p.summonData); field.forEach(pokemon => { - pokemon.lapseTags(BattlerTagLapseType.TURN_END); + const tags = pokemon.summonData.tags; + tags.filter(t => includedLapseTags.includes(t.tagType) + && t.lapseTypes.includes(BattlerTagLapseType.TURN_END) + && !(t.lapse(pokemon, BattlerTagLapseType.TURN_END))).forEach(t => { + t.onRemove(pokemon); + tags.splice(tags.indexOf(t), 1); + }); }); // Remove any status tick phases diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index 813d15ae87e..dc0bd235bb5 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -46,8 +46,7 @@ export class PokemonHealPhase extends CommonAnimPhase { const pokemon = this.getPokemon(); if (!pokemon.isOnField() || (!this.revive && !pokemon.isActive())) { - super.end(); - return; + return super.end(); } const hasMessage = !!this.message; @@ -58,7 +57,7 @@ export class PokemonHealPhase extends CommonAnimPhase { if (healBlock && this.hpHealed > 0) { this.scene.queueMessage(healBlock.onActivation(pokemon)); this.message = null; - super.end(); + return super.end(); } else if (healOrDamage) { const hpRestoreMultiplier = new Utils.IntegerHolder(1); if (!this.revive) { diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 63c7cb1b13a..af5e717c17b 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -957,7 +957,7 @@ export class GameData { enemyModifiers: scene.findModifiers(() => true, false).map(m => new PersistentModifierData(m, false)), arena: new ArenaData(scene.arena), pokeballCounts: scene.pokeballCounts, - money: scene.money, + money: Math.floor(scene.money), score: scene.score, waveIndex: scene.currentBattle.waveIndex, battleType: scene.currentBattle.battleType, @@ -1047,7 +1047,7 @@ export class GameData { scene.pokeballCounts = Overrides.POKEBALL_OVERRIDE.pokeballs; } - scene.money = sessionData.money || 0; + scene.money = Math.floor(sessionData.money || 0); scene.updateMoneyText(); if (scene.money > this.gameStats.highestMoney) { diff --git a/src/system/version-converter.ts b/src/system/version-converter.ts index 0591647aeaa..3a4416a975e 100644 --- a/src/system/version-converter.ts +++ b/src/system/version-converter.ts @@ -6,6 +6,10 @@ const LATEST_VERSION = "1.0.5"; export function applySessionDataPatches(data: SessionSaveData) { const curVersion = data.gameVersion; + + // Always sanitize money as a safeguard + data.money = Math.floor(data.money); + if (curVersion !== LATEST_VERSION) { switch (curVersion) { case "1.0.0":