Add Baton modifier

This commit is contained in:
Flashfyre 2023-04-28 19:26:41 -04:00
parent 140e759486
commit 2b95d4ce51
6 changed files with 86 additions and 22 deletions

View File

@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, HitsTagAttr, Mis
import { Mode } from './ui/ui'; import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler"; import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat"; 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 PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; 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 { Biome, biomeLinks } from "./data/biome";
import { ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, getPlayerModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import { ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, getPlayerModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; 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 { getPokemonMessage } from "./messages";
import { Starter } from "./ui/starter-select-ui-handler"; import { Starter } from "./ui/starter-select-ui-handler";
import { Gender } from "./data/gender"; import { Gender } from "./data/gender";
@ -420,12 +420,16 @@ export class SummonPhase extends BattlePhase {
export class SwitchSummonPhase extends SummonPhase { export class SwitchSummonPhase extends SummonPhase {
private slotIndex: integer; private slotIndex: integer;
private doReturn: boolean; 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); super(scene);
this.slotIndex = slotIndex; this.slotIndex = slotIndex;
this.doReturn = doReturn; this.doReturn = doReturn;
this.batonPass = batonPass;
} }
start() { start() {
@ -440,7 +444,8 @@ export class SwitchSummonPhase extends SummonPhase {
const playerPokemon = this.scene.getPlayerPokemon(); 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.ui.showText(`Come back, ${this.scene.getPlayerPokemon().name}!`);
this.scene.sound.play('pb_rel'); this.scene.sound.play('pb_rel');
@ -462,11 +467,29 @@ export class SwitchSummonPhase extends SummonPhase {
switchAndSummon() { switchAndSummon() {
const party = this.scene.getParty(); const party = this.scene.getParty();
const switchedPokemon = party[this.slotIndex]; 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; party[0] = switchedPokemon;
this.scene.ui.showText(`Go! ${switchedPokemon.name}!`); this.scene.ui.showText(`Go! ${switchedPokemon.name}!`);
this.summon(); this.summon();
} }
end() {
if (this.batonPass)
this.scene.getPlayerPokemon().transferSummon(this.lastPokemon);
this.lastPokemon.resetSummonData();
super.end();
}
} }
export class CheckSwitchPhase extends BattlePhase { export class CheckSwitchPhase extends BattlePhase {
@ -581,7 +604,7 @@ export class CommandPhase extends FieldPhase {
this.scene.ui.setMode(Mode.COMMAND); 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 playerPokemon = this.scene.getPlayerPokemon();
const enemyPokemon = this.scene.getEnemyPokemon(); const enemyPokemon = this.scene.getEnemyPokemon();
let success: boolean; let success: boolean;
@ -640,9 +663,10 @@ export class CommandPhase extends FieldPhase {
} }
break; break;
case Command.POKEMON: case Command.POKEMON:
const trapTag = playerPokemon.findTag(t => t instanceof TrapTag) as TrapTag; const trapTag = playerPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag;
if (!trapTag) { const batonPass = args[0] as boolean;
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, cursor, true)); if (batonPass || !trapTag) {
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, cursor, true, args[0] as boolean));
success = true; success = true;
} else } else
this.scene.ui.showText(`${this.scene.getPokemonById(trapTag.sourceId).name}'s ${trapTag.getMoveName()}\nprevents switching!`, null, () => { 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() { start() {
super.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) 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()); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
}, PartyUiHandler.FilterNonFainted); }, PartyUiHandler.FilterNonFainted);
} }

View File

