diff --git a/src/battle-phases.ts b/src/battle-phases.ts index 180eb5b7561..4bef981a4bc 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -25,7 +25,7 @@ import { Gender } from "./data/gender"; import { Weather, WeatherType, getRandomWeatherType, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagType, ArenaTrapTag, TrickRoomTag } from "./data/arena-tag"; -import { Abilities, CheckTrappedAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability"; +import { Abilities, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -1644,6 +1644,8 @@ class MoveEffectPhase extends PokemonPhase { const userAccuracyLevel = new Utils.IntegerHolder(this.getUserPokemon().summonData.battleStats[BattleStat.ACC]); const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this.getUserPokemon(), null, targetEvasionLevel); this.scene.applyModifiers(TempBattleStatBoosterModifier, this.player, TempBattleStat.ACC, userAccuracyLevel); const rand = Utils.randInt(100, 1); let accuracyMultiplier = 1; diff --git a/src/data/ability.ts b/src/data/ability.ts index 1d8d64fcce9..bcf2ff66a09 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -413,6 +413,18 @@ export class BattleStatMultiplierAbAttr extends AbAttr { } } +export class IgnoreOpponentStatChangesAbAttr extends AbAttr { + constructor() { + super(false); + } + + apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]) { + (args[0] as Utils.IntegerHolder).value = 0; + + return true; + } +} + export class PostSummonAbAttr extends AbAttr { applyPostSummon(pokemon: Pokemon, args: any[]) { return false; @@ -1486,7 +1498,8 @@ export function initAbilities() { new Ability(Abilities.TANGLED_FEET, "Tangled Feet (N)", "Raises Evasiveness if the Pokémon is confused.", 4), new Ability(Abilities.TECHNICIAN, "Technician (N)", "Powers up the Pokémon's weaker moves.", 4), new Ability(Abilities.TINTED_LENS, "Tinted Lens (N)", "Powers up \"not very effective\" moves.", 4), - new Ability(Abilities.UNAWARE, "Unaware (N)", "Ignores any stat changes in the Pokémon.", 4), + new Ability(Abilities.UNAWARE, "Unaware", "Ignores any stat changes in the Pokémon.", 4) + .attr(IgnoreOpponentStatChangesAbAttr), new Ability(Abilities.UNBURDEN, "Unburden (N)", "Raises Speed if a held item is used.", 4), new Ability(Abilities.ANALYTIC, "Analytic (N)", "Boosts move power when the Pokémon moves last.", 5), new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the Pokémon from Defense-lowering attacks.", 5) diff --git a/src/data/move.ts b/src/data/move.ts index f489f94a6b4..ec0a41586b2 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -214,16 +214,16 @@ export class AttackMove extends Move { attackScore = Math.pow(effectiveness - 1, 2) * effectiveness < 1 ? -2 : 2; if (attackScore) { if (this.category === MoveCategory.PHYSICAL) { - if (user.getBattleStat(Stat.ATK) > user.getBattleStat(Stat.SPATK)) { - const statRatio = user.getBattleStat(Stat.SPATK) / user.getBattleStat(Stat.ATK); + if (user.getBattleStat(Stat.ATK, target) > user.getBattleStat(Stat.SPATK, target)) { + const statRatio = user.getBattleStat(Stat.SPATK, target) / user.getBattleStat(Stat.ATK, target); if (statRatio <= 0.75) attackScore *= 2; else if (statRatio <= 0.875) attackScore *= 1.5; } } else { - if (user.getBattleStat(Stat.SPATK) > user.getBattleStat(Stat.ATK)) { - const statRatio = user.getBattleStat(Stat.ATK) / user.getBattleStat(Stat.SPATK); + if (user.getBattleStat(Stat.SPATK, target) > user.getBattleStat(Stat.ATK, target)) { + const statRatio = user.getBattleStat(Stat.ATK, target) / user.getBattleStat(Stat.SPATK, target); if (statRatio <= 0.75) attackScore *= 2; else if (statRatio <= 0.875) diff --git a/src/pokemon.ts b/src/pokemon.ts index 117a345f64c..9d6a0d36d0a 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -22,7 +22,7 @@ import { WeatherType } from './data/weather'; import { TempBattleStat } from './data/temp-battle-stat'; import { ArenaTagType, WeakenMoveTypeTag } from './data/arena-tag'; import { Biome } from './data/biome'; -import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, abilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from './data/ability'; +import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, IgnoreOpponentStatChangesAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, abilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from './data/ability'; import PokemonData from './system/pokemon-data'; import { BattlerIndex } from './battle'; import { Mode } from './ui/ui'; @@ -392,11 +392,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.stats[stat]; } - getBattleStat(stat: Stat): integer { + getBattleStat(stat: Stat, opponent?: Pokemon): integer { if (stat === Stat.HP) return this.getStat(Stat.HP); const battleStat = (stat - 1) as BattleStat; const statLevel = new Utils.IntegerHolder(this.summonData.battleStats[battleStat]); + if (opponent) + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, statLevel); if (this.isPlayer()) this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel); const statValue = new Utils.NumberHolder(this.getStat(stat)); @@ -755,8 +757,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const critChance = Math.ceil(16 / Math.pow(2, critLevel.value)); isCritical = !source.getTag(BattlerTagType.NO_CRIT) && !(this.getAbility().hasAttr(BlockCritAbAttr)) && (critChance === 1 || !Utils.randInt(critChance)); } - const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK); - const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF); + const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this); + const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source); const stabMultiplier = new Utils.IntegerHolder(source.species.type1 === move.type || (source.species.type2 !== null && source.species.type2 === move.type) ? 1.5 : 1); const criticalMultiplier = isCritical ? 2 : 1; const isTypeImmune = (typeMultiplier.value * weatherTypeMultiplier) === 0;