From f88f01554ae4e63ccf60b506268ba122d3dda0b9 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Wed, 1 May 2024 23:04:15 -0500 Subject: [PATCH 01/19] start for magic coat. Currently, when used on an arena trap the arena tag is getting set on both sides. --- src/data/battler-tags.ts | 8 ++++++ src/data/enums/battler-tag-type.ts | 3 ++- src/data/move.ts | 39 +++++++++++++++++++++++------- src/phases.ts | 7 +++++- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index aaab9f9a4..147dc7499 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -761,6 +761,12 @@ export class ContactBurnProtectedTag extends ProtectedTag { } } +export class BounceTag extends BattlerTag { + constructor(sourceMove: Moves, tagType: BattlerTagType = BattlerTagType.BOUNCE) { + super(tagType, BattlerTagLapseType.CUSTOM, 0, sourceMove); + } +} + export class EnduringTag extends BattlerTag { constructor(sourceMove: Moves) { super(BattlerTagType.ENDURING, BattlerTagLapseType.TURN_END, 0, sourceMove); @@ -1178,6 +1184,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new CursedTag(sourceId); case BattlerTagType.CHARGED: return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); + case BattlerTagType.BOUNCE: + return new BounceTag(sourceMove); case BattlerTagType.NONE: default: return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index 4d810b737..91e61c6c2 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -52,5 +52,6 @@ export enum BattlerTagType { SALT_CURED = "SALT_CURED", CURSED = "CURSED", CHARGED = "CHARGED", - GROUNDED = "GROUNDED" + GROUNDED = "GROUNDED", + BOUNCE = "BOUNCE" } diff --git a/src/data/move.ts b/src/data/move.ts index 5d5fec957..c1a3146d9 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -69,7 +69,9 @@ export enum MoveFlags { DANCE_MOVE = 4096, WIND_MOVE = 8192, TRIAGE_MOVE = 16384, - IGNORE_ABILITIES = 32768 + IGNORE_ABILITIES = 32768, + MAGIC_COAT_MOVE = 65536 + } type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean; @@ -294,6 +296,11 @@ export default class Move implements Localizable { return this; } + magicCoatMove(magicCoatMove?: boolean): this { + this.setFlag(MoveFlags.MAGIC_COAT_MOVE, magicCoatMove); + return this; + } + ignoresAbilities(ignoresAbilities?: boolean): this { this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities); return this; @@ -3868,7 +3875,8 @@ export function initMoves() { .attr(FixedDamageAttr, 20), new StatusMove(Moves.DISABLE, Type.NORMAL, 100, 20, -1, 0, 1) .attr(DisableMoveAttr) - .condition(failOnMaxCondition), + .condition(failOnMaxCondition) + .magicCoatMove(), new AttackMove(Moves.ACID, Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1) .attr(StatChangeAttr, BattleStat.SPDEF, -1) .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -3980,6 +3988,7 @@ export function initMoves() { .attr(ChargeAttr, ChargeAnim.DIG_CHARGING, 'dug a hole!', BattlerTagType.UNDERGROUND) .ignoresVirtual(), new StatusMove(Moves.TOXIC, Type.POISON, 90, 10, -1, 0, 1) + .magicCoatMove() .attr(StatusEffectAttr, StatusEffect.TOXIC) .attr(ToxicAccuracyAttr), new AttackMove(Moves.CONFUSION, Type.PSYCHIC, MoveCategory.SPECIAL, 50, 100, 25, 10, 0, 1) @@ -4018,7 +4027,8 @@ export function initMoves() { new StatusMove(Moves.SMOKESCREEN, Type.NORMAL, 100, 20, -1, 0, 1) .attr(StatChangeAttr, BattleStat.ACC, -1), new StatusMove(Moves.CONFUSE_RAY, Type.GHOST, 100, 10, -1, 0, 1) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .magicCoatMove(), new SelfStatusMove(Moves.WITHDRAW, Type.WATER, -1, 40, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, 1, true), new SelfStatusMove(Moves.DEFENSE_CURL, Type.NORMAL, -1, 40, -1, 0, 1) @@ -4221,7 +4231,8 @@ export function initMoves() { new StatusMove(Moves.COTTON_SPORE, Type.GRASS, 100, 40, -1, 0, 2) .attr(StatChangeAttr, BattleStat.SPD, -2) .powderMove() - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.REVERSAL, Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2) .attr(LowHpPowerAttr), new StatusMove(Moves.SPITE, Type.GHOST, 100, 10, -1, 0, 2) @@ -4290,6 +4301,7 @@ export function initMoves() { new SelfStatusMove(Moves.ENDURE, Type.NORMAL, -1, 10, -1, 4, 2) .attr(EndureAttr), new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2) + .magicCoatMove() .attr(StatChangeAttr, BattleStat.ATK, -2), new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2) .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), @@ -4311,6 +4323,7 @@ export function initMoves() { new StatusMove(Moves.MEAN_LOOK, Type.NORMAL, -1, 5, -1, 0, 2) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1), new StatusMove(Moves.ATTRACT, Type.NORMAL, 100, 15, -1, 0, 2) + .magicCoatMove() .attr(AddBattlerTagAttr, BattlerTagType.INFATUATED) .condition((user, target, move) => user.isOppositeGender(target)), new SelfStatusMove(Moves.SLEEP_TALK, Type.NORMAL, -1, 10, -1, 0, 2) @@ -4502,7 +4515,7 @@ export function initMoves() { new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 3) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF ], -1, true), new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3) - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.BOUNCE), new SelfStatusMove(Moves.RECYCLE, Type.NORMAL, -1, 10, -1, 0, 3) .unimplemented(), new AttackMove(Moves.REVENGE, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, -4, 3) @@ -4655,6 +4668,7 @@ export function initMoves() { new SelfStatusMove(Moves.IRON_DEFENSE, Type.STEEL, -1, 15, -1, 0, 3) .attr(StatChangeAttr, BattleStat.DEF, 2, true), new StatusMove(Moves.BLOCK, Type.NORMAL, -1, 5, -1, 0, 3) + .magicCoatMove() .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1), new StatusMove(Moves.HOWL, Type.NORMAL, -1, 40, -1, 0, 3) .attr(StatChangeAttr, BattleStat.ATK, 1) @@ -4814,6 +4828,7 @@ export function initMoves() { new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].category !== MoveCategory.STATUS), new StatusMove(Moves.TOXIC_SPIKES, Type.POISON, -1, 20, -1, 0, 4) + .magicCoatMove() .attr(AddArenaTrapTagAttr, ArenaTagType.TOXIC_SPIKES) .target(MoveTarget.ENEMY_SIDE), new StatusMove(Moves.HEART_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 4) @@ -4920,7 +4935,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.EVA, -1) .attr(ClearWeatherAttr, WeatherType.FOG) .attr(ClearTerrainAttr) - .attr(RemoveScreensAttr, true), + .attr(RemoveScreensAttr, true) + .magicCoatMove(), new StatusMove(Moves.TRICK_ROOM, Type.PSYCHIC, -1, 5, -1, -7, 4) .attr(AddArenaTagAttr, ArenaTagType.TRICK_ROOM, 5) .ignoresProtect() @@ -4958,10 +4974,12 @@ export function initMoves() { new StatusMove(Moves.CAPTIVATE, Type.NORMAL, 100, 20, -1, 0, 4) .attr(StatChangeAttr, BattleStat.SPATK, -2) .condition((user, target, move) => target.isOppositeGender(user)) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new StatusMove(Moves.STEALTH_ROCK, Type.ROCK, -1, 20, -1, 0, 4) .attr(AddArenaTrapTagAttr, ArenaTagType.STEALTH_ROCK) - .target(MoveTarget.ENEMY_SIDE), + .target(MoveTarget.ENEMY_SIDE) + .magicCoatMove(), new AttackMove(Moves.GRASS_KNOT, Type.GRASS, MoveCategory.SPECIAL, -1, 100, 20, -1, 0, 4) .attr(WeightPowerAttr) .makesContact() @@ -5005,7 +5023,8 @@ export function initMoves() { .attr(TrapAttr, BattlerTagType.MAGMA_STORM), new StatusMove(Moves.DARK_VOID, Type.DARK, 50, 10, -1, 0, 4) .attr(StatusEffectAttr, StatusEffect.SLEEP) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.SEED_FLARE, Type.GRASS, MoveCategory.SPECIAL, 120, 85, 5, 40, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new AttackMove(Moves.OMINOUS_WIND, Type.GHOST, MoveCategory.SPECIAL, 60, 100, 5, 10, 0, 4) @@ -5392,6 +5411,7 @@ export function initMoves() { new StatusMove(Moves.HOLD_HANDS, Type.NORMAL, -1, 40, -1, 0, 6) .target(MoveTarget.NEAR_ALLY), new StatusMove(Moves.BABY_DOLL_EYES, Type.FAIRY, 100, 30, -1, 1, 6) + .magicCoatMove() .attr(StatChangeAttr, BattleStat.ATK, -1), new AttackMove(Moves.NUZZLE, Type.ELECTRIC, MoveCategory.PHYSICAL, 20, 100, 20, 100, 0, 6) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), @@ -5931,6 +5951,7 @@ export function initMoves() { .partial(), new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8) .target(MoveTarget.ALL_NEAR_OTHERS) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.COACHING, Type.FIGHTING, -1, 10, 100, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF ], 1) diff --git a/src/phases.ts b/src/phases.ts index 8eda33de2..a120e5224 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -21,7 +21,7 @@ import { Biome } from "./data/enums/biome"; import { ModifierTier } from "./modifier/modifier-tier"; import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTagLapseType, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; +import { BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; import { BattlerTagType } from "./data/enums/battler-tag-type"; import { getPokemonMessage } from "./messages"; import { Starter } from "./ui/starter-select-ui-handler"; @@ -2262,11 +2262,16 @@ export class MovePhase extends BattlePhase { // Assume conditions affecting targets only apply to moves with a single target let success = this.move.getMove().applyConditions(this.pokemon, targets[0], this.move.getMove()); let failedText = null; + const isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)); if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove())) success = false; else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.move.getMove())) { success = false; failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType); + } else if (success && isBounced) { + this.showFailedText(this.pokemon.getOpponentDescriptor() + "\nbounced the move back!"); + this.targets = [this.pokemon.getBattlerIndex()]; + this.pokemon = targets[0]; } if (success) this.scene.unshiftPhase(this.getEffectPhase()); From 88d05bcec24cfec7b2c37da480903dd6f73e8832 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Fri, 3 May 2024 22:07:37 -0500 Subject: [PATCH 02/19] add magic bounce. move to right after the check if the move missed. still issues with arena traps --- src/data/ability.ts | 4 +- src/phases.ts | 303 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 242 insertions(+), 65 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 2ac7d6be1..5c68a7978 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2301,6 +2301,8 @@ export class NoFusionAbilityAbAttr extends AbAttr { } } +export class MagicBounceAbAttr extends AbAttr { } + function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { return new Promise(resolve => { @@ -2925,7 +2927,7 @@ export function initAbilities() { .partial(), new Ability(Abilities.MAGIC_BOUNCE, 5) .ignorable() - .unimplemented(), + .attr(MagicBounceAbAttr), new Ability(Abilities.SAP_SIPPER, 5) .attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1) .ignorable(), diff --git a/src/phases.ts b/src/phases.ts index a120e5224..1ea3b30ee 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,63 +1,231 @@ -import BattleScene, { bypassLogin, startingWave } from "./battle-scene"; -import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; +import BattleScene, {bypassLogin, startingWave} from "./battle-scene"; +import { + DamageResult, + default as Pokemon, + EnemyPokemon, + FieldPosition, + HitResult, + MoveResult, + PlayerPokemon, + PokemonMove, + TurnMove +} from "./field/pokemon"; import * as Utils from './utils'; -import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr } from "./data/move"; -import { Mode } from './ui/ui'; -import { Command } from "./ui/command-ui-handler"; -import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; -import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; -import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; -import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; -import { StatusEffect, getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./data/status-effect"; -import { SummaryUiMode } from "./ui/summary-ui-handler"; +import {Moves} from "./data/enums/moves"; +import { + allMoves, + applyFilteredMoveAttrs, + applyMoveAttrs, + AttackMove, + BypassSleepAttr, + ChargeAttr, + CopyMoveAttr, + FixedDamageAttr, + ForceSwitchOutAttr, + getMoveTargets, + HealStatusEffectAttr, + HitsTagAttr, + IgnoreOpponentStatChangesAttr, + MissEffectAttr, + MoveAttr, + MoveEffectAttr, + MoveEffectTrigger, + MoveFlags, + MoveTarget, + MoveTargetSet, + MultiHitAttr, + NoEffectAttr, + OneHitKOAccuracyAttr, + OverrideMoveEffectAttr, + PreMoveMessageAttr, + SelfStatusMove, + VariableAccuracyAttr +} from "./data/move"; +import {Mode} from './ui/ui'; +import {Command} from "./ui/command-ui-handler"; +import {Stat} from "./data/pokemon-stat"; +import { + BerryModifier, + ContactHeldItemTransferChanceModifier, + EnemyAttackStatusEffectChanceModifier, + EnemyPersistentModifier, + EnemyStatusEffectHealChanceModifier, + EnemyTurnHealModifier, + ExpBalanceModifier, + ExpBoosterModifier, + ExpShareModifier, + ExtraModifierModifier, + FlinchChanceModifier, + HealingBoosterModifier, + HitHealModifier, + IvScannerModifier, + LapsingPersistentModifier, + LapsingPokemonHeldItemModifier, + MapModifier, + Modifier, + MoneyInterestModifier, + MoneyMultiplierModifier, + MultipleParticipantExpBonusModifier, + PersistentModifier, + PokemonExpBoosterModifier, + PokemonFriendshipBoosterModifier, + PokemonHeldItemModifier, + PokemonInstantReviveModifier, + PokemonMoveAccuracyBoosterModifier, + PokemonMultiHitModifier, + SwitchEffectTransferModifier, + TempBattleStatBoosterModifier, + TurnHealModifier, + TurnHeldItemTransferModifier +} from "./modifier/modifier"; +import PartyUiHandler, {PartyOption, PartyUiMode} from "./ui/party-ui-handler"; +import { + doPokeballBounceAnim, + getPokeballAtlasKey, + getPokeballCatchMultiplier, + getPokeballTintColor, + PokeballType +} from "./data/pokeball"; +import {CommonAnim, CommonBattleAnim, initMoveAnim, loadMoveAnimAssets, MoveAnim} from "./data/battle-anims"; +import { + getStatusEffectActivationText, + getStatusEffectCatchRateMultiplier, + getStatusEffectHealText, + getStatusEffectObtainText, + getStatusEffectOverlapText, + StatusEffect +} from "./data/status-effect"; +import {SummaryUiMode} from "./ui/summary-ui-handler"; import EvolutionSceneHandler from "./ui/evolution-scene-handler"; -import { EvolutionPhase } from "./evolution-phase"; -import { Phase } from "./phase"; -import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat"; -import { biomeLinks, getBiomeName } from "./data/biomes"; -import { Biome } from "./data/enums/biome"; -import { ModifierTier } from "./modifier/modifier-tier"; -import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; +import {EvolutionPhase} from "./evolution-phase"; +import {Phase} from "./phase"; +import {BattleStat, getBattleStatLevelChangeDescription, getBattleStatName} from "./data/battle-stat"; +import {biomeLinks, getBiomeName} from "./data/biomes"; +import {Biome} from "./data/enums/biome"; +import {ModifierTier} from "./modifier/modifier-tier"; +import { + FusePokemonModifierType, + getDailyRunStarterModifiers, + getEnemyBuffModifierForWave, + getModifierType, + getPlayerModifierTypeOptions, + getPlayerShopModifierTypeOptionsForWave, + ModifierPoolType, + ModifierType, + ModifierTypeFunc, + ModifierTypeOption, + modifierTypes, + PokemonModifierType, + PokemonMoveModifierType, + regenerateModifierPoolThresholds, + RememberMoveModifierType, + TmModifierType +} from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; -import { BattlerTagType } from "./data/enums/battler-tag-type"; -import { getPokemonMessage } from "./messages"; -import { Starter } from "./ui/starter-select-ui-handler"; -import { Gender } from "./data/gender"; -import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; -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 { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr } from "./data/ability"; -import { Unlockables, getUnlockableName } from "./system/unlockables"; -import { getBiomeKey } from "./field/arena"; -import { BattleType, BattlerIndex, TurnCommand } from "./battle"; -import { BattleSpec } from "./enums/battle-spec"; -import { Species } from "./data/enums/species"; -import { HealAchv, LevelAchv, achvs } from "./system/achv"; -import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; -import { TrainerType } from "./data/enums/trainer-type"; -import { EggHatchPhase } from "./egg-hatch-phase"; -import { Egg } from "./data/egg"; -import { vouchers } from "./system/voucher"; -import { loggedInUser, updateUserInfo } from "./account"; -import { PlayerGender, SessionSaveData } from "./system/game-data"; -import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; -import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; -import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue"; -import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler"; -import { Setting } from "./system/settings"; -import { Tutorial, handleTutorial } from "./tutorial"; -import { TerrainType } from "./data/terrain"; -import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; -import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; -import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; -import { GameModes, gameModes } from "./game-mode"; -import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; +import { + BattlerTag, + BattlerTagLapseType, + BounceTag, + EncoreTag, + HideSpriteTag as HiddenTag, + ProtectedTag, + TrappedTag +} from "./data/battler-tags"; +import {BattlerTagType} from "./data/enums/battler-tag-type"; +import {getPokemonMessage} from "./messages"; +import {Starter} from "./ui/starter-select-ui-handler"; +import {Gender} from "./data/gender"; +import { + getRandomWeatherType, + getTerrainBlockMessage, + getWeatherDamageMessage, + getWeatherLapseMessage, + Weather, + WeatherType +} from "./data/weather"; +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 { + AlwaysHitAbAttr, + applyAbAttrs, + applyBattleStatMultiplierAbAttrs, + applyCheckTrappedAbAttrs, + applyPostAttackAbAttrs, + applyPostBattleAbAttrs, + applyPostBattleInitAbAttrs, + applyPostDefendAbAttrs, + applyPostFaintAbAttrs, + applyPostKnockOutAbAttrs, + applyPostStatChangeAbAttrs, + applyPostSummonAbAttrs, + applyPostTurnAbAttrs, + applyPostVictoryAbAttrs, + applyPostWeatherLapseAbAttrs, + applyPreStatChangeAbAttrs, + applyPreSwitchOutAbAttrs, + applyPreWeatherEffectAbAttrs, + BattleStatMultiplierAbAttr, + BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, + CheckTrappedAbAttr, + IgnoreOpponentStatChangesAbAttr, + IncreasePpAbAttr, + IncrementMovePriorityAbAttr, + PostAttackAbAttr, + PostBattleAbAttr, + PostBattleInitAbAttr, + PostBiomeChangeAbAttr, + PostDefendAbAttr, + PostFaintAbAttr, + PostKnockOutAbAttr, + PostStatChangeAbAttr, + PostSummonAbAttr, + PostTurnAbAttr, + PostVictoryAbAttr, + PostWeatherLapseAbAttr, + PreSwitchOutAbAttr, + PreventBerryUseAbAttr, + PreWeatherDamageAbAttr, + ProtectStatAbAttr, + RedirectMoveAbAttr, + RunSuccessAbAttr, + StatChangeMultiplierAbAttr, + SuppressWeatherEffectAbAttr, + SyncEncounterNatureAbAttr +} from "./data/ability"; +import {getUnlockableName, Unlockables} from "./system/unlockables"; +import {getBiomeKey} from "./field/arena"; +import {BattlerIndex, BattleType, TurnCommand} from "./battle"; +import {BattleSpec} from "./enums/battle-spec"; +import {Species} from "./data/enums/species"; +import {achvs, HealAchv, LevelAchv} from "./system/achv"; +import {trainerConfigs, TrainerSlot} from "./data/trainer-config"; +import {TrainerType} from "./data/enums/trainer-type"; +import {EggHatchPhase} from "./egg-hatch-phase"; +import {Egg} from "./data/egg"; +import {vouchers} from "./system/voucher"; +import {loggedInUser, updateUserInfo} from "./account"; +import {PlayerGender, SessionSaveData} from "./system/game-data"; +import {addPokeballCaptureStars, addPokeballOpenParticles} from "./field/anims"; +import { + SpeciesFormChangeActiveTrigger, + SpeciesFormChangeManualTrigger, + SpeciesFormChangeMoveLearnedTrigger, + SpeciesFormChangePostMoveTrigger, + SpeciesFormChangePreMoveTrigger +} from "./data/pokemon-forms"; +import {battleSpecDialogue, getCharVariantFromDialogue} from "./data/dialogue"; +import ModifierSelectUiHandler, {SHOP_OPTIONS_ROW_LIMIT} from "./ui/modifier-select-ui-handler"; +import {Setting} from "./system/settings"; +import {handleTutorial, Tutorial} from "./tutorial"; +import {TerrainType} from "./data/terrain"; +import {OptionSelectConfig, OptionSelectItem} from "./ui/abstact-option-select-ui-handler"; +import {SaveSlotUiMode} from "./ui/save-slot-select-ui-handler"; +import {fetchDailyRunSeed, getDailyRunStarters} from "./data/daily-run"; +import {GameModes, gameModes} from "./game-mode"; +import {getPokemonSpecies, speciesStarters} from "./data/pokemon-species"; import i18next from './plugins/i18n'; -import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides'; +import {STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE} from './overrides'; export class LoginPhase extends Phase { private showText: boolean; @@ -2262,16 +2430,11 @@ export class MovePhase extends BattlePhase { // Assume conditions affecting targets only apply to moves with a single target let success = this.move.getMove().applyConditions(this.pokemon, targets[0], this.move.getMove()); let failedText = null; - const isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)); if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove())) success = false; else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.move.getMove())) { success = false; failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType); - } else if (success && isBounced) { - this.showFailedText(this.pokemon.getOpponentDescriptor() + "\nbounced the move back!"); - this.targets = [this.pokemon.getBattlerIndex()]; - this.pokemon = targets[0]; } if (success) this.scene.unshiftPhase(this.getEffectPhase()); @@ -2369,8 +2532,8 @@ export class MoveEffectPhase extends PokemonPhase { start() { super.start(); - const user = this.getUserPokemon(); - const targets = this.getTargets(); + let user = this.getUserPokemon(); + let targets = this.getTargets(); if (!user?.isOnField()) return super.end(); @@ -2413,12 +2576,24 @@ export class MoveEffectPhase extends PokemonPhase { return this.end(); } + let isBounced: BattlerTag | boolean = false; + for (let opponent of targets) { + isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); + if (isBounced) { + this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); + const tempTargets = targets; + targets = [user]; + user = tempTargets[0]; + break; + } + } + const applyAttrs: Promise[] = []; // Move animation only needs one target new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { for (let target of targets) { - if (!targetHitChecks[target.getBattlerIndex()]) { + if (!targetHitChecks[target.getBattlerIndex()] && !isBounced) { user.turnData.hitCount = 1; user.turnData.hitsLeft = 1; this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!')); From 18907b52260baa12efc6aa62a4baf7901fc31302 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Fri, 3 May 2024 22:13:31 -0500 Subject: [PATCH 03/19] fix imports --- src/phases.ts | 357 +++++++++++++------------------------------------- 1 file changed, 91 insertions(+), 266 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 1ea3b30ee..3c5274b31 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,231 +1,63 @@ -import BattleScene, {bypassLogin, startingWave} from "./battle-scene"; -import { - DamageResult, - default as Pokemon, - EnemyPokemon, - FieldPosition, - HitResult, - MoveResult, - PlayerPokemon, - PokemonMove, - TurnMove -} from "./field/pokemon"; +import BattleScene, { bypassLogin, startingWave } from "./battle-scene"; +import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; -import {Moves} from "./data/enums/moves"; -import { - allMoves, - applyFilteredMoveAttrs, - applyMoveAttrs, - AttackMove, - BypassSleepAttr, - ChargeAttr, - CopyMoveAttr, - FixedDamageAttr, - ForceSwitchOutAttr, - getMoveTargets, - HealStatusEffectAttr, - HitsTagAttr, - IgnoreOpponentStatChangesAttr, - MissEffectAttr, - MoveAttr, - MoveEffectAttr, - MoveEffectTrigger, - MoveFlags, - MoveTarget, - MoveTargetSet, - MultiHitAttr, - NoEffectAttr, - OneHitKOAccuracyAttr, - OverrideMoveEffectAttr, - PreMoveMessageAttr, - SelfStatusMove, - VariableAccuracyAttr -} from "./data/move"; -import {Mode} from './ui/ui'; -import {Command} from "./ui/command-ui-handler"; -import {Stat} from "./data/pokemon-stat"; -import { - BerryModifier, - ContactHeldItemTransferChanceModifier, - EnemyAttackStatusEffectChanceModifier, - EnemyPersistentModifier, - EnemyStatusEffectHealChanceModifier, - EnemyTurnHealModifier, - ExpBalanceModifier, - ExpBoosterModifier, - ExpShareModifier, - ExtraModifierModifier, - FlinchChanceModifier, - HealingBoosterModifier, - HitHealModifier, - IvScannerModifier, - LapsingPersistentModifier, - LapsingPokemonHeldItemModifier, - MapModifier, - Modifier, - MoneyInterestModifier, - MoneyMultiplierModifier, - MultipleParticipantExpBonusModifier, - PersistentModifier, - PokemonExpBoosterModifier, - PokemonFriendshipBoosterModifier, - PokemonHeldItemModifier, - PokemonInstantReviveModifier, - PokemonMoveAccuracyBoosterModifier, - PokemonMultiHitModifier, - SwitchEffectTransferModifier, - TempBattleStatBoosterModifier, - TurnHealModifier, - TurnHeldItemTransferModifier -} from "./modifier/modifier"; -import PartyUiHandler, {PartyOption, PartyUiMode} from "./ui/party-ui-handler"; -import { - doPokeballBounceAnim, - getPokeballAtlasKey, - getPokeballCatchMultiplier, - getPokeballTintColor, - PokeballType -} from "./data/pokeball"; -import {CommonAnim, CommonBattleAnim, initMoveAnim, loadMoveAnimAssets, MoveAnim} from "./data/battle-anims"; -import { - getStatusEffectActivationText, - getStatusEffectCatchRateMultiplier, - getStatusEffectHealText, - getStatusEffectObtainText, - getStatusEffectOverlapText, - StatusEffect -} from "./data/status-effect"; -import {SummaryUiMode} from "./ui/summary-ui-handler"; +import { Moves } from "./data/enums/moves"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr } from "./data/move"; +import { Mode } from './ui/ui'; +import { Command } from "./ui/command-ui-handler"; +import { Stat } from "./data/pokemon-stat"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; +import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; +import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; +import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; +import { StatusEffect, getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./data/status-effect"; +import { SummaryUiMode } from "./ui/summary-ui-handler"; import EvolutionSceneHandler from "./ui/evolution-scene-handler"; -import {EvolutionPhase} from "./evolution-phase"; -import {Phase} from "./phase"; -import {BattleStat, getBattleStatLevelChangeDescription, getBattleStatName} from "./data/battle-stat"; -import {biomeLinks, getBiomeName} from "./data/biomes"; -import {Biome} from "./data/enums/biome"; -import {ModifierTier} from "./modifier/modifier-tier"; -import { - FusePokemonModifierType, - getDailyRunStarterModifiers, - getEnemyBuffModifierForWave, - getModifierType, - getPlayerModifierTypeOptions, - getPlayerShopModifierTypeOptionsForWave, - ModifierPoolType, - ModifierType, - ModifierTypeFunc, - ModifierTypeOption, - modifierTypes, - PokemonModifierType, - PokemonMoveModifierType, - regenerateModifierPoolThresholds, - RememberMoveModifierType, - TmModifierType -} from "./modifier/modifier-type"; +import { EvolutionPhase } from "./evolution-phase"; +import { Phase } from "./phase"; +import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat"; +import { biomeLinks, getBiomeName } from "./data/biomes"; +import { Biome } from "./data/enums/biome"; +import { ModifierTier } from "./modifier/modifier-tier"; +import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { - BattlerTag, - BattlerTagLapseType, - BounceTag, - EncoreTag, - HideSpriteTag as HiddenTag, - ProtectedTag, - TrappedTag -} from "./data/battler-tags"; -import {BattlerTagType} from "./data/enums/battler-tag-type"; -import {getPokemonMessage} from "./messages"; -import {Starter} from "./ui/starter-select-ui-handler"; -import {Gender} from "./data/gender"; -import { - getRandomWeatherType, - getTerrainBlockMessage, - getWeatherDamageMessage, - getWeatherLapseMessage, - Weather, - WeatherType -} from "./data/weather"; -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 { - AlwaysHitAbAttr, - applyAbAttrs, - applyBattleStatMultiplierAbAttrs, - applyCheckTrappedAbAttrs, - applyPostAttackAbAttrs, - applyPostBattleAbAttrs, - applyPostBattleInitAbAttrs, - applyPostDefendAbAttrs, - applyPostFaintAbAttrs, - applyPostKnockOutAbAttrs, - applyPostStatChangeAbAttrs, - applyPostSummonAbAttrs, - applyPostTurnAbAttrs, - applyPostVictoryAbAttrs, - applyPostWeatherLapseAbAttrs, - applyPreStatChangeAbAttrs, - applyPreSwitchOutAbAttrs, - applyPreWeatherEffectAbAttrs, - BattleStatMultiplierAbAttr, - BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, - CheckTrappedAbAttr, - IgnoreOpponentStatChangesAbAttr, - IncreasePpAbAttr, - IncrementMovePriorityAbAttr, - PostAttackAbAttr, - PostBattleAbAttr, - PostBattleInitAbAttr, - PostBiomeChangeAbAttr, - PostDefendAbAttr, - PostFaintAbAttr, - PostKnockOutAbAttr, - PostStatChangeAbAttr, - PostSummonAbAttr, - PostTurnAbAttr, - PostVictoryAbAttr, - PostWeatherLapseAbAttr, - PreSwitchOutAbAttr, - PreventBerryUseAbAttr, - PreWeatherDamageAbAttr, - ProtectStatAbAttr, - RedirectMoveAbAttr, - RunSuccessAbAttr, - StatChangeMultiplierAbAttr, - SuppressWeatherEffectAbAttr, - SyncEncounterNatureAbAttr -} from "./data/ability"; -import {getUnlockableName, Unlockables} from "./system/unlockables"; -import {getBiomeKey} from "./field/arena"; -import {BattlerIndex, BattleType, TurnCommand} from "./battle"; -import {BattleSpec} from "./enums/battle-spec"; -import {Species} from "./data/enums/species"; -import {achvs, HealAchv, LevelAchv} from "./system/achv"; -import {trainerConfigs, TrainerSlot} from "./data/trainer-config"; -import {TrainerType} from "./data/enums/trainer-type"; -import {EggHatchPhase} from "./egg-hatch-phase"; -import {Egg} from "./data/egg"; -import {vouchers} from "./system/voucher"; -import {loggedInUser, updateUserInfo} from "./account"; -import {PlayerGender, SessionSaveData} from "./system/game-data"; -import {addPokeballCaptureStars, addPokeballOpenParticles} from "./field/anims"; -import { - SpeciesFormChangeActiveTrigger, - SpeciesFormChangeManualTrigger, - SpeciesFormChangeMoveLearnedTrigger, - SpeciesFormChangePostMoveTrigger, - SpeciesFormChangePreMoveTrigger -} from "./data/pokemon-forms"; -import {battleSpecDialogue, getCharVariantFromDialogue} from "./data/dialogue"; -import ModifierSelectUiHandler, {SHOP_OPTIONS_ROW_LIMIT} from "./ui/modifier-select-ui-handler"; -import {Setting} from "./system/settings"; -import {handleTutorial, Tutorial} from "./tutorial"; -import {TerrainType} from "./data/terrain"; -import {OptionSelectConfig, OptionSelectItem} from "./ui/abstact-option-select-ui-handler"; -import {SaveSlotUiMode} from "./ui/save-slot-select-ui-handler"; -import {fetchDailyRunSeed, getDailyRunStarters} from "./data/daily-run"; -import {GameModes, gameModes} from "./game-mode"; -import {getPokemonSpecies, speciesStarters} from "./data/pokemon-species"; +import { BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; +import { BattlerTagType } from "./data/enums/battler-tag-type"; +import { getPokemonMessage } from "./messages"; +import { Starter } from "./ui/starter-select-ui-handler"; +import { Gender } from "./data/gender"; +import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; +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 { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr } from "./data/ability"; +import { Unlockables, getUnlockableName } from "./system/unlockables"; +import { getBiomeKey } from "./field/arena"; +import { BattleType, BattlerIndex, TurnCommand } from "./battle"; +import { BattleSpec } from "./enums/battle-spec"; +import { Species } from "./data/enums/species"; +import { HealAchv, LevelAchv, achvs } from "./system/achv"; +import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; +import { TrainerType } from "./data/enums/trainer-type"; +import { EggHatchPhase } from "./egg-hatch-phase"; +import { Egg } from "./data/egg"; +import { vouchers } from "./system/voucher"; +import { loggedInUser, updateUserInfo } from "./account"; +import { PlayerGender, SessionSaveData } from "./system/game-data"; +import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; +import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; +import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue"; +import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler"; +import { Setting } from "./system/settings"; +import { Tutorial, handleTutorial } from "./tutorial"; +import { TerrainType } from "./data/terrain"; +import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; +import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; +import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; +import { GameModes, gameModes } from "./game-mode"; +import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; import i18next from './plugins/i18n'; -import {STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE} from './overrides'; +import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides'; export class LoginPhase extends Phase { private showText: boolean; @@ -249,13 +81,13 @@ export class LoginPhase extends Phase { if (!statusCode || statusCode === 400) { if (this.showText) this.scene.ui.showText(i18next.t('menu:logInOrCreateAccount')); - + this.scene.playSound('menu_open'); const loadData = () => { updateUserInfo().then(() => this.scene.gameData.loadSystem().then(() => this.end())); }; - + this.scene.ui.setMode(Mode.LOGIN_FORM, { buttonActions: [ () => { @@ -300,7 +132,7 @@ export class LoginPhase extends Phase { if (!this.scene.gameData.gender) this.scene.unshiftPhase(new SelectGenderPhase(this.scene)); - + handleTutorial(this.scene, Tutorial.Intro).then(() => super.end()); } } @@ -480,7 +312,7 @@ export class TitlePhase extends Phase { party.push(starterPokemon); loadPokemonAssets.push(starterPokemon.loadAssets()); } - + regenerateModifierPoolThresholds(party, ModifierPoolType.DAILY_STARTER); const modifiers: Modifier[] = Array(3).fill(null).map(() => modifierTypes.EXP_SHARE().withIdFromFunc(modifierTypes.EXP_SHARE).newModifier()) .concat(Array(3).fill(null).map(() => modifierTypes.GOLDEN_EXP_CHARM().withIdFromFunc(modifierTypes.GOLDEN_EXP_CHARM).newModifier())) @@ -589,7 +421,7 @@ export class SelectGenderPhase extends Phase { constructor(scene: BattleScene) { super(scene); } - + start(): void { super.start(); @@ -886,11 +718,11 @@ export class EncounterPhase extends BattlePhase { enemyPokemon.updateScale(); } } - + totalBst += enemyPokemon.getSpeciesForm().baseTotal; loadEnemyAssets.push(enemyPokemon.loadAssets()); - + console.log(enemyPokemon.name, enemyPokemon.species.speciesId, enemyPokemon.stats); }); @@ -1013,7 +845,7 @@ export class EncounterPhase extends BattlePhase { const trainer = this.scene.currentBattle.trainer; trainer.untint(100, 'Sine.easeOut'); trainer.playAnim(); - + const doSummon = () => { this.scene.currentBattle.started = true; this.scene.playBgm(undefined); @@ -1032,7 +864,7 @@ export class EncounterPhase extends BattlePhase { else doTrainerSummon(); }; - + const encounterMessages = this.scene.currentBattle.trainer.getEncounterMessages(); if (!encounterMessages?.length) @@ -1089,7 +921,7 @@ export class EncounterPhase extends BattlePhase { this.scene.pushPhase(new ReturnPhase(this.scene, 1)); this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, false)); } - + if (this.scene.currentBattle.waveIndex > startingWave && this.scene.currentBattle.battleType !== BattleType.TRAINER) { this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double)); if (this.scene.currentBattle.double && availablePartyMembers.length > 1) @@ -1145,7 +977,7 @@ export class NextEncounterPhase extends EncounterPhase { this.scene.arenaNextEnemy.setVisible(false); if (this.scene.lastEnemyTrainer) this.scene.lastEnemyTrainer.destroy(); - + if (!this.tryOverrideForBattleSpec()) this.doEncounterCommon(); } @@ -2037,7 +1869,7 @@ export class EnemyCommandPhase extends FieldPhase { if (partyMemberScores.length) { const matchupScores = opponents.map(opp => enemyPokemon.getMatchupScore(opp)); const matchupScore = matchupScores.reduce((total, score) => total += score, 0) / matchupScores.length; - + const sortedPartyMemberScores = trainer.getSortedPartyMemberMatchupScores(partyMemberScores); const switchMultiplier = 1 - (battle.enemySwitchCounter ? Math.pow(0.1, (1 / battle.enemySwitchCounter)) : 0); @@ -2047,7 +1879,7 @@ export class EnemyCommandPhase extends FieldPhase { battle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] = { command: Command.POKEMON, cursor: index, args: [ false ] }; - + battle.enemySwitchCounter++; return this.end(); @@ -2122,11 +1954,11 @@ export class TurnStartPhase extends FieldPhase { applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority); applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority); - + if (aPriority.value !== bPriority.value) return aPriority.value < bPriority.value ? 1 : -1; } - + const aIndex = order.indexOf(a); const bIndex = order.indexOf(b); @@ -2194,10 +2026,10 @@ export class TurnEndPhase extends FieldPhase { super.start(); this.scene.currentBattle.incrementTurn(this.scene); - + const handlePokemon = (pokemon: Pokemon) => { pokemon.lapseTags(BattlerTagLapseType.TURN_END); - + if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('menu:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); pokemon.summonData.disabledMove = Moves.NONE; @@ -2227,7 +2059,7 @@ export class TurnEndPhase extends FieldPhase { }; this.executeForAll(handlePokemon); - + this.scene.arena.lapseTags(); if (this.scene.arena.weather && !this.scene.arena.weather.lapse()) @@ -2385,9 +2217,9 @@ export class MovePhase extends BattlePhase { const doMove = () => { this.pokemon.turnData.acted = true; // Record that the move was attempted, even if it fails - + this.pokemon.lapseTags(BattlerTagLapseType.PRE_MOVE); - + if (!this.followUp && this.canMove() && !this.cancelled) { this.pokemon.lapseTags(BattlerTagLapseType.MOVE); } @@ -2402,7 +2234,7 @@ export class MovePhase extends BattlePhase { if (this.move.moveId) this.showMoveText(); - + if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) { moveQueue.shift(); this.cancel(); @@ -2430,11 +2262,16 @@ export class MovePhase extends BattlePhase { // Assume conditions affecting targets only apply to moves with a single target let success = this.move.getMove().applyConditions(this.pokemon, targets[0], this.move.getMove()); let failedText = null; + const isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)); if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove())) success = false; else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.move.getMove())) { success = false; failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType); + } else if (success && isBounced) { + this.showFailedText(this.pokemon.getOpponentDescriptor() + "\nbounced the move back!"); + this.targets = [this.pokemon.getBattlerIndex()]; + this.pokemon = targets[0]; } if (success) this.scene.unshiftPhase(this.getEffectPhase()); @@ -2442,7 +2279,7 @@ export class MovePhase extends BattlePhase { this.pokemon.pushMoveHistory({ move: this.move.moveId, targets: this.targets, result: MoveResult.FAIL, virtual: this.move.virtual }); this.showFailedText(failedText); } - + this.end(); }; @@ -2450,7 +2287,7 @@ export class MovePhase extends BattlePhase { this.pokemon.status.incrementTurn(); let activated = false; let healed = false; - + switch (this.pokemon.status.effect) { case StatusEffect.PARALYSIS: if (!this.pokemon.randSeedInt(4)) { @@ -2470,7 +2307,7 @@ export class MovePhase extends BattlePhase { this.cancelled = activated; break; } - + if (activated) { this.scene.queueMessage(getPokemonMessage(this.pokemon, getStatusEffectActivationText(this.pokemon.status.effect))); this.scene.unshiftPhase(new CommonAnimPhase(this.scene, this.pokemon.getBattlerIndex(), undefined, CommonAnim.POISON + (this.pokemon.status.effect - 1))); @@ -2501,7 +2338,7 @@ export class MovePhase extends BattlePhase { if (this.pokemon.getTag(BattlerTagType.RECHARGING)) return; - + this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); applyMoveAttrs(PreMoveMessageAttr, this.pokemon, this.pokemon.getOpponents().find(() => true), this.move.getMove()); } @@ -2521,7 +2358,7 @@ export class MovePhase extends BattlePhase { export class MoveEffectPhase extends PokemonPhase { public move: PokemonMove; protected targets: BattlerIndex[]; - + constructor(scene: BattleScene, battlerIndex: BattlerIndex, targets: BattlerIndex[], move: PokemonMove) { super(scene, battlerIndex); @@ -2532,8 +2369,8 @@ export class MoveEffectPhase extends PokemonPhase { start() { super.start(); - let user = this.getUserPokemon(); - let targets = this.getTargets(); + const user = this.getUserPokemon(); + const targets = this.getTargets(); if (!user?.isOnField()) return super.end(); @@ -2545,7 +2382,7 @@ export class MoveEffectPhase extends PokemonPhase { if (overridden.value) return this.end(); - + user.lapseTags(BattlerTagLapseType.MOVE_EFFECT); if (user.turnData.hitsLeft === undefined) { @@ -2576,24 +2413,12 @@ export class MoveEffectPhase extends PokemonPhase { return this.end(); } - let isBounced: BattlerTag | boolean = false; - for (let opponent of targets) { - isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); - if (isBounced) { - this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); - const tempTargets = targets; - targets = [user]; - user = tempTargets[0]; - break; - } - } - const applyAttrs: Promise[] = []; // Move animation only needs one target new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { for (let target of targets) { - if (!targetHitChecks[target.getBattlerIndex()] && !isBounced) { + if (!targetHitChecks[target.getBattlerIndex()]) { user.turnData.hitCount = 1; user.turnData.hitsLeft = 1; this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!')); From 8b0abff838315f0c5c1a4284c0801cbbff5d93d7 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Fri, 3 May 2024 22:57:51 -0500 Subject: [PATCH 04/19] have arena traps check their sides. --- src/data/move.ts | 4 ++-- src/field/arena.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index c1a3146d9..4884528ac 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2768,7 +2768,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { public tagType: ArenaTagType; public turnCount: integer; private failOnOverlap: boolean; - private selfSideTarget: boolean; + public selfSideTarget: boolean; constructor(tagType: ArenaTagType, turnCount?: integer, failOnOverlap: boolean = false, selfSideTarget: boolean = false) { super(true, MoveEffectTrigger.POST_APPLY, true); @@ -2801,7 +2801,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTag(this.tagType)) + if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) return true; const tag = user.scene.arena.getTag(this.tagType) as ArenaTrapTag; return tag.layers < tag.maxLayers; diff --git a/src/field/arena.ts b/src/field/arena.ts index 5b14560d4..61c0e4964 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -492,7 +492,7 @@ export class Arena { } addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, targetIndex?: BattlerIndex): boolean { - const existingTag = this.getTag(tagType); + const existingTag = this.getTagOnSide(tagType, side); if (existingTag) { existingTag.onOverlap(this); return false; From 6158e35b11d12fe7fc04f854c31584b61dd704dd Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Fri, 3 May 2024 23:31:21 -0500 Subject: [PATCH 05/19] make sure we check the right tags layers --- src/data/move.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 4884528ac..88845e786 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2801,9 +2801,10 @@ export class AddArenaTagAttr extends MoveEffectAttr { export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) + const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, side)) return true; - const tag = user.scene.arena.getTag(this.tagType) as ArenaTrapTag; + const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; return tag.layers < tag.maxLayers; }; } From 08337a1b3d744bf4924921f2b763de2a3313266f Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Fri, 3 May 2024 23:55:17 -0500 Subject: [PATCH 06/19] Revert "fix imports" This reverts commit 18907b52260baa12efc6aa62a4baf7901fc31302. --- src/phases.ts | 357 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 266 insertions(+), 91 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 3c5274b31..1ea3b30ee 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,63 +1,231 @@ -import BattleScene, { bypassLogin, startingWave } from "./battle-scene"; -import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; +import BattleScene, {bypassLogin, startingWave} from "./battle-scene"; +import { + DamageResult, + default as Pokemon, + EnemyPokemon, + FieldPosition, + HitResult, + MoveResult, + PlayerPokemon, + PokemonMove, + TurnMove +} from "./field/pokemon"; import * as Utils from './utils'; -import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr } from "./data/move"; -import { Mode } from './ui/ui'; -import { Command } from "./ui/command-ui-handler"; -import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; -import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; -import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; -import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; -import { StatusEffect, getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./data/status-effect"; -import { SummaryUiMode } from "./ui/summary-ui-handler"; +import {Moves} from "./data/enums/moves"; +import { + allMoves, + applyFilteredMoveAttrs, + applyMoveAttrs, + AttackMove, + BypassSleepAttr, + ChargeAttr, + CopyMoveAttr, + FixedDamageAttr, + ForceSwitchOutAttr, + getMoveTargets, + HealStatusEffectAttr, + HitsTagAttr, + IgnoreOpponentStatChangesAttr, + MissEffectAttr, + MoveAttr, + MoveEffectAttr, + MoveEffectTrigger, + MoveFlags, + MoveTarget, + MoveTargetSet, + MultiHitAttr, + NoEffectAttr, + OneHitKOAccuracyAttr, + OverrideMoveEffectAttr, + PreMoveMessageAttr, + SelfStatusMove, + VariableAccuracyAttr +} from "./data/move"; +import {Mode} from './ui/ui'; +import {Command} from "./ui/command-ui-handler"; +import {Stat} from "./data/pokemon-stat"; +import { + BerryModifier, + ContactHeldItemTransferChanceModifier, + EnemyAttackStatusEffectChanceModifier, + EnemyPersistentModifier, + EnemyStatusEffectHealChanceModifier, + EnemyTurnHealModifier, + ExpBalanceModifier, + ExpBoosterModifier, + ExpShareModifier, + ExtraModifierModifier, + FlinchChanceModifier, + HealingBoosterModifier, + HitHealModifier, + IvScannerModifier, + LapsingPersistentModifier, + LapsingPokemonHeldItemModifier, + MapModifier, + Modifier, + MoneyInterestModifier, + MoneyMultiplierModifier, + MultipleParticipantExpBonusModifier, + PersistentModifier, + PokemonExpBoosterModifier, + PokemonFriendshipBoosterModifier, + PokemonHeldItemModifier, + PokemonInstantReviveModifier, + PokemonMoveAccuracyBoosterModifier, + PokemonMultiHitModifier, + SwitchEffectTransferModifier, + TempBattleStatBoosterModifier, + TurnHealModifier, + TurnHeldItemTransferModifier +} from "./modifier/modifier"; +import PartyUiHandler, {PartyOption, PartyUiMode} from "./ui/party-ui-handler"; +import { + doPokeballBounceAnim, + getPokeballAtlasKey, + getPokeballCatchMultiplier, + getPokeballTintColor, + PokeballType +} from "./data/pokeball"; +import {CommonAnim, CommonBattleAnim, initMoveAnim, loadMoveAnimAssets, MoveAnim} from "./data/battle-anims"; +import { + getStatusEffectActivationText, + getStatusEffectCatchRateMultiplier, + getStatusEffectHealText, + getStatusEffectObtainText, + getStatusEffectOverlapText, + StatusEffect +} from "./data/status-effect"; +import {SummaryUiMode} from "./ui/summary-ui-handler"; import EvolutionSceneHandler from "./ui/evolution-scene-handler"; -import { EvolutionPhase } from "./evolution-phase"; -import { Phase } from "./phase"; -import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat"; -import { biomeLinks, getBiomeName } from "./data/biomes"; -import { Biome } from "./data/enums/biome"; -import { ModifierTier } from "./modifier/modifier-tier"; -import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; +import {EvolutionPhase} from "./evolution-phase"; +import {Phase} from "./phase"; +import {BattleStat, getBattleStatLevelChangeDescription, getBattleStatName} from "./data/battle-stat"; +import {biomeLinks, getBiomeName} from "./data/biomes"; +import {Biome} from "./data/enums/biome"; +import {ModifierTier} from "./modifier/modifier-tier"; +import { + FusePokemonModifierType, + getDailyRunStarterModifiers, + getEnemyBuffModifierForWave, + getModifierType, + getPlayerModifierTypeOptions, + getPlayerShopModifierTypeOptionsForWave, + ModifierPoolType, + ModifierType, + ModifierTypeFunc, + ModifierTypeOption, + modifierTypes, + PokemonModifierType, + PokemonMoveModifierType, + regenerateModifierPoolThresholds, + RememberMoveModifierType, + TmModifierType +} from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; -import { BattlerTagType } from "./data/enums/battler-tag-type"; -import { getPokemonMessage } from "./messages"; -import { Starter } from "./ui/starter-select-ui-handler"; -import { Gender } from "./data/gender"; -import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; -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 { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr } from "./data/ability"; -import { Unlockables, getUnlockableName } from "./system/unlockables"; -import { getBiomeKey } from "./field/arena"; -import { BattleType, BattlerIndex, TurnCommand } from "./battle"; -import { BattleSpec } from "./enums/battle-spec"; -import { Species } from "./data/enums/species"; -import { HealAchv, LevelAchv, achvs } from "./system/achv"; -import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; -import { TrainerType } from "./data/enums/trainer-type"; -import { EggHatchPhase } from "./egg-hatch-phase"; -import { Egg } from "./data/egg"; -import { vouchers } from "./system/voucher"; -import { loggedInUser, updateUserInfo } from "./account"; -import { PlayerGender, SessionSaveData } from "./system/game-data"; -import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; -import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; -import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue"; -import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler"; -import { Setting } from "./system/settings"; -import { Tutorial, handleTutorial } from "./tutorial"; -import { TerrainType } from "./data/terrain"; -import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; -import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; -import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; -import { GameModes, gameModes } from "./game-mode"; -import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; +import { + BattlerTag, + BattlerTagLapseType, + BounceTag, + EncoreTag, + HideSpriteTag as HiddenTag, + ProtectedTag, + TrappedTag +} from "./data/battler-tags"; +import {BattlerTagType} from "./data/enums/battler-tag-type"; +import {getPokemonMessage} from "./messages"; +import {Starter} from "./ui/starter-select-ui-handler"; +import {Gender} from "./data/gender"; +import { + getRandomWeatherType, + getTerrainBlockMessage, + getWeatherDamageMessage, + getWeatherLapseMessage, + Weather, + WeatherType +} from "./data/weather"; +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 { + AlwaysHitAbAttr, + applyAbAttrs, + applyBattleStatMultiplierAbAttrs, + applyCheckTrappedAbAttrs, + applyPostAttackAbAttrs, + applyPostBattleAbAttrs, + applyPostBattleInitAbAttrs, + applyPostDefendAbAttrs, + applyPostFaintAbAttrs, + applyPostKnockOutAbAttrs, + applyPostStatChangeAbAttrs, + applyPostSummonAbAttrs, + applyPostTurnAbAttrs, + applyPostVictoryAbAttrs, + applyPostWeatherLapseAbAttrs, + applyPreStatChangeAbAttrs, + applyPreSwitchOutAbAttrs, + applyPreWeatherEffectAbAttrs, + BattleStatMultiplierAbAttr, + BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, + CheckTrappedAbAttr, + IgnoreOpponentStatChangesAbAttr, + IncreasePpAbAttr, + IncrementMovePriorityAbAttr, + PostAttackAbAttr, + PostBattleAbAttr, + PostBattleInitAbAttr, + PostBiomeChangeAbAttr, + PostDefendAbAttr, + PostFaintAbAttr, + PostKnockOutAbAttr, + PostStatChangeAbAttr, + PostSummonAbAttr, + PostTurnAbAttr, + PostVictoryAbAttr, + PostWeatherLapseAbAttr, + PreSwitchOutAbAttr, + PreventBerryUseAbAttr, + PreWeatherDamageAbAttr, + ProtectStatAbAttr, + RedirectMoveAbAttr, + RunSuccessAbAttr, + StatChangeMultiplierAbAttr, + SuppressWeatherEffectAbAttr, + SyncEncounterNatureAbAttr +} from "./data/ability"; +import {getUnlockableName, Unlockables} from "./system/unlockables"; +import {getBiomeKey} from "./field/arena"; +import {BattlerIndex, BattleType, TurnCommand} from "./battle"; +import {BattleSpec} from "./enums/battle-spec"; +import {Species} from "./data/enums/species"; +import {achvs, HealAchv, LevelAchv} from "./system/achv"; +import {trainerConfigs, TrainerSlot} from "./data/trainer-config"; +import {TrainerType} from "./data/enums/trainer-type"; +import {EggHatchPhase} from "./egg-hatch-phase"; +import {Egg} from "./data/egg"; +import {vouchers} from "./system/voucher"; +import {loggedInUser, updateUserInfo} from "./account"; +import {PlayerGender, SessionSaveData} from "./system/game-data"; +import {addPokeballCaptureStars, addPokeballOpenParticles} from "./field/anims"; +import { + SpeciesFormChangeActiveTrigger, + SpeciesFormChangeManualTrigger, + SpeciesFormChangeMoveLearnedTrigger, + SpeciesFormChangePostMoveTrigger, + SpeciesFormChangePreMoveTrigger +} from "./data/pokemon-forms"; +import {battleSpecDialogue, getCharVariantFromDialogue} from "./data/dialogue"; +import ModifierSelectUiHandler, {SHOP_OPTIONS_ROW_LIMIT} from "./ui/modifier-select-ui-handler"; +import {Setting} from "./system/settings"; +import {handleTutorial, Tutorial} from "./tutorial"; +import {TerrainType} from "./data/terrain"; +import {OptionSelectConfig, OptionSelectItem} from "./ui/abstact-option-select-ui-handler"; +import {SaveSlotUiMode} from "./ui/save-slot-select-ui-handler"; +import {fetchDailyRunSeed, getDailyRunStarters} from "./data/daily-run"; +import {GameModes, gameModes} from "./game-mode"; +import {getPokemonSpecies, speciesStarters} from "./data/pokemon-species"; import i18next from './plugins/i18n'; -import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides'; +import {STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE} from './overrides'; export class LoginPhase extends Phase { private showText: boolean; @@ -81,13 +249,13 @@ export class LoginPhase extends Phase { if (!statusCode || statusCode === 400) { if (this.showText) this.scene.ui.showText(i18next.t('menu:logInOrCreateAccount')); - + this.scene.playSound('menu_open'); const loadData = () => { updateUserInfo().then(() => this.scene.gameData.loadSystem().then(() => this.end())); }; - + this.scene.ui.setMode(Mode.LOGIN_FORM, { buttonActions: [ () => { @@ -132,7 +300,7 @@ export class LoginPhase extends Phase { if (!this.scene.gameData.gender) this.scene.unshiftPhase(new SelectGenderPhase(this.scene)); - + handleTutorial(this.scene, Tutorial.Intro).then(() => super.end()); } } @@ -312,7 +480,7 @@ export class TitlePhase extends Phase { party.push(starterPokemon); loadPokemonAssets.push(starterPokemon.loadAssets()); } - + regenerateModifierPoolThresholds(party, ModifierPoolType.DAILY_STARTER); const modifiers: Modifier[] = Array(3).fill(null).map(() => modifierTypes.EXP_SHARE().withIdFromFunc(modifierTypes.EXP_SHARE).newModifier()) .concat(Array(3).fill(null).map(() => modifierTypes.GOLDEN_EXP_CHARM().withIdFromFunc(modifierTypes.GOLDEN_EXP_CHARM).newModifier())) @@ -421,7 +589,7 @@ export class SelectGenderPhase extends Phase { constructor(scene: BattleScene) { super(scene); } - + start(): void { super.start(); @@ -718,11 +886,11 @@ export class EncounterPhase extends BattlePhase { enemyPokemon.updateScale(); } } - + totalBst += enemyPokemon.getSpeciesForm().baseTotal; loadEnemyAssets.push(enemyPokemon.loadAssets()); - + console.log(enemyPokemon.name, enemyPokemon.species.speciesId, enemyPokemon.stats); }); @@ -845,7 +1013,7 @@ export class EncounterPhase extends BattlePhase { const trainer = this.scene.currentBattle.trainer; trainer.untint(100, 'Sine.easeOut'); trainer.playAnim(); - + const doSummon = () => { this.scene.currentBattle.started = true; this.scene.playBgm(undefined); @@ -864,7 +1032,7 @@ export class EncounterPhase extends BattlePhase { else doTrainerSummon(); }; - + const encounterMessages = this.scene.currentBattle.trainer.getEncounterMessages(); if (!encounterMessages?.length) @@ -921,7 +1089,7 @@ export class EncounterPhase extends BattlePhase { this.scene.pushPhase(new ReturnPhase(this.scene, 1)); this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, false)); } - + if (this.scene.currentBattle.waveIndex > startingWave && this.scene.currentBattle.battleType !== BattleType.TRAINER) { this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double)); if (this.scene.currentBattle.double && availablePartyMembers.length > 1) @@ -977,7 +1145,7 @@ export class NextEncounterPhase extends EncounterPhase { this.scene.arenaNextEnemy.setVisible(false); if (this.scene.lastEnemyTrainer) this.scene.lastEnemyTrainer.destroy(); - + if (!this.tryOverrideForBattleSpec()) this.doEncounterCommon(); } @@ -1869,7 +2037,7 @@ export class EnemyCommandPhase extends FieldPhase { if (partyMemberScores.length) { const matchupScores = opponents.map(opp => enemyPokemon.getMatchupScore(opp)); const matchupScore = matchupScores.reduce((total, score) => total += score, 0) / matchupScores.length; - + const sortedPartyMemberScores = trainer.getSortedPartyMemberMatchupScores(partyMemberScores); const switchMultiplier = 1 - (battle.enemySwitchCounter ? Math.pow(0.1, (1 / battle.enemySwitchCounter)) : 0); @@ -1879,7 +2047,7 @@ export class EnemyCommandPhase extends FieldPhase { battle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] = { command: Command.POKEMON, cursor: index, args: [ false ] }; - + battle.enemySwitchCounter++; return this.end(); @@ -1954,11 +2122,11 @@ export class TurnStartPhase extends FieldPhase { applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority); applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority); - + if (aPriority.value !== bPriority.value) return aPriority.value < bPriority.value ? 1 : -1; } - + const aIndex = order.indexOf(a); const bIndex = order.indexOf(b); @@ -2026,10 +2194,10 @@ export class TurnEndPhase extends FieldPhase { super.start(); this.scene.currentBattle.incrementTurn(this.scene); - + const handlePokemon = (pokemon: Pokemon) => { pokemon.lapseTags(BattlerTagLapseType.TURN_END); - + if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('menu:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); pokemon.summonData.disabledMove = Moves.NONE; @@ -2059,7 +2227,7 @@ export class TurnEndPhase extends FieldPhase { }; this.executeForAll(handlePokemon); - + this.scene.arena.lapseTags(); if (this.scene.arena.weather && !this.scene.arena.weather.lapse()) @@ -2217,9 +2385,9 @@ export class MovePhase extends BattlePhase { const doMove = () => { this.pokemon.turnData.acted = true; // Record that the move was attempted, even if it fails - + this.pokemon.lapseTags(BattlerTagLapseType.PRE_MOVE); - + if (!this.followUp && this.canMove() && !this.cancelled) { this.pokemon.lapseTags(BattlerTagLapseType.MOVE); } @@ -2234,7 +2402,7 @@ export class MovePhase extends BattlePhase { if (this.move.moveId) this.showMoveText(); - + if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) { moveQueue.shift(); this.cancel(); @@ -2262,16 +2430,11 @@ export class MovePhase extends BattlePhase { // Assume conditions affecting targets only apply to moves with a single target let success = this.move.getMove().applyConditions(this.pokemon, targets[0], this.move.getMove()); let failedText = null; - const isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)); if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove())) success = false; else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.move.getMove())) { success = false; failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType); - } else if (success && isBounced) { - this.showFailedText(this.pokemon.getOpponentDescriptor() + "\nbounced the move back!"); - this.targets = [this.pokemon.getBattlerIndex()]; - this.pokemon = targets[0]; } if (success) this.scene.unshiftPhase(this.getEffectPhase()); @@ -2279,7 +2442,7 @@ export class MovePhase extends BattlePhase { this.pokemon.pushMoveHistory({ move: this.move.moveId, targets: this.targets, result: MoveResult.FAIL, virtual: this.move.virtual }); this.showFailedText(failedText); } - + this.end(); }; @@ -2287,7 +2450,7 @@ export class MovePhase extends BattlePhase { this.pokemon.status.incrementTurn(); let activated = false; let healed = false; - + switch (this.pokemon.status.effect) { case StatusEffect.PARALYSIS: if (!this.pokemon.randSeedInt(4)) { @@ -2307,7 +2470,7 @@ export class MovePhase extends BattlePhase { this.cancelled = activated; break; } - + if (activated) { this.scene.queueMessage(getPokemonMessage(this.pokemon, getStatusEffectActivationText(this.pokemon.status.effect))); this.scene.unshiftPhase(new CommonAnimPhase(this.scene, this.pokemon.getBattlerIndex(), undefined, CommonAnim.POISON + (this.pokemon.status.effect - 1))); @@ -2338,7 +2501,7 @@ export class MovePhase extends BattlePhase { if (this.pokemon.getTag(BattlerTagType.RECHARGING)) return; - + this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); applyMoveAttrs(PreMoveMessageAttr, this.pokemon, this.pokemon.getOpponents().find(() => true), this.move.getMove()); } @@ -2358,7 +2521,7 @@ export class MovePhase extends BattlePhase { export class MoveEffectPhase extends PokemonPhase { public move: PokemonMove; protected targets: BattlerIndex[]; - + constructor(scene: BattleScene, battlerIndex: BattlerIndex, targets: BattlerIndex[], move: PokemonMove) { super(scene, battlerIndex); @@ -2369,8 +2532,8 @@ export class MoveEffectPhase extends PokemonPhase { start() { super.start(); - const user = this.getUserPokemon(); - const targets = this.getTargets(); + let user = this.getUserPokemon(); + let targets = this.getTargets(); if (!user?.isOnField()) return super.end(); @@ -2382,7 +2545,7 @@ export class MoveEffectPhase extends PokemonPhase { if (overridden.value) return this.end(); - + user.lapseTags(BattlerTagLapseType.MOVE_EFFECT); if (user.turnData.hitsLeft === undefined) { @@ -2413,12 +2576,24 @@ export class MoveEffectPhase extends PokemonPhase { return this.end(); } + let isBounced: BattlerTag | boolean = false; + for (let opponent of targets) { + isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); + if (isBounced) { + this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); + const tempTargets = targets; + targets = [user]; + user = tempTargets[0]; + break; + } + } + const applyAttrs: Promise[] = []; // Move animation only needs one target new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { for (let target of targets) { - if (!targetHitChecks[target.getBattlerIndex()]) { + if (!targetHitChecks[target.getBattlerIndex()] && !isBounced) { user.turnData.hitCount = 1; user.turnData.hitsLeft = 1; this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!')); From d6ab5dd2d07898e2d23897c3c2b7f07e62ac5845 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 00:01:21 -0500 Subject: [PATCH 07/19] fix import styles --- src/phases.ts | 188 +++----------------------------------------------- 1 file changed, 10 insertions(+), 178 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 1ea3b30ee..d2e216fae 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,100 +1,16 @@ import BattleScene, {bypassLogin, startingWave} from "./battle-scene"; -import { - DamageResult, - default as Pokemon, - EnemyPokemon, - FieldPosition, - HitResult, - MoveResult, - PlayerPokemon, - PokemonMove, - TurnMove -} from "./field/pokemon"; +import {DamageResult, default as Pokemon, EnemyPokemon, FieldPosition, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove} from "./field/pokemon"; import * as Utils from './utils'; import {Moves} from "./data/enums/moves"; -import { - allMoves, - applyFilteredMoveAttrs, - applyMoveAttrs, - AttackMove, - BypassSleepAttr, - ChargeAttr, - CopyMoveAttr, - FixedDamageAttr, - ForceSwitchOutAttr, - getMoveTargets, - HealStatusEffectAttr, - HitsTagAttr, - IgnoreOpponentStatChangesAttr, - MissEffectAttr, - MoveAttr, - MoveEffectAttr, - MoveEffectTrigger, - MoveFlags, - MoveTarget, - MoveTargetSet, - MultiHitAttr, - NoEffectAttr, - OneHitKOAccuracyAttr, - OverrideMoveEffectAttr, - PreMoveMessageAttr, - SelfStatusMove, - VariableAccuracyAttr -} from "./data/move"; +import {allMoves, applyFilteredMoveAttrs, applyMoveAttrs, AttackMove, BypassSleepAttr, ChargeAttr, CopyMoveAttr, FixedDamageAttr, ForceSwitchOutAttr, getMoveTargets, HealStatusEffectAttr, HitsTagAttr, IgnoreOpponentStatChangesAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveEffectTrigger, MoveFlags, MoveTarget, MoveTargetSet, MultiHitAttr, NoEffectAttr, OneHitKOAccuracyAttr, OverrideMoveEffectAttr, PreMoveMessageAttr, SelfStatusMove, VariableAccuracyAttr} from "./data/move"; import {Mode} from './ui/ui'; import {Command} from "./ui/command-ui-handler"; import {Stat} from "./data/pokemon-stat"; -import { - BerryModifier, - ContactHeldItemTransferChanceModifier, - EnemyAttackStatusEffectChanceModifier, - EnemyPersistentModifier, - EnemyStatusEffectHealChanceModifier, - EnemyTurnHealModifier, - ExpBalanceModifier, - ExpBoosterModifier, - ExpShareModifier, - ExtraModifierModifier, - FlinchChanceModifier, - HealingBoosterModifier, - HitHealModifier, - IvScannerModifier, - LapsingPersistentModifier, - LapsingPokemonHeldItemModifier, - MapModifier, - Modifier, - MoneyInterestModifier, - MoneyMultiplierModifier, - MultipleParticipantExpBonusModifier, - PersistentModifier, - PokemonExpBoosterModifier, - PokemonFriendshipBoosterModifier, - PokemonHeldItemModifier, - PokemonInstantReviveModifier, - PokemonMoveAccuracyBoosterModifier, - PokemonMultiHitModifier, - SwitchEffectTransferModifier, - TempBattleStatBoosterModifier, - TurnHealModifier, - TurnHeldItemTransferModifier -} from "./modifier/modifier"; +import {BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, IvScannerModifier, LapsingPersistentModifier, LapsingPokemonHeldItemModifier, MapModifier, Modifier, MoneyInterestModifier, MoneyMultiplierModifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier} from "./modifier/modifier"; import PartyUiHandler, {PartyOption, PartyUiMode} from "./ui/party-ui-handler"; -import { - doPokeballBounceAnim, - getPokeballAtlasKey, - getPokeballCatchMultiplier, - getPokeballTintColor, - PokeballType -} from "./data/pokeball"; +import {doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType} from "./data/pokeball"; import {CommonAnim, CommonBattleAnim, initMoveAnim, loadMoveAnimAssets, MoveAnim} from "./data/battle-anims"; -import { - getStatusEffectActivationText, - getStatusEffectCatchRateMultiplier, - getStatusEffectHealText, - getStatusEffectObtainText, - getStatusEffectOverlapText, - StatusEffect -} from "./data/status-effect"; +import {getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText, StatusEffect} from "./data/status-effect"; import {SummaryUiMode} from "./ui/summary-ui-handler"; import EvolutionSceneHandler from "./ui/evolution-scene-handler"; import {EvolutionPhase} from "./evolution-phase"; @@ -103,96 +19,18 @@ import {BattleStat, getBattleStatLevelChangeDescription, getBattleStatName} from import {biomeLinks, getBiomeName} from "./data/biomes"; import {Biome} from "./data/enums/biome"; import {ModifierTier} from "./modifier/modifier-tier"; -import { - FusePokemonModifierType, - getDailyRunStarterModifiers, - getEnemyBuffModifierForWave, - getModifierType, - getPlayerModifierTypeOptions, - getPlayerShopModifierTypeOptionsForWave, - ModifierPoolType, - ModifierType, - ModifierTypeFunc, - ModifierTypeOption, - modifierTypes, - PokemonModifierType, - PokemonMoveModifierType, - regenerateModifierPoolThresholds, - RememberMoveModifierType, - TmModifierType -} from "./modifier/modifier-type"; +import {FusePokemonModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, modifierTypes, PokemonModifierType, PokemonMoveModifierType, regenerateModifierPoolThresholds, RememberMoveModifierType, TmModifierType} from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { - BattlerTag, - BattlerTagLapseType, - BounceTag, - EncoreTag, - HideSpriteTag as HiddenTag, - ProtectedTag, - TrappedTag -} from "./data/battler-tags"; +import {BattlerTag, BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag} from "./data/battler-tags"; import {BattlerTagType} from "./data/enums/battler-tag-type"; import {getPokemonMessage} from "./messages"; import {Starter} from "./ui/starter-select-ui-handler"; import {Gender} from "./data/gender"; -import { - getRandomWeatherType, - getTerrainBlockMessage, - getWeatherDamageMessage, - getWeatherLapseMessage, - Weather, - WeatherType -} from "./data/weather"; +import {getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage, Weather, WeatherType} from "./data/weather"; 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 { - AlwaysHitAbAttr, - applyAbAttrs, - applyBattleStatMultiplierAbAttrs, - applyCheckTrappedAbAttrs, - applyPostAttackAbAttrs, - applyPostBattleAbAttrs, - applyPostBattleInitAbAttrs, - applyPostDefendAbAttrs, - applyPostFaintAbAttrs, - applyPostKnockOutAbAttrs, - applyPostStatChangeAbAttrs, - applyPostSummonAbAttrs, - applyPostTurnAbAttrs, - applyPostVictoryAbAttrs, - applyPostWeatherLapseAbAttrs, - applyPreStatChangeAbAttrs, - applyPreSwitchOutAbAttrs, - applyPreWeatherEffectAbAttrs, - BattleStatMultiplierAbAttr, - BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, - CheckTrappedAbAttr, - IgnoreOpponentStatChangesAbAttr, - IncreasePpAbAttr, - IncrementMovePriorityAbAttr, - PostAttackAbAttr, - PostBattleAbAttr, - PostBattleInitAbAttr, - PostBiomeChangeAbAttr, - PostDefendAbAttr, - PostFaintAbAttr, - PostKnockOutAbAttr, - PostStatChangeAbAttr, - PostSummonAbAttr, - PostTurnAbAttr, - PostVictoryAbAttr, - PostWeatherLapseAbAttr, - PreSwitchOutAbAttr, - PreventBerryUseAbAttr, - PreWeatherDamageAbAttr, - ProtectStatAbAttr, - RedirectMoveAbAttr, - RunSuccessAbAttr, - StatChangeMultiplierAbAttr, - SuppressWeatherEffectAbAttr, - SyncEncounterNatureAbAttr -} from "./data/ability"; +import {AlwaysHitAbAttr, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostBattleInitAbAttrs, applyPostDefendAbAttrs, applyPostFaintAbAttrs, applyPostKnockOutAbAttrs, applyPostStatChangeAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostVictoryAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IncreasePpAbAttr, IncrementMovePriorityAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostBattleInitAbAttr, PostBiomeChangeAbAttr, PostDefendAbAttr, PostFaintAbAttr, PostKnockOutAbAttr, PostStatChangeAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostVictoryAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreventBerryUseAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr} from "./data/ability"; import {getUnlockableName, Unlockables} from "./system/unlockables"; import {getBiomeKey} from "./field/arena"; import {BattlerIndex, BattleType, TurnCommand} from "./battle"; @@ -207,13 +45,7 @@ import {vouchers} from "./system/voucher"; import {loggedInUser, updateUserInfo} from "./account"; import {PlayerGender, SessionSaveData} from "./system/game-data"; import {addPokeballCaptureStars, addPokeballOpenParticles} from "./field/anims"; -import { - SpeciesFormChangeActiveTrigger, - SpeciesFormChangeManualTrigger, - SpeciesFormChangeMoveLearnedTrigger, - SpeciesFormChangePostMoveTrigger, - SpeciesFormChangePreMoveTrigger -} from "./data/pokemon-forms"; +import {SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger} from "./data/pokemon-forms"; import {battleSpecDialogue, getCharVariantFromDialogue} from "./data/dialogue"; import ModifierSelectUiHandler, {SHOP_OPTIONS_ROW_LIMIT} from "./ui/modifier-select-ui-handler"; import {Setting} from "./system/settings"; From bbbd55e265409721833d6be6f8e000f4366e22e1 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 12:06:00 -0500 Subject: [PATCH 08/19] have move fail if conditions are no longer met after bounce. --- src/phases.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/phases.ts b/src/phases.ts index d2e216fae..cc395565d 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2416,6 +2416,10 @@ export class MoveEffectPhase extends PokemonPhase { const tempTargets = targets; targets = [user]; user = tempTargets[0]; + if (!this.move.getMove().applyConditions(targets[0], targets[0], this.move.getMove())) { + this.scene.queueMessage(i18next.t('menu:attackFailed')); + return this.end(); + } break; } } From 9eec2c3e3a2c4f4392146b99c1e0bc9f26fe8154 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 16:12:00 -0500 Subject: [PATCH 09/19] change target of phase also, check conditions using the bouncer. --- src/phases.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/phases.ts b/src/phases.ts index cc395565d..05bbb4913 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2415,8 +2415,9 @@ export class MoveEffectPhase extends PokemonPhase { this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); const tempTargets = targets; targets = [user]; + this.targets = [user.getBattlerIndex()]; user = tempTargets[0]; - if (!this.move.getMove().applyConditions(targets[0], targets[0], this.move.getMove())) { + if (!this.move.getMove().applyConditions(user, targets[0], this.move.getMove())) { this.scene.queueMessage(i18next.t('menu:attackFailed')); return this.end(); } From 1e28f9545338e54070a32ebf830b7e57176ffa46 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 17:17:49 -0500 Subject: [PATCH 10/19] properly bounce multi targeted attacks --- src/phases.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 05bbb4913..aeba4fbef 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2414,8 +2414,13 @@ export class MoveEffectPhase extends PokemonPhase { if (isBounced) { this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); const tempTargets = targets; - targets = [user]; - this.targets = [user.getBattlerIndex()]; + this.targets = getMoveTargets(tempTargets[0], this.move.moveId).targets; + targets = []; + for (let index of this.targets){ + const target = this.scene.getField()[index]; + if (target) + targets.push(target); + } user = tempTargets[0]; if (!this.move.getMove().applyConditions(user, targets[0], this.move.getMove())) { this.scene.queueMessage(i18next.t('menu:attackFailed')); From 4b1f979af2dc54c2222b746a6460208c29e35595 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 17:33:46 -0500 Subject: [PATCH 11/19] properly handle targets on mutli moves. also checks which pokemon did the bouncing. --- src/phases.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index aeba4fbef..59bb70ed1 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2410,19 +2410,24 @@ export class MoveEffectPhase extends PokemonPhase { let isBounced: BattlerTag | boolean = false; for (let opponent of targets) { - isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (targets[0].findTags(t => t instanceof BounceTag).find(t => targets[0].lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); + isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof BounceTag).find(t => opponent.lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); if (isBounced) { - this.scene.queueMessage(getPokemonMessage(targets[0], '\nbounced the move back!')); + this.scene.queueMessage(getPokemonMessage(opponent, '\nbounced the move back!')); const tempTargets = targets; - this.targets = getMoveTargets(tempTargets[0], this.move.moveId).targets; - targets = []; - for (let index of this.targets){ - const target = this.scene.getField()[index]; - if (target) - targets.push(target); + if (this.move.getMove().isMultiTarget()){ + this.targets = getMoveTargets(tempTargets[0], this.move.moveId).targets; + targets = []; + for (let index of this.targets){ + const target = this.scene.getField()[index]; + if (target) + targets.push(target); + } + } else { + this.targets = [user.getBattlerIndex()]; + targets = [user]; } user = tempTargets[0]; - if (!this.move.getMove().applyConditions(user, targets[0], this.move.getMove())) { + if (!this.move.getMove().applyConditions(user, opponent, this.move.getMove())) { this.scene.queueMessage(i18next.t('menu:attackFailed')); return this.end(); } From d4b09761ecf8d7c5787aff1d7e78d1853b3efdaa Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 18:12:53 -0500 Subject: [PATCH 12/19] add flag to every applicable move. --- src/data/move.ts | 178 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 124 insertions(+), 54 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 88845e786..ce2287d26 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3796,7 +3796,8 @@ export function initMoves() { .attr(ForceSwitchOutAttr) .attr(HitsTagAttr, BattlerTagType.FLYING, false) .hidesTarget() - .windMove(), + .windMove() + .magicCoatMove(), new AttackMove(Moves.FLY, Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, -1, 0, 1) .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, 'flew\nup high!', BattlerTagType.FLYING) .condition(failOnGravityCondition) @@ -3817,7 +3818,8 @@ export function initMoves() { new AttackMove(Moves.ROLLING_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 85, 15, 30, 0, 1) .attr(FlinchAttr), new StatusMove(Moves.SAND_ATTACK, Type.GROUND, 100, 15, -1, 0, 1) - .attr(StatChangeAttr, BattleStat.ACC, -1), + .attr(StatChangeAttr, BattleStat.ACC, -1) + .magicCoatMove(), new AttackMove(Moves.HEADBUTT, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 15, 30, 0, 1) .attr(FlinchAttr), new AttackMove(Moves.HORN_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 25, -1, 0, 1), @@ -3841,7 +3843,8 @@ export function initMoves() { .attr(RecoilAttr, false, 0.33), new StatusMove(Moves.TAIL_WHIP, Type.NORMAL, 100, 30, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, -1) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.POISON_STING, Type.POISON, MoveCategory.PHYSICAL, 15, 100, 35, 30, 0, 1) .attr(StatusEffectAttr, StatusEffect.POISON) .makesContact(false), @@ -3854,24 +3857,29 @@ export function initMoves() { .makesContact(false), new StatusMove(Moves.LEER, Type.NORMAL, 100, 30, 100, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, -1) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.BITE, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, 30, 0, 1) .attr(FlinchAttr) .bitingMove(), new StatusMove(Moves.GROWL, Type.NORMAL, 100, 40, -1, 0, 1) .attr(StatChangeAttr, BattleStat.ATK, -1) .soundBased() - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new StatusMove(Moves.ROAR, Type.NORMAL, -1, 20, -1, -6, 1) .attr(ForceSwitchOutAttr) .soundBased() - .hidesTarget(), + .hidesTarget() + .magicCoatMove(), new StatusMove(Moves.SING, Type.NORMAL, 55, 15, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP) - .soundBased(), + .soundBased() + .magicCoatMove(), new StatusMove(Moves.SUPERSONIC, Type.NORMAL, 55, 20, -1, 0, 1) .attr(ConfuseAttr) - .soundBased(), + .soundBased() + .magicCoatMove(), new AttackMove(Moves.SONIC_BOOM, Type.NORMAL, MoveCategory.SPECIAL, -1, 90, 20, -1, 0, 1) .attr(FixedDamageAttr, 20), new StatusMove(Moves.DISABLE, Type.NORMAL, 100, 20, -1, 0, 1) @@ -3929,7 +3937,8 @@ export function initMoves() { .triageMove(), new StatusMove(Moves.LEECH_SEED, Type.GRASS, 90, 10, -1, 0, 1) .attr(AddBattlerTagAttr, BattlerTagType.SEEDED) - .condition((user, target, move) => !target.getTag(BattlerTagType.SEEDED) && !target.isOfType(Type.GRASS)), + .condition((user, target, move) => !target.getTag(BattlerTagType.SEEDED) && !target.isOfType(Type.GRASS)) + .magicCoatMove(), new SelfStatusMove(Moves.GROWTH, Type.NORMAL, -1, 20, -1, 0, 1) .attr(GrowthStatChangeAttr), new AttackMove(Moves.RAZOR_LEAF, Type.GRASS, MoveCategory.PHYSICAL, 55, 95, 25, -1, 0, 1) @@ -3943,13 +3952,16 @@ export function initMoves() { .ignoresVirtual(), new StatusMove(Moves.POISON_POWDER, Type.POISON, 75, 35, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.POISON) - .powderMove(), + .powderMove() + .magicCoatMove(), new StatusMove(Moves.STUN_SPORE, Type.GRASS, 75, 30, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) - .powderMove(), + .powderMove() + .magicCoatMove(), new StatusMove(Moves.SLEEP_POWDER, Type.GRASS, 75, 15, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP) - .powderMove(), + .powderMove() + .magicCoatMove(), new AttackMove(Moves.PETAL_DANCE, Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 1) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) @@ -3958,7 +3970,8 @@ export function initMoves() { .target(MoveTarget.RANDOM_NEAR_ENEMY), new StatusMove(Moves.STRING_SHOT, Type.BUG, 95, 40, -1, 0, 1) .attr(StatChangeAttr, BattleStat.SPD, -2) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.DRAGON_RAGE, Type.DRAGON, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 1) .attr(FixedDamageAttr, 40), new AttackMove(Moves.FIRE_SPIN, Type.FIRE, MoveCategory.SPECIAL, 35, 85, 15, 100, 0, 1) @@ -3969,7 +3982,8 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new StatusMove(Moves.THUNDER_WAVE, Type.ELECTRIC, 90, 20, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) - .attr(StatusMoveTypeImmunityAttr, Type.GROUND), + .attr(StatusMoveTypeImmunityAttr, Type.GROUND) + .magicCoatMove(), new AttackMove(Moves.THUNDER, Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 1) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .attr(ThunderAccuracyAttr) @@ -3997,7 +4011,8 @@ export function initMoves() { new AttackMove(Moves.PSYCHIC, Type.PSYCHIC, MoveCategory.SPECIAL, 90, 100, 10, 10, 0, 1) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new StatusMove(Moves.HYPNOSIS, Type.PSYCHIC, 60, 20, -1, 0, 1) - .attr(StatusEffectAttr, StatusEffect.SLEEP), + .attr(StatusEffectAttr, StatusEffect.SLEEP) + .magicCoatMove(), new SelfStatusMove(Moves.MEDITATE, Type.PSYCHIC, -1, 40, -1, 0, 1) .attr(StatChangeAttr, BattleStat.ATK, 1, true), new SelfStatusMove(Moves.AGILITY, Type.PSYCHIC, -1, 30, -1, 0, 1) @@ -4015,7 +4030,8 @@ export function initMoves() { .ignoresVirtual(), new StatusMove(Moves.SCREECH, Type.NORMAL, 85, 40, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, -2) - .soundBased(), + .soundBased() + .magicCoatMove(), new SelfStatusMove(Moves.DOUBLE_TEAM, Type.NORMAL, -1, 15, -1, 0, 1) .attr(StatChangeAttr, BattleStat.EVA, 1, true), new SelfStatusMove(Moves.RECOVER, Type.NORMAL, -1, 5, -1, 0, 1) @@ -4026,7 +4042,8 @@ export function initMoves() { new SelfStatusMove(Moves.MINIMIZE, Type.NORMAL, -1, 10, -1, 0, 1) .attr(StatChangeAttr, BattleStat.EVA, 2, true), new StatusMove(Moves.SMOKESCREEN, Type.NORMAL, 100, 20, -1, 0, 1) - .attr(StatChangeAttr, BattleStat.ACC, -1), + .attr(StatChangeAttr, BattleStat.ACC, -1) + .magicCoatMove(), new StatusMove(Moves.CONFUSE_RAY, Type.GHOST, 100, 10, -1, 0, 1) .attr(ConfuseAttr) .magicCoatMove(), @@ -4094,7 +4111,8 @@ export function initMoves() { new SelfStatusMove(Moves.AMNESIA, Type.PSYCHIC, -1, 20, -1, 0, 1) .attr(StatChangeAttr, BattleStat.SPDEF, 2, true), new StatusMove(Moves.KINESIS, Type.PSYCHIC, 80, 15, -1, 0, 1) - .attr(StatChangeAttr, BattleStat.ACC, -1), + .attr(StatChangeAttr, BattleStat.ACC, -1) + .magicCoatMove(), new SelfStatusMove(Moves.SOFT_BOILED, Type.NORMAL, -1, 5, -1, 0, 1) .attr(HealAttr, 0.5) .triageMove(), @@ -4103,14 +4121,16 @@ export function initMoves() { .attr(NoEffectAttr, crashDamageFunc) .condition(failOnGravityCondition), new StatusMove(Moves.GLARE, Type.NORMAL, 100, 30, -1, 0, 1) - .attr(StatusEffectAttr, StatusEffect.PARALYSIS), + .attr(StatusEffectAttr, StatusEffect.PARALYSIS) + .magicCoatMove(), new AttackMove(Moves.DREAM_EATER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 15, -1, 0, 1) .attr(HitHealAttr) .condition((user, target, move) => target.status?.effect === StatusEffect.SLEEP) .triageMove(), new StatusMove(Moves.POISON_GAS, Type.POISON, 90, 40, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.POISON) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.BARRAGE, Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, 0, 1) .attr(MultiHitAttr) .makesContact(false) @@ -4119,7 +4139,8 @@ export function initMoves() { .attr(HitHealAttr) .triageMove(), new StatusMove(Moves.LOVELY_KISS, Type.NORMAL, 75, 10, -1, 0, 1) - .attr(StatusEffectAttr, StatusEffect.SLEEP), + .attr(StatusEffectAttr, StatusEffect.SLEEP) + .magicCoatMove(), new AttackMove(Moves.SKY_ATTACK, Type.FLYING, MoveCategory.PHYSICAL, 140, 90, 5, 30, 0, 1) .attr(ChargeAttr, ChargeAnim.SKY_ATTACK_CHARGING, 'is glowing!') .attr(HighCritAttr) @@ -4137,9 +4158,11 @@ export function initMoves() { .punchingMove(), new StatusMove(Moves.SPORE, Type.GRASS, 100, 15, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP) - .powderMove(), + .powderMove() + .magicCoatMove(), new StatusMove(Moves.FLASH, Type.NORMAL, 100, 20, -1, 0, 1) - .attr(StatChangeAttr, BattleStat.ACC, -1), + .attr(StatChangeAttr, BattleStat.ACC, -1) + .magicCoatMove(), new AttackMove(Moves.PSYWAVE, Type.PSYCHIC, MoveCategory.SPECIAL, -1, 100, 15, -1, 0, 1) .attr(RandomLevelDamageAttr), new SelfStatusMove(Moves.SPLASH, Type.NORMAL, -1, 40, -1, 0, 1) @@ -4204,7 +4227,8 @@ export function initMoves() { new AttackMove(Moves.THIEF, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, -1, 0, 2) .attr(StealHeldItemChanceAttr, 0.3), new StatusMove(Moves.SPIDER_WEB, Type.BUG, -1, 10, -1, 0, 2) - .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1), + .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1) + .magicCoatMove(), new StatusMove(Moves.MIND_READER, Type.NORMAL, -1, 5, -1, 0, 2) .attr(IgnoreAccuracyAttr), new StatusMove(Moves.NIGHTMARE, Type.GHOST, 100, 15, -1, 0, 2) @@ -4237,7 +4261,8 @@ export function initMoves() { new AttackMove(Moves.REVERSAL, Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2) .attr(LowHpPowerAttr), new StatusMove(Moves.SPITE, Type.GHOST, 100, 10, -1, 0, 2) - .attr(ReducePpMoveAttr), + .attr(ReducePpMoveAttr) + .magicCoatMove(), new AttackMove(Moves.POWDER_SNOW, Type.ICE, MoveCategory.SPECIAL, 40, 100, 25, 10, 0, 2) .attr(StatusEffectAttr, StatusEffect.FREEZE) .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -4246,10 +4271,12 @@ export function initMoves() { new AttackMove(Moves.MACH_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 2) .punchingMove(), new StatusMove(Moves.SCARY_FACE, Type.NORMAL, 100, 10, -1, 0, 2) - .attr(StatChangeAttr, BattleStat.SPD, -2), + .attr(StatChangeAttr, BattleStat.SPD, -2) + .magicCoatMove(), new AttackMove(Moves.FEINT_ATTACK, Type.DARK, MoveCategory.PHYSICAL, 60, -1, 20, -1, 0, 2), new StatusMove(Moves.SWEET_KISS, Type.FAIRY, 75, 10, -1, 0, 2) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .magicCoatMove(), new SelfStatusMove(Moves.BELLY_DRUM, Type.NORMAL, -1, 10, -1, 0, 2) .attr(HalfHpStatMaxAttr, BattleStat.ATK), new AttackMove(Moves.SLUDGE_BOMB, Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, 30, 0, 2) @@ -4267,6 +4294,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .ballBombMove(), new StatusMove(Moves.FORESIGHT, Type.NORMAL, -1, 40, -1, 0, 2) + .magicCoatMove() .unimplemented(), new SelfStatusMove(Moves.DESTINY_BOND, Type.GHOST, -1, 5, -1, 0, 2) .ignoresProtect() @@ -4310,7 +4338,8 @@ export function initMoves() { .attr(SurviveDamageAttr), new StatusMove(Moves.SWAGGER, Type.NORMAL, 85, 15, -1, 0, 2) .attr(StatChangeAttr, BattleStat.ATK, 2) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .magicCoatMove(), new SelfStatusMove(Moves.MILK_DRINK, Type.NORMAL, -1, 5, -1, 0, 2) .attr(HealAttr, 0.5) .triageMove(), @@ -4322,7 +4351,8 @@ export function initMoves() { new AttackMove(Moves.STEEL_WING, Type.STEEL, MoveCategory.PHYSICAL, 70, 90, 25, 10, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, 1, true), new StatusMove(Moves.MEAN_LOOK, Type.NORMAL, -1, 5, -1, 0, 2) - .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1), + .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, true, 1) + .magicCoatMove(), new StatusMove(Moves.ATTRACT, Type.NORMAL, 100, 15, -1, 0, 2) .magicCoatMove() .attr(AddBattlerTagAttr, BattlerTagType.INFATUATED) @@ -4370,7 +4400,8 @@ export function initMoves() { .hidesUser(), new StatusMove(Moves.ENCORE, Type.NORMAL, 100, 5, -1, 0, 2) .attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, true) - .condition((user, target, move) => new EncoreTag(user.id).canAdd(target)), + .condition((user, target, move) => new EncoreTag(user.id).canAdd(target)) + .magicCoatMove(), new AttackMove(Moves.PURSUIT, Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, 0, 2) .partial(), new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2) @@ -4391,7 +4422,8 @@ export function initMoves() { .partial(), new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2) .attr(StatChangeAttr, BattleStat.EVA, -1) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new AttackMove(Moves.IRON_TAIL, Type.STEEL, MoveCategory.PHYSICAL, 100, 75, 15, 30, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, -1), new AttackMove(Moves.METAL_CLAW, Type.STEEL, MoveCategory.PHYSICAL, 50, 95, 35, 10, 0, 2) @@ -4469,12 +4501,15 @@ export function initMoves() { .attr(WeatherChangeAttr, WeatherType.HAIL) .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.TORMENT, Type.DARK, 100, 15, -1, 0, 3) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.FLATTER, Type.DARK, 100, 15, -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, 1) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .magicCoatMove(), new StatusMove(Moves.WILL_O_WISP, Type.FIRE, 85, 15, -1, 0, 3) - .attr(StatusEffectAttr, StatusEffect.BURN), + .attr(StatusEffectAttr, StatusEffect.BURN) + .magicCoatMove(), new StatusMove(Moves.MEMENTO, Type.DARK, 100, 10, -1, 0, 3) .attr(SacrificialAttr) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2), @@ -4497,6 +4532,7 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPDEF, 1, true) .attr(AddBattlerTagAttr, BattlerTagType.CHARGED, true, true), new StatusMove(Moves.TAUNT, Type.DARK, 100, 20, -1, 0, 3) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.HELPING_HAND, Type.NORMAL, -1, 20, -1, 5, 3) .attr(AddBattlerTagAttr, BattlerTagType.HELPING_HAND) @@ -4525,7 +4561,8 @@ export function initMoves() { .attr(RemoveScreensAttr), new StatusMove(Moves.YAWN, Type.NORMAL, -1, 10, -1, 0, 3) .attr(AddBattlerTagAttr, BattlerTagType.DROWSY, false, true) - .condition((user, target, move) => !target.status), + .condition((user, target, move) => !target.status) + .magicCoatMove(), new AttackMove(Moves.KNOCK_OFF, Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, 0, 3) .partial(), new AttackMove(Moves.ENDEAVOR, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 3) @@ -4564,7 +4601,8 @@ export function initMoves() { .ballBombMove(), new StatusMove(Moves.FEATHER_DANCE, Type.FLYING, 100, 15, -1, 0, 3) .attr(StatChangeAttr, BattleStat.ATK, -2) - .danceMove(), + .danceMove() + .magicCoatMove(), new StatusMove(Moves.TEETER_DANCE, Type.NORMAL, 100, 20, -1, 0, 3) .attr(ConfuseAttr) .danceMove() @@ -4608,7 +4646,8 @@ export function initMoves() { .target(MoveTarget.USER_AND_ALLIES) .unimplemented(), new StatusMove(Moves.FAKE_TEARS, Type.DARK, 100, 20, -1, 0, 3) - .attr(StatChangeAttr, BattleStat.SPDEF, -2), + .attr(StatChangeAttr, BattleStat.SPDEF, -2) + .magicCoatMove(), new AttackMove(Moves.AIR_CUTTER, Type.FLYING, MoveCategory.SPECIAL, 60, 95, 25, -1, 0, 3) .attr(HighCritAttr) .slicingMove() @@ -4618,6 +4657,7 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPATK, -2, true) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE), new StatusMove(Moves.ODOR_SLEUTH, Type.NORMAL, -1, 40, -1, 0, 3) + .magicCoatMove() .unimplemented(), new AttackMove(Moves.ROCK_TOMB, Type.ROCK, MoveCategory.PHYSICAL, 60, 95, 15, 100, 0, 3) .attr(StatChangeAttr, BattleStat.SPD, -1) @@ -4627,13 +4667,16 @@ export function initMoves() { .windMove(), new StatusMove(Moves.METAL_SOUND, Type.STEEL, 85, 40, -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPDEF, -2) - .soundBased(), + .soundBased() + .magicCoatMove(), new StatusMove(Moves.GRASS_WHISTLE, Type.GRASS, 55, 15, -1, 0, 3) .attr(StatusEffectAttr, StatusEffect.SLEEP) - .soundBased(), + .soundBased() + .magicCoatMove(), new StatusMove(Moves.TICKLE, Type.NORMAL, 100, 20, -1, 0, 3) .attr(StatChangeAttr, BattleStat.ATK, -1) - .attr(StatChangeAttr, BattleStat.DEF, -1), + .attr(StatChangeAttr, BattleStat.DEF, -1) + .magicCoatMove(), new SelfStatusMove(Moves.COSMIC_POWER, Type.PSYCHIC, -1, 20, -1, 0, 3) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, true), new AttackMove(Moves.WATER_SPOUT, Type.WATER, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 3) @@ -4727,6 +4770,7 @@ export function initMoves() { .attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5) .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.MIRACLE_EYE, Type.PSYCHIC, -1, 40, -1, 0, 4) + .magicCoatMove() .unimplemented(), new AttackMove(Moves.WAKE_UP_SLAP, Type.FIGHTING, MoveCategory.PHYSICAL, 70, 100, 10, -1, 0, 4) .attr(MovePowerMultiplierAttr, (user, target, move) => target.status?.effect === StatusEffect.SLEEP ? 2 : 1) @@ -4771,6 +4815,7 @@ export function initMoves() { new AttackMove(Moves.ASSURANCE, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 4) .attr(MovePowerMultiplierAttr, (user, target, move) => target.turnData.damageTaken > 0 ? 2 : 1), new StatusMove(Moves.EMBARGO, Type.DARK, 100, 15, -1, 0, 4) + .magicCoatMove() .unimplemented(), new AttackMove(Moves.FLING, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 4) .makesContact(false) @@ -4789,6 +4834,7 @@ export function initMoves() { .unimplemented(), new StatusMove(Moves.HEAL_BLOCK, Type.PSYCHIC, 100, 15, -1, 0, 4) .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove() .unimplemented(), new AttackMove(Moves.WRING_OUT, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 4) .attr(OpponentHighHpPowerAttr) @@ -4796,6 +4842,7 @@ export function initMoves() { new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4) .unimplemented(), new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, false, 5) @@ -4825,7 +4872,8 @@ export function initMoves() { return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1; }), new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4) - .attr(AbilityChangeAttr, Abilities.INSOMNIA), + .attr(AbilityChangeAttr, Abilities.INSOMNIA) + .magicCoatMove(), new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].category !== MoveCategory.STATUS), new StatusMove(Moves.TOXIC_SPIKES, Type.POISON, -1, 20, -1, 0, 4) @@ -5060,6 +5108,7 @@ export function initMoves() { .unimplemented(), new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5) .condition(failOnGravityCondition) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.MAGIC_ROOM, Type.PSYCHIC, -1, 10, -1, 0, 5) .ignoresProtect() @@ -5089,7 +5138,8 @@ export function initMoves() { .attr(BattleStatRatioPowerAttr, Stat.SPD) .ballBombMove(), new StatusMove(Moves.SOAK, Type.WATER, 100, 20, -1, 0, 5) - .attr(ChangeTypeAttr, Type.WATER), + .attr(ChangeTypeAttr, Type.WATER) + .magicCoatMove(), new AttackMove(Moves.FLAME_CHARGE, Type.FIRE, MoveCategory.PHYSICAL, 50, 100, 20, 100, 0, 5) .attr(StatChangeAttr, BattleStat.SPD, 1, true), new SelfStatusMove(Moves.COIL, Type.POISON, -1, 20, -1, 0, 5) @@ -5102,9 +5152,11 @@ export function initMoves() { new AttackMove(Moves.FOUL_PLAY, Type.DARK, MoveCategory.PHYSICAL, 95, 100, 15, -1, 0, 5) .attr(TargetAtkUserAtkAttr), new StatusMove(Moves.SIMPLE_BEAM, Type.NORMAL, 100, 15, -1, 0, 5) - .attr(AbilityChangeAttr, Abilities.SIMPLE), + .attr(AbilityChangeAttr, Abilities.SIMPLE) + .magicCoatMove(), new StatusMove(Moves.ENTRAINMENT, Type.NORMAL, 100, 15, -1, 0, 5) - .attr(AbilityGiveAttr), + .attr(AbilityGiveAttr) + .magicCoatMove(), new StatusMove(Moves.AFTER_YOU, Type.NORMAL, -1, 15, -1, 0, 5) .ignoresProtect() .unimplemented(), @@ -5136,7 +5188,8 @@ export function initMoves() { new StatusMove(Moves.HEAL_PULSE, Type.PSYCHIC, -1, 10, -1, 0, 5) .attr(HealAttr, 0.5, false, false) .pulseMove() - .triageMove(), + .triageMove() + .magicCoatMove(), new AttackMove(Moves.HEX, Type.GHOST, MoveCategory.SPECIAL, 65, 100, 10, -1, 0, 5) .attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1), new AttackMove(Moves.SKY_DROP, Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) @@ -5299,10 +5352,12 @@ export function initMoves() { .ignoresVirtual(), new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6) .attr(AddTypeAttr, Type.GHOST) + .magicCoatMove() .partial(), new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, 100, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1) - .soundBased(), + .soundBased() + .magicCoatMove(), new StatusMove(Moves.ION_DELUGE, Type.ELECTRIC, -1, 25, -1, 1, 6) .target(MoveTarget.BOTH_SIDES) .unimplemented(), @@ -5312,6 +5367,7 @@ export function initMoves() { .triageMove(), new StatusMove(Moves.FORESTS_CURSE, Type.GRASS, 100, 20, -1, 0, 6) .attr(AddTypeAttr, Type.GRASS) + .magicCoatMove() .partial(), new AttackMove(Moves.PETAL_BLIZZARD, Type.GRASS, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 6) .windMove() @@ -5326,9 +5382,11 @@ export function initMoves() { new StatusMove(Moves.PARTING_SHOT, Type.DARK, 100, 20, 100, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1) .attr(ForceSwitchOutAttr, true, false) - .soundBased(), + .soundBased() + .magicCoatMove(), new StatusMove(Moves.TOPSY_TURVY, Type.DARK, -1, 20, -1, 0, 6) - .attr(InvertStatsAttr), + .attr(InvertStatsAttr) + .magicCoatMove(), new AttackMove(Moves.DRAINING_KISS, Type.FAIRY, MoveCategory.SPECIAL, 50, 100, 10, -1, 0, 6) .attr(HitHealAttr, 0.75) .makesContact() @@ -5362,7 +5420,8 @@ export function initMoves() { new SelfStatusMove(Moves.KINGS_SHIELD, Type.STEEL, -1, 10, -1, 4, 6) .attr(ProtectAttr, BattlerTagType.KINGS_SHIELD), new StatusMove(Moves.PLAY_NICE, Type.NORMAL, -1, 20, 100, 0, 6) - .attr(StatChangeAttr, BattleStat.ATK, -1), + .attr(StatChangeAttr, BattleStat.ATK, -1) + .magicCoatMove(), new StatusMove(Moves.CONFIDE, Type.NORMAL, -1, 20, 100, 0, 6) .attr(StatChangeAttr, BattleStat.SPATK, -1) .soundBased(), @@ -5385,12 +5444,15 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPDEF, 1) .target(MoveTarget.NEAR_ALLY), new StatusMove(Moves.EERIE_IMPULSE, Type.ELECTRIC, 100, 15, -1, 0, 6) - .attr(StatChangeAttr, BattleStat.SPATK, -2), + .attr(StatChangeAttr, BattleStat.SPATK, -2) + .magicCoatMove(), new StatusMove(Moves.VENOM_DRENCH, Type.POISON, 100, 20, 100, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], -1, false, (user, target, move) => target.status?.effect === StatusEffect.POISON) - .target(MoveTarget.ALL_NEAR_ENEMIES), + .target(MoveTarget.ALL_NEAR_ENEMIES) + .magicCoatMove(), new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6) .powderMove() + .magicCoatMove() .unimplemented(), new SelfStatusMove(Moves.GEOMANCY, Type.FAIRY, -1, 10, -1, 0, 6) .attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, "is charging its power!") @@ -5550,13 +5612,15 @@ export function initMoves() { new StatusMove(Moves.FLORAL_HEALING, Type.FAIRY, -1, 10, -1, 0, 7) .attr(HealAttr, 0.5, true, false) .triageMove() + .magicCoatMove() .partial(), new AttackMove(Moves.HIGH_HORSEPOWER, Type.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7), new StatusMove(Moves.STRENGTH_SAP, Type.GRASS, 100, 10, 100, 0, 7) .attr(StrengthSapHealAttr) .attr(StatChangeAttr, BattleStat.ATK, -1) .condition((user, target, move) => target.summonData.battleStats[BattleStat.ATK] > -6) - .triageMove(), + .triageMove() + .magicCoatMove(), new AttackMove(Moves.SOLAR_BLADE, Type.GRASS, MoveCategory.PHYSICAL, 125, 100, 10, -1, 0, 7) .attr(SunlightChargeAttr, ChargeAnim.SOLAR_BLADE_CHARGING, "is glowing!") .attr(AntiSunlightPowerDecreaseAttr) @@ -5564,10 +5628,12 @@ export function initMoves() { new AttackMove(Moves.LEAFAGE, Type.GRASS, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 7) .makesContact(false), new StatusMove(Moves.SPOTLIGHT, Type.NORMAL, -1, 15, -1, 3, 7) + .magicCoatMove() .unimplemented(), new StatusMove(Moves.TOXIC_THREAD, Type.POISON, 100, 20, 100, 0, 7) .attr(StatusEffectAttr, StatusEffect.POISON) - .attr(StatChangeAttr, BattleStat.SPD, -1), + .attr(StatChangeAttr, BattleStat.SPD, -1) + .magicCoatMove(), new SelfStatusMove(Moves.LASER_FOCUS, Type.NORMAL, -1, 30, -1, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false), new StatusMove(Moves.GEAR_UP, Type.STEEL, -1, 20, -1, 0, 7) @@ -5604,6 +5670,7 @@ export function initMoves() { new AttackMove(Moves.SMART_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 70, -1, 10, -1, 0, 7), new StatusMove(Moves.PURIFY, Type.POISON, -1, 20, -1, 0, 7) .triageMove() + .magicCoatMove() .unimplemented(), new AttackMove(Moves.REVELATION_DANCE, Type.NORMAL, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7) .danceMove() @@ -5680,7 +5747,8 @@ export function initMoves() { .partial(), new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, 100, 0, 7) .attr(StatChangeAttr, BattleStat.ATK, -1) - .attr(StatChangeAttr, BattleStat.SPATK, -1), + .attr(StatChangeAttr, BattleStat.SPATK, -1) + .magicCoatMove(), new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7) .attr(FlinchAttr), new AttackMove(Moves.NATURES_MADNESS, Type.FAIRY, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 7) @@ -5774,10 +5842,12 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, true, 1), new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, 100, 0, 8) .attr(StatChangeAttr, BattleStat.SPD, -1) + .magicCoatMove() .partial(), new StatusMove(Moves.MAGIC_POWDER, Type.PSYCHIC, 100, 20, -1, 0, 8) .attr(ChangeTypeAttr, Type.PSYCHIC) - .powderMove(), + .powderMove() + .magicCoatMove(), new AttackMove(Moves.DRAGON_DARTS, Type.DRAGON, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 8) .attr(MultiHitAttr, MultiHitType._2) .makesContact(false) From 58dbefa60396564e831e3ec80ef8aec122f3432c Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 18:36:11 -0500 Subject: [PATCH 13/19] fix imports --- src/phases.ts | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index a28c4d719..48e9f2cde 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,5 +1,5 @@ -import BattleScene, {bypassLogin, startingWave} from "./battle-scene"; -import {DamageResult, default as Pokemon, EnemyPokemon, FieldPosition, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove} from "./field/pokemon"; +import BattleScene, { bypassLogin, startingWave } from "./battle-scene"; +import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; import { Moves } from "./data/enums/moves"; import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; @@ -21,41 +21,41 @@ import { Biome } from "./data/enums/biome"; import { ModifierTier } from "./modifier/modifier-tier"; import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import {BattlerTag, BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag} from "./data/battler-tags"; -import {BattlerTagType} from "./data/enums/battler-tag-type"; -import {getPokemonMessage} from "./messages"; -import {Starter} from "./ui/starter-select-ui-handler"; -import {Gender} from "./data/gender"; -import {getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage, Weather, WeatherType} from "./data/weather"; -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 {AlwaysHitAbAttr, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostBattleInitAbAttrs, applyPostDefendAbAttrs, applyPostFaintAbAttrs, applyPostKnockOutAbAttrs, applyPostStatChangeAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostVictoryAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, MagicBounceAbAttr, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IncreasePpAbAttr, IncrementMovePriorityAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostBattleInitAbAttr, PostBiomeChangeAbAttr, PostDefendAbAttr, PostFaintAbAttr, PostKnockOutAbAttr, PostStatChangeAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostVictoryAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreventBerryUseAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr} from "./data/ability"; -import {getUnlockableName, Unlockables} from "./system/unlockables"; -import {getBiomeKey} from "./field/arena"; -import {BattlerIndex, BattleType, TurnCommand} from "./battle"; -import {BattleSpec} from "./enums/battle-spec"; -import {Species} from "./data/enums/species"; -import {achvs, HealAchv, LevelAchv} from "./system/achv"; -import {trainerConfigs, TrainerSlot} from "./data/trainer-config"; -import {TrainerType} from "./data/enums/trainer-type"; -import {EggHatchPhase} from "./egg-hatch-phase"; -import {Egg} from "./data/egg"; -import {vouchers} from "./system/voucher"; -import {loggedInUser, updateUserInfo} from "./account"; -import {PlayerGender, SessionSaveData} from "./system/game-data"; -import {addPokeballCaptureStars, addPokeballOpenParticles} from "./field/anims"; -import {SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger} from "./data/pokemon-forms"; -import {battleSpecDialogue, getCharVariantFromDialogue} from "./data/dialogue"; -import ModifierSelectUiHandler, {SHOP_OPTIONS_ROW_LIMIT} from "./ui/modifier-select-ui-handler"; -import {Setting} from "./system/settings"; -import {handleTutorial, Tutorial} from "./tutorial"; -import {TerrainType} from "./data/terrain"; -import {OptionSelectConfig, OptionSelectItem} from "./ui/abstact-option-select-ui-handler"; -import {SaveSlotUiMode} from "./ui/save-slot-select-ui-handler"; -import {fetchDailyRunSeed, getDailyRunStarters} from "./data/daily-run"; -import {GameModes, gameModes} from "./game-mode"; -import {getPokemonSpecies, speciesStarters} from "./data/pokemon-species"; +import { BattlerTag, BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; +import { BattlerTagType } from "./data/enums/battler-tag-type"; +import { getPokemonMessage } from "./messages"; +import { Starter } from "./ui/starter-select-ui-handler"; +import { Gender } from "./data/gender"; +import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; +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 { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, MagicBounceAbAttr } from "./data/ability"; +import { Unlockables, getUnlockableName } from "./system/unlockables"; +import { getBiomeKey } from "./field/arena"; +import { BattleType, BattlerIndex, TurnCommand } from "./battle"; +import { BattleSpec } from "./enums/battle-spec"; +import { Species } from "./data/enums/species"; +import { HealAchv, LevelAchv, achvs } from "./system/achv"; +import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; +import { TrainerType } from "./data/enums/trainer-type"; +import { EggHatchPhase } from "./egg-hatch-phase"; +import { Egg } from "./data/egg"; +import { vouchers } from "./system/voucher"; +import { loggedInUser, updateUserInfo } from "./account"; +import { PlayerGender, SessionSaveData } from "./system/game-data"; +import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; +import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; +import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue"; +import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler"; +import { Setting } from "./system/settings"; +import { Tutorial, handleTutorial } from "./tutorial"; +import { TerrainType } from "./data/terrain"; +import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; +import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; +import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; +import { GameModes, gameModes } from "./game-mode"; +import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; import i18next from './plugins/i18n'; import { Abilities } from "./data/enums/abilities"; import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides'; From 243151d9877835bf140ac8c6321da5034b93724d Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 19:06:06 -0500 Subject: [PATCH 14/19] rename some bounce things to magic coat. give magic coat its move text. --- src/data/battler-tags.ts | 14 ++++++++++---- src/data/enums/battler-tag-type.ts | 2 +- src/data/move.ts | 2 +- src/phases.ts | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index f21456aa5..0f2594ec6 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -790,10 +790,16 @@ export class ContactBurnProtectedTag extends ProtectedTag { } } -export class BounceTag extends BattlerTag { - constructor(sourceMove: Moves, tagType: BattlerTagType = BattlerTagType.BOUNCE) { +export class MagicCoatTag extends BattlerTag { + constructor(sourceMove: Moves, tagType: BattlerTagType = BattlerTagType.MAGIC_COAT) { super(tagType, BattlerTagLapseType.CUSTOM, 0, sourceMove); } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' shrouded\nitself with Magic Coat!')); + } } export class EnduringTag extends BattlerTag { @@ -1232,8 +1238,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); case BattlerTagType.MAGNET_RISEN: return new MagnetRisenTag(tagType, sourceMove); - case BattlerTagType.BOUNCE: - return new BounceTag(sourceMove); + case BattlerTagType.MAGIC_COAT: + return new MagicCoatTag(sourceMove); case BattlerTagType.NONE: default: return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index fa0ce70ca..603209b6a 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -56,5 +56,5 @@ export enum BattlerTagType { CHARGED = "CHARGED", GROUNDED = "GROUNDED", MAGNET_RISEN = "MAGNET_RISEN", - BOUNCE = "BOUNCE" + MAGIC_COAT = "MAGIC_COAT" } diff --git a/src/data/move.ts b/src/data/move.ts index d393e33b6..2cd009f66 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4669,7 +4669,7 @@ export function initMoves() { new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 3) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF ], -1, true), new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3) - .attr(AddBattlerTagAttr, BattlerTagType.BOUNCE), + .attr(AddBattlerTagAttr, BattlerTagType.MAGIC_COAT), new SelfStatusMove(Moves.RECYCLE, Type.NORMAL, -1, 10, -1, 0, 3) .unimplemented(), new AttackMove(Moves.REVENGE, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, -4, 3) diff --git a/src/phases.ts b/src/phases.ts index 48e9f2cde..97dac4dba 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -21,7 +21,7 @@ import { Biome } from "./data/enums/biome"; import { ModifierTier } from "./modifier/modifier-tier"; import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTag, BattlerTagLapseType, BounceTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; +import { BattlerTag, BattlerTagLapseType, MagicCoatTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; import { BattlerTagType } from "./data/enums/battler-tag-type"; import { getPokemonMessage } from "./messages"; import { Starter } from "./ui/starter-select-ui-handler"; @@ -2416,7 +2416,7 @@ export class MoveEffectPhase extends PokemonPhase { let isBounced: BattlerTag | boolean = false; for (let opponent of targets) { - isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof BounceTag).find(t => opponent.lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); + isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof MagicCoatTag).find(t => opponent.lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); if (isBounced) { this.scene.queueMessage(getPokemonMessage(opponent, '\nbounced the move back!')); const tempTargets = targets; From 53f464669917b5d94725c511b0736f6da9663516 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 19:08:12 -0500 Subject: [PATCH 15/19] Revert "make sure we check the right tags layers" This reverts commit 6158e35b11d12fe7fc04f854c31584b61dd704dd. --- src/data/move.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 2cd009f66..f9a814188 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2857,10 +2857,9 @@ export class AddArenaTagAttr extends MoveEffectAttr { export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, side)) + if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) return true; - const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + const tag = user.scene.arena.getTag(this.tagType) as ArenaTrapTag; return tag.layers < tag.maxLayers; }; } From cd9064217dcc1caff03185c75460fcd035ea2905 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 19:08:13 -0500 Subject: [PATCH 16/19] Revert "have arena traps check their sides." This reverts commit 8b0abff838315f0c5c1a4284c0801cbbff5d93d7. --- src/data/move.ts | 4 ++-- src/field/arena.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index f9a814188..e14d835b8 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2824,7 +2824,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { public tagType: ArenaTagType; public turnCount: integer; private failOnOverlap: boolean; - public selfSideTarget: boolean; + private selfSideTarget: boolean; constructor(tagType: ArenaTagType, turnCount?: integer, failOnOverlap: boolean = false, selfSideTarget: boolean = false) { super(true, MoveEffectTrigger.POST_APPLY, true); @@ -2857,7 +2857,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) + if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTag(this.tagType)) return true; const tag = user.scene.arena.getTag(this.tagType) as ArenaTrapTag; return tag.layers < tag.maxLayers; diff --git a/src/field/arena.ts b/src/field/arena.ts index 61c0e4964..5b14560d4 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -492,7 +492,7 @@ export class Arena { } addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, targetIndex?: BattlerIndex): boolean { - const existingTag = this.getTagOnSide(tagType, side); + const existingTag = this.getTag(tagType); if (existingTag) { existingTag.onOverlap(this); return false; From 8c720eac69625eecee2f3a1e019390d963cec08b Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 19:19:43 -0500 Subject: [PATCH 17/19] missed confide oops. small format change also for charm. --- src/data/move.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index e14d835b8..17c3e7440 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4446,8 +4446,8 @@ export function initMoves() { new SelfStatusMove(Moves.ENDURE, Type.NORMAL, -1, 10, -1, 4, 2) .attr(EndureAttr), new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2) - .magicCoatMove() - .attr(StatChangeAttr, BattleStat.ATK, -2), + .attr(StatChangeAttr, BattleStat.ATK, -2) + .magicCoatMove(), new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2) .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2) @@ -5539,7 +5539,8 @@ export function initMoves() { .magicCoatMove(), new StatusMove(Moves.CONFIDE, Type.NORMAL, -1, 20, 100, 0, 6) .attr(StatChangeAttr, BattleStat.SPATK, -1) - .soundBased(), + .soundBased() + .magicCoatMove(), new AttackMove(Moves.DIAMOND_STORM, Type.ROCK, MoveCategory.PHYSICAL, 100, 95, 5, 50, 0, 6) .attr(StatChangeAttr, BattleStat.DEF, 2, true) .makesContact(false) From e2f9d1b9e858683e421a41fb1213d707a5524d38 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 21:26:55 -0500 Subject: [PATCH 18/19] change how the ability is detected. --- src/data/ability.ts | 8 +++++++- src/phases.ts | 6 ++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 571ef3337..1c9f41909 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2427,7 +2427,13 @@ export class NoFusionAbilityAbAttr extends AbAttr { } } -export class MagicBounceAbAttr extends AbAttr { } +export class MagicBounceAbAttr extends AbAttr { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + (args[0] as Utils.BooleanHolder).value = true; + + return true; + } +} function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { diff --git a/src/phases.ts b/src/phases.ts index 30bcede4b..9030da2ab 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ 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 { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, MagicBounceAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, 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, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, MagicBounceAbAttr, MaxMultiHitAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -2416,7 +2416,9 @@ export class MoveEffectPhase extends PokemonPhase { let isBounced: BattlerTag | boolean = false; for (let opponent of targets) { - isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof MagicCoatTag).find(t => opponent.lapseTag(t.tagType)) || opponent.hasAbilityWithAttr(MagicBounceAbAttr)); + const targetHasMagicBounce = new Utils.BooleanHolder(false); + applyAbAttrs(MagicBounceAbAttr, opponent, null, targetHasMagicBounce); + isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof MagicCoatTag).find(t => opponent.lapseTag(t.tagType)) || targetHasMagicBounce.value); if (isBounced) { this.scene.queueMessage(getPokemonMessage(opponent, '\nbounced the move back!')); const tempTargets = targets; From 7ad50490019ab0967f42fb2ad14bc6d2b43816e8 Mon Sep 17 00:00:00 2001 From: Reldnahc Date: Sat, 4 May 2024 21:49:24 -0500 Subject: [PATCH 19/19] remove unneeded const. --- src/phases.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 9030da2ab..5da7500e8 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2421,9 +2421,8 @@ export class MoveEffectPhase extends PokemonPhase { isBounced = this.move.getMove().hasFlag(MoveFlags.MAGIC_COAT_MOVE) && (opponent.findTags(t => t instanceof MagicCoatTag).find(t => opponent.lapseTag(t.tagType)) || targetHasMagicBounce.value); if (isBounced) { this.scene.queueMessage(getPokemonMessage(opponent, '\nbounced the move back!')); - const tempTargets = targets; if (this.move.getMove().isMultiTarget()){ - this.targets = getMoveTargets(tempTargets[0], this.move.moveId).targets; + this.targets = getMoveTargets(opponent, this.move.moveId).targets; targets = []; for (let index of this.targets){ const target = this.scene.getField()[index]; @@ -2434,7 +2433,7 @@ export class MoveEffectPhase extends PokemonPhase { this.targets = [user.getBattlerIndex()]; targets = [user]; } - user = tempTargets[0]; + user = opponent; if (!this.move.getMove().applyConditions(user, opponent, this.move.getMove())) { this.scene.queueMessage(i18next.t('menu:attackFailed')); return this.end();