From fa38ccca2def4c4bd358f0fcdc43f40025e13aca Mon Sep 17 00:00:00 2001 From: Jakub Hanko <60473007+JakubHanko@users.noreply.github.com> Date: Thu, 16 May 2024 22:09:40 +0200 Subject: [PATCH] Implement proof of concept of Friend Guard ability --- src/data/ability.ts | 16 ++++++++++++++-- src/data/battler-tags.ts | 20 ++++++++++++++++++++ src/data/enums/battler-tag-type.ts | 3 ++- src/field/pokemon.ts | 10 +++++++++- src/phases.ts | 3 ++- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 0ff03ed6776..c905ae99b6f 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2690,6 +2690,18 @@ export class IgnoreTypeStatusEffectImmunityAbAttr extends AbAttr { } } +export class FriendGuardAbAttr extends AbAttr { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ally = pokemon.getAlly(); + if (!ally) { + return false; + } + ally.addTag(BattlerTagType.FRIEND_GUARD, 1, undefined, pokemon.id); + + return true; + } +} + function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { return new Promise(resolve => { @@ -3263,8 +3275,8 @@ export function initAbilities() { new Ability(Abilities.HEALER, 5) .conditionalAttr(pokemon => pokemon.getAlly() && Utils.randSeedInt(10) < 3, PostTurnResetStatusAbAttr, true), new Ability(Abilities.FRIEND_GUARD, 5) - .ignorable() - .unimplemented(), + .attr(FriendGuardAbAttr) + .ignorable(), new Ability(Abilities.WEAK_ARMOR, 5) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, BattleStat.DEF, -1) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, BattleStat.SPD, 2), diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 257f56d46ed..dc0f9392dbe 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1249,6 +1249,24 @@ export class CursedTag extends BattlerTag { } } +export class FriendGuardTag extends BattlerTag { + public powerMultiplier: number; + + constructor(powerMultiplier: number) { + super(BattlerTagType.FRIEND_GUARD, BattlerTagLapseType.PRE_MOVE, 1, undefined); + this.powerMultiplier = 1 - powerMultiplier; + } + + /** + * When given a battler tag or json representing one, load the data for it. + * @param {BattlerTag | any} source A battler tag + */ + loadTag(source: BattlerTag | any): void { + super.loadTag(source); + this.powerMultiplier = source.powerMultiplier; + } +} + export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag { switch (tagType) { case BattlerTagType.RECHARGING: @@ -1358,6 +1376,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); case BattlerTagType.MAGNET_RISEN: return new MagnetRisenTag(tagType, sourceMove); + case BattlerTagType.FRIEND_GUARD: + return new FriendGuardTag(0.25); case BattlerTagType.NONE: default: return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index d18ccf1c52f..d8f31bbf9d5 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -55,5 +55,6 @@ export enum BattlerTagType { CURSED = "CURSED", CHARGED = "CHARGED", GROUNDED = "GROUNDED", - MAGNET_RISEN = "MAGNET_RISEN" + MAGNET_RISEN = "MAGNET_RISEN", + FRIEND_GUARD = "FRIEND_GUARD" } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 97d94bdba7c..aa862412e9e 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -19,7 +19,7 @@ import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEv import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from '../data/tms'; import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases'; import { BattleStat } from '../data/battle-stat'; -import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; +import { BattlerTag, BattlerTagLapseType, EncoreTag, FriendGuardTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; import { BattlerTagType } from "../data/enums/battler-tag-type"; import { Species } from '../data/enums/species'; import { WeatherType } from '../data/weather'; @@ -1448,6 +1448,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, battlerMove, power)); applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, battlerMove, cancelled, power); + const reducedDamageTag = this.getTag(BattlerTagType.FRIEND_GUARD) as FriendGuardTag; + console.log(this.findTags(t => true)); + if (reducedDamageTag) { + console.log(power); + console.log(reducedDamageTag.powerMultiplier); + power.value *= reducedDamageTag.powerMultiplier; + console.log(power); + } power.value *= typeChangeMovePowerMultiplier.value; diff --git a/src/phases.ts b/src/phases.ts index 8aa179d359a..3ecc0f12c81 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, FriendGuardAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -1616,6 +1616,7 @@ export class TurnInitPhase extends FieldPhase { this.scene.getField().forEach((pokemon, i) => { if (pokemon?.isActive()) { + applyAbAttrs(FriendGuardAbAttr, pokemon, undefined); if (pokemon.isPlayer()) this.scene.currentBattle.addParticipant(pokemon as PlayerPokemon);