Add simulated support for Arena Tag application

This commit is contained in:
innerthunder 2024-10-13 22:07:21 -07:00
parent 8981f0e7a8
commit 08da3ed936
11 changed files with 91 additions and 49 deletions

View File

@ -36,7 +36,7 @@ export abstract class ArenaTag {
public side: ArenaTagSide = ArenaTagSide.BOTH public side: ArenaTagSide = ArenaTagSide.BOTH
) {} ) {}
apply(arena: Arena, args: any[]): boolean { apply(arena: Arena, simulated: boolean, args: any[]): boolean {
return true; return true;
} }
@ -122,10 +122,20 @@ export class MistTag extends ArenaTag {
} }
} }
apply(arena: Arena, args: any[]): boolean { /**
* Cancels the lowering of stats
* @param arena the {@linkcode Arena} containing this effect
* @param simulated `true` if the effect should be applied quietly
* @param args `[0]` a {@linkcode Utils.BooleanHolder | BooleanHolder} whose value is set to `true`
* to flag the stat reduction as cancelled
* @returns `true` if a stat reduction was cancelled; `false` otherwise
*/
override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
(args[0] as Utils.BooleanHolder).value = true; (args[0] as Utils.BooleanHolder).value = true;
arena.scene.queueMessage(i18next.t("arenaTag:mistApply")); if (!simulated) {
arena.scene.queueMessage(i18next.t("arenaTag:mistApply"));
}
return true; return true;
} }
@ -157,15 +167,15 @@ export class WeakenMoveScreenTag extends ArenaTag {
/** /**
* Applies the weakening effect to the move. * Applies the weakening effect to the move.
* *
* @param arena - The arena where the move is applied. * @param arena the {@linkcode Arena} where the move is applied.
* @param args - The arguments for the move application. * @param simulated n/a
* @param args[0] - The category of the move. * @param args the arguments for this tag's application:
* @param args[1] - A boolean indicating whether it is a double battle. * - `[0]` The attacking move's {@linkcode MoveCategory}.
* @param args[2] - An object of type `Utils.NumberHolder` that holds the damage multiplier * - `[1]` A boolean indicating whether it is a double battle.
* * - `[2]` A {@linkcode Utils.NumberHolder | NumberHolder} containing the damage multiplier
* @returns True if the move was weakened, otherwise false. * @returns `true` if the attacking move was weakened; `false` otherwise.
*/ */
apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
if (this.weakenedCategories.includes((args[0] as MoveCategory))) { if (this.weakenedCategories.includes((args[0] as MoveCategory))) {
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732 / 4096 : 0.5; (args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732 / 4096 : 0.5;
return true; return true;
@ -249,17 +259,19 @@ export class ConditionalProtectTag extends ArenaTag {
onRemove(arena: Arena): void { } onRemove(arena: Arena): void { }
/** /**
* apply(): Checks incoming moves against the condition function * Checks incoming moves against the condition function
* and protects the target if conditions are met * and protects the target if conditions are met
* @param arena The arena containing this tag * @param arena the {@linkcode Arena} containing this tag
* @param args\[0\] (Utils.BooleanHolder) Signals if the move is cancelled * @param simulated `true` if the tag is applied quietly; `false` otherwise.
* @param args\[1\] (Pokemon) The Pokemon using the move * @param args the arguments for this tag's application:
* @param args\[2\] (Pokemon) The intended target of the move * - `[0]` a {@linkcode Utils.BooleanHolder | BooleanHolder} used to flag if the move is protected against
* @param args\[3\] (Moves) The parameters to the condition function * - `[1]` the attacking {@linkcode Pokemon}
* @param args\[4\] (Utils.BooleanHolder) Signals if the applied protection supercedes protection-ignoring effects * - `[2]` the defending {@linkcode Pokemon}
* - `[3]` the {@linkcode Moves | identifier} for the move being used
* - `[4]` a {@linkcode Utils.BooleanHolder | BooleanHolder} used to flag if a protection effect supercedes effects that ignore protection
* @returns * @returns
*/ */
apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
const [ cancelled, user, target, moveId, ignoresBypass ] = args; const [ cancelled, user, target, moveId, ignoresBypass ] = args;
if (cancelled instanceof Utils.BooleanHolder if (cancelled instanceof Utils.BooleanHolder
@ -272,10 +284,12 @@ export class ConditionalProtectTag extends ArenaTag {
&& this.protectConditionFunc(arena, moveId)) { && this.protectConditionFunc(arena, moveId)) {
if (!cancelled.value) { if (!cancelled.value) {
cancelled.value = true; cancelled.value = true;
user.stopMultiHit(target); if (!simulated) {
user.stopMultiHit(target);
new CommonBattleAnim(CommonAnim.PROTECT, target).play(arena.scene); new CommonBattleAnim(CommonAnim.PROTECT, target).play(arena.scene);
arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(target) })); arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(target) }));
}
} }
ignoresBypass.value = ignoresBypass.value || this.ignoresBypass; ignoresBypass.value = ignoresBypass.value || this.ignoresBypass;
@ -497,7 +511,16 @@ export class WeakenMoveTypeTag extends ArenaTag {
this.weakenedType = type; this.weakenedType = type;
} }
apply(arena: Arena, args: any[]): boolean { /**
* Reduces an attack's power by 0.33x if it matches this tag's weakened type.
* @param arena n/a
* @param simulated n/a
* @param args the arguments for this tag's application:
* - `[0]` the attack's {@linkcode Type}
* - `[1]` a {@linkcode Utils.NumberHolder | NumberHolder} containing the attack's power
* @returns `true` if the attack's power was reduced; `false` otherwise.
*/
override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
if ((args[0] as Type) === this.weakenedType) { if ((args[0] as Type) === this.weakenedType) {
(args[1] as Utils.NumberHolder).value *= 0.33; (args[1] as Utils.NumberHolder).value *= 0.33;
return true; return true;
@ -563,11 +586,12 @@ export class IonDelugeTag extends ArenaTag {
/** /**
* Converts Normal-type moves to Electric type * Converts Normal-type moves to Electric type
* @param arena n/a * @param arena n/a
* @param simulated n/a
* @param args * @param args
* - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type} * - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type}
* @returns `true` if the given move type changed; `false` otherwise. * @returns `true` if the given move type changed; `false` otherwise.
*/ */
apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
const moveType = args[0]; const moveType = args[0];
if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) { if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) {
moveType.value = Type.ELECTRIC; moveType.value = Type.ELECTRIC;
@ -608,16 +632,16 @@ export class ArenaTrapTag extends ArenaTag {
} }
} }
apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
const pokemon = args[0] as Pokemon; const pokemon = args[0] as Pokemon;
if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) { if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) {
return false; return false;
} }
return this.activateTrap(pokemon); return this.activateTrap(pokemon, simulated);
} }
activateTrap(pokemon: Pokemon): boolean { activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
return false; return false;
} }
@ -651,11 +675,15 @@ class SpikesTag extends ArenaTrapTag {
} }
} }
activateTrap(pokemon: Pokemon): boolean { override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
if (pokemon.isGrounded()) { if (pokemon.isGrounded()) {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
if (simulated) {
return !cancelled.value;
}
if (!cancelled.value) { if (!cancelled.value) {
const damageHpRatio = 1 / (10 - 2 * this.layers); const damageHpRatio = 1 / (10 - 2 * this.layers);
const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio);
@ -702,8 +730,11 @@ class ToxicSpikesTag extends ArenaTrapTag {
} }
} }
activateTrap(pokemon: Pokemon): boolean { override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
if (pokemon.isGrounded()) { if (pokemon.isGrounded()) {
if (simulated) {
return true;
}
if (pokemon.isOfType(Type.POISON)) { if (pokemon.isOfType(Type.POISON)) {
this.neutralized = true; this.neutralized = true;
if (pokemon.scene.arena.removeTag(this.tagType)) { if (pokemon.scene.arena.removeTag(this.tagType)) {
@ -807,7 +838,7 @@ class StealthRockTag extends ArenaTrapTag {
return damageHpRatio; return damageHpRatio;
} }
activateTrap(pokemon: Pokemon): boolean { override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
@ -818,12 +849,16 @@ class StealthRockTag extends ArenaTrapTag {
const damageHpRatio = this.getDamageHpRatio(pokemon); const damageHpRatio = this.getDamageHpRatio(pokemon);
if (damageHpRatio) { if (damageHpRatio) {
if (simulated) {
return true;
}
const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio);
pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
pokemon.damageAndUpdate(damage, HitResult.OTHER); pokemon.damageAndUpdate(damage, HitResult.OTHER);
if (pokemon.turnData) { if (pokemon.turnData) {
pokemon.turnData.damageTaken += damage; pokemon.turnData.damageTaken += damage;
} }
return true;
} }
return false; return false;
@ -853,14 +888,20 @@ class StickyWebTag extends ArenaTrapTag {
} }
} }
activateTrap(pokemon: Pokemon): boolean { override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
if (pokemon.isGrounded()) { if (pokemon.isGrounded()) {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
if (simulated) {
return !cancelled.value;
}
if (!cancelled.value) { if (!cancelled.value) {
pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() })); pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() }));
const stages = new Utils.NumberHolder(-1); const stages = new Utils.NumberHolder(-1);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value));
return true;
} }
} }
@ -879,7 +920,7 @@ export class TrickRoomTag extends ArenaTag {
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId); super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
} }
apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
const speedReversed = args[0] as Utils.BooleanHolder; const speedReversed = args[0] as Utils.BooleanHolder;
speedReversed.value = !speedReversed.value; speedReversed.value = !speedReversed.value;
return true; return true;
@ -1111,7 +1152,7 @@ class WaterFirePledgeTag extends ArenaTag {
arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`)); arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
} }
override apply(arena: Arena, args: any[]): boolean { override apply(arena: Arena, simulated: boolean, args: any[]): boolean {
const moveChance = args[0] as Utils.NumberHolder; const moveChance = args[0] as Utils.NumberHolder;
moveChance.value *= 2; moveChance.value *= 2;
return true; return true;

View File

@ -808,7 +808,7 @@ export default class Move implements Localizable {
source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power); source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power);
if (!this.hasAttr(TypelessAttr)) { if (!this.hasAttr(TypelessAttr)) {
source.scene.arena.applyTags(WeakenMoveTypeTag, this.type, power); source.scene.arena.applyTags(WeakenMoveTypeTag, simulated, this.type, power);
source.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, this.type, power); source.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, this.type, power);
} }
@ -1026,7 +1026,7 @@ export class MoveEffectAttr extends MoveAttr {
if (!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) { if (!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) {
const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
user.scene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, moveChance); user.scene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, false, moveChance);
} }
if (!selfEffect) { if (!selfEffect) {

View File

@ -579,26 +579,28 @@ export class Arena {
* Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter * Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
* @param side {@linkcode ArenaTagSide} which side's arena tags to apply * @param side {@linkcode ArenaTagSide} which side's arena tags to apply
* @param simulated if `true`, this applies arena tags without changing game state
* @param args array of parameters that the called upon tags may need * @param args array of parameters that the called upon tags may need
*/ */
applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, ...args: unknown[]): void { applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, simulated: boolean, ...args: unknown[]): void {
let tags = typeof tagType === "string" let tags = typeof tagType === "string"
? this.tags.filter(t => t.tagType === tagType) ? this.tags.filter(t => t.tagType === tagType)
: this.tags.filter(t => t instanceof tagType); : this.tags.filter(t => t instanceof tagType);
if (side !== ArenaTagSide.BOTH) { if (side !== ArenaTagSide.BOTH) {
tags = tags.filter(t => t.side === side); tags = tags.filter(t => t.side === side);
} }
tags.forEach(t => t.apply(this, args)); tags.forEach(t => t.apply(this, simulated, args));
} }
/** /**
* Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified) * Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified)
* by calling {@linkcode applyTagsForSide()} * by calling {@linkcode applyTagsForSide()}
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
* @param simulated if `true`, this applies arena tags without changing game state
* @param args array of parameters that the called upon tags may need * @param args array of parameters that the called upon tags may need
*/ */
applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, ...args: unknown[]): void { applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, simulated: boolean, ...args: unknown[]): void {
this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); this.applyTagsForSide(tagType, ArenaTagSide.BOTH, simulated, ...args);
} }
/** /**

View File

@ -1538,7 +1538,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder); applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder); applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
this.scene.arena.applyTags(ArenaTagType.ION_DELUGE, moveTypeHolder); this.scene.arena.applyTags(ArenaTagType.ION_DELUGE, simulated, moveTypeHolder);
if (this.getTag(BattlerTagType.ELECTRIFIED)) { if (this.getTag(BattlerTagType.ELECTRIFIED)) {
moveTypeHolder.value = Type.ELECTRIC; moveTypeHolder.value = Type.ELECTRIC;
} }
@ -2605,7 +2605,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
/** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */ /** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */
const screenMultiplier = new Utils.NumberHolder(1); const screenMultiplier = new Utils.NumberHolder(1);
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, move.category, this.scene.currentBattle.double, screenMultiplier); this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, simulated, move.category, this.scene.currentBattle.double, screenMultiplier);
/** /**
* For each {@linkcode HitsTagAttr} the move has, doubles the damage of the move if: * For each {@linkcode HitsTagAttr} the move has, doubles the damage of the move if:

View File

@ -140,7 +140,7 @@ export class MoveEffectPhase extends PokemonPhase {
const bypassIgnoreProtect = new Utils.BooleanHolder(false); const bypassIgnoreProtect = new Utils.BooleanHolder(false);
/** If the move is not targeting a Pokemon on the user's side, try to apply conditional protection effects */ /** If the move is not targeting a Pokemon on the user's side, try to apply conditional protection effects */
if (!this.move.getMove().isAllyTarget()) { if (!this.move.getMove().isAllyTarget()) {
this.scene.arena.applyTagsForSide(ConditionalProtectTag, targetSide, hasConditionalProtectApplied, user, target, move.id, bypassIgnoreProtect); this.scene.arena.applyTagsForSide(ConditionalProtectTag, targetSide, false, hasConditionalProtectApplied, user, target, move.id, bypassIgnoreProtect);
} }
/** Is the target protected by Protect, etc. or a relevant conditional protection effect? */ /** Is the target protected by Protect, etc. or a relevant conditional protection effect? */

View File

@ -20,7 +20,7 @@ export class PostSummonPhase extends PokemonPhase {
if (pokemon.status?.effect === StatusEffect.TOXIC) { if (pokemon.status?.effect === StatusEffect.TOXIC) {
pokemon.status.turnCount = 0; pokemon.status.turnCount = 0;
} }
this.scene.arena.applyTags(ArenaTrapTag, pokemon); this.scene.arena.applyTags(ArenaTrapTag, false, pokemon);
// If this is mystery encounter and has post summon phase tag, apply post summon effects // If this is mystery encounter and has post summon phase tag, apply post summon effects
if (this.scene.currentBattle.isBattleMysteryEncounter() && pokemon.findTags(t => t instanceof MysteryEncounterPostSummonTag).length > 0) { if (this.scene.currentBattle.isBattleMysteryEncounter() && pokemon.findTags(t => t instanceof MysteryEncounterPostSummonTag).length > 0) {

View File

@ -64,8 +64,7 @@ export class StatStageChangePhase extends PokemonPhase {
const cancelled = new BooleanHolder(false); const cancelled = new BooleanHolder(false);
if (!this.selfTarget && stages.value < 0) { if (!this.selfTarget && stages.value < 0) {
// TODO: Include simulate boolean when tag applications can be simulated this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, false, cancelled);
this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled);
} }
if (!cancelled.value && !this.selfTarget && stages.value < 0) { if (!cancelled.value && !this.selfTarget && stages.value < 0) {

View File

@ -45,7 +45,7 @@ export class TurnStartPhase extends FieldPhase {
// Next, a check for Trick Room is applied to determine sort order. // Next, a check for Trick Room is applied to determine sort order.
const speedReversed = new Utils.BooleanHolder(false); const speedReversed = new Utils.BooleanHolder(false);
this.scene.arena.applyTags(TrickRoomTag, speedReversed); this.scene.arena.applyTags(TrickRoomTag, false, speedReversed);
// Adjust the sort function based on whether Trick Room is active. // Adjust the sort function based on whether Trick Room is active.
orderedTargets.sort((a: Pokemon, b: Pokemon) => { orderedTargets.sort((a: Pokemon, b: Pokemon) => {

View File

@ -111,7 +111,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) =
const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (defender.scene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) { if (defender.scene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) {
defender.scene.arena.applyTagsForSide(ArenaTagType.AURORA_VEIL, side, move.category, defender.scene.currentBattle.double, multiplierHolder); defender.scene.arena.applyTagsForSide(ArenaTagType.AURORA_VEIL, side, false, move.category, defender.scene.currentBattle.double, multiplierHolder);
} }
return move.power * multiplierHolder.value; return move.power * multiplierHolder.value;

View File

@ -94,7 +94,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) =
const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (defender.scene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) { if (defender.scene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) {
defender.scene.arena.applyTagsForSide(ArenaTagType.LIGHT_SCREEN, side, move.category, defender.scene.currentBattle.double, multiplierHolder); defender.scene.arena.applyTagsForSide(ArenaTagType.LIGHT_SCREEN, side, false, move.category, defender.scene.currentBattle.double, multiplierHolder);
} }
return move.power * multiplierHolder.value; return move.power * multiplierHolder.value;

View File

@ -94,7 +94,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) =
const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (defender.scene.arena.getTagOnSide(ArenaTagType.REFLECT, side)) { if (defender.scene.arena.getTagOnSide(ArenaTagType.REFLECT, side)) {
defender.scene.arena.applyTagsForSide(ArenaTagType.REFLECT, side, move.category, defender.scene.currentBattle.double, multiplierHolder); defender.scene.arena.applyTagsForSide(ArenaTagType.REFLECT, side, false, move.category, defender.scene.currentBattle.double, multiplierHolder);
} }
return move.power * multiplierHolder.value; return move.power * multiplierHolder.value;