mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-03-21 09:35:44 -05:00
Track Gen 3 Pressure (#2607)
Some checks failed
Node.js CI / build (22.x) (push) Has been cancelled
Some checks failed
Node.js CI / build (22.x) (push) Has been cancelled
This commit is contained in:
parent
1f8317aedd
commit
31e23b39d3
|
|
@ -8,7 +8,7 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Pokemon, type Battle, type ServerPokemon } from "./battle";
|
||||
import { Pokemon, type Battle, type PPState, type ServerPokemon } from "./battle";
|
||||
import { Dex, type ModdedDex, toID, type ID } from "./battle-dex";
|
||||
import type { BattleScene } from "./battle-animations";
|
||||
import { BattleLog } from "./battle-log";
|
||||
|
|
@ -993,8 +993,8 @@ export class BattleTooltips {
|
|||
}).length > 4) {
|
||||
text += `(More than 4 moves is usually a sign of Illusion Zoroark/Zorua.) `;
|
||||
}
|
||||
if (this.battle.gen === 3) {
|
||||
text += `(Pressure is not visible in Gen 3, so in certain situations, more PP may have been lost than shown here.) `;
|
||||
if (this.battle.gen === 3 && clientPokemon.moveTrack.some(([_, pp]) => typeof pp !== 'number')) {
|
||||
text += `(Pressure is not visible in Gen 3, so in certain situations, the exact amount of PP used may be unknown.) `;
|
||||
}
|
||||
if (this.pokemonHasClones(clientPokemon)) {
|
||||
text += `(Your opponent has two indistinguishable Pokémon, making it impossible for you to tell which one has which moves/ability/item.) `;
|
||||
|
|
@ -1472,7 +1472,7 @@ export class BattleTooltips {
|
|||
return buf;
|
||||
}
|
||||
|
||||
getPPUseText(moveTrackRow: [string, number], showKnown?: boolean) {
|
||||
getPPUseText(moveTrackRow: [string, PPState], showKnown?: boolean) {
|
||||
let [moveName, ppUsed] = moveTrackRow;
|
||||
let move;
|
||||
let maxpp;
|
||||
|
|
@ -1490,7 +1490,11 @@ export class BattleTooltips {
|
|||
return `${bullet} ${move.name} <small>(0/${maxpp})</small>`;
|
||||
}
|
||||
if (ppUsed || moveName.startsWith('*')) {
|
||||
return `${bullet} ${move.name} <small>(${maxpp - ppUsed}/${maxpp})</small>`;
|
||||
if (typeof ppUsed === 'number') {
|
||||
return `${bullet} ${move.name} <small>(${maxpp - ppUsed}/${maxpp})</small>`;
|
||||
} else {
|
||||
return `${bullet} ${move.name} <small>(${maxpp - ppUsed[0]}/${maxpp} to ${maxpp - ppUsed[1]}/${maxpp})</small>`;
|
||||
}
|
||||
}
|
||||
return `${bullet} ${move.name} ${showKnown ? ' <small>(revealed)</small>' : ''}`;
|
||||
}
|
||||
|
|
@ -1988,7 +1992,8 @@ export class BattleTooltips {
|
|||
value.set(20 + 20 * boostCount);
|
||||
}
|
||||
if (move.id === 'trumpcard') {
|
||||
const ppLeft = 5 - this.ppUsed(move, pokemon);
|
||||
const pp = this.ppUsed(move, pokemon);
|
||||
const ppLeft = 5 - (typeof pp === 'number' ? pp : pp[1]);
|
||||
let basePower = 40;
|
||||
if (ppLeft === 1) basePower = 200;
|
||||
else if (ppLeft === 2) basePower = 80;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ declare const app: { user: AnyObject, rooms: AnyObject, ignore?: AnyObject } | u
|
|||
export type EffectState = any[] & { 0: ID };
|
||||
export type WeatherState = [name: string, minTimeLeft: number, maxTimeLeft: number];
|
||||
export type HPColor = 'r' | 'y' | 'g';
|
||||
export type PPState = number | [number, number];
|
||||
|
||||
export class Pokemon implements PokemonDetails, PokemonHealth {
|
||||
name = '';
|
||||
|
|
@ -106,7 +107,7 @@ export class Pokemon implements PokemonDetails, PokemonHealth {
|
|||
lastMove = '';
|
||||
|
||||
/** [[moveName, ppUsed]] */
|
||||
moveTrack: [string, number][] = [];
|
||||
moveTrack: [string, PPState][] = [];
|
||||
statusData = { sleepTurns: 0, toxicTurns: 0 };
|
||||
timesAttacked = 0;
|
||||
|
||||
|
|
@ -340,7 +341,37 @@ export class Pokemon implements PokemonDetails, PokemonHealth {
|
|||
this.clearMovestatuses();
|
||||
this.side.battle.scene.clearEffects(this);
|
||||
}
|
||||
rememberMove(moveName: string, pp = 1, recursionSource?: string) {
|
||||
private mergePP(entry: [string, PPState], pp: PPState): PPState {
|
||||
let ppUsed = entry[1];
|
||||
if (typeof ppUsed === 'number') {
|
||||
if (typeof pp === 'number') {
|
||||
ppUsed += pp;
|
||||
} else {
|
||||
ppUsed = [ppUsed + pp[0], ppUsed + pp[1]];
|
||||
}
|
||||
} else {
|
||||
if (typeof pp === 'number') {
|
||||
ppUsed[0] += pp;
|
||||
ppUsed[1] += pp;
|
||||
} else {
|
||||
ppUsed[0] += pp[0];
|
||||
ppUsed[1] += pp[1];
|
||||
}
|
||||
}
|
||||
if (typeof ppUsed === 'number') {
|
||||
if (ppUsed < 0) ppUsed = 0;
|
||||
} else {
|
||||
if (ppUsed[0] < 0) ppUsed[0] = 0;
|
||||
if (ppUsed[1] < 0) ppUsed[1] = 0;
|
||||
const move = this.side.battle.dex.moves.get(entry[0]);
|
||||
const maxpp = (move.pp === 1 || move.noPPBoosts ? move.pp : move.pp * 8 / 5);
|
||||
if (ppUsed[0] > maxpp) ppUsed[0] = maxpp;
|
||||
if (ppUsed[0] < ppUsed[1]) ppUsed[0] = ppUsed[1];
|
||||
if (ppUsed[0] === ppUsed[1]) ppUsed = ppUsed[0];
|
||||
}
|
||||
return ppUsed;
|
||||
}
|
||||
rememberMove(moveName: string, pp: PPState = 1, recursionSource?: string) {
|
||||
if (recursionSource === this.ident) return;
|
||||
moveName = Dex.moves.get(moveName).name;
|
||||
if (moveName.startsWith('*')) return;
|
||||
|
|
@ -353,8 +384,7 @@ export class Pokemon implements PokemonDetails, PokemonHealth {
|
|||
}
|
||||
for (const entry of this.moveTrack) {
|
||||
if (moveName === entry[0]) {
|
||||
entry[1] += pp;
|
||||
if (entry[1] < 0) entry[1] = 0;
|
||||
entry[1] = this.mergePP(entry, pp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1537,8 +1567,8 @@ export class Battle {
|
|||
}
|
||||
}
|
||||
}
|
||||
let pp = 1;
|
||||
if (this.abilityActive('Pressure') && move.id !== 'stickyweb') {
|
||||
let pp: PPState = callerMoveForPressure ? 0 : 1; // 1 pp was already deducted from using the move itself
|
||||
if ((this.abilityActive('Pressure') || this.gen === 3) && move.id !== 'stickyweb') {
|
||||
const foeTargets = [];
|
||||
const moveTarget = move.pressureTarget;
|
||||
|
||||
|
|
@ -1559,18 +1589,9 @@ export class Battle {
|
|||
} else if (target && target.side !== pokemon.side) {
|
||||
foeTargets.push(target);
|
||||
}
|
||||
|
||||
for (const foe of foeTargets) {
|
||||
if (foe && !foe.fainted && foe.effectiveAbility() === 'Pressure') {
|
||||
pp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!callerMoveForPressure) {
|
||||
pokemon.rememberMove(moveName, pp);
|
||||
} else {
|
||||
pokemon.rememberMove(callerMoveForPressure.name, pp - 1); // 1 pp was already deducted from using the move itself
|
||||
pp = this.getPressurePP(pp, foeTargets.filter(foe => foe && !foe.fainted) as Pokemon[]);
|
||||
}
|
||||
pokemon.rememberMove(callerMoveForPressure ? callerMoveForPressure.name : moveName, pp);
|
||||
}
|
||||
pokemon.lastMove = move.id;
|
||||
this.lastMove = move.id;
|
||||
|
|
@ -1578,6 +1599,26 @@ export class Battle {
|
|||
pokemon.side.wisher = pokemon;
|
||||
}
|
||||
}
|
||||
private getPressurePP(pp: PPState, foes: Pokemon[]) {
|
||||
for (const foe of foes) {
|
||||
const abilities = Object.values(this.dex.species.get(foe.speciesForme).abilities);
|
||||
const canHavePressure = this.gen === 3 && abilities.includes('Pressure');
|
||||
if (foe.effectiveAbility() === 'Pressure' || (canHavePressure && abilities.length === 1)) {
|
||||
if (typeof pp === 'number') {
|
||||
pp += 1;
|
||||
} else {
|
||||
pp[0] += 1;
|
||||
pp[1] += 1;
|
||||
}
|
||||
} else if (canHavePressure) {
|
||||
if (typeof pp === 'number') {
|
||||
pp = [pp, pp];
|
||||
}
|
||||
pp[0] += 1;
|
||||
}
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
animateMove(pokemon: Pokemon, move: Dex.Move, target: Pokemon | null, kwArgs: KWArgs) {
|
||||
this.activeMoveIsSpread = kwArgs.spread;
|
||||
if (this.seeking !== null || kwArgs.still) return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user