From ff348919926565e3719dfb373e67ec803e1b2a6d Mon Sep 17 00:00:00 2001 From: Luc Date: Thu, 25 Apr 2024 14:11:46 -0400 Subject: [PATCH 1/5] implemented stakeout --- src/data/ability.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index e129bf8ec2e..d2f0f88538b 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -19,6 +19,7 @@ import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; import { Abilities } from "./enums/abilities"; import i18next, { Localizable } from "#app/plugins/i18n.js"; +import { Command } from "../ui/command-ui-handler"; export class Ability implements Localizable { public id: Abilities; @@ -3004,7 +3005,7 @@ export function initAbilities() { .attr(NoFusionAbilityAbAttr) .partial(), new Ability(Abilities.STAKEOUT, 7) - .unimplemented(), + .attr(MovePowerBoostAbAttr, (user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON, 2), new Ability(Abilities.WATER_BUBBLE, 7) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) From e01731639f7760af7301c9e023227312222021d3 Mon Sep 17 00:00:00 2001 From: Luc Date: Thu, 25 Apr 2024 14:23:54 -0400 Subject: [PATCH 2/5] implemented analytic --- src/data/ability.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index d2f0f88538b..681fff65199 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2859,7 +2859,7 @@ export function initAbilities() { .ignorable() .unimplemented(), new Ability(Abilities.ANALYTIC, 5) - .unimplemented(), + .attr(MovePowerBoostAbAttr, (user, target, move) => !!target.getLastXMoves(1).find(m => m.turn === target.scene.currentBattle.turn) || user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command !== Command.FIGHT, 1.3), new Ability(Abilities.ILLUSION, 5) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) From f4f40634b7bbf07a3325c4c72f761f9071d43477 Mon Sep 17 00:00:00 2001 From: Luc Date: Thu, 25 Apr 2024 19:52:50 -0400 Subject: [PATCH 3/5] defeated the stakeout demons --- src/data/ability.ts | 29 +++++++++++++++++++++++++++-- src/data/move.ts | 10 ++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 681fff65199..2a236168bcd 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -9,7 +9,7 @@ import { BattlerTag } from "./battler-tags"; import { BattlerTagType } from "./enums/battler-tag-type"; import { StatusEffect, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect"; import { Gender } from "./gender"; -import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, RecoilAttr, StatusMoveTypeImmunityAttr, FlinchAttr, OneHitKOAttr, HitHealAttr, StrengthSapHealAttr, allMoves } from "./move"; +import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, RecoilAttr, StatusMoveTypeImmunityAttr, FlinchAttr, OneHitKOAttr, HitHealAttr, StrengthSapHealAttr, allMoves, ForceSwitchOutAttr } from "./move"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; import { Stat } from "./pokemon-stat"; @@ -920,6 +920,31 @@ export class MoveTypePowerBoostAbAttr extends MovePowerBoostAbAttr { } } +export class StakeoutAbAttr extends MovePowerBoostAbAttr { + constructor(powerMultiplier: number = 2) { + const condition: PokemonAttackCondition = (user, target, move) => { + + if(user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON) // covers hard switching + return true; + // find what move the target's slot used this turn and check if it's a switch-in move. + const moveId = user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move + const targetMove = allMoves[moveId]; + const usedSwitchMove = targetMove.findAttr(attr => attr instanceof ForceSwitchOutAttr) as ForceSwitchOutAttr; + + if(usedSwitchMove?.isSelfSwitch?.() && target.battleSummonData?.turnCount === 1){ // check if the move switches the user out + if(usedSwitchMove.returnUser().id === target.id) // dont activate if the move was used by the target (meaning it hasnt switched out yet) + return false; + return true; + } + + return false; + }; + + super(condition, powerMultiplier); + } +} + + export class LowHpMoveTypePowerBoostAbAttr extends MoveTypePowerBoostAbAttr { constructor(boostedType: Type) { super(boostedType); @@ -3005,7 +3030,7 @@ export function initAbilities() { .attr(NoFusionAbilityAbAttr) .partial(), new Ability(Abilities.STAKEOUT, 7) - .attr(MovePowerBoostAbAttr, (user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON, 2), + .attr(StakeoutAbAttr), new Ability(Abilities.WATER_BUBBLE, 7) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) diff --git a/src/data/move.ts b/src/data/move.ts index 4b80908ea54..25f5b7e6794 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2810,6 +2810,7 @@ export class RemoveScreensAttr extends MoveEffectAttr { export class ForceSwitchOutAttr extends MoveEffectAttr { private user: boolean; private batonPass: boolean; + private userReference: Pokemon; constructor(user?: boolean, batonPass?: boolean) { super(false, MoveEffectTrigger.POST_APPLY, true); @@ -2822,6 +2823,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (!this.user && target.isMax()) return resolve(false); + this.userReference = user; // Check if the move category is not STATUS or if the switch out condition is not met if (move.category !== MoveCategory.STATUS && !this.getSwitchOutCondition()(user, target, move)) { //Apply effects before switch out i.e. poison point, flame body, etc @@ -2882,6 +2884,14 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return (user, target, move) => move.category !== MoveCategory.STATUS || this.getSwitchOutCondition()(user, target, move); } + public isSelfSwitch(): boolean { + return this.user; + } + + returnUser(): Pokemon { + return this.userReference; + } + getSwitchOutCondition(): MoveConditionFunc { return (user, target, move) => { const switchOutTarget = (this.user ? user : target); From 643f796cfebf9cc220425d82de4d4f4a1726b36b Mon Sep 17 00:00:00 2001 From: Luc Date: Thu, 25 Apr 2024 21:10:28 -0400 Subject: [PATCH 4/5] fixed analytic implementation --- src/data/ability.ts | 52 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 2a236168bcd..7ea533436b1 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -927,14 +927,15 @@ export class StakeoutAbAttr extends MovePowerBoostAbAttr { if(user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON) // covers hard switching return true; // find what move the target's slot used this turn and check if it's a switch-in move. - const moveId = user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move - const targetMove = allMoves[moveId]; - const usedSwitchMove = targetMove.findAttr(attr => attr instanceof ForceSwitchOutAttr) as ForceSwitchOutAttr; - - if(usedSwitchMove?.isSelfSwitch?.() && target.battleSummonData?.turnCount === 1){ // check if the move switches the user out - if(usedSwitchMove.returnUser().id === target.id) // dont activate if the move was used by the target (meaning it hasnt switched out yet) - return false; - return true; + const moveId = user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move + if(moveId){ + const targetMove = allMoves[moveId]; + const usedSwitchMove = targetMove.findAttr(attr => attr instanceof ForceSwitchOutAttr) as ForceSwitchOutAttr; + if(usedSwitchMove && usedSwitchMove.returnUser() && usedSwitchMove?.isSelfSwitch?.() && target.battleSummonData?.turnCount === 1){ // check if the move switches the user out + if(usedSwitchMove.returnUser().id === target.id) // dont activate if the move was used by the target (meaning it hasnt switched out yet) + return false; + return true; + } } return false; @@ -944,6 +945,38 @@ export class StakeoutAbAttr extends MovePowerBoostAbAttr { } } +export class AnalyticAbAttr extends MovePowerBoostAbAttr { + constructor(powerMultiplier: number = 1.3) { + const condition: PokemonAttackCondition = (user, target, move) => { + const otherPokemons = target.scene.getField(true).filter(pokemon => pokemon.id !== user.id); + let fasterPokemon = 0; // increment for each pokemon that has moved before user + + otherPokemons.forEach(pokemon => { + + let switchMove = false; + const moveMatches = pokemon.getLastXMoves(1).find(m => m.turn === pokemon.scene.currentBattle.turn); + const prioCommand = user.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()].command !== Command.FIGHT; + const moveId = user.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.move?.move + if(moveId){ + const targetMove = allMoves[moveId]; + const usedSwitchMove = targetMove.findAttr(attr => attr instanceof ForceSwitchOutAttr) as ForceSwitchOutAttr; + if(usedSwitchMove && usedSwitchMove.returnUser() && usedSwitchMove?.isSelfSwitch?.() && (pokemon.battleSummonData?.turnCount === 1)){ // check if the target was switched in by a move + if(usedSwitchMove.returnUser().id === target.id) + switchMove = true; + } + } + if(moveMatches || prioCommand || switchMove) // check to see if they've used a move this round, ball/pokemon/run command, or switched out with a move + fasterPokemon++ + }); + if(fasterPokemon === otherPokemons.length) // only activate if ALL other pokemon have moved + return true; + else + return false; + }; + + super(condition, powerMultiplier); + } +} export class LowHpMoveTypePowerBoostAbAttr extends MoveTypePowerBoostAbAttr { constructor(boostedType: Type) { @@ -2884,7 +2917,8 @@ export function initAbilities() { .ignorable() .unimplemented(), new Ability(Abilities.ANALYTIC, 5) - .attr(MovePowerBoostAbAttr, (user, target, move) => !!target.getLastXMoves(1).find(m => m.turn === target.scene.currentBattle.turn) || user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command !== Command.FIGHT, 1.3), + .attr(AnalyticAbAttr), + //.attr(MovePowerBoostAbAttr, (user, target, move) => !!target.getLastXMoves(1).find(m => m.turn === target.scene.currentBattle.turn) || user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command !== Command.FIGHT, 1.3), new Ability(Abilities.ILLUSION, 5) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) From 7219fecf828f187d8d076669cf2633ba34228bb5 Mon Sep 17 00:00:00 2001 From: lucfd <83493765+lucfd@users.noreply.github.com> Date: Thu, 25 Apr 2024 21:47:44 -0400 Subject: [PATCH 5/5] removed unnecessary code --- src/data/move.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index b502a9f6137..c4ca88dc393 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2916,7 +2916,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return (user, target, move) => move.category !== MoveCategory.STATUS || this.getSwitchOutCondition()(user, target, move); } - public isSelfSwitch(): boolean { + isSelfSwitch(): boolean { return this.user; }