diff --git a/src/battle-phases.ts b/src/battle-phases.ts index b98ca6825c7..cdcec8ed4c7 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 { ModifierType, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getPlayerModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; +import { ModifierPoolType, ModifierType, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getPlayerModifierTypeOptionsForWave, 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"; @@ -266,6 +266,7 @@ export class EncounterPhase extends BattlePhase { if (e < (battle.double ? 2 : 1)) { if (battle.battleType === BattleType.WILD) { this.scene.field.add(enemyPokemon); + battle.seenEnemyPartyMemberIds.add(enemyPokemon.id); const playerPokemon = this.scene.getPlayerPokemon(); if (playerPokemon.visible) this.scene.field.moveBelow(enemyPokemon as Pokemon, playerPokemon); @@ -280,7 +281,7 @@ export class EncounterPhase extends BattlePhase { }); if (!this.loaded) { - regenerateModifierPoolThresholds(this.scene.getEnemyField(), false); + regenerateModifierPoolThresholds(this.scene.getEnemyField(), battle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD); this.scene.generateEnemyModifiers(); } @@ -632,6 +633,8 @@ export class SummonPhase extends PartyMemberPokemonPhase { const playerPokemon = this.scene.getPlayerPokemon() as Pokemon; if (playerPokemon.visible) this.scene.field.moveBelow(pokemon, playerPokemon); + this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id); + this.scene.updateModifiers(false); } pokemon.showInfo(); pokemon.playAnim(); @@ -2753,7 +2756,7 @@ export class SelectModifierPhase extends BattlePhase { this.scene.resetSeed(); const party = this.scene.getParty(); - regenerateModifierPoolThresholds(party); + regenerateModifierPoolThresholds(party, ModifierPoolType.PLAYER); const modifierCount = new Utils.IntegerHolder(3); this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount); const typeOptions: Array = getPlayerModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, modifierCount.value, party); diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 34dc3aabad9..1109c822a26 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -16,7 +16,7 @@ import { GameData } from './system/game-data'; import StarterSelectUiHandler from './ui/starter-select-ui-handler'; import { TextStyle, addTextObject } from './ui/text'; import { Moves, initMoves } from './data/move'; -import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; +import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; import AbilityBar from './ui/ability-bar'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; @@ -1128,7 +1128,10 @@ export default class BattleScene extends Phaser.Scene { const isBoss = !(waveIndex % 10); let count = 0; for (let c = 0; c < chances; c++) { - if (!Utils.randInt(!isBoss ? 12 : 4)) + let modifierChance = !isBoss ? 16 : 6; + if (this.currentBattle.battleType === BattleType.TRAINER) + modifierChance /= 2; + if (!Utils.randSeedInt(modifierChance)) count++; if (count === 12) break; @@ -1136,7 +1139,7 @@ export default class BattleScene extends Phaser.Scene { if (isBoss) count = Math.max(count, Math.floor(chances / 2)); const enemyField = this.getEnemyField(); - getEnemyModifierTypesForWave(waveIndex, count, this.getEnemyField()) + getEnemyModifierTypesForWave(waveIndex, count, this.getEnemyField(), this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD) .map(mt => mt.newModifier(enemyField[Utils.randInt(enemyField.length)]).add(this.enemyModifiers, false)); this.updateModifiers(false).then(() => resolve()); diff --git a/src/battle.ts b/src/battle.ts index 555eb66cc3e..d639b625adb 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -37,6 +37,7 @@ export default class Battle { public trainer: Trainer; public enemyLevels: integer[]; public enemyParty: EnemyPokemon[]; + public seenEnemyPartyMemberIds: Set; public double: boolean; public started: boolean; public turn: integer; @@ -54,6 +55,7 @@ export default class Battle { ? new Array(double ? 2 : 1).fill(null).map(() => this.getLevelForWave()) : trainer.getPartyLevels(this.waveIndex); this.enemyParty = []; + this.seenEnemyPartyMemberIds = new Set(); this.double = double; this.turn = 0; this.started = false; diff --git a/src/data/move.ts b/src/data/move.ts index 4ca86fcb734..6c90fe619a7 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2177,7 +2177,7 @@ function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon, targe const moveAttrs = move.attrs.filter(a => attrFilter(a)); for (let attr of moveAttrs) { const result = attr.apply(user, target, move, args); - if (result instanceof Promise) + if (result instanceof Promise) attrPromises.push(result); } Promise.allSettled(attrPromises).then(() => resolve()); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 12998394e3a..9e99031443b 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -23,6 +23,12 @@ export enum ModifierTier { LUXURY }; +export enum ModifierPoolType { + PLAYER, + WILD, + TRAINER +} + type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier; export class ModifierType { @@ -623,7 +629,7 @@ export const modifierTypes = { GOLDEN_EXP_CHARM: () => new ExpBoosterModifierType('Golden EXP. Charm', 75), LUCKY_EGG: () => new PokemonExpBoosterModifierType('Lucky Egg', 50), - GOLDEN_EGG: () => new PokemonExpBoosterModifierType('Golden Egg', 200), + GOLDEN_EGG: () => new PokemonExpBoosterModifierType('Golden Egg', 150), GRIP_CLAW: () => new ContactHeldItemTransferChanceModifierType('Grip Claw', 10), @@ -719,7 +725,7 @@ const modifierPool = { new WeightedModifierType(modifierTypes.MAP, (party: Pokemon[]) => party[0].scene.gameMode === GameMode.CLASSIC ? 1 : 0), new WeightedModifierType(modifierTypes.TM_GREAT, 2), new WeightedModifierType(modifierTypes.EXP_SHARE, 1), - new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3) + new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3), ].map(m => { m.setTier(ModifierTier.GREAT); return m; }), [ModifierTier.ULTRA]: [ new WeightedModifierType(modifierTypes.ULTRA_BALL, 8), @@ -738,7 +744,7 @@ const modifierPool = { new WeightedModifierType(modifierTypes.BERRY_POUCH, 3), new WeightedModifierType(modifierTypes.EXP_CHARM, 4), new WeightedModifierType(modifierTypes.OVAL_CHARM, 2), - new WeightedModifierType(modifierTypes.EXP_BALANCE, 1) + new WeightedModifierType(modifierTypes.EXP_BALANCE, 1), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), [ModifierTier.MASTER]: [ new WeightedModifierType(modifierTypes.MASTER_BALL, 3), @@ -748,11 +754,11 @@ const modifierPool = { [ModifierTier.LUXURY]: [ new WeightedModifierType(modifierTypes.GOLDEN_EXP_CHARM, 1), new WeightedModifierType(modifierTypes.GOLDEN_POKEBALL, 1), - new WeightedModifierType(modifierTypes.RARER_CANDY, 1) + new WeightedModifierType(modifierTypes.RARER_CANDY, 1), ].map(m => { m.setTier(ModifierTier.LUXURY); return m; }), }; -const enemyModifierPool = { +const wildModifierPool = { [ModifierTier.COMMON]: [ new WeightedModifierType(modifierTypes.BERRY, 1) ].map(m => { m.setTier(ModifierTier.COMMON); return m; }), @@ -760,16 +766,34 @@ const enemyModifierPool = { new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1) ].map(m => { m.setTier(ModifierTier.GREAT); return m; }), [ModifierTier.ULTRA]: [ - new WeightedModifierType(modifierTypes.REVIVER_SEED, 2), new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), + new WeightedModifierType(modifierTypes.LUCKY_EGG, 4), + ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), + [ModifierTier.MASTER]: [ + new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1) + ].map(m => { m.setTier(ModifierTier.MASTER); return m; }) +}; + +const trainerModifierPool = { + [ModifierTier.COMMON]: [ + new WeightedModifierType(modifierTypes.BERRY, 8), + new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3) + ].map(m => { m.setTier(ModifierTier.COMMON); return m; }), + [ModifierTier.GREAT]: [ + new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3), + new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 1), + ].map(m => { m.setTier(ModifierTier.GREAT); return m; }), + [ModifierTier.ULTRA]: [ + new WeightedModifierType(modifierTypes.REVIVER_SEED, 2), new WeightedModifierType(modifierTypes.FOCUS_BAND, 2), new WeightedModifierType(modifierTypes.LUCKY_EGG, 4), + new WeightedModifierType(modifierTypes.GRIP_CLAW, 1), new WeightedModifierType(modifierTypes.KINGS_ROCK, 1), new WeightedModifierType(modifierTypes.LEFTOVERS, 1), new WeightedModifierType(modifierTypes.SHELL_BELL, 1), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), [ModifierTier.MASTER]: [ - new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1) + new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1), ].map(m => { m.setTier(ModifierTier.MASTER); return m; }) }; @@ -779,10 +803,9 @@ let ignoredPoolIndexes = {}; let enemyModifierPoolThresholds = {}; let enemyIgnoredPoolIndexes = {}; -export function regenerateModifierPoolThresholds(party: Pokemon[], player?: boolean) { - if (player === undefined) - player = true; - const pool = player ? modifierPool : enemyModifierPool; +export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType) { + const player = !poolType; + const pool = player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : trainerModifierPool; const ignoredIndexes = {}; const thresholds = Object.fromEntries(new Map(Object.keys(pool).map(t => { ignoredIndexes[t] = []; @@ -826,25 +849,24 @@ export function getPlayerModifierTypeOptionsForWave(waveIndex: integer, count: i const options: ModifierTypeOption[] = []; const retryCount = Math.min(count * 5, 50); new Array(count).fill(0).map(() => { - let candidate = getNewModifierTypeOption(party); + let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER); let r = 0; while (options.length && ++r < retryCount && options.filter(o => o.type.name === candidate.type.name || o.type.group === candidate.type.group).length) - candidate = getNewModifierTypeOption(party, true, candidate.type.tier, candidate.upgraded); + candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, candidate.type.tier, candidate.upgraded); options.push(candidate); }); return options; } -export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[]): PokemonHeldItemModifierType[] { - const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, false).type as PokemonHeldItemModifierType); +export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER): PokemonHeldItemModifierType[] { + const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType).type as PokemonHeldItemModifierType); if (waveIndex === 200) ret.push(modifierTypes.MINI_BLACK_HOLE()); return ret; } -function getNewModifierTypeOption(party: Pokemon[], player?: boolean, tier?: ModifierTier, upgrade?: boolean): ModifierTypeOption { - if (player === undefined) - player = true; +function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgrade?: boolean): ModifierTypeOption { + const player = !poolType; if (tier === undefined) { const tierValue = Utils.randSeedInt(256); if (player && tierValue) { @@ -870,13 +892,13 @@ function getNewModifierTypeOption(party: Pokemon[], player?: boolean, tier?: Mod if (player) console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier]) - let modifierType: ModifierType = ((player ? modifierPool : enemyModifierPool)[tier][index]).modifierType; + let modifierType: ModifierType = ((player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : trainerModifierPool)[tier][index]).modifierType; if (modifierType instanceof ModifierTypeGenerator) { modifierType = (modifierType as ModifierTypeGenerator).generateType(party); if (modifierType === null) { if (player) console.log(ModifierTier[tier], upgrade); - return getNewModifierTypeOption(party, player, tier, upgrade); + return getNewModifierTypeOption(party, poolType, tier, upgrade); } } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 5e53a775474..4abdaa73f8e 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -334,10 +334,13 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier { if (!forSummary) { const pokemon = this.getPokemon(scene); - const pokemonIcon = scene.add.sprite(0, 8, pokemon.species.getIconAtlasKey()); - if (pokemon.species.isObtainable()) - pokemonIcon.play(pokemon.getIconKey()).stop(); - else { + const isIconShown = pokemon instanceof PlayerPokemon || scene.currentBattle.seenEnemyPartyMemberIds.has(pokemon.id); + const iconAtlasKey = isIconShown ? pokemon.species.getIconAtlasKey() : 'pokemon_icons_0'; + const pokemonIcon = scene.add.sprite(0, 8, iconAtlasKey); + if (pokemon.species.isObtainable()) { + const iconKey = isIconShown ? pokemon.getIconKey() : 'pkmn_icon__000'; + pokemonIcon.play(iconKey).stop(); + } else { if (pokemon.species.speciesId === Species.ETERNATUS) pokemonIcon.setScale(0.5, 0.5); else @@ -395,7 +398,7 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier { } shouldApply(args: any[]): boolean { - return super.shouldApply(args) && args.length === 2 && args[1] instanceof Array; + return super.shouldApply(args) && args.length === 2 && args[1] instanceof Array; } apply(args: any[]): boolean { diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 9cfaf983bc0..e4873e3dda1 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -226,6 +226,8 @@ export class GameData { sessionData.enemyParty.forEach((enemyData, e) => { const enemyPokemon = enemyData.toPokemon(scene) as EnemyPokemon; battle.enemyParty[e] = enemyPokemon; + if (battleType === BattleType.WILD) + battle.seenEnemyPartyMemberIds.add(enemyPokemon.id); loadPokemonAssets.push(enemyPokemon.loadAssets()); }); diff --git a/src/ui/text.ts b/src/ui/text.ts index 54f87ed9ac1..7ff32520ebb 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -47,7 +47,7 @@ export function addTextObject(scene: Phaser.Scene, x: number, y: number, content if (extraStyleOptions) { if (extraStyleOptions.fontSize) { - const sizeRatio = parseInt(extraStyleOptions.fontSize.slice(0, -2)) / parseInt(styleOptions.fontSize.slice(0, -2)); + const sizeRatio = parseInt(extraStyleOptions.fontSize.toString().slice(0, -2)) / parseInt(styleOptions.fontSize.slice(0, -2)); shadowSize *= sizeRatio; } styleOptions = Object.assign(styleOptions, extraStyleOptions);