From 073a36a33e5b357ffc06a198df1d1e7f36012844 Mon Sep 17 00:00:00 2001 From: Lugiad <2070109+Adri1@users.noreply.github.com> Date: Fri, 21 Feb 2025 00:49:57 +0100 Subject: [PATCH 1/3] [Localization] Corrections move-touch-controls-handler local key names (#5365) * Update move-touch-controls-handler.ts * Update locales submodule --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- public/locales | 2 +- src/ui/settings/move-touch-controls-handler.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/locales b/public/locales index 58dda14ee83..ef43efffe5f 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 58dda14ee834204c4bd5ece47694a3c068df4b0e +Subproject commit ef43efffe5fe454862c350f1b9393c3ad755bcc2 diff --git a/src/ui/settings/move-touch-controls-handler.ts b/src/ui/settings/move-touch-controls-handler.ts index da7ac7f0514..48677122363 100644 --- a/src/ui/settings/move-touch-controls-handler.ts +++ b/src/ui/settings/move-touch-controls-handler.ts @@ -93,9 +93,9 @@ export default class MoveTouchControlsHandler { toolbar.innerHTML = `
-
${i18next.t("settings:reset")}
-
${i18next.t("settings:saveClose")}
-
${i18next.t("settings:cancel")}
+
${i18next.t("settings:touchReset")}
+
${i18next.t("settings:touchSaveClose")}
+
${i18next.t("settings:touchCancel")}
From ed8d162125e87f7942a39a8ab8f7684948af0140 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Fri, 21 Feb 2025 10:50:39 +1100 Subject: [PATCH 2/3] [Balance] Make stat a much larger factor in moveset gen #5383 --- src/field/pokemon.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 714f1ec7026..246f82b8164 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2348,12 +2348,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const maxPower = Math.min(movePool.reduce((v, m) => Math.max(allMoves[m[0]].power, v), 40), 90); movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power / maxPower, 1), 0.5)) ]); - // Weight damaging moves against the lower stat + // Weight damaging moves against the lower stat. This uses a non-linear relationship. + // If the higher stat is 1 - 1.09x higher, no change. At higher stat ~1.38x lower stat, off-stat moves have half weight. + // One third weight at ~1.58x higher, one quarter weight at ~1.73x higher, one fifth at ~1.87x, and one tenth at ~2.35x higher. const atk = this.getStat(Stat.ATK); const spAtk = this.getStat(Stat.SPATK); const worseCategory: MoveCategory = atk > spAtk ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL; const statRatio = worseCategory === MoveCategory.PHYSICAL ? atk / spAtk : spAtk / atk; - movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1) ]); + movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].category === worseCategory ? Math.min(Math.pow(statRatio, 3) * 1.3, 1) : 1) ]); /** The higher this is the more the game weights towards higher level moves. At `0` all moves are equal weight. */ let weightMultiplier = 0.9; From 5072460f4c33dbec9a138a0bd7cebdf8ac60fdc0 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Thu, 20 Feb 2025 18:16:41 -0600 Subject: [PATCH 3/3] [Bug] Fix endless tokens allowing attacks to deal 0 damage (#5347) --- src/data/ability.ts | 2 +- src/modifier/modifier.ts | 2 +- src/test/battle/damage_calculation.test.ts | 24 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 940b5f0c7d7..95601dc2010 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1404,7 +1404,7 @@ export class DamageBoostAbAttr extends PreAttackAbAttr { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { if (this.condition(pokemon, defender, move)) { const power = args[0] as Utils.NumberHolder; - power.value = Math.floor(power.value * this.damageMultiplier); + power.value = Utils.toDmgValue(power.value * this.damageMultiplier); return true; } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index fe61eadaccd..3af2aa2144f 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -3390,7 +3390,7 @@ abstract class EnemyDamageMultiplierModifier extends EnemyPersistentModifier { * @returns always `true` */ override apply(multiplier: NumberHolder): boolean { - multiplier.value = Math.floor(multiplier.value * Math.pow(this.damageMultiplier, this.getStackCount())); + multiplier.value = toDmgValue(multiplier.value * Math.pow(this.damageMultiplier, this.getStackCount())); return true; } diff --git a/src/test/battle/damage_calculation.test.ts b/src/test/battle/damage_calculation.test.ts index e6aca828156..22d072f313c 100644 --- a/src/test/battle/damage_calculation.test.ts +++ b/src/test/battle/damage_calculation.test.ts @@ -1,4 +1,6 @@ import { allMoves } from "#app/data/move"; +import type { EnemyPersistentModifier } from "#app/modifier/modifier"; +import { modifierTypes } from "#app/modifier/modifier-type"; import { Abilities } from "#enums/abilities"; import { ArenaTagType } from "#enums/arena-tag-type"; import { Moves } from "#enums/moves"; @@ -65,6 +67,28 @@ describe("Battle Mechanics - Damage Calculation", () => { expect(aggron.hp).toBe(aggron.getMaxHp() - 1); }); + it("Attacks deal 1 damage at minimum even with many tokens", async () => { + game.override + .startingLevel(1) + .enemySpecies(Species.AGGRON) + .enemyAbility(Abilities.STURDY) + .enemyLevel(10000); + + await game.classicMode.startBattle([ Species.SHUCKLE ]); + + const dmg_redux_modifier = modifierTypes.ENEMY_DAMAGE_REDUCTION().newModifier() as EnemyPersistentModifier; + dmg_redux_modifier.stackCount = 1000; + await game.scene.addEnemyModifier(modifierTypes.ENEMY_DAMAGE_REDUCTION().newModifier() as EnemyPersistentModifier); + + const aggron = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TACKLE); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(aggron.hp).toBe(aggron.getMaxHp() - 1); + }); + it("Fixed-damage moves ignore damage multipliers", async () => { game.override .enemySpecies(Species.DRAGONITE)