From 81628e634fcf222ef2875b570dbee4e0e0308398 Mon Sep 17 00:00:00 2001 From: Marek Sison Date: Wed, 8 May 2024 23:00:58 +0800 Subject: [PATCH 1/2] HOTFIX: squashed bugs with stockpiles not properly being detected --- src/data/move.ts | 96 +++++++++++++++++++++++--------------------- src/field/pokemon.ts | 4 +- src/overrides.ts | 1 + 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index b98e2c899..f35903ba7 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1608,35 +1608,32 @@ export class GrowthStatChangeAttr extends StatChangeAttr { } export class StockpileStatChangeAttr extends StatChangeAttr { - constructor(move: string = "Stockpile") { + tagTypes = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; + + constructor(move: Moves = Moves.STOCKPILE) { let l = 1; - if (move === "Spit-Up" || move === "Swallow"){ + if (move === Moves.SPIT_UP || move === Moves.SWALLOW){ l = -1; } - super([ BattleStat.ATK, BattleStat.SPATK ], l, true); + super([ BattleStat.DEF, BattleStat.SPDEF ], l, true); } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { - if (!super.apply(user, target, move, args)) - return false; - - this.levels = this.levels < 0 ? (this.getStockpiles(user) * -1) : 1; - return true; - } + const stock = getStockpiles(user); - getStockpiles(user: Pokemon): integer { - let s = 0; - const stock = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; + if (this.levels < 0) { + this.levels = stock * -1; - for (let x = 0 ; x < stock.length ; x++){ - if (user.getTag(stock[x])){ - s++; - } + for (let tagType of this.tagTypes) + (this.selfTarget ? user : target).removeTag(tagType); } - return s; + if (!super.apply(user, target, move, args)) + return false; + + return true; } } @@ -2990,12 +2987,13 @@ export class FaintCountdownAttr extends AddBattlerTagAttr { export class StockpileAttr extends AddBattlerTagAttr { constructor() { - super(BattlerTagType.STOCKPILE_THREE, true, true, 20, 20); + super(BattlerTagType.STOCKPILE_THREE, true, false, 20, 20); } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const stock = this.getStockpiles(user); + const stock = getStockpiles(user); let stockType = BattlerTagType.STOCKPILE_THREE; + let willFail = false; switch (stock){ case 0: @@ -3003,28 +3001,24 @@ export class StockpileAttr extends AddBattlerTagAttr { break; case 1: stockType = BattlerTagType.STOCKPILE_TWO; + break; + case 3: + willFail = true; + break + default: + // keep it at STOCKPILE_THREE + break; } - if (!super.apply(user, target, move, args)) + this.tagType = stockType; + + if (!super.apply(user, target, move, args) || willFail) return false; user.scene.queueMessage(getPokemonMessage(target, `\nstockpiled ${stock+1}.`)); return true; } - - getStockpiles(user: Pokemon): integer { - let s = 0; - const stock = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; - - for (let x = 0 ; x < stock.length ; x++){ - if (user.getTag(stock[x])){ - s++; - } - } - - return s; - } } export class HitsTagAttr extends MoveAttr { @@ -3961,12 +3955,29 @@ export class VariableTargetAttr extends MoveAttr { } } +function getStockpiles(user: Pokemon) : integer { + let s = 0; + const stock = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; + + for (let x = 0 ; x < stock.length ; x++){ + if (user.getTag(stock[x])){ + s++; + } + } + + return s; +} + const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY); const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune(); const failOnMaxCondition: MoveConditionFunc = (user, target, move) => !target.isMax(); +const failOnMaxStockCondition: MoveConditionFunc = (user, target, move) => getStockpiles(user) != 3; + +const failOnNoStockCondition: MoveConditionFunc = (user, target, move) => getStockpiles(user) != 0; + const failIfDampCondition: MoveConditionFunc = (user, target, move) => { const cancelled = new Utils.BooleanHolder(false); user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); @@ -4797,25 +4808,18 @@ export function initMoves() { .partial(), new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3) .attr(StockpileAttr) - .attr(StockpileStatChangeAttr, 'Stockpile') + .attr(StockpileStatChangeAttr, Moves.STOCKPILE) + .condition(failOnMaxStockCondition) .partial(), new AttackMove(Moves.SPIT_UP, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 3) .attr(SpitUpPowerAttr) - .attr(StockpileStatChangeAttr, 'Spit-Up') - .attr(RemoveBattlerTagAttr, [ - BattlerTagType.STOCKPILE_ONE, - BattlerTagType.STOCKPILE_TWO, - BattlerTagType.STOCKPILE_THREE, - ], true) + .attr(StockpileStatChangeAttr, Moves.SPIT_UP) + .condition(failOnNoStockCondition) .partial(), new SelfStatusMove(Moves.SWALLOW, Type.NORMAL, -1, 10, -1, 0, 3) .attr(SwallowHealAttr, 1) - .attr(StockpileStatChangeAttr, 'Swallow') - .attr(RemoveBattlerTagAttr, [ - BattlerTagType.STOCKPILE_ONE, - BattlerTagType.STOCKPILE_TWO, - BattlerTagType.STOCKPILE_THREE, - ], true) + .attr(StockpileStatChangeAttr, Moves.SWALLOW) + .condition(failOnNoStockCondition) .triageMove() .partial(), new AttackMove(Moves.HEAT_WAVE, Type.FIRE, MoveCategory.SPECIAL, 95, 90, 10, 10, 0, 3) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 2242b1ee6..ca122c2b2 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -43,7 +43,7 @@ import { Nature, getNatureStatMultiplier } from '../data/nature'; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms'; import { TerrainType } from '../data/terrain'; import { TrainerSlot } from '../data/trainer-config'; -import { ABILITY_OVERRIDE, MOVE_OVERRIDE, MOVE_OVERRIDE_2, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_MOVE_OVERRIDE_2, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; +import { ABILITY_OVERRIDE, MOVE_OVERRIDE, MOVE_OVERRIDE_2, MOVE_OVERRIDE_3, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_MOVE_OVERRIDE_2, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; import { BerryType } from '../data/berry'; import i18next from '../plugins/i18n'; @@ -733,6 +733,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.moveset[1] = new PokemonMove(MOVE_OVERRIDE_2, Math.min(this.moveset[1].ppUsed, allMoves[MOVE_OVERRIDE_2].pp)); else if (OPP_MOVE_OVERRIDE_2 && !this.isPlayer()) this.moveset[1] = new PokemonMove(OPP_MOVE_OVERRIDE_2, Math.min(this.moveset[1].ppUsed, allMoves[OPP_MOVE_OVERRIDE_2].pp)); + if (MOVE_OVERRIDE_3 && this.isPlayer()) + this.moveset[2] = new PokemonMove(MOVE_OVERRIDE_3, Math.min(this.moveset[2].ppUsed, allMoves[MOVE_OVERRIDE_3].pp)); return ret; diff --git a/src/overrides.ts b/src/overrides.ts index 4b9bcaa0b..ddbb8176e 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -16,6 +16,7 @@ export const WEATHER_OVERRIDE = WeatherType.NONE; export const ABILITY_OVERRIDE = Abilities.NONE; export const MOVE_OVERRIDE = Moves.NONE; export const MOVE_OVERRIDE_2 = Moves.NONE; +export const MOVE_OVERRIDE_3 = Moves.NONE; export const OPP_SPECIES_OVERRIDE = 0; export const OPP_ABILITY_OVERRIDE = Abilities.NONE; export const OPP_MOVE_OVERRIDE = Moves.NONE; From a317d2fb7e25f8a3cf728efbf49f25f798bad51d Mon Sep 17 00:00:00 2001 From: Marek Sison Date: Fri, 10 May 2024 12:17:59 +0800 Subject: [PATCH 2/2] UPDATE: cleaned StockpileStatChangeAttr --- src/data/move.ts | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 74c5d46de..5fab974b4 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1648,24 +1648,23 @@ export class GrowthStatChangeAttr extends StatChangeAttr { } export class StockpileStatChangeAttr extends StatChangeAttr { - tagTypes = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; + private tagTypes = [BattlerTagType.STOCKPILE_ONE, BattlerTagType.STOCKPILE_TWO, BattlerTagType.STOCKPILE_THREE]; + private gainStats:boolean; - constructor(move: Moves = Moves.STOCKPILE) { - let l = 1; + constructor(gainStats:boolean = true) { + super([ BattleStat.DEF, BattleStat.SPDEF ], 1, true); - if (move === Moves.SPIT_UP || move === Moves.SWALLOW){ - l = -1; - } - - super([ BattleStat.DEF, BattleStat.SPDEF ], l, true); + this.gainStats = gainStats; } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { const stock = getStockpiles(user); - - if (this.levels < 0) { + + if (!this.gainStats) { + // levels become equal to the negative of stock this.levels = stock * -1; + // remove the stats equal to the number of stock for (let tagType of this.tagTypes) (this.selfTarget ? user : target).removeTag(tagType); } @@ -3052,7 +3051,7 @@ export class StockpileAttr extends AddBattlerTagAttr { this.tagType = stockType; - if (!super.apply(user, target, move, args) || willFail) + if (willFail || !super.apply(user, target, move, args)) return false; user.scene.queueMessage(getPokemonMessage(target, `\nstockpiled ${stock+1}.`)); @@ -4889,17 +4888,17 @@ export function initMoves() { .partial(), new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3) .attr(StockpileAttr) - .attr(StockpileStatChangeAttr, Moves.STOCKPILE) + .attr(StockpileStatChangeAttr) .condition(failOnMaxStockCondition) .partial(), new AttackMove(Moves.SPIT_UP, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 3) .attr(SpitUpPowerAttr) - .attr(StockpileStatChangeAttr, Moves.SPIT_UP) + .attr(StockpileStatChangeAttr, false) .condition(failOnNoStockCondition) .partial(), new SelfStatusMove(Moves.SWALLOW, Type.NORMAL, -1, 10, -1, 0, 3) .attr(SwallowHealAttr, 1) - .attr(StockpileStatChangeAttr, Moves.SWALLOW) + .attr(StockpileStatChangeAttr, false) .condition(failOnNoStockCondition) .triageMove() .partial(),