Adds simulated tag support to all abilities

pull/686/head
Xavion3 2024-05-10 02:01:17 +10:00
parent 407d9b7c49
commit 2582748903
7 changed files with 349 additions and 317 deletions

View File

@ -823,7 +823,7 @@ export default class BattleScene extends SceneBase {
else if (trainerConfigs[trainerType].hasDouble) {
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance));
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
doubleTrainer = !Utils.randSeedInt(doubleChance.value);
}
newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, doubleTrainer ? TrainerVariant.DOUBLE : Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT);
@ -835,7 +835,7 @@ export default class BattleScene extends SceneBase {
if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) {
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance));
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
newDouble = !Utils.randSeedInt(doubleChance.value);
} else if (newBattleType === BattleType.TRAINER)
newDouble = newTrainer.variant === TrainerVariant.DOUBLE;
@ -1542,7 +1542,7 @@ export default class BattleScene extends SceneBase {
pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void {
const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority);
applyAbAttrs(IncrementMovePriorityAbAttr, movePhase.pokemon, null, movePhase.move.getMove(), movePriority);
applyAbAttrs(IncrementMovePriorityAbAttr, movePhase.pokemon, null, false, movePhase.move.getMove(), movePriority);
const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value);
if (lowerPriorityPhase)
this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase);

File diff suppressed because it is too large Load Diff

View File

@ -68,25 +68,25 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25);
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < threshold.value && pokemon.summonData.battleStats[battleStat] < 6;
};
case BerryType.LANSAT:
return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
};
case BerryType.STARF:
return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25;
};
case BerryType.LEPPA:
return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return !!pokemon.getMoveset().find(m => !m.getPpRatio());
};
}
@ -102,7 +102,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData)
pokemon.battleData.berriesEaten.push(berryType);
const hpHealed = new Utils.NumberHolder(Math.floor(pokemon.getMaxHp() / 4));
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, hpHealed);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed);
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
hpHealed.value, getPokemonMessage(pokemon, `'s ${getBerryName(berryType)}\nrestored its HP!`), true));
};
@ -128,7 +128,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
pokemon.battleData.berriesEaten.push(berryType);
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
const statLevels = new Utils.NumberHolder(1);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ battleStat ], statLevels.value));
};
case BerryType.LANSAT:
@ -142,7 +142,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData)
pokemon.battleData.berriesEaten.push(berryType);
const statLevels = new Utils.NumberHolder(2);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ BattleStat.RAND ], statLevels.value));
};
case BerryType.LEPPA:

View File

