Fix mold breaker + implement neutralising gas
parent
3a64a8390a
commit
453c5644aa
|
@ -2034,13 +2034,35 @@ export class SyncEncounterNatureAbAttr extends AbAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MoveAbilityBypassAbAttr extends AbAttr {
|
export class MoveAbilityBypassAbAttr extends AbAttr {
|
||||||
|
private moveIgnoreFunc: (pokemon: Pokemon, move: Move) => boolean;
|
||||||
|
|
||||||
|
constructor(moveIgnoreFunc?: (pokemon: Pokemon, move: Move) => boolean) {
|
||||||
|
super(false);
|
||||||
|
|
||||||
|
this.moveIgnoreFunc = moveIgnoreFunc || ((pokemon, move) => true);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||||
|
if (this.moveIgnoreFunc(pokemon, (args[0] as Move))) {
|
||||||
|
cancelled.value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SuppressFieldAbilitiesAbAttr extends AbAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(false);
|
super(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||||
cancelled.value = true;
|
const ability = (args[0] as Ability);
|
||||||
return true;
|
if (!ability.hasAttr(UnsuppressableAbilityAbAttr) && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) {
|
||||||
|
cancelled.value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2912,7 +2934,8 @@ export function initAbilities() {
|
||||||
.attr(PostDefendAbilitySwapAbAttr)
|
.attr(PostDefendAbilitySwapAbAttr)
|
||||||
.bypassFaint(),
|
.bypassFaint(),
|
||||||
new Ability(Abilities.GORILLA_TACTICS, "Gorilla Tactics (N)", "Boosts the Pokémon's Attack stat but only allows the use of the first selected move.", 8),
|
new Ability(Abilities.GORILLA_TACTICS, "Gorilla Tactics (N)", "Boosts the Pokémon's Attack stat but only allows the use of the first selected move.", 8),
|
||||||
new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas (N)", "If the Pokémon with Neutralizing Gas is in the battle, the effects of all Pokémon's Abilities will be nullified or will not be triggered.", 8)
|
new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas (P)", "If the Pokémon with Neutralizing Gas is in the battle, the effects of all Pokémon's Abilities will be nullified or will not be triggered.", 8)
|
||||||
|
.attr(SuppressFieldAbilitiesAbAttr)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr),
|
.attr(NoTransformAbilityAbAttr),
|
||||||
|
@ -3028,7 +3051,8 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
|
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
|
||||||
.attr(TypeImmunityHealAbAttr, Type.GROUND)
|
.attr(TypeImmunityHealAbAttr, Type.GROUND)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.MYCELIUM_MIGHT, "Mycelium Might (N)", "The Pokémon will always act more slowly when using status moves, but these moves will be unimpeded by the Ability of the target.", 9),
|
new Ability(Abilities.MYCELIUM_MIGHT, "Mycelium Might (P)", "The Pokémon will always act more slowly when using status moves, but these moves will be unimpeded by the Ability of the target.", 9)
|
||||||
|
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
|
||||||
new Ability(Abilities.MINDS_EYE, "Mind's Eye (N)", "The Pokémon ignores changes to opponents' evasiveness, its accuracy can't be lowered, and it can hit Ghost types with Normal- and Fighting-type moves.", 9)
|
new Ability(Abilities.MINDS_EYE, "Mind's Eye (N)", "The Pokémon ignores changes to opponents' evasiveness, its accuracy can't be lowered, and it can hit Ghost types with Normal- and Fighting-type moves.", 9)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.SUPERSWEET_SYRUP, "Supersweet Syrup (N)", "A sickly sweet scent spreads across the field the first time the Pokémon enters a battle, lowering the evasiveness of opposing Pokémon.", 9),
|
new Ability(Abilities.SUPERSWEET_SYRUP, "Supersweet Syrup (N)", "A sickly sweet scent spreads across the field the first time the Pokémon enters a battle, lowering the evasiveness of opposing Pokémon.", 9),
|
||||||
|
|
|
@ -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 } from "./ability";
|
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr } 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";
|
||||||
|
@ -68,7 +68,8 @@ export enum MoveFlags {
|
||||||
POWDER_MOVE = 2048,
|
POWDER_MOVE = 2048,
|
||||||
DANCE_MOVE = 4096,
|
DANCE_MOVE = 4096,
|
||||||
WIND_MOVE = 8192,
|
WIND_MOVE = 8192,
|
||||||
TRIAGE_MOVE = 16384
|
TRIAGE_MOVE = 16384,
|
||||||
|
IGNORE_ABILITIES = 32768
|
||||||
}
|
}
|
||||||
|
|
||||||
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
||||||
|
@ -286,12 +287,24 @@ export default class Move {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ignoresAbilities(ignoresAbilities?: boolean): this {
|
||||||
|
this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case MoveFlags.MAKES_CONTACT:
|
case MoveFlags.MAKES_CONTACT:
|
||||||
if (user.hasAbilityWithAttr(IgnoreContactAbAttr))
|
if (user.hasAbilityWithAttr(IgnoreContactAbAttr))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
case MoveFlags.IGNORE_ABILITIES:
|
||||||
|
if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) {
|
||||||
|
const abilityEffectsIgnored = new Utils.BooleanHolder(false);
|
||||||
|
applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, this);
|
||||||
|
if (abilityEffectsIgnored.value)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!(this.flags & flag);
|
return !!(this.flags & flag);
|
||||||
|
@ -5405,8 +5418,10 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7)
|
new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7)
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7)
|
||||||
|
.ignoresAbilities()
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||||
|
.ignoresAbilities()
|
||||||
.partial(),
|
.partial(),
|
||||||
new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, 100, 0, 7)
|
new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, 100, 0, 7)
|
||||||
.attr(StatChangeAttr, BattleStat.ATK, -1)
|
.attr(StatChangeAttr, BattleStat.ATK, -1)
|
||||||
|
@ -5429,15 +5444,16 @@ export function initMoves() {
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||||
.attr(PhotonGeyserCategoryAttr)
|
.attr(PhotonGeyserCategoryAttr)
|
||||||
|
.ignoresAbilities()
|
||||||
.partial(),
|
.partial(),
|
||||||
/* Unused */
|
/* Unused */
|
||||||
new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
||||||
.attr(PhotonGeyserCategoryAttr)
|
.attr(PhotonGeyserCategoryAttr)
|
||||||
.partial(),
|
.ignoresAbilities(),
|
||||||
new AttackMove(Moves.SEARING_SUNRAZE_SMASH, Type.STEEL, MoveCategory.PHYSICAL, 200, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.SEARING_SUNRAZE_SMASH, Type.STEEL, MoveCategory.PHYSICAL, 200, -1, 1, -1, 0, 7)
|
||||||
.partial(),
|
.ignoresAbilities(),
|
||||||
new AttackMove(Moves.MENACING_MOONRAZE_MAELSTROM, Type.GHOST, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.MENACING_MOONRAZE_MAELSTROM, Type.GHOST, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
||||||
.partial(),
|
.ignoresAbilities(),
|
||||||
new AttackMove(Moves.LETS_SNUGGLE_FOREVER, Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.LETS_SNUGGLE_FOREVER, Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { TempBattleStat } from '../data/temp-battle-stat';
|
||||||
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
|
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
|
||||||
import { ArenaTagType } from "../data/enums/arena-tag-type";
|
import { ArenaTagType } from "../data/enums/arena-tag-type";
|
||||||
import { Biome } from "../data/enums/biome";
|
import { Biome } from "../data/enums/biome";
|
||||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability';
|
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr } from '../data/ability';
|
||||||
import { Abilities } from "#app/data/enums/abilities";
|
import { Abilities } from "#app/data/enums/abilities";
|
||||||
import PokemonData from '../system/pokemon-data';
|
import PokemonData from '../system/pokemon-data';
|
||||||
import Battle, { BattlerIndex } from '../battle';
|
import Battle, { BattlerIndex } from '../battle';
|
||||||
|
@ -740,8 +740,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (passive && !this.hasPassive())
|
if (passive && !this.hasPassive())
|
||||||
return false;
|
return false;
|
||||||
const ability = (!passive ? this.getAbility() : this.getPassiveAbility());
|
const ability = (!passive ? this.getAbility() : this.getPassiveAbility());
|
||||||
if (ability.isIgnorable && this.scene.arena.ignoreAbilities)
|
if (this.scene?.arena.ignoreAbilities && ability.isIgnorable)
|
||||||
|
return false;
|
||||||
|
if (this.summonData?.abilitySuppressed && !ability.hasAttr(UnsuppressableAbilityAbAttr))
|
||||||
|
return false;
|
||||||
|
if (this.isOnField() && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) {
|
||||||
|
const suppressed = new Utils.BooleanHolder(false);
|
||||||
|
this.scene.getField(true).map(p => {
|
||||||
|
if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility())
|
||||||
|
p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, suppressed, [ability]));
|
||||||
|
if (p.getPassiveAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility(true))
|
||||||
|
p.getPassiveAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, true, suppressed, [ability]));
|
||||||
|
});
|
||||||
|
if (suppressed.value)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this));
|
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2829,6 +2842,7 @@ export class PokemonSummonData {
|
||||||
public disabledMove: Moves = Moves.NONE;
|
public disabledMove: Moves = Moves.NONE;
|
||||||
public disabledTurns: integer = 0;
|
public disabledTurns: integer = 0;
|
||||||
public tags: BattlerTag[] = [];
|
public tags: BattlerTag[] = [];
|
||||||
|
public abilitySuppressed: boolean = false;
|
||||||
|
|
||||||
public speciesForm: PokemonSpeciesForm;
|
public speciesForm: PokemonSpeciesForm;
|
||||||
public fusionSpeciesForm: PokemonSpeciesForm;
|
public fusionSpeciesForm: PokemonSpeciesForm;
|
||||||
|
|
|
@ -2141,10 +2141,8 @@ export class MovePhase extends BattlePhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.followUp) {
|
if (!this.followUp) {
|
||||||
const abilityEffectsIgnored = new Utils.BooleanHolder(false);
|
if (this.move.getMove().checkFlag(MoveFlags.IGNORE_ABILITIES, this.pokemon, null))
|
||||||
this.scene.getField(true).map(p => applyAbAttrs(MoveAbilityBypassAbAttr, p, abilityEffectsIgnored));
|
this.scene.arena.setIgnoreAbilities();
|
||||||
if (abilityEffectsIgnored.value)
|
|
||||||
this.scene.arena.setIgnoreAbilities(true);
|
|
||||||
} else {
|
} else {
|
||||||
this.pokemon.turnData.hitsLeft = undefined;
|
this.pokemon.turnData.hitsLeft = undefined;
|
||||||
this.pokemon.turnData.hitCount = undefined;
|
this.pokemon.turnData.hitCount = undefined;
|
||||||
|
|
Loading…
Reference in New Issue