@ -201,8 +201,8 @@ export class ConfusedTag extends BattlerTag {
} }
export class SeedTag extends BattlerTag { export class SeedTag extends BattlerTag {
constructor() { constructor(sourceId: integer) {
super(BattlerTagType.SEEDED, BattlerTagLapseType.AFTER_MOVE, 1, Moves.LEECH_SEED); super(BattlerTagType.SEEDED, BattlerTagLapseType.AFTER_MOVE, 1, Moves.LEECH_SEED, sourceId);
} }
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
@ -517,7 +517,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
case BattlerTagType.CONFUSED: case BattlerTagType.CONFUSED:
return new ConfusedTag(turnCount, sourceMove); return new ConfusedTag(turnCount, sourceMove);
case BattlerTagType.SEEDED: case BattlerTagType.SEEDED:
return new SeedTag(); return new SeedTag(sourceId);
case BattlerTagType.NIGHTMARE: case BattlerTagType.NIGHTMARE:
return new NightmareTag(); return new NightmareTag();
case BattlerTagType.INGRAIN: case BattlerTagType.INGRAIN:

View File

@ -607,6 +607,9 @@ const modifierTypes = {
SHELL_BELL: () => new PokemonHeldItemModifierType('SHELL BELL', 'Heals 1/8 of a POKéMON\'s dealt damage', 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)), (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)), 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'), MINI_BLACK_HOLE: () => new HeldItemTransferModifierType('MINI BLACK HOLE'),
@ -684,6 +687,7 @@ const modifierPool = {
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5), new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5),
new WeightedModifierType(modifierTypes.CANDY_JAR, 3), new WeightedModifierType(modifierTypes.CANDY_JAR, 3),
new WeightedModifierType(modifierTypes.HEALING_CHARM, 1), new WeightedModifierType(modifierTypes.HEALING_CHARM, 1),
new WeightedModifierType(modifierTypes.BATON, 1),
new WeightedModifierType(modifierTypes.FOCUS_BAND, 3), new WeightedModifierType(modifierTypes.FOCUS_BAND, 3),
new WeightedModifierType(modifierTypes.KINGS_ROCK, 2), new WeightedModifierType(modifierTypes.KINGS_ROCK, 2),
new WeightedModifierType(modifierTypes.LEFTOVERS, 2), new WeightedModifierType(modifierTypes.LEFTOVERS, 2),

View File

@ -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 { export class HeldItemTransferModifier extends PokemonHeldItemModifier {
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) { constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
super(type, pokemonId, stackCount); super(type, pokemonId, stackCount);
@ -1030,7 +1052,7 @@ export class ExtraModifierModifier extends PersistentModifier {
return true; return true;
} }
getMaxStackCount(): integer { getMaxStackCount(): integer {
return 3; return 3;
} }
} }

View File

@ -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[] { getMoveHistory(): TurnMove[] {
return this.battleSummonData.moveHistory; return this.battleSummonData.moveHistory;
} }

View File

@ -6,7 +6,7 @@ import { Command } from "./command-ui-handler";
import MessageUiHandler from "./message-ui-handler"; import MessageUiHandler from "./message-ui-handler";
import { Mode } from "./ui"; import { Mode } from "./ui";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier";
const defaultMessage = 'Choose a Pokémon.'; const defaultMessage = 'Choose a Pokémon.';
@ -22,8 +22,8 @@ export enum PartyUiMode {
export enum PartyOption { export enum PartyOption {
CANCEL = -1, CANCEL = -1,
SHIFT,
SEND_OUT, SEND_OUT,
PASS_BATON,
APPLY, APPLY,
TRANSFER, TRANSFER,
SUMMARY, SUMMARY,
@ -212,7 +212,7 @@ export default class PartyUiHandler extends MessageUiHandler {
selectCallback(this.cursor, option); selectCallback(this.cursor, option);
} }
} else if (this.cursor) } 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) if (this.partyUiMode !== PartyUiMode.MODIFIER && this.partyUiMode !== PartyUiMode.MOVE_MODIFIER)
ui.playSelect(); ui.playSelect();
return; return;
@ -409,13 +409,14 @@ export default class PartyUiHandler extends MessageUiHandler {
if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) {
switch (this.partyUiMode) { switch (this.partyUiMode) {
case PartyUiMode.SWITCH: case PartyUiMode.SWITCH:
if (this.cursor)
this.options.push(PartyOption.SHIFT);
break;
case PartyUiMode.FAINT_SWITCH: case PartyUiMode.FAINT_SWITCH:
case PartyUiMode.POST_BATTLE_SWITCH: case PartyUiMode.POST_BATTLE_SWITCH:
if (this.cursor) if (this.cursor) {
this.options.push(PartyOption.SEND_OUT); 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; break;
case PartyUiMode.MODIFIER: case PartyUiMode.MODIFIER:
this.options.push(PartyOption.APPLY); this.options.push(PartyOption.APPLY);