From 3ee2a7beeeb16db6b0abd45896a2bf2982b064f0 Mon Sep 17 00:00:00 2001 From: frutescens Date: Fri, 20 Sep 2024 15:01:28 -0700 Subject: [PATCH] Pollen Puff works now --- src/data/battler-tags.ts | 15 ++++++++++++++- src/data/move.ts | 5 +++-- src/field/pokemon.ts | 17 +++++++++++++++-- src/phases/select-target-phase.ts | 11 +++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 3d718f128ed..c907b60b820 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -3,7 +3,7 @@ import { getPokemonNameWithAffix } from "../messages"; import Pokemon, { MoveResult, HitResult } from "../field/pokemon"; import { StatusEffect } from "./status-effect"; import * as Utils from "../utils"; -import { ChargeAttr, MoveFlags, allMoves, MoveCategory } from "./move"; +import { ChargeAttr, MoveFlags, allMoves, MoveCategory, applyMoveAttrs, StatusCategoryOnAllyAttr, HealOnAllyAttr } from "./move"; import { Type } from "./type"; import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs, ProtectStatAbAttr } from "./ability"; import { TerrainType } from "./terrain"; @@ -141,6 +141,10 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag { */ abstract isMoveRestricted(move: Moves): boolean; + isMoveTargetRestricted(move: Moves, user: Pokemon, target: Pokemon): boolean { + return false; + } + /** * Gets the text to display when the player attempts to select a move that is restricted by this tag. * @@ -2205,6 +2209,15 @@ export class HealBlockTag extends MoveRestrictionBattlerTag { return false; } + override isMoveTargetRestricted(move: Moves, user: Pokemon, target: Pokemon) { + const moveCategory = new Utils.IntegerHolder(allMoves[move].category); + applyMoveAttrs(StatusCategoryOnAllyAttr, user, target, allMoves[move], moveCategory); + if (allMoves[move].hasAttr(HealOnAllyAttr) && moveCategory.value === MoveCategory.STATUS ) { + return true; + } + return false; + } + override selectionDeniedText(pokemon: Pokemon, move: Moves): string { return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name }); } diff --git a/src/data/move.ts b/src/data/move.ts index a479b157d35..530d78cc698 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3969,8 +3969,9 @@ export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr { */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const category = (args[0] as Utils.IntegerHolder); + const isAlly = (user.isPlayer() && target.isPlayer()) || (!user.isPlayer() && !target.isPlayer()); - if (user.getAlly() === target) { + if (isAlly) { category.value = MoveCategory.STATUS; return true; } @@ -9609,7 +9610,7 @@ export function initMoves() { .recklessMove(), new AttackMove(Moves.PSYCHIC_NOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9) .soundBased() - .partial(), + .attr(AddBattlerTagAttr, BattlerTagType.HEAL_BLOCK, false, false, 2), new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9) .attr(FlinchAttr) .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 && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].priority > 0 ) // TODO: is this bang correct? diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index f7b19572038..51566408d91 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2971,15 +2971,28 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.getRestrictingTag(moveId) !== null; } + /** + * + * + */ + isMoveTargetRestricted(moveId: Moves, user: Pokemon, target: Pokemon): boolean { + for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) { + if ((tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) { + return (tag as MoveRestrictionBattlerTag !== null); + } + } + return false; + } + /** * Gets the {@link MoveRestrictionBattlerTag} that is restricting a move, if it exists. * * @param {Moves} moveId {@linkcode Moves} ID of the move to check * @returns {MoveRestrictionBattlerTag | null} the first tag on this Pokemon that restricts the move, or `null` if the move is not restricted. */ - getRestrictingTag(moveId: Moves): MoveRestrictionBattlerTag | null { + getRestrictingTag(moveId: Moves, hasTargetRestriction: boolean = false): MoveRestrictionBattlerTag | null { for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) { - if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId)) { + if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId) || hasTargetRestriction ) { return tag as MoveRestrictionBattlerTag; } } diff --git a/src/phases/select-target-phase.ts b/src/phases/select-target-phase.ts index 716d2737a6c..c8205f6523d 100644 --- a/src/phases/select-target-phase.ts +++ b/src/phases/select-target-phase.ts @@ -4,6 +4,8 @@ import { Command } from "#app/ui/command-ui-handler"; import { Mode } from "#app/ui/ui"; import { CommandPhase } from "./command-phase"; import { PokemonPhase } from "./pokemon-phase"; +import i18next from "#app/plugins/i18n"; +import { allMoves } from "#app/data/move"; export class SelectTargetPhase extends PokemonPhase { constructor(scene: BattleScene, fieldIndex: integer) { @@ -17,6 +19,15 @@ export class SelectTargetPhase extends PokemonPhase { const move = turnCommand?.move?.move; this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (targets: BattlerIndex[]) => { this.scene.ui.setMode(Mode.MESSAGE); + const fieldSide = this.scene.getField(); + const user = fieldSide[this.fieldIndex]; + const moveObject = allMoves[move!]; + const hasTargetRestriction = user.isMoveTargetRestricted(moveObject.id, user, fieldSide[targets[0]]); + if (moveObject && hasTargetRestriction) { + const errorMessage = user.getRestrictingTag(move, hasTargetRestriction)!.selectionDeniedText(user, moveObject.id); + user.scene.queueMessage(i18next.t(errorMessage, { moveName: moveObject.name }), 0, true); + targets.length = 0; + } if (targets.length < 1) { this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex));