Merge branch 'hotfix-1.11.2' into shiny-daily-starters

This commit is contained in:
Wlowscha 2025-11-01 00:37:57 +01:00 committed by GitHub
commit a4b11d901e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 60 additions and 10 deletions

View File

@ -34,6 +34,7 @@ import { MoveCategory } from "#enums/move-category";
import { MoveFlags } from "#enums/move-flags"; import { MoveFlags } from "#enums/move-flags";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
import { MoveResult } from "#enums/move-result"; import { MoveResult } from "#enums/move-result";
import { MoveTarget } from "#enums/move-target"; import { MoveTarget } from "#enums/move-target";
import { MoveUseMode } from "#enums/move-use-mode"; import { MoveUseMode } from "#enums/move-use-mode";
@ -4142,6 +4143,25 @@ export class ChangeMovePriorityAbAttr extends AbAttr {
} }
} }
export class ChangeMovePriorityInBracketAbAttr extends AbAttr {
private readonly newModifier: MovePriorityInBracket;
private readonly moveFunc: (pokemon: Pokemon, move: Move) => boolean;
constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, newModifier: MovePriorityInBracket) {
super(false);
this.newModifier = newModifier;
this.moveFunc = moveFunc;
}
override canApply({ pokemon, move }: ChangeMovePriorityAbAttrParams): boolean {
return this.moveFunc(pokemon, move);
}
override apply({ priority }: ChangeMovePriorityAbAttrParams): void {
priority.value = this.newModifier;
}
}
export class IgnoreContactAbAttr extends AbAttr { export class IgnoreContactAbAttr extends AbAttr {
private declare readonly _: never; private declare readonly _: never;
} }
@ -6721,6 +6741,7 @@ const AbilityAttrs = Object.freeze({
BlockStatusDamageAbAttr, BlockStatusDamageAbAttr,
BlockOneHitKOAbAttr, BlockOneHitKOAbAttr,
ChangeMovePriorityAbAttr, ChangeMovePriorityAbAttr,
ChangeMovePriorityInBracketAbAttr,
IgnoreContactAbAttr, IgnoreContactAbAttr,
PreWeatherEffectAbAttr, PreWeatherEffectAbAttr,
PreWeatherDamageAbAttr, PreWeatherDamageAbAttr,
@ -7238,7 +7259,7 @@ export function initAbilities() {
.attr(DoubleBattleChanceAbAttr) .attr(DoubleBattleChanceAbAttr)
.build(), .build(),
new AbBuilder(AbilityId.STALL, 4) new AbBuilder(AbilityId.STALL, 4)
.attr(ChangeMovePriorityAbAttr, (_pokemon, _move: Move) => true, -0.2) .attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, _move: Move) => true, MovePriorityInBracket.LAST)
.build(), .build(),
new AbBuilder(AbilityId.TECHNICIAN, 4) new AbBuilder(AbilityId.TECHNICIAN, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => { .attr(MovePowerBoostAbAttr, (user, target, move) => {
@ -8185,7 +8206,7 @@ export function initAbilities() {
.ignorable() .ignorable()
.build(), .build(),
new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9) new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9)
.attr(ChangeMovePriorityAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, -0.2) .attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, MovePriorityInBracket.LAST)
.attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS) .attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS)
.attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => move.category === MoveCategory.STATUS) .attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => move.category === MoveCategory.STATUS)
.build(), .build(),

View File

