From ae8fecb7fde4aa387ef92b8649d1e8b6e97ed62e Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Tue, 10 Sep 2024 02:41:29 -0700 Subject: [PATCH] Replace magic numbers, add/update various comments --- src/battle-scene.ts | 30 ++++++++++++++++++------------ src/constants.ts | 1 + src/data/ability.ts | 26 +++++++++++++++++++++----- src/enums/battle-spec.ts | 4 ++++ src/game-mode.ts | 34 +++++++++++++++++----------------- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 2f066b71f50..67851899ec4 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -15,7 +15,7 @@ import { TextStyle, addTextObject, getTextColor } from "./ui/text"; import { allMoves } from "./data/move"; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, modifierTypes } from "./modifier/modifier-type"; import AbilityBar from "./ui/ability-bar"; -import { BlockItemTheftAbAttr, BonusItemChanceAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability"; +import { BlockItemTheftAbAttr, BonusItemChanceAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs, applyPreEncounterAbAttrs } from "./data/ability"; import { allAbilities } from "./data/ability"; import Battle, { BattleType, FixedBattleConfig } from "./battle"; import { GameMode, GameModes, getGameMode } from "./game-mode"; @@ -84,6 +84,7 @@ import { TitlePhase } from "./phases/title-phase"; import { ToggleDoublePositionPhase } from "./phases/toggle-double-position-phase"; import { TurnInitPhase } from "./phases/turn-init-phase"; import { ShopCursorTarget } from "./enums/shop-cursor-target"; +import { BOSS_BONUS_ENEMY_ITEM_CHANCE_MULTIPLIER } from "#app/constants"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -2478,17 +2479,20 @@ export default class BattleScene extends SceneBase { generateEnemyModifiers(): Promise { return new Promise(resolve => { - if (this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { + if (this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { // Classic mode final boss return resolve(); } + const difficultyWaveIndex = this.gameMode.getWaveForDifficulty(this.currentBattle.waveIndex); const isFinalBoss = this.gameMode.isWaveFinal(this.currentBattle.waveIndex); - let chances = Math.ceil(difficultyWaveIndex / 10); - if (this.getPlayerPokemon()?.hasAbilityWithAttr(BonusItemChanceAbAttr)) { - chances += Math.floor(chances * 1.2); - } + + const chances = new Utils.NumberHolder(Math.ceil(difficultyWaveIndex / 10)); + + applyPreEncounterAbAttrs(BonusItemChanceAbAttr, this.getPlayerPokemon()!, false, chances); + chances.value = Math.ceil(chances.value); + if (isFinalBoss) { - chances = Math.ceil(chances * 2.5); + chances.value = Math.ceil(chances.value * BOSS_BONUS_ENEMY_ITEM_CHANCE_MULTIPLIER); } const party = this.getEnemyParty(); @@ -2510,17 +2514,19 @@ export default class BattleScene extends SceneBase { upgradeChance /= 8; } const modifierChance = this.gameMode.getEnemyModifierChance(isBoss); - let pokemonModifierChance = modifierChance; - if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer) - pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line + // TODO: Is this supposed to be used? + /* let pokemonModifierChance = modifierChance; + if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer) { + pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); + } */ let count = 0; - for (let c = 0; c < chances; c++) { + for (let c = 0; c < chances.value; c++) { if (!Utils.randSeedInt(modifierChance)) { count++; } } if (isBoss) { - count = Math.max(count, Math.floor(chances / 2)); + count = Math.max(count, Math.floor(chances.value / 2)); } getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance) .map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this)); diff --git a/src/constants.ts b/src/constants.ts index a2f7e47b996..9a5b2fedc0d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1 +1,2 @@ export const PLAYER_PARTY_MAX_SIZE = 6; +export const BOSS_BONUS_ENEMY_ITEM_CHANCE_MULTIPLIER = 2.5; diff --git a/src/data/ability.ts b/src/data/ability.ts index 4851b0a6244..777151df944 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2815,16 +2815,27 @@ export class BonusCritAbAttr extends AbAttr { } } +export class PreEncounterAbAttr extends AbAttr { + applyPreEncounter(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return false; + } +} + /** - * If an ability has this tag, it will increase the chance of items by 20%. - * This is used in battle-scene.ts in generateEnemyModifiers. + * If an ability has this tag, it will increase the chance of enemy pokemon having items by {@linkcode chanceMultiplier} (default 1.2x). + * This is used in `battle-scene.ts` in `generateEnemyModifiers`. */ -export class BonusItemChanceAbAttr extends AbAttr { - constructor() { +export class BonusItemChanceAbAttr extends PreEncounterAbAttr { + constructor(protected chanceMultiplier: number = 1.2) { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { + return true; + } + + override applyPreEncounter(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + (args[0] as Utils.NumberHolder).value *= this.chanceMultiplier; return true; } } @@ -4764,6 +4775,11 @@ export function applyPostFaintAbAttrs(attrType: Constructor, return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated); } +export function applyPreEncounterAbAttrs(attrType: Constructor, + pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreEncounter(pokemon, passive, simulated, args), args, false, simulated); +} + function queueShowAbility(pokemon: Pokemon, passive: boolean): void { pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, passive)); pokemon.scene.clearPhaseQueueSplice(); diff --git a/src/enums/battle-spec.ts b/src/enums/battle-spec.ts index 00bc7f92fea..0e8eddf4632 100644 --- a/src/enums/battle-spec.ts +++ b/src/enums/battle-spec.ts @@ -1,4 +1,8 @@ export enum BattleSpec { DEFAULT, + /** + * This is currently only used for the wave 200 Eternatus fight in Classic mode + * @see `Battle.initBattleSpec` in `src/battle.ts` + */ FINAL_BOSS } diff --git a/src/game-mode.ts b/src/game-mode.ts index f5dadad6f1b..7c4d89a7365 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -215,38 +215,38 @@ export class GameMode implements GameModeConfig { } /** - * Every 10 waves is a boss battle - * @returns true if waveIndex is a multiple of 10 - */ + * Every 10 waves is a boss battle + * @returns true if waveIndex is a multiple of 10 + */ isBoss(waveIndex: integer): boolean { return waveIndex % 10 === 0; } /** - * Every 50 waves of an Endless mode is a boss - * At this time it is paradox pokemon - * @returns true if waveIndex is a multiple of 50 in Endless - */ - isEndlessBoss(waveIndex: integer): boolean { - return !!(waveIndex % 50) && + * Every 50 waves of an Endless mode is a boss + * At this time it is paradox pokemon + * @returns true if waveIndex is a multiple of 50 in Endless + */ + isEndlessMiniBoss(waveIndex: integer): boolean { + return (waveIndex % 50 === 0) && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } /** - * Every 250 waves of an Endless mode is a minor boss - * At this time it is Eternatus - * @returns true if waveIndex is a multiple of 250 in Endless - */ + * Every 250 waves of an Endless mode is a minor boss + * At this time it is Eternatus + * @returns true if waveIndex is a multiple of 250 in Endless + */ isEndlessMinorBoss(waveIndex: integer): boolean { return waveIndex % 250 === 0 && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } /** - * Every 1000 waves of an Endless mode is a major boss - * At this time it is Eternamax Eternatus - * @returns true if waveIndex is a multiple of 1000 in Endless - */ + * Every 1000 waves of an Endless mode is a major boss + * At this time it is Eternamax Eternatus + * @returns true if waveIndex is a multiple of 1000 in Endless + */ isEndlessMajorBoss(waveIndex: integer): boolean { return waveIndex % 1000 === 0 && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS);