[Bug] Adjust how counter attacks target to account for uturn/voltswitch and double battles (#2462)

* Adjust how counter attacks target to account for uturn/voltswitch

* Creates move flag for metal burst/comeuppance to redirect in some cases

* Remove debug printing

* Bit shifts the redirect counter flag

* Removes extraneous class from prior testing

* Remove vitest timestamp file that was accidentally added
This commit is contained in:
schmidtc1 2024-07-24 16:07:32 -04:00 committed by GitHub
parent 3c93aa6d36
commit e1662b8251
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 4 deletions

View File

@ -92,6 +92,10 @@ export enum MoveFlags {
* Enables all hits of a multi-hit move to be accuracy checked individually
*/
CHECK_ALL_HITS = 1 << 17,
/**
* Indicates a move is able to be redirected to allies in a double battle if the attacker faints
*/
REDIRECT_COUNTER = 1 << 18,
}
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
@ -549,6 +553,17 @@ export default class Move implements Localizable {
return this;
}
/**
* Sets the {@linkcode MoveFlags.REDIRECT_COUNTER} flag for the calling Move
* @param redirectCounter The value (boolean) to set the flag to
* example: @see {@linkcode Moves.METAL_BURST}
* @returns The {@linkcode Move} that called this function
*/
redirectCounter(redirectCounter?: boolean): this {
this.setFlag(MoveFlags.REDIRECT_COUNTER, redirectCounter);
return this;
}
/**
* Checks if the move flag applies to the pokemon(s) using/receiving the move
* @param flag {@linkcode MoveFlags} MoveFlag to check on user and/or target
@ -6907,6 +6922,7 @@ export function initMoves() {
.target(MoveTarget.USER_OR_NEAR_ALLY),
new AttackMove(Moves.METAL_BURST, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 4)
.attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5)
.redirectCounter()
.makesContact(false)
.target(MoveTarget.ATTACKER),
new AttackMove(Moves.U_TURN, Type.BUG, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 4)
@ -8587,6 +8603,7 @@ export function initMoves() {
}), // TODO Add Instruct/Encore interaction
new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 9)
.attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5)
.redirectCounter()
.target(MoveTarget.ATTACKER),
new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9)
.attr(HighCritAttr)

View File

@ -2075,7 +2075,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
source.turnData.damageDealt += damage.value;
source.turnData.currDamageDealt = damage.value;
this.battleData.hitCount++;
const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id };
const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id, attackingPosition: source.getBattlerIndex() };
this.turnData.attacksReceived.unshift(attackResult);
if (source.isPlayer() && !this.isPlayer()) {
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage);
@ -3990,6 +3990,7 @@ export interface AttackMoveResult {
damage: integer;
critical: boolean;
sourceId: integer;
attackingPosition: BattlerIndex;
}
export class PokemonSummonData {

View File

@ -2661,11 +2661,18 @@ export class MovePhase extends BattlePhase {
this.targets[0] = moveTarget.value;
}
// Check for counterattack moves to switch target
if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) {
if (this.pokemon.turnData.attacksReceived.length) {
const attacker = this.pokemon.turnData.attacksReceived.length ? this.pokemon.scene.getPokemonById(this.pokemon.turnData.attacksReceived[0].sourceId) : null;
if (attacker?.isActive(true)) {
this.targets[0] = attacker.getBattlerIndex();
const attack = this.pokemon.turnData.attacksReceived[0];
this.targets[0] = attack.attackingPosition;
// account for metal burst and comeuppance hitting remaining targets in double battles
// counterattack will redirect to remaining ally if original attacker faints
if (this.scene.currentBattle.double && this.move.getMove().hasFlag(MoveFlags.REDIRECT_COUNTER)) {
if (!this.scene.getEnemyField()[this.targets[0]]) {
this.targets[0] = this.scene.getEnemyField().find(p => p.isActive(true)).getBattlerIndex();
}
}
}
if (this.targets[0] === BattlerIndex.ATTACKER) {