@ -101,6 +101,7 @@ import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
import { inSpeedOrder } from "#utils/speed-order-generator"; import { inSpeedOrder } from "#utils/speed-order-generator";
import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils"; import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils";
import type { ReadonlyGenericUint8Array } from "#types/typed-arrays"; import type { ReadonlyGenericUint8Array } from "#types/typed-arrays";
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
/** /**
* A function used to conditionally determine execution of a given {@linkcode MoveAttr}. * A function used to conditionally determine execution of a given {@linkcode MoveAttr}.
@ -1060,17 +1061,21 @@ export abstract class Move implements Localizable {
getPriority(user: Pokemon, simulated: boolean = true) { getPriority(user: Pokemon, simulated: boolean = true) {
const priority = new NumberHolder(this.priority); const priority = new NumberHolder(this.priority);
applyMoveAttrs("IncrementMovePriorityAttr", user, null, this, priority); applyMoveAttrs("IncrementMovePriorityAttr", user, null, this, priority);
applyAbAttrs("ChangeMovePriorityAbAttr", {pokemon: user, simulated, move: this, priority}); applyAbAttrs("ChangeMovePriorityAbAttr", {pokemon: user, simulated, move: this, priority});
if (user.getTag(BattlerTagType.BYPASS_SPEED)) {
priority.value += 0.2;
}
return priority.value; return priority.value;
} }
public getPriorityModifier(user: Pokemon, simulated = true) {
if (user.getTag(BattlerTagType.BYPASS_SPEED)) {
return MovePriorityInBracket.FIRST;
}
const modifierHolder = new NumberHolder(MovePriorityInBracket.NORMAL);
applyAbAttrs("ChangeMovePriorityInBracketAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder });
return modifierHolder.value;
}
/** /**
* Calculate the [Expected Power](https://en.wikipedia.org/wiki/Expected_value) per turn * Calculate the [Expected Power](https://en.wikipedia.org/wiki/Expected_value) per turn
* of this move, taking into account multi hit moves, accuracy, and the number of turns it * of this move, taking into account multi hit moves, accuracy, and the number of turns it

View File

@ -67,7 +67,7 @@ export class Terrain {
return ( return (
!isFieldTargeted(move) !isFieldTargeted(move)
&& !isSpreadMove(move) && !isSpreadMove(move)
&& move.getPriority(user) > 0.2 // fractional priority is used by quick claw etc and is not blocked by terrain && move.getPriority(user) > 0
&& user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()) && user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded())
); );
} }

View File

@ -0,0 +1,13 @@
import type { ObjectValues } from "#types/type-helpers";
/**
* Enum representing modifiers for Move priorities.
*/
export const MovePriorityInBracket = Object.freeze({
/** Used when moves go last in their priority bracket, but before moves of lower priority. */
LAST: 0,
NORMAL: 1,
/** Used when moves go first in their priority bracket, but before moves of lower priority. */
FIRST: 2,
});
export type MovePriorityInBracket = ObjectValues<typeof MovePriorityInBracket>;

View File

@ -69,6 +69,10 @@ export class TurnStartPhase extends FieldPhase {
const phaseManager = globalScene.phaseManager; const phaseManager = globalScene.phaseManager;
for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) {
if (globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.command !== Command.FIGHT) {
continue;
}
applyAbAttrs("BypassSpeedChanceAbAttr", { pokemon }); applyAbAttrs("BypassSpeedChanceAbAttr", { pokemon });
globalScene.applyModifiers(BypassSpeedChanceModifier, pokemon.isPlayer(), pokemon); globalScene.applyModifiers(BypassSpeedChanceModifier, pokemon.isPlayer(), pokemon);
} }

View File

@ -92,11 +92,18 @@ export class MovePhasePriorityQueue extends PokemonPhasePriorityQueue<MovePhase>
}); });
const timingModifiers = [a, b].map(movePhase => movePhase.timingModifier); const timingModifiers = [a, b].map(movePhase => movePhase.timingModifier);
const priorityModifiers = [a, b].map(movePhase =>
movePhase.move.getMove().getPriorityModifier(movePhase.pokemon),
);
if (timingModifiers[0] !== timingModifiers[1]) { if (timingModifiers[0] !== timingModifiers[1]) {
return timingModifiers[1] - timingModifiers[0]; return timingModifiers[1] - timingModifiers[0];
} }
if (priority[0] === priority[1] && priorityModifiers[0] !== priorityModifiers[1]) {
return priorityModifiers[1] - priorityModifiers[0];
}
return priority[1] - priority[0]; return priority[1] - priority[0];
}); });
} }

View File

@ -72,7 +72,7 @@ describe("Arena - Psychic Terrain", () => {
await game.phaseInterceptor.to("MovePhase", false); await game.phaseInterceptor.to("MovePhase", false);
const feebas = game.field.getPlayerPokemon(); const feebas = game.field.getPlayerPokemon();
expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0.2); expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0);
await game.toEndOfTurn(); await game.toEndOfTurn();
@ -93,7 +93,7 @@ describe("Arena - Psychic Terrain", () => {
await game.phaseInterceptor.to("MovePhase", false); await game.phaseInterceptor.to("MovePhase", false);
const feebas = game.field.getPlayerPokemon(); const feebas = game.field.getPlayerPokemon();
expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1.2); expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1);
await game.toEndOfTurn(); await game.toEndOfTurn();