mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-21 14:59:26 +02:00
unburden implemented
This commit is contained in:
parent
c9664b66d3
commit
0d894e9009
@ -1692,6 +1692,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
defender.turnData.itemsLost += 1;
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:postAttackStealHeldItem", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), defenderName: defender.name, stolenItemType: stolenItem.type.name }));
|
||||
}
|
||||
resolve(success);
|
||||
@ -1785,6 +1786,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
attacker.turnData.itemsLost += 1;
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:postDefendStealHeldItem", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), attackerName: attacker.name, stolenItemType: stolenItem.type.name }));
|
||||
}
|
||||
resolve(success);
|
||||
@ -3835,6 +3837,92 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class UnburdenBerryAbAttr extends PostTurnAbAttr {
|
||||
private stats: BattleStat[];
|
||||
private stages: number;
|
||||
|
||||
constructor(stats: BattleStat[], stages: number) {
|
||||
super(true);
|
||||
|
||||
this.stats = Array.isArray(stats)
|
||||
? stats
|
||||
: [ stats ];
|
||||
this.stages = stages;
|
||||
}
|
||||
|
||||
applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
const multipleItems = pokemon.battleData.berriesEaten.length * this.stages;
|
||||
if (multipleItems > 6) {
|
||||
this.stages = 6;
|
||||
} else {
|
||||
this.stages = multipleItems;
|
||||
}
|
||||
if (!simulated) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.stages));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): AbAttrCondition {
|
||||
return (pokemon: Pokemon) => pokemon.battleData.berriesEaten.length !== 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class UnburdenDefStolenAbAttr extends PostDefendAbAttr {
|
||||
private stats: BattleStat[];
|
||||
private stages: number;
|
||||
|
||||
constructor(stats: BattleStat[], stages: number) {
|
||||
super(true);
|
||||
|
||||
this.stats = Array.isArray(stats)
|
||||
? stats
|
||||
: [ stats ];
|
||||
this.stages = stages;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!simulated) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.stages));
|
||||
pokemon.turnData.itemsLost -= 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): AbAttrCondition {
|
||||
return (pokemon: Pokemon) => pokemon.turnData.itemsLost > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class UnburdenAtkStolenAbAttr extends PostAttackAbAttr {
|
||||
private stats: BattleStat[];
|
||||
private stages: number;
|
||||
|
||||
constructor(stats: BattleStat[], stages: number) {
|
||||
super();
|
||||
|
||||
this.stats = Array.isArray(stats)
|
||||
? stats
|
||||
: [ stats ];
|
||||
this.stages = stages;
|
||||
}
|
||||
|
||||
applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!simulated) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.stages));
|
||||
pokemon.turnData.itemsLost -= 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): AbAttrCondition {
|
||||
return (pokemon: Pokemon) => pokemon.turnData.itemsLost > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class StatStageChangeMultiplierAbAttr extends AbAttr {
|
||||
private multiplier: integer;
|
||||
|
||||
@ -5146,7 +5234,9 @@ export function initAbilities() {
|
||||
new Ability(Abilities.ANGER_POINT, 4)
|
||||
.attr(PostDefendCritStatStageChangeAbAttr, Stat.ATK, 6),
|
||||
new Ability(Abilities.UNBURDEN, 4)
|
||||
.unimplemented(),
|
||||
.attr(UnburdenBerryAbAttr, [ Stat.SPD ], 2)
|
||||
.attr(UnburdenAtkStolenAbAttr, [ Stat.SPD ], 2)
|
||||
.attr(UnburdenDefStolenAbAttr, [ Stat.SPD ], 2),
|
||||
new Ability(Abilities.HEATPROOF, 4)
|
||||
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5)
|
||||
.attr(ReduceBurnDamageAbAttr, 0.5)
|
||||
|
@ -2146,6 +2146,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
||||
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
|
||||
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
|
||||
if (success) {
|
||||
target.turnData.itemsLost += 1;
|
||||
user.scene.queueMessage(i18next.t("moveTriggers:stoleItem", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: stolenItem.type.name}));
|
||||
}
|
||||
resolve(success);
|
||||
@ -2227,6 +2228,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
||||
// Decrease item amount and update icon
|
||||
!--removedItem.stackCount;
|
||||
target.scene.updateModifiers(target.isPlayer());
|
||||
target.turnData.itemsLost+=1;
|
||||
|
||||
if (this.berriesOnly) {
|
||||
user.scene.queueMessage(i18next.t("moveTriggers:incineratedItem", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name}));
|
||||
@ -2341,6 +2343,7 @@ export class StealEatBerryAttr extends EatBerryAttr {
|
||||
}
|
||||
// if the target has berries, pick a random berry and steal it
|
||||
this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)];
|
||||
target.turnData.itemsLost+=1;
|
||||
const message = i18next.t("battle:stealEatBerry", {pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name});
|
||||
user.scene.queueMessage(message);
|
||||
this.reduceBerryModifier(target);
|
||||
|
@ -5011,6 +5011,7 @@ export class PokemonTurnData {
|
||||
public order: number;
|
||||
public statStagesIncreased: boolean = false;
|
||||
public statStagesDecreased: boolean = false;
|
||||
public itemsLost: number = 0;
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
@ -2719,6 +2719,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
||||
const randItem = itemModifiers[randItemIndex];
|
||||
heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
targetPokemon.turnData.itemsLost += 1;
|
||||
transferredModifierTypes.push(randItem.type);
|
||||
itemModifiers.splice(randItemIndex, 1);
|
||||
}
|
||||
|
136
src/test/abilities/unburden.test.ts
Normal file
136
src/test/abilities/unburden.test.ts
Normal file
@ -0,0 +1,136 @@
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { BerryType } from "#app/enums/berry-type";
|
||||
import { allMoves, StealHeldItemChanceAttr } from "#app/data/move";
|
||||
|
||||
|
||||
describe("Abilities - Unburden", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.starterSpecies(Species.TREECKO)
|
||||
.startingLevel(1)
|
||||
.moveset([Moves.POPULATION_BOMB, Moves.KNOCK_OFF, Moves.PLUCK, Moves.THIEF])
|
||||
.ability(Abilities.UNBURDEN)
|
||||
.startingHeldItems([
|
||||
{ name: "BERRY", count: 1, type: BerryType.SITRUS },
|
||||
{ name: "BERRY", count: 2, type: BerryType.APICOT },
|
||||
{ name: "BERRY", count: 2, type: BerryType.LUM },
|
||||
])
|
||||
.enemySpecies(Species.NINJASK)
|
||||
.enemyLevel(100)
|
||||
.enemyMoveset([Moves.FALSE_SWIPE])
|
||||
.enemyAbility(Abilities.UNBURDEN)
|
||||
.enemyHeldItems([
|
||||
{ name: "BERRY", type: BerryType.SITRUS, count: 1 },
|
||||
{ name: "BERRY", type: BerryType.LUM, count: 1 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should activate when a berry is eaten", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerHeldItems = playerPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.FALSE_SWIPE);
|
||||
await game.toNextTurn();
|
||||
expect(playerPokemon.getHeldItems().length).toBeLessThan(playerHeldItems);
|
||||
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(4);
|
||||
|
||||
});
|
||||
it("should activate when a berry is stolen", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyHeldItemCt = enemyPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.PLUCK);
|
||||
await game.toNextTurn();
|
||||
expect(enemyPokemon.getHeldItems().length).toBeLessThan(enemyHeldItemCt);
|
||||
expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(2);
|
||||
});
|
||||
it("should activate when an item is knocked off", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyHeldItemCt = enemyPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.KNOCK_OFF);
|
||||
await game.toNextTurn();
|
||||
expect(enemyPokemon.getHeldItems().length).toBeLessThan(enemyHeldItemCt);
|
||||
expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(2);
|
||||
});
|
||||
it("should activate when an item is stolen via attacking ability", async () => {
|
||||
game.override
|
||||
.ability(Abilities.MAGICIAN)
|
||||
.startingHeldItems([
|
||||
{ name: "MULTI_LENS", count: 3 },
|
||||
]);
|
||||
await game.classicMode.startBattle();
|
||||
vi.spyOn(allMoves[Moves.POPULATION_BOMB], "accuracy", "get").mockReturnValue(100);
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyHeldItemCt = enemyPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.POPULATION_BOMB);
|
||||
await game.toNextTurn();
|
||||
expect(enemyPokemon.getHeldItems().length).toBeLessThan(enemyHeldItemCt);
|
||||
expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(4);
|
||||
});
|
||||
it("should activate when an item is stolen via defending ability", async () => {
|
||||
game.override
|
||||
.enemyAbility(Abilities.PICKPOCKET)
|
||||
.startingHeldItems([
|
||||
{ name: "MULTI_LENS", count: 3 },
|
||||
{ name: "SOUL_DEW", count: 1},
|
||||
{ name: "LUCKY_EGG", count: 1 },
|
||||
]);
|
||||
await game.classicMode.startBattle();
|
||||
vi.spyOn(allMoves[Moves.POPULATION_BOMB], "accuracy", "get").mockReturnValue(100);
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerHeldItems = playerPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.POPULATION_BOMB);
|
||||
await game.toNextTurn();
|
||||
expect(playerPokemon.getHeldItems().length).toBeLessThan(playerHeldItems);
|
||||
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(6);
|
||||
});
|
||||
it("should activate when an item is stolen via move", async () => {
|
||||
vi.spyOn(allMoves[Moves.THIEF], "attrs", "get").mockReturnValue([new StealHeldItemChanceAttr(1.0)]); // give Thief 100% steal rate
|
||||
game.override.startingHeldItems([
|
||||
{ name: "MULTI_LENS", count: 3 },
|
||||
]);
|
||||
await game.classicMode.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyHeldItemCt = enemyPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.THIEF);
|
||||
await game.toNextTurn();
|
||||
expect(enemyPokemon.getHeldItems().length).toBeLessThan(enemyHeldItemCt);
|
||||
expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(4);
|
||||
});
|
||||
it("should activate when an item is stolen via grip claw", async () => {
|
||||
game.override.startingHeldItems([
|
||||
{ name: "GRIP_CLAW", count: 5 },
|
||||
{ name: "MULTI_LENS", count: 3 },
|
||||
]);
|
||||
await game.classicMode.startBattle();
|
||||
vi.spyOn(allMoves[Moves.POPULATION_BOMB], "accuracy", "get").mockReturnValue(100);
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyHeldItemCt = enemyPokemon.getHeldItems().length;
|
||||
game.move.select(Moves.POPULATION_BOMB);
|
||||
await game.toNextTurn();
|
||||
expect(enemyPokemon.getHeldItems().length).toBeLessThan(enemyHeldItemCt);
|
||||
expect(enemyPokemon.getStatStage(Stat.SPD)).toBe(4);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user