From 31050a5181e89c6db423a60cbd60579f4533e886 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 11 Apr 2024 09:24:03 -0400 Subject: [PATCH] Add passive secondary abilities for bosses --- src/battle-scene.ts | 3 +- src/data/ability.ts | 672 ++++++++++-------------------------- src/data/api.ts | 3 +- src/data/battler-tags.ts | 13 +- src/data/enums/abilities.ts | 313 +++++++++++++++++ src/data/move.ts | 13 +- src/data/pokemon-forms.ts | 2 +- src/data/pokemon-species.ts | 574 +++++++++++++++++++++++++++++- src/data/weather.ts | 4 +- src/field/pokemon.ts | 22 +- src/phases.ts | 23 +- src/ui/ability-bar.ts | 6 +- 12 files changed, 1127 insertions(+), 521 deletions(-) create mode 100644 src/data/enums/abilities.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 3090bbe1c8b..27166347039 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -19,7 +19,8 @@ import { } from "./data/move"; import { initMoves } from './data/move'; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; import AbilityBar from './ui/ability-bar'; -import { Abilities, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; +import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; +import { Abilities } from "./data/enums/abilities"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; import { GameMode, GameModes, gameModes } from './game-mode'; import FieldSpritePipeline from './pipelines/field-sprite'; diff --git a/src/data/ability.ts b/src/data/ability.ts index 713a28d10d9..1d5dcb7581f 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -15,13 +15,14 @@ import { PokemonHeldItemModifier } from "../modifier/modifier"; import { Moves } from "./enums/moves"; import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; +import { Abilities } from "./enums/abilities"; export class Ability { public id: Abilities; public name: string; public description: string; public generation: integer; - public isPassive: boolean; + public isBypassFaint: boolean; public isIgnorable: boolean; public attrs: AbAttr[]; public conditions: AbAttrCondition[]; @@ -58,8 +59,8 @@ export class Ability { return !!this.getAttrs(attrType).length; } - passive(): Ability { - this.isPassive = true; + bypassFaint(): Ability { + this.isBypassFaint = true; return this; } @@ -75,7 +76,7 @@ export class Ability { } } -type AbAttrApplyFunc = (attr: TAttr) => boolean | Promise; +type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => boolean | Promise; type AbAttrCondition = (pokemon: Pokemon) => boolean; type PokemonAttackCondition = (user: Pokemon, target: Pokemon, move: Move) => boolean; @@ -89,11 +90,11 @@ export abstract class AbAttr { this.showAbility = showAbility; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { return null; } @@ -108,14 +109,14 @@ export abstract class AbAttr { } export class BlockRecoilDamageAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]) { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprotected it from recoil!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprotected it from recoil!`); } } @@ -124,7 +125,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const doubleChance = (args[0] as Utils.IntegerHolder); doubleChance.value = Math.max(doubleChance.value / 2, 1); return true; @@ -132,7 +133,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { } export class PostBattleInitAbAttr extends AbAttr { - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -146,7 +147,7 @@ export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { this.formFunc = formFunc; } - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -170,7 +171,7 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { this.selfTarget = !!selfTarget; } - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const statChangePhases: StatChangePhase[] = []; if (this.selfTarget) @@ -194,13 +195,13 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: PokemonMove) => boolean; export class PreDefendAbAttr extends AbAttr { - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (pokemon.getHpRatio() < 1 || (args[0] as Utils.NumberHolder).value < pokemon.hp) return false; @@ -209,19 +210,19 @@ export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { } export class BlockItemTheftAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]) { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents item theft!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents item theft!`); } } export class StabBoostAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((args[0] as Utils.NumberHolder).value > 1) { (args[0] as Utils.NumberHolder).value += 0.5; return true; @@ -242,7 +243,7 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.condition(pokemon, attacker, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; @@ -269,7 +270,7 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { this.condition = condition; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((move.getMove() instanceof AttackMove || move.getMove().getAttrs(StatusMoveTypeImmunityAttr).find(attr => (attr as StatusMoveTypeImmunityAttr).immuneType === this.immuneType)) && move.getMove().type === this.immuneType) { (args[0] as Utils.NumberHolder).value = 0; return true; @@ -288,15 +289,16 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { super(immuneType); } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { if (pokemon.getHpRatio() < 1) { const simulated = args.length > 1 && args[1]; if (!simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); } } return true; @@ -317,8 +319,8 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; @@ -342,8 +344,8 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { this.turnCount = turnCount; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; @@ -361,7 +363,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { super(null, condition); } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type) < 2) { cancelled.value = true; (args[0] as Utils.NumberHolder).value = 0; @@ -371,13 +373,13 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, ` avoided damage\nwith ${pokemon.getAbility().name}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, ` avoided damage\nwith ${abilityName}!`); } } export class PostDefendAbAttr extends AbAttr { - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } @@ -391,7 +393,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { this.immuneCondition = immuneCondition; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.immuneCondition(pokemon, attacker, move)) { cancelled.value = true; return true; @@ -400,7 +402,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { return `It doesn\'t affect ${pokemon.name}!`; } } @@ -420,7 +422,7 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (this.condition(pokemon, attacker, move.getMove())) { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, [ this.stat ], this.levels)); return true; @@ -431,7 +433,7 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { const type = move.getMove().type; const pokemonTypes = pokemon.getTypes(true); @@ -444,8 +446,8 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nmade it the ${Utils.toReadableString(Type[pokemon.getTypes(true)[0]])} type!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nmade it the ${Utils.toReadableString(Type[pokemon.getTypes(true)[0]])} type!`); } } @@ -458,7 +460,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) return pokemon.scene.arena.trySetTerrain(this.terrainType, true); @@ -477,7 +479,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { this.effects = effects; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true); @@ -500,7 +502,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) return attacker.addTag(this.tagType, this.turnCount, move.moveId, attacker.id); @@ -519,7 +521,7 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr { this.levels = levels; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); return true; @@ -539,7 +541,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); return true; @@ -548,8 +550,8 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nhurt its attacker!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nhurt its attacker!`); } } @@ -562,7 +564,7 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { this.weatherType = weatherType; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -571,20 +573,20 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { } export class PreAttackAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise { return false; } } export class VariableMovePowerAbAttr extends PreAttackAbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } } export class VariableMoveTypeAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { //const power = args[0] as Utils.IntegerHolder; return false; } @@ -602,7 +604,7 @@ export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr this.powerMultiplier = powerMultiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const type = (args[0] as Utils.IntegerHolder); if (type.value == this.matchType) { type.value = this.newType; @@ -624,7 +626,7 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { if (this.condition(pokemon, defender, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -652,7 +654,7 @@ export class LowHpMoveTypePowerBoostAbAttr extends MoveTypePowerBoostAbAttr { } export class FieldVariableMovePowerAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } @@ -668,7 +670,7 @@ export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { if (this.condition(pokemon, defender, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -696,7 +698,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - applyBattleStat(pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { + applyBattleStat(pokemon: Pokemon, passive: boolean, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { if (battleStat === this.battleStat) { statValue.value *= this.multiplier; return true; @@ -707,7 +709,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { } export class PostAttackAbAttr extends AbAttr { - applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } @@ -721,7 +723,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.condition = condition; } - applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move.getMove()))) { const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false)); @@ -756,7 +758,7 @@ export class PostAttackContactApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttack(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true); @@ -775,7 +777,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { this.condition = condition; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move.getMove()))) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false)); @@ -800,7 +802,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { } export class PostVictoryAbAttr extends AbAttr { - applyPostVictory(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -816,7 +818,7 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr { this.levels = levels; } - applyPostVictory(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const stat = typeof this.stat === 'function' ? this.stat(pokemon) : this.stat; @@ -827,7 +829,7 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr { } export class PostKnockOutAbAttr extends AbAttr { - applyPostKnockOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -843,7 +845,7 @@ export class PostKnockOutStatChangeAbAttr extends PostKnockOutAbAttr { this.levels = levels; } - applyPostKnockOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const stat = typeof this.stat === 'function' ? this.stat(pokemon) : this.stat; @@ -858,7 +860,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]) { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]) { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -866,7 +868,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr { } export class PostSummonAbAttr extends AbAttr { - applyPostSummon(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -880,7 +882,7 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr { this.messageFunc = messageFunc; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { pokemon.scene.queueMessage(this.messageFunc(pokemon)); return true; @@ -898,7 +900,7 @@ export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { this.turnCount = turnCount; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return pokemon.addTag(this.tagType, this.turnCount); } } @@ -918,7 +920,7 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr { this.selfTarget = !!selfTarget; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const statChangePhases: StatChangePhase[] = []; if (this.selfTarget) @@ -948,7 +950,7 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr { this.weatherType = weatherType; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -965,7 +967,7 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr { this.terrainType = terrainType; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -979,7 +981,7 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { this.formFunc = formFunc; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -993,7 +995,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const targets = pokemon.getOpponents(); let target: Pokemon; if (targets.length > 1) @@ -1025,13 +1027,13 @@ export class PreSwitchOutAbAttr extends AbAttr { super(true); } - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.status) { pokemon.resetStatus(); pokemon.updateInfo(); @@ -1043,7 +1045,7 @@ export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { } export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.getHpRatio() < 1 ) { const healAmount = Math.floor(pokemon.getMaxHp() * 0.33); pokemon.heal(healAmount); @@ -1056,7 +1058,7 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { } export class PreStatChangeAbAttr extends AbAttr { - applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1070,7 +1072,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { this.protectedStat = protectedStat; } - applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.protectedStat === undefined || stat === this.protectedStat) { cancelled.value = true; return true; @@ -1079,13 +1081,13 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); } } export class PreSetStatusAbAttr extends AbAttr { - applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1099,7 +1101,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { this.immuneEffects = immuneEffects; } - applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { cancelled.value = true; return true; @@ -1108,13 +1110,13 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); } } export class PreApplyBattlerTagAbAttr extends AbAttr { - applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1128,7 +1130,7 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { this.immuneTagType = immuneTagType; } - applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (tag.tagType === this.immuneTagType) { cancelled.value = true; return true; @@ -1137,27 +1139,27 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); } } export class BlockCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; return true; } } export class BlockNonDirectDamageAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } } export class BlockOneHitKOAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -1174,7 +1176,7 @@ export class IncrementMovePriorityAbAttr extends AbAttr { this.increaseAmount = increaseAmount; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.moveIncrementFunc(pokemon, args[0] as Move)) return false; @@ -1186,7 +1188,7 @@ export class IncrementMovePriorityAbAttr extends AbAttr { export class IgnoreContactAbAttr extends AbAttr { } export class PreWeatherEffectAbAttr extends AbAttr { - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1202,7 +1204,7 @@ export class BlockWeatherDamageAttr extends PreWeatherDamageAbAttr { this.weatherTypes = weatherTypes; } - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.weatherTypes.length || this.weatherTypes.indexOf(weather?.weatherType) > -1) cancelled.value = true; @@ -1219,7 +1221,7 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { this.affectsImmutable = affectsImmutable; } - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.affectsImmutable || weather.isImmutable()) { cancelled.value = true; return true; @@ -1239,7 +1241,7 @@ function getWeatherCondition(...weatherTypes: WeatherType[]): AbAttrCondition { } export class PostWeatherChangeAbAttr extends AbAttr { - applyPostWeatherChange(pokemon: Pokemon, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { return false; } } @@ -1257,7 +1259,7 @@ export class PostWeatherChangeAddBattlerTagAttr extends PostWeatherChangeAbAttr this.weatherTypes = weatherTypes; } - applyPostWeatherChange(pokemon: Pokemon, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { console.log(this.weatherTypes.find(w => weather === w), WeatherType[weather]); if (!this.weatherTypes.find(w => weather === w)) return false; @@ -1275,7 +1277,7 @@ export class PostWeatherLapseAbAttr extends AbAttr { this.weatherTypes = weatherTypes; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean | Promise { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean | Promise { return false; } @@ -1293,11 +1295,12 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { this.healFactor = healFactor; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); return true; } @@ -1314,10 +1317,11 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { this.damageFactor = damageFactor; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; - scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby its ${pokemon.getAbility().name}!`)); + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby its ${abilityName}!`)); pokemon.damageAndUpdate(Math.ceil(pokemon.getMaxHp() / (16 / this.damageFactor)), HitResult.OTHER); return true; } @@ -1327,7 +1331,7 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { } export class PostTerrainChangeAbAttr extends AbAttr { - applyPostTerrainChange(pokemon: Pokemon, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { return false; } } @@ -1345,7 +1349,7 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr this.terrainTypes = terrainTypes; } - applyPostTerrainChange(pokemon: Pokemon, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { if (!this.terrainTypes.find(t => terrain === terrain)) return false; @@ -1361,13 +1365,13 @@ function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition { } export class PostTurnAbAttr extends AbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (pokemon.status) { pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status?.effect))); @@ -1393,18 +1397,19 @@ export class PostTurnStatChangeAbAttr extends PostTurnAbAttr { this.levels = levels; } - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } export class PostTurnHealAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); return true; } @@ -1421,7 +1426,7 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { this.formFunc = formFunc; } - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -1443,7 +1448,7 @@ export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr { this.weatherType = weatherType; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -1460,7 +1465,7 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { this.terrainType = terrainType; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -1474,7 +1479,7 @@ export class StatChangeMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value *= this.multiplier; return true; @@ -1486,7 +1491,7 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -1494,7 +1499,7 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { } export class DoubleBerryEffectAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= 2; return true; @@ -1502,7 +1507,7 @@ export class DoubleBerryEffectAbAttr extends AbAttr { } export class PreventBerryUseAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -1510,7 +1515,7 @@ export class PreventBerryUseAbAttr extends AbAttr { } export class RunSuccessAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 256; return true; @@ -1522,24 +1527,24 @@ export class CheckTrappedAbAttr extends AbAttr { super(false); } - applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } export class ArenaTrapAbAttr extends CheckTrappedAbAttr { - applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean { trapped.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `\'s ${pokemon.getAbility().name}\nprevents switching!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `\'s ${abilityName}\nprevents switching!`); } } export class MaxMultiHitAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -1551,13 +1556,13 @@ export class PostBattleAbAttr extends AbAttr { super(true); } - applyPostBattle(pokemon: Pokemon, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return false; } } export class PostBattleLootAbAttr extends PostBattleAbAttr { - applyPostBattle(pokemon: Pokemon, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot; if (postBattleLoot.length) { const randItem = Utils.randSeedItem(postBattleLoot); @@ -1573,7 +1578,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { } export class PostFaintAbAttr extends AbAttr { - applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { return false; } } @@ -1587,7 +1592,7 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { this.damageRatio = damageRatio; } - applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); return true; @@ -1596,13 +1601,13 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name} hurt\nits attacker!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName} hurt\nits attacker!`); } } export class RedirectMoveAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.canRedirect(args[0] as Moves)) { const target = args[1] as Utils.IntegerHolder; const newTarget = pokemon.getBattlerIndex(); @@ -1643,7 +1648,7 @@ export class ReduceStatusEffectDurationAbAttr extends AbAttr { this.statusEffect = statusEffect; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (args[0] === this.statusEffect) { (args[1] as Utils.IntegerHolder).value = Math.floor((args[1] as Utils.IntegerHolder).value / 2); return true; @@ -1672,18 +1677,20 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr { this.levels = levels; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } +export class IncreasePpAbAttr extends AbAttr { } + export class ReduceBerryUseThresholdAbAttr extends AbAttr { constructor() { - super(true); + super(); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const hpRatio = pokemon.getHpRatio(); if (args[0].value < hpRatio) { @@ -1699,12 +1706,12 @@ export class WeightMultiplierAbAttr extends AbAttr { private multiplier: integer; constructor(multiplier: integer) { - super(true); + super(); this.multiplier = multiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= this.multiplier; return true; @@ -1716,7 +1723,7 @@ export class SyncEncounterNatureAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Pokemon).setNature(pokemon.getNature()); return true; @@ -1728,7 +1735,7 @@ export class MoveAbilityBypassAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -1741,17 +1748,24 @@ export class ProtectAbilityAbAttr extends AbAttr { } function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, - pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false): Promise { + pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { return new Promise(resolve => { - if (!pokemon.canApplyAbility()) - return resolve(); + if (!pokemon.canApplyAbility(passive)) { + if (!passive) + return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve()); + else + return resolve(); + } - const ability = pokemon.getAbility(); + const ability = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()); const attrs = ability.getAttrs(attrType) as TAttr[]; const clearSpliceQueueAndResolve = () => { pokemon.scene.clearPhaseQueueSplice(); - resolve(); + if (!passive) + return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve()); + else + return resolve(); }; const applyNextAbAttr = () => { if (attrs.length) @@ -1766,12 +1780,12 @@ function applyAbAttrsInternal(attrType: { new(...args: any const onApplySuccess = () => { if (attr.showAbility && !quiet) { if (showAbilityInstant) - pokemon.scene.abilityBar.showAbility(pokemon); + pokemon.scene.abilityBar.showAbility(pokemon, passive); else - queueShowAbility(pokemon); + queueShowAbility(pokemon, passive); } if (!quiet) { - const message = attr.getTriggerMessage(pokemon, args); + const message = attr.getTriggerMessage(pokemon, (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name, args); if (message) { if (isAsync) pokemon.scene.ui.showText(message, null, () => pokemon.scene.ui.showText(null, 0), null, true); @@ -1780,7 +1794,7 @@ function applyAbAttrsInternal(attrType: { new(...args: any } } }; - const result = applyFunc(attr); + const result = applyFunc(attr, passive); if (result instanceof Promise) { result.then(success => { if (success) @@ -1798,114 +1812,114 @@ function applyAbAttrsInternal(attrType: { new(...args: any } export function applyAbAttrs(attrType: { new(...args: any[]): AbAttr }, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.apply(pokemon, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, cancelled, args), args); } export function applyPostBattleInitAbAttrs(attrType: { new(...args: any[]): PostBattleInitAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostBattleInit(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, args), args); } export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreDefend(pokemon, attacker, move, cancelled, args), args, false, false, simulated); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, false, simulated); } export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostDefend(pokemon, attacker, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args); } export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]): BattleStatMultiplierAbAttr }, pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyBattleStat(pokemon, battleStat, statValue, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyBattleStat(pokemon, passive, battleStat, statValue, args), args); } export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr }, pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreAttack(pokemon, defender, move, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args); } export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr }, pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostAttack(pokemon, defender, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args); } export function applyPostKnockOutAbAttrs(attrType: { new(...args: any[]): PostKnockOutAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostKnockOut(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, args), args); } export function applyPostVictoryAbAttrs(attrType: { new(...args: any[]): PostVictoryAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostVictory(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, args), args); } export function applyPostSummonAbAttrs(attrType: { new(...args: any[]): PostSummonAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostSummon(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args); } export function applyPreSwitchOutAbAttrs(attrType: { new(...args: any[]): PreSwitchOutAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreSwitchOut(pokemon, args), args, false, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, false, true); } export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr }, pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreStatChange(pokemon, stat, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, stat, cancelled, args), args); } export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr }, pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreSetStatus(pokemon, effect, cancelled, args), args, false, false, !simulated); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, !simulated); } export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr }, pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreApplyBattlerTag(pokemon, tag, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, tag, cancelled, args), args); } export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): PreWeatherEffectAbAttr }, pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreWeatherEffect(pokemon, weather, cancelled, args), args, false, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, weather, cancelled, args), args, false, true); } export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostTurn(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, args), args); } export function applyPostWeatherChangeAbAttrs(attrType: { new(...args: any[]): PostWeatherChangeAbAttr }, pokemon: Pokemon, weather: WeatherType, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostWeatherChange(pokemon, weather, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, weather, args), args); } export function applyPostWeatherLapseAbAttrs(attrType: { new(...args: any[]): PostWeatherLapseAbAttr }, pokemon: Pokemon, weather: Weather, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostWeatherLapse(pokemon, weather, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, weather, args), args); } export function applyPostTerrainChangeAbAttrs(attrType: { new(...args: any[]): PostTerrainChangeAbAttr }, pokemon: Pokemon, terrain: TerrainType, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostTerrainChange(pokemon, terrain, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, terrain, args), args); } export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckTrappedAbAttr }, pokemon: Pokemon, trapped: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyCheckTrapped(pokemon, trapped, args), args, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, args), args, true); } export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, args), args); } export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostFaint(pokemon, attacker, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args); } function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { @@ -1913,325 +1927,11 @@ function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { return !condition || condition(pokemon); } -function queueShowAbility(pokemon: Pokemon): void { - pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id)); +function queueShowAbility(pokemon: Pokemon, passive: boolean): void { + pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, passive)); pokemon.scene.clearPhaseQueueSplice(); } -export enum Abilities { - NONE, - STENCH, - DRIZZLE, - SPEED_BOOST, - BATTLE_ARMOR, - STURDY, - DAMP, - LIMBER, - SAND_VEIL, - STATIC, - VOLT_ABSORB, - WATER_ABSORB, - OBLIVIOUS, - CLOUD_NINE, - COMPOUND_EYES, - INSOMNIA, - COLOR_CHANGE, - IMMUNITY, - FLASH_FIRE, - SHIELD_DUST, - OWN_TEMPO, - SUCTION_CUPS, - INTIMIDATE, - SHADOW_TAG, - ROUGH_SKIN, - WONDER_GUARD, - LEVITATE, - EFFECT_SPORE, - SYNCHRONIZE, - CLEAR_BODY, - NATURAL_CURE, - LIGHTNING_ROD, - SERENE_GRACE, - SWIFT_SWIM, - CHLOROPHYLL, - ILLUMINATE, - TRACE, - HUGE_POWER, - POISON_POINT, - INNER_FOCUS, - MAGMA_ARMOR, - WATER_VEIL, - MAGNET_PULL, - SOUNDPROOF, - RAIN_DISH, - SAND_STREAM, - PRESSURE, - THICK_FAT, - EARLY_BIRD, - FLAME_BODY, - RUN_AWAY, - KEEN_EYE, - HYPER_CUTTER, - PICKUP, - TRUANT, - HUSTLE, - CUTE_CHARM, - PLUS, - MINUS, - FORECAST, - STICKY_HOLD, - SHED_SKIN, - GUTS, - MARVEL_SCALE, - LIQUID_OOZE, - OVERGROW, - BLAZE, - TORRENT, - SWARM, - ROCK_HEAD, - DROUGHT, - ARENA_TRAP, - VITAL_SPIRIT, - WHITE_SMOKE, - PURE_POWER, - SHELL_ARMOR, - AIR_LOCK, - TANGLED_FEET, - MOTOR_DRIVE, - RIVALRY, - STEADFAST, - SNOW_CLOAK, - GLUTTONY, - ANGER_POINT, - UNBURDEN, - HEATPROOF, - SIMPLE, - DRY_SKIN, - DOWNLOAD, - IRON_FIST, - POISON_HEAL, - ADAPTABILITY, - SKILL_LINK, - HYDRATION, - SOLAR_POWER, - QUICK_FEET, - NORMALIZE, - SNIPER, - MAGIC_GUARD, - NO_GUARD, - STALL, - TECHNICIAN, - LEAF_GUARD, - KLUTZ, - MOLD_BREAKER, - SUPER_LUCK, - AFTERMATH, - ANTICIPATION, - FOREWARN, - UNAWARE, - TINTED_LENS, - FILTER, - SLOW_START, - SCRAPPY, - STORM_DRAIN, - ICE_BODY, - SOLID_ROCK, - SNOW_WARNING, - HONEY_GATHER, - FRISK, - RECKLESS, - MULTITYPE, - FLOWER_GIFT, - BAD_DREAMS, - PICKPOCKET, - SHEER_FORCE, - CONTRARY, - UNNERVE, - DEFIANT, - DEFEATIST, - CURSED_BODY, - HEALER, - FRIEND_GUARD, - WEAK_ARMOR, - HEAVY_METAL, - LIGHT_METAL, - MULTISCALE, - TOXIC_BOOST, - FLARE_BOOST, - HARVEST, - TELEPATHY, - MOODY, - OVERCOAT, - POISON_TOUCH, - REGENERATOR, - BIG_PECKS, - SAND_RUSH, - WONDER_SKIN, - ANALYTIC, - ILLUSION, - IMPOSTER, - INFILTRATOR, - MUMMY, - MOXIE, - JUSTIFIED, - RATTLED, - MAGIC_BOUNCE, - SAP_SIPPER, - PRANKSTER, - SAND_FORCE, - IRON_BARBS, - ZEN_MODE, - VICTORY_STAR, - TURBOBLAZE, - TERAVOLT, - AROMA_VEIL, - FLOWER_VEIL, - CHEEK_POUCH, - PROTEAN, - FUR_COAT, - MAGICIAN, - BULLETPROOF, - COMPETITIVE, - STRONG_JAW, - REFRIGERATE, - SWEET_VEIL, - STANCE_CHANGE, - GALE_WINGS, - MEGA_LAUNCHER, - GRASS_PELT, - SYMBIOSIS, - TOUGH_CLAWS, - PIXILATE, - GOOEY, - AERILATE, - PARENTAL_BOND, - DARK_AURA, - FAIRY_AURA, - AURA_BREAK, - PRIMORDIAL_SEA, - DESOLATE_LAND, - DELTA_STREAM, - STAMINA, - WIMP_OUT, - EMERGENCY_EXIT, - WATER_COMPACTION, - MERCILESS, - SHIELDS_DOWN, - STAKEOUT, - WATER_BUBBLE, - STEELWORKER, - BERSERK, - SLUSH_RUSH, - LONG_REACH, - LIQUID_VOICE, - TRIAGE, - GALVANIZE, - SURGE_SURFER, - SCHOOLING, - DISGUISE, - BATTLE_BOND, - POWER_CONSTRUCT, - CORROSION, - COMATOSE, - QUEENLY_MAJESTY, - INNARDS_OUT, - DANCER, - BATTERY, - FLUFFY, - DAZZLING, - SOUL_HEART, - TANGLING_HAIR, - RECEIVER, - POWER_OF_ALCHEMY, - BEAST_BOOST, - RKS_SYSTEM, - ELECTRIC_SURGE, - PSYCHIC_SURGE, - MISTY_SURGE, - GRASSY_SURGE, - FULL_METAL_BODY, - SHADOW_SHIELD, - PRISM_ARMOR, - NEUROFORCE, - INTREPID_SWORD, - DAUNTLESS_SHIELD, - LIBERO, - BALL_FETCH, - COTTON_DOWN, - PROPELLER_TAIL, - MIRROR_ARMOR, - GULP_MISSILE, - STALWART, - STEAM_ENGINE, - PUNK_ROCK, - SAND_SPIT, - ICE_SCALES, - RIPEN, - ICE_FACE, - POWER_SPOT, - MIMICRY, - SCREEN_CLEANER, - STEELY_SPIRIT, - PERISH_BODY, - WANDERING_SPIRIT, - GORILLA_TACTICS, - NEUTRALIZING_GAS, - PASTEL_VEIL, - HUNGER_SWITCH, - QUICK_DRAW, - UNSEEN_FIST, - CURIOUS_MEDICINE, - TRANSISTOR, - DRAGONS_MAW, - CHILLING_NEIGH, - GRIM_NEIGH, - AS_ONE_GLASTRIER, - AS_ONE_SPECTRIER, - LINGERING_AROMA, - SEED_SOWER, - THERMAL_EXCHANGE, - ANGER_SHELL, - PURIFYING_SALT, - WELL_BAKED_BODY, - WIND_RIDER, - GUARD_DOG, - ROCKY_PAYLOAD, - WIND_POWER, - ZERO_TO_HERO, - COMMANDER, - ELECTROMORPHOSIS, - PROTOSYNTHESIS, - QUARK_DRIVE, - GOOD_AS_GOLD, - VESSEL_OF_RUIN, - SWORD_OF_RUIN, - TABLETS_OF_RUIN, - BEADS_OF_RUIN, - ORICHALCUM_PULSE, - HADRON_ENGINE, - OPPORTUNIST, - CUD_CHEW, - SHARPNESS, - SUPREME_OVERLORD, - COSTAR, - TOXIC_DEBRIS, - ARMOR_TAIL, - EARTH_EATER, - MYCELIUM_MIGHT, - MINDS_EYE, - SUPERSWEET_SYRUP, - HOSPITALITY, - TOXIC_CHAIN, - EMBODY_ASPECT_TEAL, - EMBODY_ASPECT_WELLSPRING, - EMBODY_ASPECT_HEARTHFLAME, - EMBODY_ASPECT_CORNERSTONE, - TERA_SHIFT, - TERA_SHELL, - TERAFORM_ZERO, - POISON_PUPPETEER -}; - export const allAbilities = [ new Ability(Abilities.NONE, "-", "", 3) ]; export function initAbilities() { @@ -2299,7 +1999,7 @@ export function initAbilities() { new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3) .attr(PostDefendContactDamageAbAttr, 8) .ignorable() - .passive(), + .bypassFaint(), new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3) .attr(NonSuperEffectiveImmunityAbAttr) .attr(ProtectAbilityAbAttr) @@ -2388,7 +2088,7 @@ export function initAbilities() { new Ability(Abilities.FORECAST, "Forecast (N)", "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", 3), new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", 3) .attr(BlockItemTheftAbAttr) - .passive() + .bypassFaint() .ignorable(), new Ability(Abilities.SHED_SKIN, "Shed Skin", "The Pokémon may heal its own status conditions by shedding its skin.", 3) .conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr), @@ -2493,7 +2193,7 @@ export function initAbilities() { new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4), new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4) .attr(PostFaintContactDamageAbAttr,4) - .passive(), + .bypassFaint(), new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4), new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4), new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4) @@ -2613,7 +2313,7 @@ export function initAbilities() { .condition(getWeatherCondition(WeatherType.SANDSTORM)), new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5) .attr(PostDefendContactDamageAbAttr, 8) - .passive(), + .bypassFaint(), new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5) .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) diff --git a/src/data/api.ts b/src/data/api.ts index aee0ece9581..9d342dab288 100644 --- a/src/data/api.ts +++ b/src/data/api.ts @@ -5,7 +5,8 @@ import fs from 'vite-plugin-fs/browser'; import PokemonSpecies, { PokemonForm, SpeciesFormKey, allSpecies } from './pokemon-species'; import { GrowthRate } from './exp'; import { Type } from './type'; -import { Abilities, allAbilities } from './ability'; +import { allAbilities } from './ability'; +import { Abilities } from "./enums/abilities"; import { Species } from './enums/species'; import { pokemonFormLevelMoves } from './pokemon-level-moves'; import { tmSpecies } from './tms'; diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index f50ad87d61b..25567b83c27 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -8,11 +8,13 @@ import * as Utils from "../utils"; import { Moves } from "./enums/moves"; import { ChargeAttr, MoveFlags, allMoves } from "./move"; import { Type } from "./type"; -import { Abilities, BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs } from "./ability"; +import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs } from "./ability"; +import { Abilities } from "./enums/abilities"; import { BattlerTagType } from "./enums/battler-tag-type"; import { TerrainType } from "./terrain"; import { WeatherType } from "./weather"; import { BattleStat } from "./battle-stat"; +import { allAbilities } from "./ability" export enum BattlerTagLapseType { FAINT, @@ -797,14 +799,15 @@ export class TruantTag extends AbilityBattlerTag { } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (pokemon.getAbility().id !== Abilities.TRUANT) + if ((!pokemon.canApplyAbility() || pokemon.getAbility().id !== Abilities.TRUANT) && (!pokemon.canApplyAbility(true) || pokemon.getPassiveAbility().id !== Abilities.TRUANT)) return super.lapse(pokemon, lapseType); + const passive = pokemon.getAbility().id !== Abilities.TRUANT; const lastMove = pokemon.getLastXMoves().find(() => true); if (lastMove && lastMove.move !== Moves.NONE) { (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); - pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id)); + pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, passive)); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nloafing around!')); } @@ -824,7 +827,7 @@ export class SlowStartTag extends AbilityBattlerTag { } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (pokemon.getAbility().id !== this.ability) + if (pokemon.getAbility().id !== this.ability && (pokemon.canApplyAbility(true) && pokemon.getPassiveAbility().id !== this.ability)) this.turnCount = 1; return super.lapse(pokemon, lapseType); @@ -875,7 +878,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag { onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - pokemon.scene.queueMessage(`The effects of ${getPokemonMessage(pokemon, `'s\n${pokemon.getAbility().name} wore off!`)}`); + pokemon.scene.queueMessage(`The effects of ${getPokemonMessage(pokemon, `'s\n${allAbilities[this.ability].name} wore off!`)}`); } } diff --git a/src/data/enums/abilities.ts b/src/data/enums/abilities.ts new file mode 100644 index 00000000000..4be87d8181b --- /dev/null +++ b/src/data/enums/abilities.ts @@ -0,0 +1,313 @@ +export enum Abilities { + NONE, + STENCH, + DRIZZLE, + SPEED_BOOST, + BATTLE_ARMOR, + STURDY, + DAMP, + LIMBER, + SAND_VEIL, + STATIC, + VOLT_ABSORB, + WATER_ABSORB, + OBLIVIOUS, + CLOUD_NINE, + COMPOUND_EYES, + INSOMNIA, + COLOR_CHANGE, + IMMUNITY, + FLASH_FIRE, + SHIELD_DUST, + OWN_TEMPO, + SUCTION_CUPS, + INTIMIDATE, + SHADOW_TAG, + ROUGH_SKIN, + WONDER_GUARD, + LEVITATE, + EFFECT_SPORE, + SYNCHRONIZE, + CLEAR_BODY, + NATURAL_CURE, + LIGHTNING_ROD, + SERENE_GRACE, + SWIFT_SWIM, + CHLOROPHYLL, + ILLUMINATE, + TRACE, + HUGE_POWER, + POISON_POINT, + INNER_FOCUS, + MAGMA_ARMOR, + WATER_VEIL, + MAGNET_PULL, + SOUNDPROOF, + RAIN_DISH, + SAND_STREAM, + PRESSURE, + THICK_FAT, + EARLY_BIRD, + FLAME_BODY, + RUN_AWAY, + KEEN_EYE, + HYPER_CUTTER, + PICKUP, + TRUANT, + HUSTLE, + CUTE_CHARM, + PLUS, + MINUS, + FORECAST, + STICKY_HOLD, + SHED_SKIN, + GUTS, + MARVEL_SCALE, + LIQUID_OOZE, + OVERGROW, + BLAZE, + TORRENT, + SWARM, + ROCK_HEAD, + DROUGHT, + ARENA_TRAP, + VITAL_SPIRIT, + WHITE_SMOKE, + PURE_POWER, + SHELL_ARMOR, + AIR_LOCK, + TANGLED_FEET, + MOTOR_DRIVE, + RIVALRY, + STEADFAST, + SNOW_CLOAK, + GLUTTONY, + ANGER_POINT, + UNBURDEN, + HEATPROOF, + SIMPLE, + DRY_SKIN, + DOWNLOAD, + IRON_FIST, + POISON_HEAL, + ADAPTABILITY, + SKILL_LINK, + HYDRATION, + SOLAR_POWER, + QUICK_FEET, + NORMALIZE, + SNIPER, + MAGIC_GUARD, + NO_GUARD, + STALL, + TECHNICIAN, + LEAF_GUARD, + KLUTZ, + MOLD_BREAKER, + SUPER_LUCK, + AFTERMATH, + ANTICIPATION, + FOREWARN, + UNAWARE, + TINTED_LENS, + FILTER, + SLOW_START, + SCRAPPY, + STORM_DRAIN, + ICE_BODY, + SOLID_ROCK, + SNOW_WARNING, + HONEY_GATHER, + FRISK, + RECKLESS, + MULTITYPE, + FLOWER_GIFT, + BAD_DREAMS, + PICKPOCKET, + SHEER_FORCE, + CONTRARY, + UNNERVE, + DEFIANT, + DEFEATIST, + CURSED_BODY, + HEALER, + FRIEND_GUARD, + WEAK_ARMOR, + HEAVY_METAL, + LIGHT_METAL, + MULTISCALE, + TOXIC_BOOST, + FLARE_BOOST, + HARVEST, + TELEPATHY, + MOODY, + OVERCOAT, + POISON_TOUCH, + REGENERATOR, + BIG_PECKS, + SAND_RUSH, + WONDER_SKIN, + ANALYTIC, + ILLUSION, + IMPOSTER, + INFILTRATOR, + MUMMY, + MOXIE, + JUSTIFIED, + RATTLED, + MAGIC_BOUNCE, + SAP_SIPPER, + PRANKSTER, + SAND_FORCE, + IRON_BARBS, + ZEN_MODE, + VICTORY_STAR, + TURBOBLAZE, + TERAVOLT, + AROMA_VEIL, + FLOWER_VEIL, + CHEEK_POUCH, + PROTEAN, + FUR_COAT, + MAGICIAN, + BULLETPROOF, + COMPETITIVE, + STRONG_JAW, + REFRIGERATE, + SWEET_VEIL, + STANCE_CHANGE, + GALE_WINGS, + MEGA_LAUNCHER, + GRASS_PELT, + SYMBIOSIS, + TOUGH_CLAWS, + PIXILATE, + GOOEY, + AERILATE, + PARENTAL_BOND, + DARK_AURA, + FAIRY_AURA, + AURA_BREAK, + PRIMORDIAL_SEA, + DESOLATE_LAND, + DELTA_STREAM, + STAMINA, + WIMP_OUT, + EMERGENCY_EXIT, + WATER_COMPACTION, + MERCILESS, + SHIELDS_DOWN, + STAKEOUT, + WATER_BUBBLE, + STEELWORKER, + BERSERK, + SLUSH_RUSH, + LONG_REACH, + LIQUID_VOICE, + TRIAGE, + GALVANIZE, + SURGE_SURFER, + SCHOOLING, + DISGUISE, + BATTLE_BOND, + POWER_CONSTRUCT, + CORROSION, + COMATOSE, + QUEENLY_MAJESTY, + INNARDS_OUT, + DANCER, + BATTERY, + FLUFFY, + DAZZLING, + SOUL_HEART, + TANGLING_HAIR, + RECEIVER, + POWER_OF_ALCHEMY, + BEAST_BOOST, + RKS_SYSTEM, + ELECTRIC_SURGE, + PSYCHIC_SURGE, + MISTY_SURGE, + GRASSY_SURGE, + FULL_METAL_BODY, + SHADOW_SHIELD, + PRISM_ARMOR, + NEUROFORCE, + INTREPID_SWORD, + DAUNTLESS_SHIELD, + LIBERO, + BALL_FETCH, + COTTON_DOWN, + PROPELLER_TAIL, + MIRROR_ARMOR, + GULP_MISSILE, + STALWART, + STEAM_ENGINE, + PUNK_ROCK, + SAND_SPIT, + ICE_SCALES, + RIPEN, + ICE_FACE, + POWER_SPOT, + MIMICRY, + SCREEN_CLEANER, + STEELY_SPIRIT, + PERISH_BODY, + WANDERING_SPIRIT, + GORILLA_TACTICS, + NEUTRALIZING_GAS, + PASTEL_VEIL, + HUNGER_SWITCH, + QUICK_DRAW, + UNSEEN_FIST, + CURIOUS_MEDICINE, + TRANSISTOR, + DRAGONS_MAW, + CHILLING_NEIGH, + GRIM_NEIGH, + AS_ONE_GLASTRIER, + AS_ONE_SPECTRIER, + LINGERING_AROMA, + SEED_SOWER, + THERMAL_EXCHANGE, + ANGER_SHELL, + PURIFYING_SALT, + WELL_BAKED_BODY, + WIND_RIDER, + GUARD_DOG, + ROCKY_PAYLOAD, + WIND_POWER, + ZERO_TO_HERO, + COMMANDER, + ELECTROMORPHOSIS, + PROTOSYNTHESIS, + QUARK_DRIVE, + GOOD_AS_GOLD, + VESSEL_OF_RUIN, + SWORD_OF_RUIN, + TABLETS_OF_RUIN, + BEADS_OF_RUIN, + ORICHALCUM_PULSE, + HADRON_ENGINE, + OPPORTUNIST, + CUD_CHEW, + SHARPNESS, + SUPREME_OVERLORD, + COSTAR, + TOXIC_DEBRIS, + ARMOR_TAIL, + EARTH_EATER, + MYCELIUM_MIGHT, + MINDS_EYE, + SUPERSWEET_SYRUP, + HOSPITALITY, + TOXIC_CHAIN, + EMBODY_ASPECT_TEAL, + EMBODY_ASPECT_WELLSPRING, + EMBODY_ASPECT_HEARTHFLAME, + EMBODY_ASPECT_CORNERSTONE, + TERA_SHIFT, + TERA_SHELL, + TERAFORM_ZERO, + POISON_PUPPETEER +} diff --git a/src/data/move.ts b/src/data/move.ts index c8ead786b33..2ea99430211 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -12,7 +12,8 @@ import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { Abilities, ProtectAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "./ability"; +import { ProtectAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "./ability"; +import { Abilities } from "./enums/abilities"; import { PokemonHeldItemModifier } from "../modifier/modifier"; import { BattlerIndex } from "../battle"; import { Stat } from "./pokemon-stat"; @@ -271,7 +272,7 @@ export default class Move { checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean { switch (flag) { case MoveFlags.MAKES_CONTACT: - if (user.getAbility().hasAttr(IgnoreContactAbAttr)) + if ((user.canApplyAbility() && user.getAbility().hasAttr(IgnoreContactAbAttr)) || (user.canApplyAbility(true) && user.getPassiveAbility().hasAttr(IgnoreContactAbAttr))) return false; break; } @@ -4504,9 +4505,9 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), new StatusMove(Moves.MAGNETIC_FLUX, "Magnetic Flux", Type.ELECTRIC, -1, 20, "The user manipulates magnetic fields, which raises the Defense and Sp. Def stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 6) - .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id)) + .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id)))), new StatusMove(Moves.HAPPY_HOUR, "Happy Hour (N)", Type.NORMAL, -1, 30, "Using Happy Hour doubles the amount of prize money received after battle.", -1, 0, 6) // No animation .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ELECTRIC_TERRAIN, "Electric Terrain", Type.ELECTRIC, -1, 10, "The user electrifies the ground for five turns, powering up Electric-type moves. Pokémon on the ground no longer fall asleep.", -1, 0, 6) @@ -4631,9 +4632,9 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1), new SelfStatusMove(Moves.LASER_FOCUS, "Laser Focus (N)", Type.NORMAL, -1, 30, "The user concentrates intensely. The attack on the next turn always results in a critical hit.", -1, 0, 7), new StatusMove(Moves.GEAR_UP, "Gear Up", Type.STEEL, -1, 20, "The user engages its gears to raise the Attack and Sp. Atk stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 7) - .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].indexOf(target.getAbility().id) > -1) + .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].includes(target.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].indexOf(p.getAbility().id) > -1)), + .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].includes(p.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))), new AttackMove(Moves.THROAT_CHOP, "Throat Chop (P)", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, "The user attacks the target's throat, and the resultant suffering prevents the target from using moves that emit sound for two turns.", 100, 0, 7), new AttackMove(Moves.POLLEN_PUFF, "Pollen Puff (P)", Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks the enemy with a pollen puff that explodes. If the target is an ally, it gives the ally a pollen puff that restores its HP instead.", -1, 0, 7) .ballBombMove(), diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 63f85ae42d8..e5bcf25a4fe 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -6,7 +6,7 @@ import { SpeciesFormKey } from "./pokemon-species"; import { Species } from "./enums/species"; import { StatusEffect } from "./status-effect"; import { MoveCategory, allMoves } from "./move"; -import { Abilities } from "./ability"; +import { Abilities } from "./enums/abilities"; export enum FormChangeItem { NONE, diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index e0ef53d9628..7f52315cfa7 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -1,4 +1,4 @@ -import { Abilities } from './ability'; +import { Abilities } from "./enums/abilities"; import BattleScene, { AnySound } from '../battle-scene'; import { GrowthRate } from './exp'; import { SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from './pokemon-evolutions'; @@ -3053,6 +3053,578 @@ export const noStarterFormKeys: string[] = [ SpeciesFormKey.ETERNAMAX ].map(k => k.toString()); +export const starterPassiveAbilities = { + [Species.BULBASAUR]: Abilities.SOLAR_POWER, + [Species.CHARMANDER]: Abilities.INTIMIDATE, + [Species.SQUIRTLE]: Abilities.DAUNTLESS_SHIELD, + [Species.CATERPIE]: Abilities.MAGICIAN, + [Species.WEEDLE]: Abilities.POISON_TOUCH, + [Species.PIDGEY]: Abilities.TECHNICIAN, + [Species.RATTATA]: Abilities.STRONG_JAW, + [Species.SPEAROW]: Abilities.MOXIE, + [Species.EKANS]: Abilities.ROUGH_SKIN, + [Species.SANDSHREW]: Abilities.IRON_BARBS, + [Species.NIDORAN_F]: Abilities.QUEENLY_MAJESTY, + [Species.NIDORAN_M]: Abilities.SUPREME_OVERLORD, + [Species.VULPIX]: Abilities.CURSED_BODY, + [Species.ZUBAT]: Abilities.WIND_RIDER, + [Species.ODDISH]: Abilities.LINGERING_AROMA, + [Species.PARAS]: Abilities.POISON_HEAL, + [Species.VENONAT]: Abilities.TECHNICIAN, + [Species.DIGLETT]: Abilities.STURDY, + [Species.MEOWTH]: Abilities.NORMALIZE, + [Species.PSYDUCK]: Abilities.SIMPLE, + [Species.MANKEY]: Abilities.STAMINA, + [Species.GROWLITHE]: Abilities.BALL_FETCH, + [Species.POLIWAG]: Abilities.WATER_BUBBLE, + [Species.ABRA]: Abilities.TECHNICIAN, + [Species.MACHOP]: Abilities.IRON_FIST, + [Species.BELLSPROUT]: Abilities.CORROSION, + [Species.TENTACOOL]: Abilities.INNARDS_OUT, + [Species.GEODUDE]: Abilities.ROCKY_PAYLOAD, + [Species.PONYTA]: Abilities.PIXILATE, + [Species.SLOWPOKE]: Abilities.UNAWARE, + [Species.MAGNEMITE]: Abilities.MOTOR_DRIVE, + [Species.FARFETCHD]: Abilities.PURE_POWER, + [Species.DODUO]: Abilities.RECKLESS, + [Species.SEEL]: Abilities.REGENERATOR, + [Species.GRIMER]: Abilities.GOOEY, + [Species.SHELLDER]: Abilities.MOXIE, + [Species.GASTLY]: Abilities.PERISH_BODY, + [Species.ONIX]: Abilities.ROCKY_PAYLOAD, + [Species.DROWZEE]: Abilities.BAD_DREAMS, + [Species.KRABBY]: Abilities.ANGER_SHELL, + [Species.VOLTORB]: Abilities.GALVANIZE, + [Species.EXEGGCUTE]: Abilities.PARENTAL_BOND, + [Species.CUBONE]: Abilities.MOODY, + [Species.LICKITUNG]: Abilities.EARTH_EATER, + [Species.KOFFING]: Abilities.FLARE_BOOST, + [Species.RHYHORN]: Abilities.FILTER, + [Species.TANGELA]: Abilities.TANGLING_HAIR, + [Species.KANGASKHAN]: Abilities.IRON_FIST, + [Species.HORSEA]: Abilities.DRIZZLE, + [Species.GOLDEEN]: Abilities.VOLT_ABSORB, + [Species.STARYU]: Abilities.REGENERATOR, + [Species.SCYTHER]: Abilities.SPEED_BOOST, + [Species.PINSIR]: Abilities.SAP_SIPPER, + [Species.TAUROS]: Abilities.ROCK_HEAD, + [Species.MAGIKARP]: Abilities.BERSERK, + [Species.LAPRAS]: Abilities.LIQUID_VOICE, + [Species.DITTO]: Abilities.GOOEY, + [Species.EEVEE]: Abilities.PROTEAN, + [Species.PORYGON]: Abilities.QUARK_DRIVE, + [Species.OMANYTE]: Abilities.ANGER_SHELL, + [Species.KABUTO]: Abilities.SHARPNESS, + [Species.AERODACTYL]: Abilities.PROTOSYNTHESIS, + [Species.ARTICUNO]: Abilities.SNOW_WARNING, + [Species.ZAPDOS]: Abilities.DRIZZLE, + [Species.MOLTRES]: Abilities.DROUGHT, + [Species.DRATINI]: Abilities.DELTA_STREAM, + [Species.MEWTWO]: Abilities.BERSERK, + [Species.MEW]: Abilities.PROTEAN, + [Species.CHIKORITA]: Abilities.TRIAGE, + [Species.CYNDAQUIL]: Abilities.TURBOBLAZE, + [Species.TOTODILE]: Abilities.STRONG_JAW, + [Species.SENTRET]: Abilities.FLUFFY, + [Species.HOOTHOOT]: Abilities.CURSED_BODY, + [Species.LEDYBA]: Abilities.SCREEN_CLEANER, + [Species.SPINARAK]: Abilities.PRANKSTER, + [Species.CHINCHOU]: Abilities.REGENERATOR, + [Species.PICHU]: Abilities.TRANSISTOR, + [Species.CLEFFA]: Abilities.TRIAGE, + [Species.IGGLYBUFF]: Abilities.SERENE_GRACE, + [Species.TOGEPI]: Abilities.OPPORTUNIST, + [Species.NATU]: Abilities.TINTED_LENS, + [Species.MAREEP]: Abilities.FLUFFY, + [Species.HOPPIP]: Abilities.PRANKSTER, + [Species.AIPOM]: Abilities.SCRAPPY, + [Species.SUNKERN]: Abilities.DROUGHT, + [Species.YANMA]: Abilities.TECHNICIAN, + [Species.WOOPER]: Abilities.SIMPLE, + [Species.MURKROW]: Abilities.DEFIANT, + [Species.MISDREAVUS]: Abilities.DAZZLING, + [Species.UNOWN]: Abilities.PICKUP, + [Species.GIRAFARIG]: Abilities.PARENTAL_BOND, + [Species.PINECO]: Abilities.IRON_BARBS, + [Species.DUNSPARCE]: Abilities.MARVEL_SCALE, + [Species.GLIGAR]: Abilities.MERCILESS, + [Species.SNUBBULL]: Abilities.BALL_FETCH, + [Species.QWILFISH]: Abilities.LIQUID_OOZE, + [Species.SHUCKLE]: Abilities.WELL_BAKED_BODY, + [Species.HERACROSS]: Abilities.QUICK_FEET, + [Species.SNEASEL]: Abilities.MOXIE, + [Species.TEDDIURSA]: Abilities.GLUTTONY, + [Species.SLUGMA]: Abilities.DESOLATE_LAND, + [Species.SWINUB]: Abilities.SLUSH_RUSH, + [Species.CORSOLA]: Abilities.STORM_DRAIN, + [Species.REMORAID]: Abilities.SKILL_LINK, + [Species.DELIBIRD]: Abilities.PRANKSTER, + [Species.SKARMORY]: Abilities.OBLIVIOUS, + [Species.HOUNDOUR]: Abilities.INTIMIDATE, + [Species.PHANPY]: Abilities.ROCK_HEAD, + [Species.STANTLER]: Abilities.MAGIC_GUARD, + [Species.SMEARGLE]: Abilities.TRACE, + [Species.TYROGUE]: Abilities.STAMINA, + [Species.SMOOCHUM]: Abilities.CUTE_CHARM, + [Species.ELEKID]: Abilities.ADAPTABILITY, + [Species.MAGBY]: Abilities.CONTRARY, + [Species.MILTANK]: Abilities.GLUTTONY, + [Species.RAIKOU]: Abilities.FLARE_BOOST, + [Species.ENTEI]: Abilities.TOXIC_BOOST, + [Species.SUICUNE]: Abilities.SPEED_BOOST, + [Species.LARVITAR]: Abilities.SAND_FORCE, + [Species.LUGIA]: Abilities.STORM_DRAIN, + [Species.HO_OH]: Abilities.FLASH_FIRE, + [Species.CELEBI]: Abilities.TRIAGE, + [Species.TREECKO]: Abilities.GRASSY_SURGE, + [Species.TORCHIC]: Abilities.RECKLESS, + [Species.MUDKIP]: Abilities.REGENERATOR, + [Species.POOCHYENA]: Abilities.STRONG_JAW, + [Species.ZIGZAGOON]: Abilities.PICKPOCKET, + [Species.WURMPLE]: Abilities.TINTED_LENS, + [Species.LOTAD]: Abilities.DRIZZLE, + [Species.SEEDOT]: Abilities.DISGUISE, + [Species.TAILLOW]: Abilities.KEEN_EYE, + [Species.WINGULL]: Abilities.HYDRATION, + [Species.RALTS]: Abilities.PSYCHIC_SURGE, + [Species.SURSKIT]: Abilities.WATER_ABSORB, + [Species.SHROOMISH]: Abilities.GUTS, + [Species.SLAKOTH]: Abilities.GUTS, + [Species.NINCADA]: Abilities.OVERCOAT, + [Species.WHISMUR]: Abilities.PUNK_ROCK, + [Species.MAKUHITA]: Abilities.CONTRARY, + [Species.AZURILL]: Abilities.UNNERVE, + [Species.NOSEPASS]: Abilities.LEVITATE, + [Species.SKITTY]: Abilities.SCRAPPY, + [Species.SABLEYE]: Abilities.UNNERVE, + [Species.MAWILE]: Abilities.MOLD_BREAKER, + [Species.ARON]: Abilities.SOLID_ROCK, + [Species.MEDITITE]: Abilities.OWN_TEMPO, + [Species.ELECTRIKE]: Abilities.SPEED_BOOST, + [Species.PLUSLE]: Abilities.MINUS, + [Species.MINUN]: Abilities.PLUS, + [Species.VOLBEAT]: Abilities.TINTED_LENS, + [Species.ILLUMISE]: Abilities.SWARM, + [Species.GULPIN]: Abilities.POISON_TOUCH, + [Species.CARVANHA]: Abilities.STAKEOUT, + [Species.WAILMER]: Abilities.LEVITATE, + [Species.NUMEL]: Abilities.TURBOBLAZE, + [Species.TORKOAL]: Abilities.PROTOSYNTHESIS, + [Species.SPOINK]: Abilities.PSYCHIC_SURGE, + [Species.SPINDA]: Abilities.SIMPLE, + [Species.TRAPINCH]: Abilities.ADAPTABILITY, + [Species.CACNEA]: Abilities.SAND_RUSH, + [Species.SWABLU]: Abilities.WHITE_SMOKE, + [Species.ZANGOOSE]: Abilities.SUPER_LUCK, + [Species.SEVIPER]: Abilities.MOLD_BREAKER, + [Species.LUNATONE]: Abilities.SHADOW_SHIELD, + [Species.SOLROCK]: Abilities.FULL_METAL_BODY, + [Species.BARBOACH]: Abilities.BALL_FETCH, + [Species.CORPHISH]: Abilities.WATER_BUBBLE, + [Species.BALTOY]: Abilities.OWN_TEMPO, + [Species.LILEEP]: Abilities.WATER_ABSORB, + [Species.ANORITH]: Abilities.WATER_ABSORB, + [Species.FEEBAS]: Abilities.PASTEL_VEIL, + [Species.CASTFORM]: Abilities.ADAPTABILITY, + [Species.KECLEON]: Abilities.ADAPTABILITY, + [Species.SHUPPET]: Abilities.MUMMY, + [Species.DUSKULL]: Abilities.UNNERVE, + [Species.TROPIUS]: Abilities.CUD_CHEW, + [Species.ABSOL]: Abilities.DARK_AURA, + [Species.WYNAUT]: Abilities.STAMINA, + [Species.SNORUNT]: Abilities.SNOW_WARNING, + [Species.SPHEAL]: Abilities.SLUSH_RUSH, + [Species.CLAMPERL]: Abilities.SIMPLE, + [Species.RELICANTH]: Abilities.SOLID_ROCK, + [Species.LUVDISC]: Abilities.PICKUP, + [Species.BAGON]: Abilities.GALE_WINGS, + [Species.BELDUM]: Abilities.IRON_FIST, + [Species.REGIROCK]: Abilities.REGENERATOR, + [Species.REGICE]: Abilities.ICE_SCALES, + [Species.REGISTEEL]: Abilities.STEELY_SPIRIT, + [Species.LATIAS]: Abilities.SERENE_GRACE, + [Species.LATIOS]: Abilities.SERENE_GRACE, + [Species.KYOGRE]: Abilities.HYDRATION, + [Species.GROUDON]: Abilities.LEAF_GUARD, + [Species.RAYQUAZA]: Abilities.STEADFAST, + [Species.JIRACHI]: Abilities.COMATOSE, + [Species.DEOXYS]: Abilities.STICKY_HOLD, + [Species.TURTWIG]: Abilities.HARVEST, + [Species.CHIMCHAR]: Abilities.DEFIANT, + [Species.PIPLUP]: Abilities.BATTLE_ARMOR, + [Species.STARLY]: Abilities.ROCK_HEAD, + [Species.BIDOOF]: Abilities.NEUROFORCE, + [Species.KRICKETOT]: Abilities.SOUNDPROOF, + [Species.SHINX]: Abilities.VOLT_ABSORB, + [Species.BUDEW]: Abilities.CUTE_CHARM, + [Species.CRANIDOS]: Abilities.ROCK_HEAD, + [Species.SHIELDON]: Abilities.SOLID_ROCK, + [Species.BURMY]: Abilities.STURDY, + [Species.COMBEE]: Abilities.QUEENLY_MAJESTY, + [Species.PACHIRISU]: Abilities.BALL_FETCH, + [Species.BUIZEL]: Abilities.HYDRATION, + [Species.CHERUBI]: Abilities.DROUGHT, + [Species.SHELLOS]: Abilities.SHELL_ARMOR, + [Species.DRIFLOON]: Abilities.PICKPOCKET, + [Species.BUNEARY]: Abilities.OBLIVIOUS, + [Species.GLAMEOW]: Abilities.PICKUP, + [Species.CHINGLING]: Abilities.VICTORY_STAR, + [Species.STUNKY]: Abilities.MERCILESS, + [Species.BRONZOR]: Abilities.SOUNDPROOF, + [Species.BONSLY]: Abilities.SAP_SIPPER, + [Species.MIME_JR]: Abilities.MAGIC_BOUNCE, + [Species.HAPPINY]: Abilities.TRIAGE, + [Species.CHATOT]: Abilities.PUNK_ROCK, + [Species.SPIRITOMB]: Abilities.REGENERATOR, + [Species.GIBLE]: Abilities.SAND_STREAM, + [Species.MUNCHLAX]: Abilities.CUD_CHEW, + [Species.RIOLU]: Abilities.MEGA_LAUNCHER, + [Species.HIPPOPOTAS]: Abilities.SAND_VEIL, + [Species.SKORUPI]: Abilities.SUPER_LUCK, + [Species.CROAGUNK]: Abilities.PICKPOCKET, + [Species.CARNIVINE]: Abilities.EFFECT_SPORE, + [Species.FINNEON]: Abilities.DRIZZLE, + [Species.MANTYKE]: Abilities.STORM_DRAIN, + [Species.SNOVER]: Abilities.SNOW_CLOAK, + [Species.ROTOM]: Abilities.ELECTRIC_SURGE, + [Species.UXIE]: Abilities.ILLUSION, + [Species.MESPRIT]: Abilities.MOODY, + [Species.AZELF]: Abilities.NEUROFORCE, + [Species.DIALGA]: Abilities.SPEED_BOOST, + [Species.PALKIA]: Abilities.MAGIC_BOUNCE, + [Species.HEATRAN]: Abilities.ROUGH_SKIN, + [Species.REGIGIGAS]: Abilities.IRON_FIST, + [Species.GIRATINA]: Abilities.SHADOW_TAG, + [Species.CRESSELIA]: Abilities.MAGIC_BOUNCE, + [Species.PHIONE]: Abilities.SWIFT_SWIM, + [Species.MANAPHY]: Abilities.SIMPLE, + [Species.DARKRAI]: Abilities.UNNERVE, + [Species.SHAYMIN]: Abilities.FLOWER_VEIL, + [Species.ARCEUS]: Abilities.ADAPTABILITY, + [Species.VICTINI]: Abilities.SUPER_LUCK, + [Species.SNIVY]: Abilities.MULTISCALE, + [Species.TEPIG]: Abilities.SAND_RUSH, + [Species.OSHAWOTT]: Abilities.LIGHTNING_ROD, + [Species.PATRAT]: Abilities.STAKEOUT, + [Species.LILLIPUP]: Abilities.BALL_FETCH, + [Species.PURRLOIN]: Abilities.DEFIANT, + [Species.PANSAGE]: Abilities.SAP_SIPPER, + [Species.PANSEAR]: Abilities.FLASH_FIRE, + [Species.PANPOUR]: Abilities.STORM_DRAIN, + [Species.MUNNA]: Abilities.NEUTRALIZING_GAS, + [Species.PIDOVE]: Abilities.OPPORTUNIST, + [Species.BLITZLE]: Abilities.FLARE_BOOST, + [Species.ROGGENROLA]: Abilities.SOLID_ROCK, + [Species.WOOBAT]: Abilities.SOUL_HEART, + [Species.DRILBUR]: Abilities.SAND_STREAM, + [Species.AUDINO]: Abilities.SERENE_GRACE, + [Species.TIMBURR]: Abilities.STAMINA, + [Species.TYMPOLE]: Abilities.MOODY, + [Species.THROH]: Abilities.SIMPLE, + [Species.SAWK]: Abilities.DEFIANT, + [Species.SEWADDLE]: Abilities.SHARPNESS, + [Species.VENIPEDE]: Abilities.INTIMIDATE, + [Species.COTTONEE]: Abilities.MISTY_SURGE, + [Species.PETILIL]: Abilities.ORICHALCUM_PULSE, + [Species.BASCULIN]: Abilities.ROCK_HEAD, + [Species.SANDILE]: Abilities.STRONG_JAW, + [Species.DARUMAKA]: Abilities.IRON_FIST, + [Species.MARACTUS]: Abilities.IRON_BARBS, + [Species.DWEBBLE]: Abilities.STAMINA, + [Species.SCRAGGY]: Abilities.ROCK_HEAD, + [Species.SIGILYPH]: Abilities.MAGICIAN, + [Species.YAMASK]: Abilities.GOOD_AS_GOLD, + [Species.TIRTOUGA]: Abilities.SHELL_ARMOR, + [Species.ARCHEN]: Abilities.ROCKY_PAYLOAD, + [Species.TRUBBISH]: Abilities.GOOEY, + [Species.ZORUA]: Abilities.ADAPTABILITY, + [Species.MINCCINO]: Abilities.SCRAPPY, + [Species.GOTHITA]: Abilities.PRESSURE, + [Species.SOLOSIS]: Abilities.GOOEY, + [Species.DUCKLETT]: Abilities.GALE_WINGS, + [Species.VANILLITE]: Abilities.REFRIGERATE, + [Species.DEERLING]: Abilities.JUSTIFIED, + [Species.EMOLGA]: Abilities.WIND_POWER, + [Species.KARRABLAST]: Abilities.NO_GUARD, + [Species.FOONGUS]: Abilities.ADAPTABILITY, + [Species.FRILLISH]: Abilities.MUMMY, + [Species.ALOMOMOLA]: Abilities.MULTISCALE, + [Species.JOLTIK]: Abilities.VOLT_ABSORB, + [Species.FERROSEED]: Abilities.SKILL_LINK, + [Species.KLINK]: Abilities.STEELWORKER, + [Species.TYNAMO]: Abilities.SWIFT_SWIM, + [Species.ELGYEM]: Abilities.COMMANDER, + [Species.LITWICK]: Abilities.SOUL_HEART, + [Species.AXEW]: Abilities.SHEER_FORCE, + [Species.CUBCHOO]: Abilities.INTIMIDATE, + [Species.CRYOGONAL]: Abilities.DAZZLING, + [Species.SHELMET]: Abilities.DISGUISE, + [Species.STUNFISK]: Abilities.STORM_DRAIN, + [Species.MIENFOO]: Abilities.NO_GUARD, + [Species.DRUDDIGON]: Abilities.INTIMIDATE, + [Species.GOLETT]: Abilities.JUSTIFIED, + [Species.PAWNIARD]: Abilities.SHARPNESS, + [Species.BOUFFALANT]: Abilities.THICK_FAT, + [Species.RUFFLET]: Abilities.RECKLESS, + [Species.VULLABY]: Abilities.THICK_FAT, + [Species.HEATMOR]: Abilities.CONTRARY, + [Species.DURANT]: Abilities.TOUGH_CLAWS, + [Species.DEINO]: Abilities.BERSERK, + [Species.LARVESTA]: Abilities.DROUGHT, + [Species.COBALION]: Abilities.INTREPID_SWORD, + [Species.TERRAKION]: Abilities.ROCKY_PAYLOAD, + [Species.VIRIZION]: Abilities.SYMBIOSIS, + [Species.TORNADUS]: Abilities.DELTA_STREAM, + [Species.THUNDURUS]: Abilities.DRIZZLE, + [Species.RESHIRAM]: Abilities.ORICHALCUM_PULSE, + [Species.ZEKROM]: Abilities.HADRON_ENGINE, + [Species.LANDORUS]: Abilities.PRANKSTER, + [Species.KYUREM]: Abilities.SNOW_WARNING, + [Species.KELDEO]: Abilities.HUGE_POWER, + [Species.MELOETTA]: Abilities.PUNK_ROCK, + [Species.GENESECT]: Abilities.MEGA_LAUNCHER, + [Species.CHESPIN]: Abilities.IRON_BARBS, + [Species.FENNEKIN]: Abilities.MAGIC_GUARD, + [Species.FROAKIE]: Abilities.MERCILESS, + [Species.BUNNELBY]: Abilities.GUTS, + [Species.FLETCHLING]: Abilities.RECKLESS, + [Species.SCATTERBUG]: Abilities.PRANKSTER, + [Species.LITLEO]: Abilities.INTIMIDATE, + [Species.FLABEBE]: Abilities.GRASSY_SURGE, + [Species.SKIDDO]: Abilities.FUR_COAT, + [Species.PANCHAM]: Abilities.FLUFFY, + [Species.FURFROU]: Abilities.BALL_FETCH, + [Species.ESPURR]: Abilities.PSYCHIC_SURGE, + [Species.HONEDGE]: Abilities.SHARPNESS, + [Species.SPRITZEE]: Abilities.UNAWARE, + [Species.SWIRLIX]: Abilities.PIXILATE, + [Species.INKAY]: Abilities.SUPREME_OVERLORD, + [Species.BINACLE]: Abilities.SOLID_ROCK, + [Species.SKRELP]: Abilities.CORROSION, + [Species.CLAUNCHER]: Abilities.SWIFT_SWIM, + [Species.HELIOPTILE]: Abilities.NO_GUARD, + [Species.TYRUNT]: Abilities.SHEER_FORCE, + [Species.AMAURA]: Abilities.SERENE_GRACE, + [Species.HAWLUCHA]: Abilities.RECKLESS, + [Species.DEDENNE]: Abilities.SIMPLE, + [Species.CARBINK]: Abilities.OBLIVIOUS, + [Species.GOOMY]: Abilities.POISON_HEAL, + [Species.KLEFKI]: Abilities.TRIAGE, + [Species.PHANTUMP]: Abilities.UNNERVE, + [Species.PUMPKABOO]: Abilities.FLARE_BOOST, + [Species.BERGMITE]: Abilities.MIRROR_ARMOR, + [Species.NOIBAT]: Abilities.PUNK_ROCK, + [Species.XERNEAS]: Abilities.COMPETITIVE, + [Species.YVELTAL]: Abilities.DEFIANT, + [Species.ZYGARDE]: Abilities.REGENERATOR, + [Species.DIANCIE]: Abilities.QUEENLY_MAJESTY, + [Species.HOOPA]: Abilities.TRACE, + [Species.VOLCANION]: Abilities.FILTER, + [Species.ROWLET]: Abilities.SNIPER, + [Species.LITTEN]: Abilities.PRANKSTER, + [Species.POPPLIO]: Abilities.PUNK_ROCK, + [Species.PIKIPEK]: Abilities.ANGER_POINT, + [Species.YUNGOOS]: Abilities.HUGE_POWER, + [Species.GRUBBIN]: Abilities.GALVANIZE, + [Species.CRABRAWLER]: Abilities.REFRIGERATE, + [Species.ORICORIO]: Abilities.ADAPTABILITY, + [Species.CUTIEFLY]: Abilities.FRIEND_GUARD, + [Species.ROCKRUFF]: Abilities.ROCKY_PAYLOAD, + [Species.WISHIWASHI]: Abilities.PARENTAL_BOND, + [Species.MAREANIE]: Abilities.TOXIC_DEBRIS, + [Species.MUDBRAY]: Abilities.CUD_CHEW, + [Species.DEWPIDER]: Abilities.STRONG_JAW, + [Species.FOMANTIS]: Abilities.MIMICRY, + [Species.MORELULL]: Abilities.PERISH_BODY, + [Species.SALANDIT]: Abilities.DAZZLING, + [Species.STUFFUL]: Abilities.HOSPITALITY, + [Species.BOUNSWEET]: Abilities.RIPEN, + [Species.COMFEY]: Abilities.FRIEND_GUARD, + [Species.ORANGURU]: Abilities.HOSPITALITY, + [Species.PASSIMIAN]: Abilities.COSTAR, + [Species.WIMPOD]: Abilities.BATTLE_ARMOR, + [Species.SANDYGAST]: Abilities.DAUNTLESS_SHIELD, + [Species.PYUKUMUKU]: Abilities.IRON_BARBS, + [Species.TYPE_NULL]: Abilities.ADAPTABILITY, + [Species.MINIOR]: Abilities.ANGER_SHELL, + [Species.KOMALA]: Abilities.GUTS, + [Species.TURTONATOR]: Abilities.ANGER_SHELL, + [Species.TOGEDEMARU]: Abilities.STATIC, + [Species.MIMIKYU]: Abilities.MIMICRY, + [Species.BRUXISH]: Abilities.MULTISCALE, + [Species.DRAMPA]: Abilities.FLASH_FIRE, + [Species.DHELMISE]: Abilities.INFILTRATOR, + [Species.JANGMO_O]: Abilities.DANCER, + [Species.TAPU_KOKO]: Abilities.GALVANIZE, + [Species.TAPU_LELE]: Abilities.BERSERK, + [Species.TAPU_BULU]: Abilities.FLOWER_VEIL, + [Species.TAPU_FINI]: Abilities.FAIRY_AURA, + [Species.COSMOG]: Abilities.BEAST_BOOST, + [Species.NIHILEGO]: Abilities.POISON_PUPPETEER, + [Species.BUZZWOLE]: Abilities.MOXIE, + [Species.PHEROMOSA]: Abilities.MOXIE, + [Species.XURKITREE]: Abilities.LIGHTNING_ROD, + [Species.CELESTEELA]: Abilities.CHLOROPHYLL, + [Species.KARTANA]: Abilities.INTREPID_SWORD, + [Species.GUZZLORD]: Abilities.GLUTTONY, + [Species.NECROZMA]: Abilities.BEAST_BOOST, + [Species.MAGEARNA]: Abilities.STEELY_SPIRIT, + [Species.MARSHADOW]: Abilities.IRON_FIST, + [Species.POIPOLE]: Abilities.MERCILESS, + [Species.STAKATAKA]: Abilities.DAUNTLESS_SHIELD, + [Species.BLACEPHALON]: Abilities.REGENERATOR, + [Species.ZERAORA]: Abilities.MOTOR_DRIVE, + [Species.MELTAN]: Abilities.FULL_METAL_BODY, + [Species.GROOKEY]: Abilities.SOLID_ROCK, + [Species.SCORBUNNY]: Abilities.RECKLESS, + [Species.SOBBLE]: Abilities.MIMICRY, + [Species.SKWOVET]: Abilities.HONEY_GATHER, + [Species.ROOKIDEE]: Abilities.JUSTIFIED, + [Species.BLIPBUG]: Abilities.TINTED_LENS, + [Species.NICKIT]: Abilities.INTIMIDATE, + [Species.GOSSIFLEUR]: Abilities.STORM_DRAIN, + [Species.WOOLOO]: Abilities.ROCK_HEAD, + [Species.CHEWTLE]: Abilities.ROCK_HEAD, + [Species.YAMPER]: Abilities.SPEED_BOOST, + [Species.ROLYCOLY]: Abilities.EARTH_EATER, + [Species.APPLIN]: Abilities.DRAGONS_MAW, + [Species.SILICOBRA]: Abilities.SAND_RUSH, + [Species.CRAMORANT]: Abilities.STORM_DRAIN, + [Species.ARROKUDA]: Abilities.STRONG_JAW, + [Species.TOXEL]: Abilities.GALVANIZE, + [Species.SIZZLIPEDE]: Abilities.DEFIANT, + [Species.CLOBBOPUS]: Abilities.SWIFT_SWIM, + [Species.SINISTEA]: Abilities.WATER_ABSORB, + [Species.HATENNA]: Abilities.MAGIC_GUARD, + [Species.IMPIDIMP]: Abilities.TANGLING_HAIR, + [Species.MILCERY]: Abilities.WELL_BAKED_BODY, + [Species.FALINKS]: Abilities.MOXIE, + [Species.PINCURCHIN]: Abilities.IRON_BARBS, + [Species.SNOM]: Abilities.SNOW_WARNING, + [Species.STONJOURNER]: Abilities.SOLID_ROCK, + [Species.EISCUE]: Abilities.SLUSH_RUSH, + [Species.INDEEDEE]: Abilities.MAGIC_BOUNCE, + [Species.MORPEKO]: Abilities.GLUTTONY, + [Species.CUFANT]: Abilities.HEATPROOF, + [Species.DRACOZOLT]: Abilities.SLUSH_RUSH, + [Species.ARCTOZOLT]: Abilities.SAND_RUSH, + [Species.DRACOVISH]: Abilities.HUSTLE, + [Species.ARCTOVISH]: Abilities.STRONG_JAW, + [Species.DURALUDON]: Abilities.MEGA_LAUNCHER, + [Species.DREEPY]: Abilities.PARENTAL_BOND, + [Species.ZACIAN]: Abilities.SHARPNESS, + [Species.ZAMAZENTA]: Abilities.GUARD_DOG, + [Species.ETERNATUS]: Abilities.SUPREME_OVERLORD, + [Species.KUBFU]: Abilities.IRON_FIST, + [Species.ZARUDE]: Abilities.PRANKSTER, + [Species.REGIELEKI]: Abilities.LEVITATE, + [Species.REGIDRAGO]: Abilities.INTIMIDATE, + [Species.GLASTRIER]: Abilities.FILTER, + [Species.SPECTRIER]: Abilities.PERISH_BODY, + [Species.CALYREX]: Abilities.HARVEST, + [Species.ENAMORUS]: Abilities.MISTY_SURGE, + [Species.SPRIGATITO]: Abilities.MAGICIAN, + [Species.FUECOCO]: Abilities.EARTH_EATER, + [Species.QUAXLY]: Abilities.DANCER, + [Species.LECHONK]: Abilities.SIMPLE, + [Species.TAROUNTULA]: Abilities.PICKUP, + [Species.NYMBLE]: Abilities.TECHNICIAN, + [Species.PAWMI]: Abilities.FLUFFY, + [Species.TANDEMAUS]: Abilities.PARENTAL_BOND, + [Species.FIDOUGH]: Abilities.WATER_ABSORB, + [Species.SMOLIV]: Abilities.RIPEN, + [Species.SQUAWKABILLY]: Abilities.GALE_WINGS, + [Species.NACLI]: Abilities.EARTH_EATER, + [Species.CHARCADET]: Abilities.CONTRARY, + [Species.TADBULB]: Abilities.TRANSISTOR, + [Species.WATTREL]: Abilities.GALE_WINGS, + [Species.MASCHIFF]: Abilities.STRONG_JAW, + [Species.SHROODLE]: Abilities.CORROSION, + [Species.BRAMBLIN]: Abilities.WANDERING_SPIRIT, + [Species.TOEDSCOOL]: Abilities.PRANKSTER, + [Species.KLAWF]: Abilities.WATER_ABSORB, + [Species.CAPSAKID]: Abilities.PARENTAL_BOND, + [Species.RELLOR]: Abilities.MAGIC_GUARD, + [Species.FLITTLE]: Abilities.COMPETITIVE, + [Species.TINKATINK]: Abilities.HUGE_POWER, + [Species.WIGLETT]: Abilities.STORM_DRAIN, + [Species.BOMBIRDIER]: Abilities.UNAWARE, + [Species.FINIZEN]: Abilities.LIQUID_VOICE, + [Species.VAROOM]: Abilities.SPEED_BOOST, + [Species.CYCLIZAR]: Abilities.PROTEAN, + [Species.ORTHWORM]: Abilities.HEATPROOF, + [Species.GLIMMET]: Abilities.SYMBIOSIS, + [Species.GREAVARD]: Abilities.FUR_COAT, + [Species.FLAMIGO]: Abilities.MOXIE, + [Species.CETODDLE]: Abilities.GLUTTONY, + [Species.VELUZA]: Abilities.SIMPLE, + [Species.DONDOZO]: Abilities.GLUTTONY, + [Species.TATSUGIRI]: Abilities.WATER_BUBBLE, + [Species.GREAT_TUSK]: Abilities.INTIMIDATE, + [Species.SCREAM_TAIL]: Abilities.PIXILATE, + [Species.BRUTE_BONNET]: Abilities.ADAPTABILITY, + [Species.FLUTTER_MANE]: Abilities.DAZZLING, + [Species.SLITHER_WING]: Abilities.SCRAPPY, + [Species.SANDY_SHOCKS]: Abilities.EARTH_EATER, + [Species.IRON_TREADS]: Abilities.STEAM_ENGINE, + [Species.IRON_BUNDLE]: Abilities.SNOW_WARNING, + [Species.IRON_HANDS]: Abilities.IRON_FIST, + [Species.IRON_JUGULIS]: Abilities.NO_GUARD, + [Species.IRON_MOTH]: Abilities.TINTED_LENS, + [Species.IRON_THORNS]: Abilities.SAND_STREAM, + [Species.FRIGIBAX]: Abilities.THICK_FAT, + [Species.GIMMIGHOUL]: Abilities.SUPER_LUCK, + [Species.WO_CHIEN]: Abilities.TRIAGE, + [Species.CHIEN_PAO]: Abilities.REFRIGERATE, + [Species.TING_LU]: Abilities.STAMINA, + [Species.CHI_YU]: Abilities.BLAZE, + [Species.ROARING_MOON]: Abilities.AERILATE, + [Species.IRON_VALIANT]: Abilities.DOWNLOAD, + [Species.KORAIDON]: Abilities.PROTOSYNTHESIS, + [Species.MIRAIDON]: Abilities.QUARK_DRIVE, + [Species.WALKING_WAKE]: Abilities.BEAST_BOOST, + [Species.IRON_LEAVES]: Abilities.SHARPNESS, + [Species.POLTCHAGEIST]: Abilities.FLAME_BODY, + [Species.OKIDOGI]: Abilities.STICKY_HOLD, + [Species.MUNKIDORI]: Abilities.PRANKSTER, + [Species.FEZANDIPITI]: Abilities.DAZZLING, + [Species.OGERPON]: Abilities.DISGUISE, + [Species.GOUGING_FIRE]: Abilities.BEAST_BOOST, + [Species.RAGING_BOLT]: Abilities.BEAST_BOOST, + [Species.IRON_BOULDER]: Abilities.SHARPNESS, + [Species.IRON_CROWN]: Abilities.SHARPNESS, + [Species.TERAPAGOS]: Abilities.PROTEAN, + [Species.PECHARUNT]: Abilities.CORROSION, + [Species.ALOLA_RATTATA]: Abilities.CHEEK_POUCH, + [Species.ALOLA_SANDSHREW]: Abilities.ICE_BODY, + [Species.ALOLA_VULPIX]: Abilities.ICE_BODY, + [Species.ALOLA_DIGLETT]: Abilities.CUTE_CHARM, + [Species.ALOLA_MEOWTH]: Abilities.UNNERVE, + [Species.ALOLA_GEODUDE]: Abilities.ELECTROMORPHOSIS, + [Species.ALOLA_GRIMER]: Abilities.MERCILESS, + [Species.ETERNAL_FLOETTE]: Abilities.MAGIC_GUARD, + [Species.GALAR_MEOWTH]: Abilities.SUPER_LUCK, + [Species.GALAR_PONYTA]: Abilities.MAGIC_GUARD, + [Species.GALAR_SLOWPOKE]: Abilities.POISON_TOUCH, + [Species.GALAR_FARFETCHD]: Abilities.SUPER_LUCK, + [Species.GALAR_ARTICUNO]: Abilities.SERENE_GRACE, + [Species.GALAR_ZAPDOS]: Abilities.TOUGH_CLAWS, + [Species.GALAR_MOLTRES]: Abilities.REGENERATOR, + [Species.GALAR_CORSOLA]: Abilities.SHADOW_TAG, + [Species.GALAR_ZIGZAGOON]: Abilities.PICKPOCKET, + [Species.GALAR_DARUMAKA]: Abilities.FLASH_FIRE, + [Species.GALAR_YAMASK]: Abilities.SOLID_ROCK, + [Species.GALAR_STUNFISK]: Abilities.IRON_BARBS, + [Species.HISUI_GROWLITHE]: Abilities.STRONG_JAW, + [Species.HISUI_VOLTORB]: Abilities.HADRON_ENGINE, + [Species.HISUI_QWILFISH]: Abilities.MERCILESS, + [Species.HISUI_SNEASEL]: Abilities.SCRAPPY, + [Species.HISUI_ZORUA]: Abilities.DARK_AURA, + [Species.PALDEA_TAUROS]: Abilities.RATTLED, + [Species.PALDEA_WOOPER]: Abilities.THICK_FAT, + [Species.BLOODMOON_URSALUNA]: Abilities.BERSERK +}; + // TODO: Remove { //setTimeout(() => { diff --git a/src/data/weather.ts b/src/data/weather.ts index a198990fd61..cf3cf3434ea 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -106,7 +106,9 @@ export class Weather { const field = scene.getField(true); for (let pokemon of field) { - const suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr; + let suppressWeatherEffectAbAttr = pokemon.canApplyAbility(false) ? pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; + if (!suppressWeatherEffectAbAttr) + suppressWeatherEffectAbAttr = pokemon.canApplyAbility(true) ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable)) return true; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e5b7f75186b..d8f1ed934e0 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3,7 +3,7 @@ import BattleScene, { ABILITY_OVERRIDE, AnySound, MOVE_OVERRIDE, OPP_ABILITY_OVE import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; -import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from '../data/pokemon-species'; +import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { getLevelTotalExp } from '../data/exp'; @@ -25,7 +25,8 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; +import { Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; +import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import { BattlerIndex } from '../battle'; import { BattleSpec } from "../enums/battle-spec"; @@ -556,7 +557,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01); if (isHp) { value = value + this.level + 10; - if (this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)) + if ((this.canApplyAbility() && this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)) || (this.canApplyAbility(true) && this.getPassiveAbility().hasAttr(NonSuperEffectiveImmunityAbAttr))) value = 1; if (this.hp > value || this.hp === undefined) this.hp = value; @@ -716,11 +717,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return allAbilities[abilityId]; } - canApplyAbility(): boolean { - const ability = this.getAbility(); + getPassiveAbility(): Ability { + let starterSpeciesId = this.species.speciesId; + while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId)) + starterSpeciesId = pokemonPrevolutions[starterSpeciesId]; + return allAbilities[starterPassiveAbilities[starterSpeciesId]]; + } + + canApplyAbility(passive: boolean = false): boolean { + if (passive && !this.isBoss()) + return false; + const ability = (!passive ? this.getAbility() : this.getPassiveAbility()); if (ability.isIgnorable && this.scene.arena.ignoreAbilities) return false; - return (this.hp || ability.isPassive) && !this.getAbility().conditions.find(condition => !condition(this)); + return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this)); } getWeight(): number { diff --git a/src/phases.ts b/src/phases.ts index 8c983317239..26a0651d647 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,8 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr } from "./data/ability"; +import { Abilities } from "./data/enums/abilities"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -1207,7 +1208,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { pokemon.resetTurnData(); - if (!this.loaded) { + if (!this.loaded || this.scene.currentBattle.battleType === BattleType.TRAINER || (this.scene.currentBattle.waveIndex % 10) === 1) { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true); this.queuePostSummon(); @@ -2131,7 +2132,7 @@ export class MovePhase extends BattlePhase { for (let opponent of targetedOpponents) { if (this.move.ppUsed === this.move.getMove().pp) break; - if (opponent.getAbility().id === Abilities.PRESSURE) + if ((opponent.canApplyAbility() && opponent.getAbility().hasAttr(IncreasePpAbAttr)) || (opponent.canApplyAbility(true) && opponent.getPassiveAbility().hasAttr(IncreasePpAbAttr))) this.move.ppUsed = Math.min(this.move.ppUsed + 1, this.move.getMovePp()); } } @@ -2502,14 +2503,18 @@ export class MoveAnimTestPhase extends BattlePhase { } export class ShowAbilityPhase extends PokemonPhase { - constructor(scene: BattleScene, battlerIndex: BattlerIndex) { + private passive: boolean; + + constructor(scene: BattleScene, battlerIndex: BattlerIndex, passive: boolean = false) { super(scene, battlerIndex); + + this.passive = passive; } start() { super.start(); - this.scene.abilityBar.showAbility(this.getPokemon()); + this.scene.abilityBar.showAbility(this.getPokemon(), this.passive); this.end(); } @@ -2904,11 +2909,9 @@ export class FaintPhase extends PokemonPhase { this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true); - if (pokemon.getAbility().hasAttr(PostFaintAbAttr)) { - if (pokemon.turnData?.attacksReceived?.length) { - const lastAttack = pokemon.turnData.attacksReceived[0]; - applyPostFaintAbAttrs(PostFaintAbAttr,pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); - } + if (pokemon.turnData?.attacksReceived?.length) { + const lastAttack = pokemon.turnData.attacksReceived[0]; + applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); } const alivePlayField = this.scene.getField(true); diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index 1985844e919..155123b8553 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -38,9 +38,9 @@ export default class AbilityBar extends Phaser.GameObjects.Container { this.shown = false; } - showAbility(pokemon: Pokemon): void { - this.pokemonNameText.setText(`${pokemon.name}'s`); - this.abilityNameText.setText(pokemon.getAbility().name); + showAbility(pokemon: Pokemon, passive: boolean = false): void { + this.pokemonNameText.setText(`${pokemon.name}'s${passive ? ' Passive' : ''}`); + this.abilityNameText.setText((!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name); if (this.shown) return;