Merge branch 'pagefaultgames:main' into main

This commit is contained in:
NxKarim 2024-04-18 15:42:05 -06:00 committed by GitHub
commit 4c27b9df9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 5978 additions and 41 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -2053,14 +2053,36 @@ 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 {
const ability = (args[0] as Ability);
if (!ability.hasAttr(UnsuppressableAbilityAbAttr) && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
return false;
}
} }
export class UncopiableAbilityAbAttr extends AbAttr { export class UncopiableAbilityAbAttr extends AbAttr {
@ -2931,7 +2953,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),
@ -3047,7 +3070,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),

View File

@ -79,6 +79,7 @@ export enum CommonAnim {
MAGMA_STORM, MAGMA_STORM,
CLAMP, CLAMP,
THUNDER_CAGE, THUNDER_CAGE,
INFESTATION,
ORDER_UP_CURLY, ORDER_UP_CURLY,
ORDER_UP_DROOPY, ORDER_UP_DROOPY,
ORDER_UP_STRETCHY, ORDER_UP_STRETCHY,

View File

@ -613,6 +613,16 @@ export class ThunderCageTag extends DamagingTrapTag {
} }
} }
export class InfestationTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.INFESTATION, CommonAnim.INFESTATION, turnCount, Moves.INFESTATION, sourceId);
}
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ` has been afflicted \nwith an infestation by ${getPokemonPrefix(pokemon.scene.getPokemonById(this.sourceId))}${pokemon.scene.getPokemonById(this.sourceId).name}!`);
}
}
export class ProtectedTag extends BattlerTag { export class ProtectedTag extends BattlerTag {
constructor(sourceMove: Moves, tagType: BattlerTagType = BattlerTagType.PROTECTED) { constructor(sourceMove: Moves, tagType: BattlerTagType = BattlerTagType.PROTECTED) {
@ -1051,6 +1061,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new MagmaStormTag(turnCount, sourceId); return new MagmaStormTag(turnCount, sourceId);
case BattlerTagType.THUNDER_CAGE: case BattlerTagType.THUNDER_CAGE:
return new ThunderCageTag(turnCount, sourceId); return new ThunderCageTag(turnCount, sourceId);
case BattlerTagType.INFESTATION:
return new InfestationTag(turnCount, sourceId);
case BattlerTagType.PROTECTED: case BattlerTagType.PROTECTED:
return new ProtectedTag(sourceMove); return new ProtectedTag(sourceMove);
case BattlerTagType.SPIKY_SHIELD: case BattlerTagType.SPIKY_SHIELD:

View File

@ -22,6 +22,7 @@ export enum BattlerTagType {
SAND_TOMB = "SAND_TOMB", SAND_TOMB = "SAND_TOMB",
MAGMA_STORM = "MAGMA_STORM", MAGMA_STORM = "MAGMA_STORM",
THUNDER_CAGE = "THUNDER_CAGE", THUNDER_CAGE = "THUNDER_CAGE",
INFESTATION = "INFESTATION",
PROTECTED = "PROTECTED", PROTECTED = "PROTECTED",
SPIKY_SHIELD = "SPIKY_SHIELD", SPIKY_SHIELD = "SPIKY_SHIELD",
KINGS_SHIELD = "KINGS_SHIELD", KINGS_SHIELD = "KINGS_SHIELD",

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 } 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);
@ -1422,7 +1435,7 @@ export class HalfHpStatMaxAttr extends StatChangeAttr {
user.scene.damageNumberHandler.add(user, damage); user.scene.damageNumberHandler.add(user, damage);
user.updateInfo().then(() => { user.updateInfo().then(() => {
const ret = super.apply(user, target, move, args); const ret = super.apply(user, target, move, args);
user.scene.queueMessage(getPokemonMessage(user, ` cut its own hp\nand maximized its ${getBattleStatName(this.stats[0])}!`)); user.scene.queueMessage(getPokemonMessage(user, ` cut its own HP\nand maximized its ${getBattleStatName(this.stats[0])}!`));
resolve(ret); resolve(ret);
}); });
}); });
@ -1461,6 +1474,24 @@ export class CutHpStatBoostAttr extends StatChangeAttr {
} }
} }
export class CopyStatsAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args))
return false;
for (let s = 0; s < target.summonData.battleStats.length; s++)
user.summonData.battleStats[s] = target.summonData.battleStats[s];
if (target.getTag(BattlerTagType.CRIT_BOOST))
user.addTag(BattlerTagType.CRIT_BOOST, 0, move.id);
else
user.removeTag(BattlerTagType.CRIT_BOOST);
target.scene.queueMessage(getPokemonMessage(user, 'copied\n') + getPokemonMessage(target, `'s stat changes!`));
return true;
}
}
export class InvertStatsAttr extends MoveEffectAttr { export class InvertStatsAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) if (!super.apply(user, target, move, args))
@ -1475,6 +1506,20 @@ export class InvertStatsAttr extends MoveEffectAttr {
} }
} }
export class ResetStatsAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args))
return false;
for (let s = 0; s < target.summonData.battleStats.length; s++)
target.summonData.battleStats[s] = 0;
target.scene.queueMessage(getPokemonMessage(target, `'s stat changes\nwere eliminated!`));
return true;
}
}
export class HpSplitAttr extends MoveEffectAttr { export class HpSplitAttr 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 => {
@ -2414,6 +2459,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
case BattlerTagType.SAND_TOMB: case BattlerTagType.SAND_TOMB:
case BattlerTagType.MAGMA_STORM: case BattlerTagType.MAGMA_STORM:
case BattlerTagType.THUNDER_CAGE: case BattlerTagType.THUNDER_CAGE:
case BattlerTagType.INFESTATION:
return -3; return -3;
case BattlerTagType.ENCORE: case BattlerTagType.ENCORE:
return -2; return -2;
@ -2883,7 +2929,7 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr {
: moveTargets.targets.indexOf(target.getBattlerIndex()) > -1 : moveTargets.targets.indexOf(target.getBattlerIndex()) > -1
? [ target.getBattlerIndex() ] ? [ target.getBattlerIndex() ]
: [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; : [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ];
user.getMoveQueue().push({ move: move.moveId, targets: targets, ignorePP: this.enemyMoveset }); user.getMoveQueue().push({ move: move.moveId, targets: targets, ignorePP: true });
user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, moveset[moveIndex], true)); user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, moveset[moveIndex], true));
return true; return true;
} }
@ -3787,7 +3833,7 @@ export function initMoves() {
.target(MoveTarget.USER_SIDE), .target(MoveTarget.USER_SIDE),
new StatusMove(Moves.HAZE, Type.ICE, -1, 30, -1, 0, 1) new StatusMove(Moves.HAZE, Type.ICE, -1, 30, -1, 0, 1)
.target(MoveTarget.BOTH_SIDES) .target(MoveTarget.BOTH_SIDES)
.unimplemented(), .attr(ResetStatsAttr),
new StatusMove(Moves.REFLECT, Type.PSYCHIC, -1, 20, -1, 0, 1) new StatusMove(Moves.REFLECT, Type.PSYCHIC, -1, 20, -1, 0, 1)
.attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, true) .attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, true)
.target(MoveTarget.USER_SIDE), .target(MoveTarget.USER_SIDE),
@ -4071,7 +4117,8 @@ export function initMoves() {
new SelfStatusMove(Moves.SLEEP_TALK, Type.NORMAL, -1, 10, -1, 0, 2) new SelfStatusMove(Moves.SLEEP_TALK, Type.NORMAL, -1, 10, -1, 0, 2)
.attr(BypassSleepAttr) .attr(BypassSleepAttr)
.attr(RandomMovesetMoveAttr) .attr(RandomMovesetMoveAttr)
.condition((user, target, move) => user.status?.effect === StatusEffect.SLEEP), .condition((user, target, move) => user.status?.effect === StatusEffect.SLEEP)
.ignoresVirtual(),
new StatusMove(Moves.HEAL_BELL, Type.NORMAL, -1, 5, -1, 0, 2) new StatusMove(Moves.HEAL_BELL, Type.NORMAL, -1, 5, -1, 0, 2)
.soundBased() .soundBased()
.target(MoveTarget.USER_AND_ALLIES) .target(MoveTarget.USER_AND_ALLIES)
@ -4115,7 +4162,18 @@ export function initMoves() {
.partial(), .partial(),
new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2) new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2)
.attr(StatChangeAttr, BattleStat.SPD, 1, true) .attr(StatChangeAttr, BattleStat.SPD, 1, true)
.attr(RemoveBattlerTagAttr, [ BattlerTagType.BIND, BattlerTagType.WRAP, BattlerTagType.FIRE_SPIN, BattlerTagType.WHIRLPOOL, BattlerTagType.CLAMP, BattlerTagType.SAND_TOMB, BattlerTagType.MAGMA_STORM, BattlerTagType.THUNDER_CAGE, BattlerTagType.SEEDED ], true) .attr(RemoveBattlerTagAttr, [
BattlerTagType.BIND,
BattlerTagType.WRAP,
BattlerTagType.FIRE_SPIN,
BattlerTagType.WHIRLPOOL,
BattlerTagType.CLAMP,
BattlerTagType.SAND_TOMB,
BattlerTagType.MAGMA_STORM,
BattlerTagType.THUNDER_CAGE,
BattlerTagType.SEEDED,
BattlerTagType.INFESTATION
], true)
.partial(), .partial(),
new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2) new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2)
.attr(StatChangeAttr, BattleStat.EVA, -1) .attr(StatChangeAttr, BattleStat.EVA, -1)
@ -4156,7 +4214,7 @@ export function initMoves() {
.attr(CounterDamageAttr, (move: Move) => move.category === MoveCategory.SPECIAL, 2) .attr(CounterDamageAttr, (move: Move) => move.category === MoveCategory.SPECIAL, 2)
.target(MoveTarget.ATTACKER), .target(MoveTarget.ATTACKER),
new StatusMove(Moves.PSYCH_UP, Type.NORMAL, -1, 10, -1, 0, 2) new StatusMove(Moves.PSYCH_UP, Type.NORMAL, -1, 10, -1, 0, 2)
.unimplemented(), .attr(CopyStatsAttr),
new AttackMove(Moves.EXTREME_SPEED, Type.NORMAL, MoveCategory.PHYSICAL, 80, 100, 5, -1, 2, 2), new AttackMove(Moves.EXTREME_SPEED, Type.NORMAL, MoveCategory.PHYSICAL, 80, 100, 5, -1, 2, 2),
new AttackMove(Moves.ANCIENT_POWER, Type.ROCK, MoveCategory.SPECIAL, 60, 100, 5, 10, 0, 2) new AttackMove(Moves.ANCIENT_POWER, Type.ROCK, MoveCategory.SPECIAL, 60, 100, 5, 10, 0, 2)
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true), .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true),
@ -4443,7 +4501,7 @@ export function initMoves() {
.attr(ConfuseAttr) .attr(ConfuseAttr)
.pulseMove(), .pulseMove(),
new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3) new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3)
.attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, 'chose\nDOOM DESIRE as its destiny!'), .attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, 'chose\nDoom Desire as its destiny!'),
new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, 100, 0, 3) new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, 100, 0, 3)
.attr(StatChangeAttr, BattleStat.SPATK, -2, true), .attr(StatChangeAttr, BattleStat.SPATK, -2, true),
new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4) new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4)
@ -4837,7 +4895,7 @@ export function initMoves() {
new AttackMove(Moves.CHIP_AWAY, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 5) new AttackMove(Moves.CHIP_AWAY, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 5)
.attr(IgnoreOpponentStatChangesAttr), .attr(IgnoreOpponentStatChangesAttr),
new AttackMove(Moves.CLEAR_SMOG, Type.POISON, MoveCategory.SPECIAL, 50, -1, 15, -1, 0, 5) new AttackMove(Moves.CLEAR_SMOG, Type.POISON, MoveCategory.SPECIAL, 50, -1, 15, -1, 0, 5)
.partial(), .attr(ResetStatsAttr),
new AttackMove(Moves.STORED_POWER, Type.PSYCHIC, MoveCategory.SPECIAL, 20, 100, 10, -1, 0, 5) new AttackMove(Moves.STORED_POWER, Type.PSYCHIC, MoveCategory.SPECIAL, 20, 100, 10, -1, 0, 5)
.attr(StatChangeCountPowerAttr), .attr(StatChangeCountPowerAttr),
new StatusMove(Moves.QUICK_GUARD, Type.FIGHTING, -1, 15, -1, 3, 5) new StatusMove(Moves.QUICK_GUARD, Type.FIGHTING, -1, 15, -1, 3, 5)
@ -5134,7 +5192,7 @@ export function initMoves() {
.attr(SurviveDamageAttr), .attr(SurviveDamageAttr),
new AttackMove(Moves.INFESTATION, Type.BUG, MoveCategory.SPECIAL, 20, 100, 20, 100, 0, 6) new AttackMove(Moves.INFESTATION, Type.BUG, MoveCategory.SPECIAL, 20, 100, 20, 100, 0, 6)
.makesContact() .makesContact()
.partial(), .attr(TrapAttr, BattlerTagType.INFESTATION),
new AttackMove(Moves.POWER_UP_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 20, 100, 0, 6) new AttackMove(Moves.POWER_UP_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 20, 100, 0, 6)
.attr(StatChangeAttr, BattleStat.ATK, 1, true) .attr(StatChangeAttr, BattleStat.ATK, 1, true)
.punchingMove(), .punchingMove(),
@ -5387,8 +5445,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)
@ -5411,15 +5471,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)
@ -5453,7 +5514,7 @@ export function initMoves() {
new AttackMove(Moves.SAPPY_SEED, Type.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7) new AttackMove(Moves.SAPPY_SEED, Type.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7)
.attr(AddBattlerTagAttr, BattlerTagType.SEEDED), .attr(AddBattlerTagAttr, BattlerTagType.SEEDED),
new AttackMove(Moves.FREEZY_FROST, Type.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7) new AttackMove(Moves.FREEZY_FROST, Type.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7)
.partial(), .attr(ResetStatsAttr),
new AttackMove(Moves.SPARKLY_SWIRL, Type.FAIRY, MoveCategory.SPECIAL, 120, 85, 5, -1, 0, 7) new AttackMove(Moves.SPARKLY_SWIRL, Type.FAIRY, MoveCategory.SPECIAL, 120, 85, 5, -1, 0, 7)
.partial(), .partial(),
new AttackMove(Moves.VEEVEE_VOLLEY, Type.NORMAL, MoveCategory.PHYSICAL, -1, -1, 20, -1, 0, 7) new AttackMove(Moves.VEEVEE_VOLLEY, Type.NORMAL, MoveCategory.PHYSICAL, -1, -1, 20, -1, 0, 7)
@ -5929,7 +5990,18 @@ export function initMoves() {
new AttackMove(Moves.TRIPLE_DIVE, Type.WATER, MoveCategory.PHYSICAL, 30, 95, 10, -1, 0, 9) new AttackMove(Moves.TRIPLE_DIVE, Type.WATER, MoveCategory.PHYSICAL, 30, 95, 10, -1, 0, 9)
.attr(MultiHitAttr, MultiHitType._3), .attr(MultiHitAttr, MultiHitType._3),
new AttackMove(Moves.MORTAL_SPIN, Type.POISON, MoveCategory.PHYSICAL, 30, 100, 15, 100, 0, 9) new AttackMove(Moves.MORTAL_SPIN, Type.POISON, MoveCategory.PHYSICAL, 30, 100, 15, 100, 0, 9)
.attr(LapseBattlerTagAttr, [ BattlerTagType.BIND, BattlerTagType.WRAP, BattlerTagType.FIRE_SPIN, BattlerTagType.WHIRLPOOL, BattlerTagType.CLAMP, BattlerTagType.SAND_TOMB, BattlerTagType.MAGMA_STORM, BattlerTagType.THUNDER_CAGE, BattlerTagType.SEEDED ], true) .attr(LapseBattlerTagAttr, [
BattlerTagType.BIND,
BattlerTagType.WRAP,
BattlerTagType.FIRE_SPIN,
BattlerTagType.WHIRLPOOL,
BattlerTagType.CLAMP,
BattlerTagType.SAND_TOMB,
BattlerTagType.MAGMA_STORM,
BattlerTagType.THUNDER_CAGE,
BattlerTagType.SEEDED,
BattlerTagType.INFESTATION
], true)
.attr(StatusEffectAttr, StatusEffect.POISON) .attr(StatusEffectAttr, StatusEffect.POISON)
.target(MoveTarget.ALL_NEAR_ENEMIES), .target(MoveTarget.ALL_NEAR_ENEMIES),
new StatusMove(Moves.DOODLE, Type.NORMAL, 100, 10, -1, 0, 9) new StatusMove(Moves.DOODLE, Type.NORMAL, 100, 10, -1, 0, 9)

View File

@ -3234,7 +3234,7 @@ export const starterPassiveAbilities = {
[Species.ZIGZAGOON]: Abilities.PICKPOCKET, [Species.ZIGZAGOON]: Abilities.PICKPOCKET,
[Species.WURMPLE]: Abilities.TINTED_LENS, [Species.WURMPLE]: Abilities.TINTED_LENS,
[Species.LOTAD]: Abilities.DRIZZLE, [Species.LOTAD]: Abilities.DRIZZLE,
[Species.SEEDOT]: Abilities.DISGUISE, [Species.SEEDOT]: Abilities.EARLY_BIRD,
[Species.TAILLOW]: Abilities.KEEN_EYE, [Species.TAILLOW]: Abilities.KEEN_EYE,
[Species.WINGULL]: Abilities.HYDRATION, [Species.WINGULL]: Abilities.HYDRATION,
[Species.RALTS]: Abilities.PSYCHIC_SURGE, [Species.RALTS]: Abilities.PSYCHIC_SURGE,
@ -3409,7 +3409,7 @@ export const starterPassiveAbilities = {
[Species.AXEW]: Abilities.SHEER_FORCE, [Species.AXEW]: Abilities.SHEER_FORCE,
[Species.CUBCHOO]: Abilities.INTIMIDATE, [Species.CUBCHOO]: Abilities.INTIMIDATE,
[Species.CRYOGONAL]: Abilities.DAZZLING, [Species.CRYOGONAL]: Abilities.DAZZLING,
[Species.SHELMET]: Abilities.DISGUISE, [Species.SHELMET]: Abilities.TOXIC_DEBRIS,
[Species.STUNFISK]: Abilities.STORM_DRAIN, [Species.STUNFISK]: Abilities.STORM_DRAIN,
[Species.MIENFOO]: Abilities.NO_GUARD, [Species.MIENFOO]: Abilities.NO_GUARD,
[Species.DRUDDIGON]: Abilities.INTIMIDATE, [Species.DRUDDIGON]: Abilities.INTIMIDATE,
@ -3639,7 +3639,7 @@ export const starterPassiveAbilities = {
[Species.OKIDOGI]: Abilities.INTIMIDATE, [Species.OKIDOGI]: Abilities.INTIMIDATE,
[Species.MUNKIDORI]: Abilities.PRANKSTER, [Species.MUNKIDORI]: Abilities.PRANKSTER,
[Species.FEZANDIPITI]: Abilities.DAZZLING, [Species.FEZANDIPITI]: Abilities.DAZZLING,
[Species.OGERPON]: Abilities.DISGUISE, [Species.OGERPON]: Abilities.UNNERVE,
[Species.GOUGING_FIRE]: Abilities.BEAST_BOOST, [Species.GOUGING_FIRE]: Abilities.BEAST_BOOST,
[Species.RAGING_BOLT]: Abilities.BEAST_BOOST, [Species.RAGING_BOLT]: Abilities.BEAST_BOOST,
[Species.IRON_BOULDER]: Abilities.SHARPNESS, [Species.IRON_BOULDER]: Abilities.SHARPNESS,

View File

@ -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; 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 (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;

View File

@ -1,11 +1,4 @@
interface MoveTranslationEntry { import { MoveTranslations } from "#app/plugins/i18n";
name: string,
effect: string
}
interface MoveTranslations {
[key: string]: MoveTranslationEntry
}
export const move: MoveTranslations = { export const move: MoveTranslations = {
"pound": { "pound": {
@ -2549,8 +2542,8 @@ export const move: MoveTranslations = {
effect: "Dummy Data" effect: "Dummy Data"
}, },
"neverEndingNightmarePhysical": { "neverEndingNightmarePhysical": {
name: "Deep-seated grudges summoned by the user's Z-Power trap the target. The power varies, depending on the original move.", name: "Never-Ending Nightmare",
effect: "Dummy Data" effect: "Deep-seated grudges summoned by the user's Z-Power trap the target. The power varies, depending on the original move."
}, },
"neverEndingNightmareSpecial": { "neverEndingNightmareSpecial": {
name: "Never-Ending Nightmare", name: "Never-Ending Nightmare",

39
src/locales/fr/menu.ts Normal file
View File

@ -0,0 +1,39 @@
export const menu = {
"cancel": "Annuler",
"continue": "Continuer",
"dailyRun": "Défi du jour (Bêta)",
"loadGame": "Charger la partie",
"newGame": "Nouvelle partie",
"selectGameMode": "Sélectionnez un mode de jeu.",
"logInOrCreateAccount": "Connectez-vous ou créez un compte pour commencer. Aucun e-mail requis !",
"failedToLoadSaveData": "Échec du chargement des données. Veuillez recharger la page.\nSi cela continue, veuillez contacter l'administrateur.",
"sessionSuccess": "Session chargée avec succès.",
"failedToLoadSession": "Vos données de session n'ont pas pu être chargées.\nElles pourraient être corrompues.",
"boyOrGirl": "Es-tu un garçon ou une fille ?",
"boy": "Garçon",
"girl": "Fille",
"bossAppeared": "Un {{bossName}} est apparaît.",
"trainerAppeared": "Un combat est lancé\npar {{trainerName}} !",
"singleWildAppeared": "Un {{pokemonName}} sauvage apparaît!",
"multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !",
"playerComeBack": "{{pokemonName}}, on change!\nReviens !",
"trainerComeBack": "{{trainerName}} retire {{pokemonName}} !",
"playerGo": "{{pokemonName}} ! Go !",
"trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !",
"switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?",
"pokemon": "Pokémon",
"sendOutPokemon": "{{pokemonName}} ! Go !",
"levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !",
"moveNotImplemented": "{{moveName}} n'est pas encore implémenté et ne peut pas être sélectionné.",
"moveDisabled": "{{moveName}} est désactivé !",
"noPokeballForce": "Une force mystérieuse\nempêche l'utilisation des Poké Balls.",
"noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c'est mal !",
"noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!",
"noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez d'abord l'affaiblir !",
"noEscapeForce": "Une force mystérieuse\nempêche la fuite.",
"noEscapeTrainer": "On ne s'enfuit pas d'un\ncombat de Dresseurs !",
"noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !",
"escapeVerbSwitch": "le changement",
"escapeVerbFlee": "la fuite",
"notDisabled": "{{moveName}} n'est plus désactivé !",
} as const;

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -1,10 +1,20 @@
import i18next from 'i18next'; import i18next from 'i18next';
import { menu as enMenu } from '../locales/en/menu'; import { menu as enMenu } from '../locales/en/menu';
import { menu as itMenu } from '../locales/it/menu'; import { menu as itMenu } from '../locales/it/menu';
import { menu as frMenu } from '../locales/fr/menu';
import { move as enMove } from '../locales/en/move'; import { move as enMove } from '../locales/en/move';
import { move as frMove } from '../locales/fr/move'; import { move as frMove } from '../locales/fr/move';
export interface MoveTranslationEntry {
name: string,
effect: string
}
export interface MoveTranslations {
[key: string]: MoveTranslationEntry
}
const DEFAULT_LANGUAGE_OVERRIDE = ''; const DEFAULT_LANGUAGE_OVERRIDE = '';
/** /**
@ -35,6 +45,7 @@ i18next.init({
menu: itMenu, menu: itMenu,
}, },
fr: { fr: {
menu: frMenu,
move: frMove, move: frMove,
} }
}, },