abilities: implement guard dog, abilities that give intimidate immunity

This commit is contained in:
Madi Simpson 2024-05-03 21:45:52 -07:00
parent e02b85629f
commit a6b54c1786
2 changed files with 39 additions and 11 deletions

View File

@ -20,6 +20,7 @@ import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
import { Abilities } from "./enums/abilities"; import { Abilities } from "./enums/abilities";
import i18next, { Localizable } from "#app/plugins/i18n.js"; import i18next, { Localizable } from "#app/plugins/i18n.js";
import { Command } from "../ui/command-ui-handler"; import { Command } from "../ui/command-ui-handler";
import Battle from "#app/battle.js";
export class Ability implements Localizable { export class Ability implements Localizable {
public id: Abilities; public id: Abilities;
@ -1310,8 +1311,9 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
private stats: BattleStat[]; private stats: BattleStat[];
private levels: integer; private levels: integer;
private selfTarget: boolean; private selfTarget: boolean;
private intimidate: boolean;
constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean) { constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean, intimidate?: boolean) {
super(); super();
this.stats = typeof(stats) === 'number' this.stats = typeof(stats) === 'number'
@ -1319,16 +1321,25 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
: stats as BattleStat[]; : stats as BattleStat[];
this.levels = levels; this.levels = levels;
this.selfTarget = !!selfTarget; this.selfTarget = !!selfTarget;
this.intimidate = intimidate
} }
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
const statChangePhases: StatChangePhase[] = []; const statChangePhases: StatChangePhase[] = [];
const intimidateImmune: Pokemon[] = []
if (this.selfTarget) if (this.selfTarget)
statChangePhases.push(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); statChangePhases.push(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels));
else { else {
for (let opponent of pokemon.getOpponents()) for (let opponent of pokemon.getOpponents()) {
statChangePhases.push(new StatChangePhase(pokemon.scene, opponent.getBattlerIndex(), false, this.stats, this.levels)); const respectsAbilities: boolean = !pokemon.hasAbilityWithAttr(MoveAbilityBypassAbAttr)
const hasIntimidateImmunity: boolean = (this.intimidate && (opponent.hasAbilityWithAttr(IntimidateImmunityAbAttr) && respectsAbilities))
const invertsIntimidate: boolean = (this.intimidate && (opponent.hasAbilityWithAttr(InvertIntimidateAbAttr) && respectsAbilities))
if (!hasIntimidateImmunity)
statChangePhases.push(new StatChangePhase(pokemon.scene, opponent.getBattlerIndex(), false, this.stats, invertsIntimidate ? -this.levels : this.levels));
else
intimidateImmune.push(opponent);
}
} }
for (let statChangePhase of statChangePhases) { for (let statChangePhase of statChangePhases) {
@ -1337,6 +1348,9 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
else else
pokemon.scene.unshiftPhase(statChangePhase); pokemon.scene.unshiftPhase(statChangePhase);
} }
for (let opponent of intimidateImmune)
pokemon.scene.queueMessage(getPokemonMessage(opponent, ` can't be Intimidated!`));
return true; return true;
} }
@ -2253,6 +2267,12 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr {
export class IncreasePpAbAttr extends AbAttr { } export class IncreasePpAbAttr extends AbAttr { }
export class InvertIntimidateAbAttr extends AbAttr { }
export class IntimidateImmunityAbAttr extends AbAttr { }
export class ForceSwitchOutImmunityAbAttr extends AbAttr { }
export class ReduceBerryUseThresholdAbAttr extends AbAttr { export class ReduceBerryUseThresholdAbAttr extends AbAttr {
constructor() { constructor() {
super(); super();
@ -2593,6 +2613,7 @@ export function initAbilities() {
.ignorable(), .ignorable(),
new Ability(Abilities.OBLIVIOUS, 3) new Ability(Abilities.OBLIVIOUS, 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED) .attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED)
.attr(IntimidateImmunityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.CLOUD_NINE, 3) new Ability(Abilities.CLOUD_NINE, 3)
.attr(SuppressWeatherEffectAbAttr, true), .attr(SuppressWeatherEffectAbAttr, true),
@ -2615,12 +2636,13 @@ export function initAbilities() {
.unimplemented(), .unimplemented(),
new Ability(Abilities.OWN_TEMPO, 3) new Ability(Abilities.OWN_TEMPO, 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED) .attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
.attr(IntimidateImmunityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.SUCTION_CUPS, 3) new Ability(Abilities.SUCTION_CUPS, 3)
.ignorable() .ignorable()
.unimplemented(), .unimplemented(),
new Ability(Abilities.INTIMIDATE, 3) new Ability(Abilities.INTIMIDATE, 3)
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, -1), .attr(PostSummonStatChangeAbAttr, BattleStat.ATK, -1, false, true),
new Ability(Abilities.SHADOW_TAG, 3) new Ability(Abilities.SHADOW_TAG, 3)
.attr(ArenaTrapAbAttr), .attr(ArenaTrapAbAttr),
new Ability(Abilities.ROUGH_SKIN, 3) new Ability(Abilities.ROUGH_SKIN, 3)
@ -2669,6 +2691,7 @@ export function initAbilities() {
.attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON), .attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON),
new Ability(Abilities.INNER_FOCUS, 3) new Ability(Abilities.INNER_FOCUS, 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.FLINCHED) .attr(BattlerTagImmunityAbAttr, BattlerTagType.FLINCHED)
.attr(IntimidateImmunityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.MAGMA_ARMOR, 3) new Ability(Abilities.MAGMA_ARMOR, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE) .attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE)
@ -2865,8 +2888,9 @@ export function initAbilities() {
.ignorable(), .ignorable(),
new Ability(Abilities.SLOW_START, 4) new Ability(Abilities.SLOW_START, 4)
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5), .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
new Ability(Abilities.SCRAPPY, 4) new Ability(Abilities.SCRAPPY, 4)
.unimplemented(), .attr(IntimidateImmunityAbAttr)
.partial(),
new Ability(Abilities.STORM_DRAIN, 4) new Ability(Abilities.STORM_DRAIN, 4)
.attr(RedirectTypeMoveAbAttr, Type.WATER) .attr(RedirectTypeMoveAbAttr, Type.WATER)
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1) .attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1)
@ -3370,8 +3394,9 @@ export function initAbilities() {
.ignorable() .ignorable()
.partial(), .partial(),
new Ability(Abilities.GUARD_DOG, 9) new Ability(Abilities.GUARD_DOG, 9)
.ignorable() .attr(InvertIntimidateAbAttr)
.unimplemented(), .attr(ForceSwitchOutImmunityAbAttr)
.ignorable(),
new Ability(Abilities.ROCKY_PAYLOAD, 9) new Ability(Abilities.ROCKY_PAYLOAD, 9)
.attr(MoveTypePowerBoostAbAttr, Type.ROCK), .attr(MoveTypePowerBoostAbAttr, Type.ROCK),
new Ability(Abilities.WIND_POWER, 9) new Ability(Abilities.WIND_POWER, 9)

View File

@ -12,7 +12,7 @@ import * as Utils from "../utils";
import { WeatherType } from "./weather"; import { WeatherType } from "./weather";
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
import { ArenaTagType } from "./enums/arena-tag-type"; import { ArenaTagType } from "./enums/arena-tag-type";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr } from "./ability"; import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr } from "./ability";
import { Abilities } from "./enums/abilities"; import { Abilities } from "./enums/abilities";
import { allAbilities } from './ability'; import { allAbilities } from './ability';
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier } from "../modifier/modifier";
@ -2887,7 +2887,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise(resolve => { return new Promise(resolve => {
if (!this.user && target.isMax()) if (!this.user && (target.isMax()))
return resolve(false); return resolve(false);
// Check if the move category is not STATUS or if the switch out condition is not met // Check if the move category is not STATUS or if the switch out condition is not met
@ -2896,7 +2896,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, new PokemonMove(move.id), null); applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, new PokemonMove(move.id), null);
return resolve(false); return resolve(false);
} }
// Move the switch out logic inside the conditional block // Move the switch out logic inside the conditional block
// This ensures that the switch out only happens when the conditions are met // This ensures that the switch out only happens when the conditions are met
const switchOutTarget = this.user ? user : target; const switchOutTarget = this.user ? user : target;
@ -2953,6 +2953,9 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
const switchOutTarget = (this.user ? user : target); const switchOutTarget = (this.user ? user : target);
const player = switchOutTarget instanceof PlayerPokemon; const player = switchOutTarget instanceof PlayerPokemon;
if (!this.user && target.hasAbilityWithAttr(ForceSwitchOutImmunityAbAttr) && !user.hasAbilityWithAttr(MoveAbilityBypassAbAttr))
return false;
if (!player && !user.scene.currentBattle.battleType) { if (!player && !user.scene.currentBattle.battleType) {
if (this.batonPass) if (this.batonPass)
return false; return false;