|
|
|
@ -634,15 +634,15 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr {
|
|
|
|
|
* Examples include: Absorb, Draining Kiss, Bitter Blade, etc.
|
|
|
|
|
* Also displays a message to show this ability was activated.
|
|
|
|
|
* @param pokemon {@linkcode Pokemon} with this ability
|
|
|
|
|
* @param passive N/A
|
|
|
|
|
* @param _passive N/A
|
|
|
|
|
* @param attacker {@linkcode Pokemon} that is attacking this Pokemon
|
|
|
|
|
* @param move {@linkcode PokemonMove} that is being used
|
|
|
|
|
* @param hitResult N/A
|
|
|
|
|
* @args N/A
|
|
|
|
|
* @param _hitResult N/A
|
|
|
|
|
* @param _args N/A
|
|
|
|
|
* @returns true if healing should be reversed on a healing move, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.hasAttr(HitHealAttr)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
pokemon.scene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) }));
|
|
|
|
|
}
|
|
|
|
@ -669,8 +669,8 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.allOthers = allOthers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -707,13 +707,13 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.selfTarget = selfTarget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate);
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate);
|
|
|
|
|
const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1];
|
|
|
|
|
const damageReceived = lastAttackReceived?.damage || 0;
|
|
|
|
|
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat)) {
|
|
|
|
|
if (!simulated ) {
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.stages));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@ -734,8 +734,8 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.tagType = tagType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag;
|
|
|
|
|
if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
@ -758,8 +758,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.tagType = tagType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!pokemon.getTag(this.tagType) && !simulated) {
|
|
|
|
|
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
|
|
|
|
|
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }));
|
|
|
|
@ -771,8 +771,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (hitResult < HitResult.NO_EFFECT) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -787,7 +787,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return i18next.t("abilityTriggers:postDefendTypeChange", {
|
|
|
|
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
|
|
|
|
abilityName,
|
|
|
|
@ -805,8 +805,8 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.terrainType = terrainType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (hitResult < HitResult.NO_EFFECT) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return pokemon.scene.arena.terrain?.terrainType !== (this.terrainType || undefined);
|
|
|
|
|
} else {
|
|
|
|
@ -829,8 +829,9 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.effects = effects;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status
|
|
|
|
|
&& (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)];
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return attacker.canSetStatus(effect, true, false, pokemon);
|
|
|
|
@ -869,8 +870,8 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.turnCount = turnCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return attacker.canAddTag(this.tagType);
|
|
|
|
|
} else {
|
|
|
|
@ -893,7 +894,11 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.stages = stages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.stages));
|
|
|
|
|
}
|
|
|
|
@ -901,7 +906,7 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getCondition(): AbAttrCondition {
|
|
|
|
|
override getCondition(): AbAttrCondition {
|
|
|
|
|
return (pokemon: Pokemon) => pokemon.turnData.attacksReceived.length !== 0 && pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1].critical;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -915,8 +920,9 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.damageRatio = damageRatio;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)
|
|
|
|
|
&& !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
|
|
|
|
attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio));
|
|
|
|
|
return true;
|
|
|
|
@ -925,7 +931,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return i18next.t("abilityTriggers:postDefendContactDamage", {
|
|
|
|
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
|
|
|
|
abilityName
|
|
|
|
@ -948,8 +954,8 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.turns = turns;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
@ -963,24 +969,24 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return i18next.t("abilityTriggers:perishBody", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
|
|
|
|
private weatherType: WeatherType;
|
|
|
|
|
protected condition: PokemonDefendCondition | null;
|
|
|
|
|
protected condition?: PokemonDefendCondition;
|
|
|
|
|
|
|
|
|
|
constructor(weatherType: WeatherType, condition?: PokemonDefendCondition) {
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
|
|
this.weatherType = weatherType;
|
|
|
|
|
this.condition = condition ?? null;
|
|
|
|
|
this.condition = condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (this.condition !== null && !this.condition(pokemon, attacker, move)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!pokemon.scene.arena.weather?.isImmutable()) {
|
|
|
|
@ -999,8 +1005,9 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
|
|
|
|
|
super();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)
|
|
|
|
|
&& !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
const tempAbilityId = attacker.getAbility().id;
|
|
|
|
|
attacker.summonData.ability = pokemon.getAbility().id;
|
|
|
|
@ -1012,7 +1019,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
override getTriggerMessage(pokemon: Pokemon, _abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return i18next.t("abilityTriggers:postDefendAbilitySwap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1025,8 +1032,9 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.ability = ability;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr)
|
|
|
|
|
&& !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
attacker.summonData.ability = this.ability;
|
|
|
|
|
}
|
|
|
|
@ -1037,7 +1045,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return i18next.t("abilityTriggers:postDefendAbilityGive", {
|
|
|
|
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
|
|
|
|
abilityName
|
|
|
|
@ -1056,8 +1064,8 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
|
|
|
|
this.chance = chance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
|
|
|
|
if (attacker.getTag(BattlerTagType.DISABLED) === null) {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
|
|
|
|
if (attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
|
|
|
|
if (simulated) {
|
|
|
|
|
return true;
|
|
|
|
@ -1724,17 +1732,17 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
|
|
|
|
private condition: PokemonDefendCondition | null;
|
|
|
|
|
private condition?: PokemonDefendCondition;
|
|
|
|
|
|
|
|
|
|
constructor(condition?: PokemonDefendCondition) {
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
|
|
this.condition = condition ?? null;
|
|
|
|
|
this.condition = condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
|
|
|
|
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): Promise<boolean> {
|
|
|
|
|
return new Promise<boolean>(resolve => {
|
|
|
|
|
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) {
|
|
|
|
|
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move)) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
|
|
|
|
if (heldItems.length) {
|
|
|
|
|
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
|
|
|
@ -4476,7 +4484,7 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC
|
|
|
|
|
export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
|
|
|
|
private multiplier: number;
|
|
|
|
|
private tagType: BattlerTagType;
|
|
|
|
|
private recoilDamageFunc: ((pokemon: Pokemon) => number) | undefined;
|
|
|
|
|
private recoilDamageFunc?: ((pokemon: Pokemon) => number);
|
|
|
|
|
private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string;
|
|
|
|
|
|
|
|
|
|
constructor(condition: PokemonDefendCondition, multiplier: number, tagType: BattlerTagType, triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string, recoilDamageFunc?: (pokemon: Pokemon) => number) {
|
|
|
|
@ -4492,16 +4500,16 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
|
|
|
|
* Applies the pre-defense ability to the Pokémon.
|
|
|
|
|
* Removes the appropriate `BattlerTagType` when hit by an attack and is in its defense form.
|
|
|
|
|
*
|
|
|
|
|
* @param {Pokemon} pokemon The Pokémon with the ability.
|
|
|
|
|
* @param {boolean} passive n/a
|
|
|
|
|
* @param {Pokemon} attacker The attacking Pokémon.
|
|
|
|
|
* @param {PokemonMove} move The move being used.
|
|
|
|
|
* @param {Utils.BooleanHolder} cancelled n/a
|
|
|
|
|
* @param {any[]} args Additional arguments.
|
|
|
|
|
* @returns {boolean} Whether the immunity was applied.
|
|
|
|
|
* @param pokemon The Pokémon with the ability.
|
|
|
|
|
* @param _passive n/a
|
|
|
|
|
* @param attacker The attacking Pokémon.
|
|
|
|
|
* @param move The move being used.
|
|
|
|
|
* @param _cancelled n/a
|
|
|
|
|
* @param args Additional arguments.
|
|
|
|
|
* @returns `true` if the immunity was applied.
|
|
|
|
|
*/
|
|
|
|
|
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move)) {
|
|
|
|
|
override applyPreDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
|
|
|
|
if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) {
|
|
|
|
|
if (!simulated) {
|
|
|
|
|
(args[0] as Utils.NumberHolder).value = this.multiplier;
|
|
|
|
|
pokemon.removeTag(this.tagType);
|
|
|
|
@ -4517,12 +4525,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the message triggered when the Pokémon avoids damage using the form-changing ability.
|
|
|
|
|
* @param {Pokemon} pokemon The Pokémon with the ability.
|
|
|
|
|
* @param {string} abilityName The name of the ability.
|
|
|
|
|
* @param {...any} args n/a
|
|
|
|
|
* @returns {string} The trigger message.
|
|
|
|
|
* @param pokemon The Pokémon with the ability.
|
|
|
|
|
* @param abilityName The name of the ability.
|
|
|
|
|
* @param _args n/a
|
|
|
|
|
* @returns The trigger message.
|
|
|
|
|
*/
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
|
|
|
|
getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string {
|
|
|
|
|
return this.triggerMessageFunc(pokemon, abilityName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -5503,7 +5511,8 @@ export function initAbilities() {
|
|
|
|
|
.attr(NoFusionAbilityAbAttr)
|
|
|
|
|
// Add BattlerTagType.DISGUISE if the pokemon is in its disguised form
|
|
|
|
|
.conditionalAttr(pokemon => pokemon.formIndex === 0, PostSummonAddBattlerTagAbAttr, BattlerTagType.DISGUISE, 0, false)
|
|
|
|
|
.attr(FormBlockDamageAbAttr, (target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE,
|
|
|
|
|
.attr(FormBlockDamageAbAttr,
|
|
|
|
|
(target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE,
|
|
|
|
|
(pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }),
|
|
|
|
|
(pokemon) => Utils.toDmgValue(pokemon.getMaxHp() / 8))
|
|
|
|
|
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
|
|
|
@ -5665,7 +5674,8 @@ export function initAbilities() {
|
|
|
|
|
.conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0)
|
|
|
|
|
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
|
|
|
|
|
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
|
|
|
|
|
.attr(FormBlockDamageAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
|
|
|
|
.attr(FormBlockDamageAbAttr,
|
|
|
|
|
(target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
|
|
|
|
(pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }))
|
|
|
|
|
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
|
|
|
|
.bypassFaint()
|
|
|
|
|