Implement Pickup ability

This commit is contained in:
Flashfyre 2024-03-06 21:05:23 -05:00
parent bc236cd048
commit 113ac10c1b
4 changed files with 58 additions and 9 deletions

View File

@ -1604,9 +1604,9 @@ export default class BattleScene extends Phaser.Scene {
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferStack: boolean, playSound: boolean, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
return new Promise(resolve => {
const source = itemModifier.getPokemon(target.scene);
const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null;
const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled).then(() => {
Utils.executeIf(!!source, () => applyAbAttrs(BlockItemTheftAbAttr, source, cancelled)).then(() => {
if (cancelled.value)
return resolve(false);
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
@ -1615,7 +1615,7 @@ export default class BattleScene extends Phaser.Scene {
&& (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier;
let removeOld = true;
if (matchingModifier) {
const maxStackCount = matchingModifier.getMaxStackCount(source.scene);
const maxStackCount = matchingModifier.getMaxStackCount(target.scene);
if (matchingModifier.stackCount >= maxStackCount)
return resolve(false);
const countTaken = transferStack ? Math.min(itemModifier.stackCount, maxStackCount - matchingModifier.stackCount) : 1;
@ -1626,7 +1626,7 @@ export default class BattleScene extends Phaser.Scene {
newItemModifier.stackCount = 1;
removeOld = !(--itemModifier.stackCount);
}
if (!removeOld || this.removeModifier(itemModifier, !source.isPlayer())) {
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
const addModifier = () => {
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
if (target.isPlayer())
@ -1636,7 +1636,7 @@ export default class BattleScene extends Phaser.Scene {
} else
resolve(false);
};
if (source.isPlayer() !== target.isPlayer() && !ignoreUpdate)
if (source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate)
this.updateModifiers(source.isPlayer(), instant).then(() => addModifier());
else
addModifier();

View File

@ -9,6 +9,7 @@ import { TrainerType } from "./data/enums/trainer-type";
import { GameMode } from "./game-mode";
import { BattleSpec } from "./enums/battle-spec";
import { PlayerGender } from "./system/game-data";
import { PersistentModifier, PokemonHeldItemModifier } from "./modifier/modifier";
export enum BattleType {
WILD,
@ -49,8 +50,9 @@ export default class Battle {
public started: boolean;
public turn: integer;
public turnCommands: TurnCommands;
public playerParticipantIds: Set<integer> = new Set<integer>();
public escapeAttempts: integer = 0;
public playerParticipantIds: Set<integer>;
public postBattleLoot: PokemonHeldItemModifier[];
public escapeAttempts: integer;
public lastMove: Moves;
public battleSeed: string;
private battleSeedState: string;
@ -68,6 +70,9 @@ export default class Battle {
this.seenEnemyPartyMemberIds = new Set<integer>();
this.double = double;
this.turn = 0;
this.playerParticipantIds = new Set<integer>();
this.postBattleLoot = [];
this.escapeAttempts = 0;
this.started = false;
this.battleSeed = Utils.randomString(16, true);
this.battleSeedState = null;
@ -123,6 +128,14 @@ export default class Battle {
this.playerParticipantIds.delete(playerPokemon.id);
}
addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
this.postBattleLoot.push(...enemyPokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id, false).map(i => {
const ret = i as PokemonHeldItemModifier;
ret.pokemonId = null;
return ret;
}));
}
getBgmOverride(scene: BattleScene): string {
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
if (this.battleType === BattleType.TRAINER) {

View File

@ -1020,6 +1020,31 @@ export class MaxMultiHitAbAttr extends AbAttr {
}
}
export class PostBattleAbAttr extends AbAttr {
constructor() {
super(true);
}
applyPostBattle(pokemon: Pokemon, args: any[]): boolean {
return false;
}
}
export class PostBattleLootAbAttr extends PostBattleAbAttr {
applyPostBattle(pokemon: Pokemon, args: any[]): boolean {
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
if (postBattleLoot.length) {
const randItem = Utils.randSeedItem(postBattleLoot);
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, true, true)) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` picked up\n${randItem.type.name}!`));
return true;
}
}
return false;
}
}
export class ReduceStatusEffectDurationAbAttr extends AbAttr {
private statusEffect: StatusEffect;
@ -1247,6 +1272,11 @@ export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckT
return applyAbAttrsInternal<CheckTrappedAbAttr>(attrType, pokemon, attr => attr.applyCheckTrapped(pokemon, trapped, args), true);
}
export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr },
pokemon: Pokemon, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostBattleAbAttr>(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args));
}
function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean {
const condition = attr.getCondition();
return !condition || condition(pokemon);
@ -1676,7 +1706,8 @@ export function initAbilities() {
.attr(ProtectStatAbAttr, BattleStat.ACC),
new Ability(Abilities.HYPER_CUTTER, "Hyper Cutter", "The Pokémon's proud of its powerful pincers. They prevent other Pokémon from lowering its Attack stat.", 3)
.attr(ProtectStatAbAttr, BattleStat.ATK),
new Ability(Abilities.PICKUP, "Pickup (N)", "The Pokémon may pick up the item an opposing Pokémon used during a battle. It may pick up items outside of battle, too.", 3),
new Ability(Abilities.PICKUP, "Pickup", "The Pokémon may pick up the item an opposing Pokémon held during a battle.", 3)
.attr(PostBattleLootAbAttr),
new Ability(Abilities.TRUANT, "Truant", "The Pokémon can't use a move if it had used a move on the previous turn.", 3)
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.TRUANT, 1, false),
new Ability(Abilities.HUSTLE, "Hustle", "Boosts the Attack stat, but lowers accuracy.", 3)

View File

@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getWeatherDamageMessage, ge
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 { Abilities, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability";
import { Abilities, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability";
import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@ -1772,6 +1772,9 @@ export class BattleEndPhase extends BattlePhase {
pokemon.resetBattleSummonData();
}
for (let pokemon of this.scene.getParty())
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon);
this.scene.clearEnemyHeldItemModifiers();
const lapsingModifiers = this.scene.findModifiers(m => m instanceof LapsingPersistentModifier || m instanceof LapsingPokemonHeldItemModifier) as (LapsingPersistentModifier | LapsingPokemonHeldItemModifier)[];
@ -2688,6 +2691,8 @@ export class FaintPhase extends PokemonPhase {
pokemon.trySetStatus(StatusEffect.FAINT);
if (pokemon.isPlayer())
this.scene.currentBattle.removeFaintedParticipant(pokemon as PlayerPokemon);
else
this.scene.currentBattle.addPostBattleLoot(pokemon as EnemyPokemon);
this.scene.field.remove(pokemon);
this.end();
}