@ -325,7 +325,7 @@ export default class Move implements Localizable {
case MoveFlags.IGNORE_ABILITIES:
if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) {
const abilityEffectsIgnored = new Utils.BooleanHolder(false);
applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, this);
applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, false, this);
if (abilityEffectsIgnored.value)
return true;
}
@ -965,7 +965,7 @@ export class MultiHitAttr extends MoveAttr {
{
const rand = user.randSeedInt(16);
const hitValue = new Utils.IntegerHolder(rand);
applyAbAttrs(MaxMultiHitAbAttr, user, null, hitValue);
applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue);
if (hitValue.value >= 10)
hitTimes = 2;
else if (hitValue.value >= 4)
@ -990,7 +990,7 @@ export class MultiHitAttr extends MoveAttr {
{
const rand = user.randSeedInt(90);
const hitValue = new Utils.IntegerHolder(rand);
applyAbAttrs(MaxMultiHitAbAttr, user, null, hitValue);
applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue);
if (hitValue.value >= 81)
hitTimes = 1;
else if (hitValue.value >= 73)

View File

@ -54,7 +54,7 @@ export class Terrain {
case TerrainType.PSYCHIC:
if (!move.getAttrs(ProtectAttr).length) {
const priority = new Utils.IntegerHolder(move.priority);
applyAbAttrs(IncrementMovePriorityAbAttr, user, null, move, priority);
applyAbAttrs(IncrementMovePriorityAbAttr, user, null, false, move, priority);
return priority.value > 0 && user.getOpponents().filter(o => targets.includes(o.getBattlerIndex())).length > 0;
}
}

View File

@ -564,7 +564,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
break;
}
}
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, statLevel);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, false, statLevel);
if (move)
applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, opponent, move, statLevel);
}
@ -871,7 +871,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
getWeight(): number {
const weight = new Utils.NumberHolder(this.species.weight);
// This will trigger the ability overlay so only call this function when necessary
applyAbAttrs(WeightMultiplierAbAttr, this, null, weight);
applyAbAttrs(WeightMultiplierAbAttr, this, null, false, weight);
return weight.value;
}
@ -897,9 +897,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.getMove().type, source));
const cancelled = new Utils.BooleanHolder(false);
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true);
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
if (!cancelled.value)
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true);
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;
}
@ -911,7 +911,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let multiplier = types.map(defType => {
if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false);
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, moveType, defType);
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, false, moveType, defType);
if (ignoreImmunity.value)
return 1;
}
@ -1265,6 +1265,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1];
}
/**
* Apply the results of a move to this pokemon
* @param {Pokemon} source The pokemon using the move
* @param {PokemonMove} battlerMove The move being used
* @returns {HitResult} The result of the attack
*/
apply(source: Pokemon, battlerMove: PokemonMove): HitResult {
let result: HitResult;
const move = battlerMove.getMove();
@ -1279,8 +1285,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1);
applyMoveAttrs(VariableMoveTypeAttr, source, this, move, variableType);
// 2nd argument is for MoveTypeChangePowerMultiplierAbAttr
applyAbAttrs(VariableMoveTypeAbAttr, source, null, variableType, typeChangeMovePowerMultiplier);
applyPreAttackAbAttrs(MoveTypeChangeAttr, source, this, battlerMove, variableType, typeChangeMovePowerMultiplier);
applyAbAttrs(VariableMoveTypeAbAttr, source, null, false, variableType, typeChangeMovePowerMultiplier);
applyPreAttackAbAttrs(MoveTypeChangeAttr, source, this, battlerMove, false, variableType, typeChangeMovePowerMultiplier);
const type = variableType.value as Type;
const types = this.getTypes(true, true);
@ -1303,18 +1309,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const sourceTeraType = source.getTeraType();
if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === type && power.value < 60 && move.priority <= 0 && !move.getAttrs(MultiHitAttr).length && !this.scene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id))
power.value = 60;
applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, this, battlerMove, power);
this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, battlerMove, power));
applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, this, battlerMove, false, power);
this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, battlerMove, false, power));
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, battlerMove, cancelled, power);
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, battlerMove, cancelled, false, power);
power.value *= typeChangeMovePowerMultiplier.value;
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, false, typeMultiplier);
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, false, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, false, typeMultiplier));
}
if (cancelled.value)
@ -1349,7 +1355,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
const bonusCrit = new Utils.BooleanHolder(false);
if (applyAbAttrs(BonusCritAbAttr, source, null, bonusCrit)) {
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) {
if (bonusCrit.value)
critLevel.value += 1;
}
@ -1359,7 +1365,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance));
if (isCritical) {
const blockCrit = new Utils.BooleanHolder(false);
applyAbAttrs(BlockCritAbAttr, this, null, blockCrit);
applyAbAttrs(BlockCritAbAttr, this, null, false, blockCrit);
if (blockCrit.value)
isCritical = false;
}
@ -1367,7 +1373,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, null, isCritical));
const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical));
const criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1);
applyAbAttrs(MultCritAbAttr, source, null, criticalMultiplier);
applyAbAttrs(MultCritAbAttr, source, null, false, criticalMultiplier);
const screenMultiplier = new Utils.NumberHolder(1);
if (!isCritical) {
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, move.category, this.scene.currentBattle.double, screenMultiplier);
@ -1381,7 +1387,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === type)
stabMultiplier.value += 0.5;
applyAbAttrs(StabBoostAbAttr, source, null, stabMultiplier);
applyAbAttrs(StabBoostAbAttr, source, null, false, stabMultiplier);
if (sourceTeraType !== Type.UNKNOWN && matchesSourceType)
stabMultiplier.value = Math.min(stabMultiplier.value + 0.5, 2.25);
@ -1393,7 +1399,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value);
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) {
const burnDamageReductionCancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled);
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled, false);
if (!burnDamageReductionCancelled.value)
damage.value = Math.floor(damage.value / 2);
}
@ -1450,7 +1456,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (damage.value) {
if (this.getHpRatio() === 1)
applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, damage);
applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, false, damage);
else if (!this.isPlayer() && damage.value >= this.hp)
this.scene.applyModifiers(EnemyEndureChanceModifier, false, this);
@ -1496,10 +1502,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
break;
case MoveCategory.STATUS:
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, false, typeMultiplier);
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, false, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, false, typeMultiplier));
}
if (!typeMultiplier.value)
this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name }));
@ -1931,7 +1937,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (effect === StatusEffect.SLEEP) {
statusCureTurn = new Utils.IntegerHolder(this.randSeedIntRange(2, 4));
applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, effect, statusCureTurn);
applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, false, effect, statusCureTurn);
this.setFrameRate(4);
@ -2803,7 +2809,7 @@ export class EnemyPokemon extends Pokemon {
const move = pokemonMove.getMove();
const variableType = new Utils.IntegerHolder(move.type);
applyAbAttrs(VariableMoveTypeAbAttr, this, null, variableType);
applyAbAttrs(VariableMoveTypeAbAttr, this, null, false, variableType);
const moveType = variableType.value as Type;
let moveScore = moveScores[m];

View File

@ -696,7 +696,7 @@ export class EncounterPhase extends BattlePhase {
if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS)
battle.enemyParty[e].ivs = new Array(6).fill(31);
this.scene.getParty().slice(0, !battle.double ? 1 : 2).reverse().forEach(playerPokemon => {
applyAbAttrs(SyncEncounterNatureAbAttr, playerPokemon, null, battle.enemyParty[e]);
applyAbAttrs(SyncEncounterNatureAbAttr, playerPokemon, null, false, battle.enemyParty[e]);
});
}
}
@ -1967,8 +1967,8 @@ export class TurnStartPhase extends FieldPhase {
const aPriority = new Utils.IntegerHolder(aMove.priority);
const bPriority = new Utils.IntegerHolder(bMove.priority);
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority);
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority);
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, false, aMove, aPriority);
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, false, bMove, bPriority);
if (aPriority.value !== bPriority.value)
return aPriority.value < bPriority.value ? 1 : -1;
@ -2211,7 +2211,7 @@ export class MovePhase extends BattlePhase {
? new Utils.IntegerHolder(this.targets[0])
: null;
if (moveTarget) {
this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget));
this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, moveTarget));
this.targets[0] = moveTarget.value;
}
@ -2566,8 +2566,8 @@ export class MoveEffectPhase extends PokemonPhase {
const userAccuracyLevel = new Utils.IntegerHolder(user.summonData.battleStats[BattleStat.ACC]);
const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, user, null, targetEvasionLevel);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, false, userAccuracyLevel);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, user, null, false, targetEvasionLevel);
applyMoveAttrs(IgnoreOpponentStatChangesAttr, user, target, this.move.getMove(), targetEvasionLevel);
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.player, TempBattleStat.ACC, userAccuracyLevel);
@ -2580,7 +2580,7 @@ export class MoveEffectPhase extends PokemonPhase {
: 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6));
}
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, user, BattleStat.ACC, accuracyMultiplier, this.move.getMove());
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, user, BattleStat.ACC, accuracyMultiplier, false, this.move.getMove());
const evasionMultiplier = new Utils.NumberHolder(1);
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this.getTarget(), BattleStat.EVA, evasionMultiplier);
@ -2730,7 +2730,7 @@ export class StatChangePhase extends PokemonPhase {
const levels = new Utils.IntegerHolder(this.levels);
if (!this.ignoreAbilities)
applyAbAttrs(StatChangeMultiplierAbAttr, pokemon, null, levels);
applyAbAttrs(StatChangeMultiplierAbAttr, pokemon, null, false, levels);
const battleStats = this.getPokemon().summonData.battleStats;
const relLevels = filteredStats.map(stat => (levels.value >= 1 ? Math.min(battleStats[stat] + levels.value, 6) : Math.max(battleStats[stat] + levels.value, -6)) - battleStats[stat]);
@ -2747,7 +2747,7 @@ export class StatChangePhase extends PokemonPhase {
if (levels.value > 0 && this.canBeCopied)
for (let opponent of pokemon.getOpponents())
applyAbAttrs(StatChangeCopyAbAttr, opponent, null, this.stats, levels.value);
applyAbAttrs(StatChangeCopyAbAttr, opponent, null, false, this.stats, levels.value);
applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget);
@ -4278,7 +4278,7 @@ export class AttemptRunPhase extends PokemonPhase {
const enemySpeed = enemyField.reduce((total: integer, enemyPokemon: Pokemon) => total + enemyPokemon.getStat(Stat.SPD), 0) / enemyField.length;
const escapeChance = new Utils.IntegerHolder((((playerPokemon.getStat(Stat.SPD) * 128) / enemySpeed) + (30 * this.scene.currentBattle.escapeAttempts++)) % 256);
applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, escapeChance);
applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance);
if (playerPokemon.randSeedInt(256) < escapeChance.value) {
this.scene.playSound('flee');