From 0b75a5210aea737e18acbbadfe3013fed30136df Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Wed, 15 May 2024 13:41:40 +0100 Subject: [PATCH] Implemented Power Split and Guard Split (#699) * Implemented Power Split and Guard Split * Update changeStat method to use summonData for Pokemon stats This commit modifies the `changeStat` method in the `Pokemon` class to use the `summonData` object for updating Pokemon stats instead of directly modifying the `stats` object. This change ensures that the updated stats are correctly reflected in the `summonData` object, which is used for battle calculations and other related operations. Refactor the `getStat` method to check if `summonData` exists and return the corresponding stat value from `summonData.stats` if it does. Otherwise, return the stat value from the `stats` object. This change improves the accuracy of stat calculations during battles and ensures consistency between the `stats` and `summonData` objects. * Added documentation for Power Split and Guard Split + linting * removed incorrect files * Removed incorrect folder * removed unnecessary import * Added documentation for getStat and changeSummonStat methods * New description for getStat() * Adjusting function descriptions * adjusted descriptions according to guideline --------- Co-authored-by: Frederico Santos --- src/data/move.ts | 84 +++++++++++++++++++++++++++++++++++++- src/field/pokemon.ts | 22 +++++++++- src/system/pokemon-data.ts | 1 + 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 46216eb75..aa722b29e 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2005,6 +2005,86 @@ export class HpSplitAttr extends MoveEffectAttr { } } +/** + * Attribute used for moves which split the user and the target's offensive raw stats. + * @extends MoveEffectAttr + * @see {@link apply} +*/ +export class PowerSplitAttr extends MoveEffectAttr { + + /** + * Applying Power Split to the user and the target. + * @param user The pokemon using the move. {@link Pokemon} + * @param target The targeted pokemon of the move. {@link Pokemon} + * @param move The move used. {@link Move} + * @param args N/A + * @returns True if power split is applied successfully. + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]) : Promise { + return new Promise(resolve => { + + if (!super.apply(user, target, move, args)) + return resolve(false); + + const infoUpdates = []; + + const attackValue = Math.floor((target.getStat(Stat.ATK) + user.getStat(Stat.ATK)) / 2); + user.changeSummonStat(Stat.ATK, attackValue); + infoUpdates.push(user.updateInfo()); + target.changeSummonStat(Stat.ATK, attackValue); + infoUpdates.push(target.updateInfo()); + + const specialAttackValue = Math.floor((target.getStat(Stat.SPATK) + user.getStat(Stat.SPATK)) / 2); + user.changeSummonStat(Stat.SPATK, specialAttackValue); + infoUpdates.push(user.updateInfo()); + target.changeSummonStat(Stat.SPATK, specialAttackValue); + infoUpdates.push(target.updateInfo()); + + return Promise.all(infoUpdates).then(() => resolve(true)); + }); + } +} + +/** + * Attribute used for moves which split the user and the target's defensive raw stats. + * @extends MoveEffectAttr + * @see {@link apply} +*/ +export class GuardSplitAttr extends MoveEffectAttr { + /** + * Applying Guard Split to the user and the target. + * @param user The pokemon using the move. {@link Pokemon} + * @param target The targeted pokemon of the move. {@link Pokemon} + * @param move The move used. {@link Move} + * @param args N/A + * @returns True if power split is applied successfully. + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { + return new Promise(resolve => { + if (!super.apply(user, target, move, args)) + return resolve(false); + + const infoUpdates = []; + + const defenseValue = Math.floor((target.getStat(Stat.DEF) + user.getStat(Stat.DEF)) / 2); + user.changeSummonStat(Stat.DEF, defenseValue); + infoUpdates.push(user.updateInfo()); + target.changeSummonStat(Stat.DEF, defenseValue); + infoUpdates.push(target.updateInfo()); + + const specialDefenseValue = Math.floor((target.getStat(Stat.SPDEF) + user.getStat(Stat.SPDEF)) / 2); + user.changeSummonStat(Stat.SPDEF, specialDefenseValue); + infoUpdates.push(user.updateInfo()); + target.changeSummonStat(Stat.SPDEF, specialDefenseValue); + infoUpdates.push(target.updateInfo()); + + + return Promise.all(infoUpdates).then(() => resolve(true)); + }); + } + +} + export class VariablePowerAttr extends MoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; @@ -5664,9 +5744,9 @@ export function initMoves() { .target(MoveTarget.USER_SIDE) .unimplemented(), new StatusMove(Moves.GUARD_SPLIT, Type.PSYCHIC, -1, 10, -1, 0, 5) - .unimplemented(), + .attr(GuardSplitAttr), new StatusMove(Moves.POWER_SPLIT, Type.PSYCHIC, -1, 10, -1, 0, 5) - .unimplemented(), + .attr(PowerSplitAttr), new StatusMove(Moves.WONDER_ROOM, Type.PSYCHIC, -1, 10, -1, 0, 5) .ignoresProtect() .target(MoveTarget.BOTH_SIDES) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 48287cf39..8d6b11ae9 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -544,8 +544,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } + /** + * Returns the value of the specified stat. + * @param stat Stat to get the value of. {@link Stat} + * @returns The value of the stat. If the pokemon is already summoned, it uses those values, otherwise uses the base stats. + */ getStat(stat: Stat): integer { - return this.stats[stat]; + if (!this.summonData) { + return this.stats[stat]; + } + + return this.summonData.stats[stat]; } getBattleStat(stat: Stat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): integer { @@ -1708,6 +1717,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return healAmount; } + /** + * Sets a specific stat to a specific value. + * Used for summon data, while the pokemon is out until the next time it is retrieved. + * @param stat Stat to change. {@link Stat} + * @param value Amount to set the stat to. + */ + changeSummonStat(stat: Stat, value: integer) : void { + this.summonData.stats[stat] = value; + } + isBossImmune(): boolean { return this.isBoss(); } @@ -2166,6 +2185,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!this.battleData) this.resetBattleData(); this.resetBattleSummonData(); + this.summonData.stats = this.stats; if (this.summonDataPrimer) { for (let k of Object.keys(this.summonData)) { if (this.summonDataPrimer[k]) diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index dfbb9be57..dcf4a5744 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -112,6 +112,7 @@ export default class PokemonData { this.summonData = new PokemonSummonData(); if (!forHistory && source.summonData) { this.summonData.battleStats = source.summonData.battleStats; + this.summonData.stats = source.summonData.stats; this.summonData.moveQueue = source.summonData.moveQueue; this.summonData.disabledMove = source.summonData.disabledMove; this.summonData.disabledTurns = source.summonData.disabledTurns;