From 2b95d4ce5153aef3c3b8256904242ec8dbea9a68 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Fri, 28 Apr 2023 19:26:41 -0400 Subject: [PATCH] Add Baton modifier --- src/battle-phases.ts | 46 ++++++++++++++++++++++++++--------- src/data/battler-tag.ts | 6 ++--- src/modifier/modifier-type.ts | 4 +++ src/modifier/modifier.ts | 24 +++++++++++++++++- src/pokemon.ts | 13 ++++++++++ src/ui/party-ui-handler.ts | 15 ++++++------ 6 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/battle-phases.ts b/src/battle-phases.ts index e2a61d27745..88ade6d114d 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, HitsTagAttr, Mis import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HeldItemTransferModifier, HitHealModifier, MapModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, TempBattleStatBoosterModifier, TurnHealModifier } from "./modifier/modifier"; +import { BerryModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HeldItemTransferModifier, HitHealModifier, MapModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier } from "./modifier/modifier"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; @@ -18,7 +18,7 @@ import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } fr import { Biome, biomeLinks } from "./data/biome"; import { ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, getPlayerModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, IgnoreAccuracyTag, TrappedTag as TrapTag } from "./data/battler-tag"; +import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag"; import { getPokemonMessage } from "./messages"; import { Starter } from "./ui/starter-select-ui-handler"; import { Gender } from "./data/gender"; @@ -420,12 +420,16 @@ export class SummonPhase extends BattlePhase { export class SwitchSummonPhase extends SummonPhase { private slotIndex: integer; private doReturn: boolean; + private batonPass: boolean; - constructor(scene: BattleScene, slotIndex: integer, doReturn: boolean) { + private lastPokemon: PlayerPokemon; + + constructor(scene: BattleScene, slotIndex: integer, doReturn: boolean, batonPass: boolean) { super(scene); this.slotIndex = slotIndex; this.doReturn = doReturn; + this.batonPass = batonPass; } start() { @@ -440,7 +444,8 @@ export class SwitchSummonPhase extends SummonPhase { const playerPokemon = this.scene.getPlayerPokemon(); - this.scene.getEnemyPokemon()?.removeTagsBySourceId(playerPokemon.id); + if (!this.batonPass) + this.scene.getEnemyPokemon()?.removeTagsBySourceId(playerPokemon.id); this.scene.ui.showText(`Come back, ${this.scene.getPlayerPokemon().name}!`); this.scene.sound.play('pb_rel'); @@ -462,11 +467,29 @@ export class SwitchSummonPhase extends SummonPhase { switchAndSummon() { const party = this.scene.getParty(); const switchedPokemon = party[this.slotIndex]; - party[this.slotIndex] = this.scene.getPlayerPokemon(); + this.lastPokemon = this.scene.getPlayerPokemon(); + if (this.batonPass) { + this.scene.getEnemyPokemon()?.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id); + if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) { + const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier + && (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier; + this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false, false); + } + } + party[this.slotIndex] = this.lastPokemon; party[0] = switchedPokemon; this.scene.ui.showText(`Go! ${switchedPokemon.name}!`); this.summon(); } + + end() { + if (this.batonPass) + this.scene.getPlayerPokemon().transferSummon(this.lastPokemon); + + this.lastPokemon.resetSummonData(); + + super.end(); + } } export class CheckSwitchPhase extends BattlePhase { @@ -581,7 +604,7 @@ export class CommandPhase extends FieldPhase { this.scene.ui.setMode(Mode.COMMAND); } - handleCommand(command: Command, cursor: integer): boolean { + handleCommand(command: Command, cursor: integer, ...args: any[]): boolean { const playerPokemon = this.scene.getPlayerPokemon(); const enemyPokemon = this.scene.getEnemyPokemon(); let success: boolean; @@ -640,9 +663,10 @@ export class CommandPhase extends FieldPhase { } break; case Command.POKEMON: - const trapTag = playerPokemon.findTag(t => t instanceof TrapTag) as TrapTag; - if (!trapTag) { - this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, cursor, true)); + const trapTag = playerPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag; + const batonPass = args[0] as boolean; + if (batonPass || !trapTag) { + this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, cursor, true, args[0] as boolean)); success = true; } else this.scene.ui.showText(`${this.scene.getPokemonById(trapTag.sourceId).name}'s ${trapTag.getMoveName()}\nprevents switching!`, null, () => { @@ -1594,9 +1618,9 @@ export class SwitchPhase extends BattlePhase { start() { super.start(); - this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, (slotIndex: integer, _option: PartyOption) => { + this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, (slotIndex: integer, option: PartyOption) => { if (slotIndex && slotIndex < 6) - this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn)); + this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn, option === PartyOption.PASS_BATON)); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); }, PartyUiHandler.FilterNonFainted); } diff --git a/src/data/battler-tag.ts b/src/data/battler-tag.ts index 1fca52779de..08d99b1a5eb 100644 --- a/src/data/battler-tag.ts +++ b/src/data/battler-tag.ts @@ -201,8 +201,8 @@ export class ConfusedTag extends BattlerTag { } export class SeedTag extends BattlerTag { - constructor() { - super(BattlerTagType.SEEDED, BattlerTagLapseType.AFTER_MOVE, 1, Moves.LEECH_SEED); + constructor(sourceId: integer) { + super(BattlerTagType.SEEDED, BattlerTagLapseType.AFTER_MOVE, 1, Moves.LEECH_SEED, sourceId); } onAdd(pokemon: Pokemon): void { @@ -517,7 +517,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc case BattlerTagType.CONFUSED: return new ConfusedTag(turnCount, sourceMove); case BattlerTagType.SEEDED: - return new SeedTag(); + return new SeedTag(sourceId); case BattlerTagType.NIGHTMARE: return new NightmareTag(); case BattlerTagType.INGRAIN: diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 25f3f75b51f..bd22bfa3485 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -607,6 +607,9 @@ const modifierTypes = { SHELL_BELL: () => new PokemonHeldItemModifierType('SHELL BELL', 'Heals 1/8 of a POKéMON\'s dealt damage', (type, args) => new Modifiers.HitHealModifier(type, (args[0] as Pokemon).id)), + BATON: () => new PokemonHeldItemModifierType('BATON', 'Allows passing along effects when switching POKéMON, which also bypasses traps', + (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id), 'stick'), + SHINY_CHARM: () => new ModifierType('SHINY CHARM', 'Dramatically increases the chance of a wild POKéMON being shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), MINI_BLACK_HOLE: () => new HeldItemTransferModifierType('MINI BLACK HOLE'), @@ -684,6 +687,7 @@ const modifierPool = { new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5), new WeightedModifierType(modifierTypes.CANDY_JAR, 3), new WeightedModifierType(modifierTypes.HEALING_CHARM, 1), + new WeightedModifierType(modifierTypes.BATON, 1), new WeightedModifierType(modifierTypes.FOCUS_BAND, 3), new WeightedModifierType(modifierTypes.KINGS_ROCK, 2), new WeightedModifierType(modifierTypes.LEFTOVERS, 2), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index add70aced74..dad05611265 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -972,6 +972,28 @@ export class ShinyRateBoosterModifier extends PersistentModifier { } } +export class SwitchEffectTransferModifier extends PokemonHeldItemModifier { + constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) { + super(type, pokemonId, stackCount); + } + + matchType(modifier: Modifier): boolean { + return modifier instanceof SwitchEffectTransferModifier; + } + + clone(): SwitchEffectTransferModifier { + return new SwitchEffectTransferModifier(this.type, this.pokemonId, this.stackCount); + } + + apply(args: any[]): boolean { + return true; + } + + getMaxStackCount(): integer { + return 1; + } +} + export class HeldItemTransferModifier extends PokemonHeldItemModifier { constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) { super(type, pokemonId, stackCount); @@ -1030,7 +1052,7 @@ export class ExtraModifierModifier extends PersistentModifier { return true; } - getMaxStackCount(): integer { + getMaxStackCount(): integer { return 3; } } \ No newline at end of file diff --git a/src/pokemon.ts b/src/pokemon.ts index 5242e1a8a64..1a28a75c325 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -666,6 +666,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } + transferTagsBySourceId(sourceId: integer, newSourceId: integer): void { + const tags = this.summonData.tags; + tags.filter(t => t.sourceId === sourceId).forEach(t => t.sourceId = newSourceId); + } + + transferSummon(source: Pokemon): void { + const battleStats = Utils.getEnumValues(BattleStat); + for (let stat of battleStats) + this.summonData.battleStats[stat] = source.summonData.battleStats[stat]; + for (let tag of source.summonData.tags) + this.summonData.tags.push(tag); + } + getMoveHistory(): TurnMove[] { return this.battleSummonData.moveHistory; } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 54e4d9f7629..8e196e80085 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -6,7 +6,7 @@ import { Command } from "./command-ui-handler"; import MessageUiHandler from "./message-ui-handler"; import { Mode } from "./ui"; import * as Utils from "../utils"; -import { PokemonHeldItemModifier } from "../modifier/modifier"; +import { PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier"; const defaultMessage = 'Choose a Pokémon.'; @@ -22,8 +22,8 @@ export enum PartyUiMode { export enum PartyOption { CANCEL = -1, - SHIFT, SEND_OUT, + PASS_BATON, APPLY, TRANSFER, SUMMARY, @@ -212,7 +212,7 @@ export default class PartyUiHandler extends MessageUiHandler { selectCallback(this.cursor, option); } } else if (this.cursor) - (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor); + (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor, option === PartyOption.PASS_BATON); if (this.partyUiMode !== PartyUiMode.MODIFIER && this.partyUiMode !== PartyUiMode.MOVE_MODIFIER) ui.playSelect(); return; @@ -409,13 +409,14 @@ export default class PartyUiHandler extends MessageUiHandler { if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { switch (this.partyUiMode) { case PartyUiMode.SWITCH: - if (this.cursor) - this.options.push(PartyOption.SHIFT); - break; case PartyUiMode.FAINT_SWITCH: case PartyUiMode.POST_BATTLE_SWITCH: - if (this.cursor) + if (this.cursor) { this.options.push(PartyOption.SEND_OUT); + if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH + && this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerPokemon().id)) + this.options.push(PartyOption.PASS_BATON); + } break; case PartyUiMode.MODIFIER: this.options.push(PartyOption.APPLY);