From 028fb74cf02d617b982f81246d49168bf9e9f4ff Mon Sep 17 00:00:00 2001 From: Aurastic <33085835+ISenseAura@users.noreply.github.com> Date: Mon, 16 Mar 2026 03:29:54 +0530 Subject: [PATCH] Preact: Show ally side pokemon in multi battles (#2602) --- play.pokemonshowdown.com/src/battle-choices.ts | 16 ++++++++++++++++ play.pokemonshowdown.com/src/panel-battle.tsx | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/play.pokemonshowdown.com/src/battle-choices.ts b/play.pokemonshowdown.com/src/battle-choices.ts index 65f6ce4f2..3c97f1f6b 100644 --- a/play.pokemonshowdown.com/src/battle-choices.ts +++ b/play.pokemonshowdown.com/src/battle-choices.ts @@ -20,6 +20,11 @@ export interface BattleRequestSideInfo { id: 'p1' | 'p2' | 'p3' | 'p4'; pokemon: ServerPokemon[]; } +export interface BattleRequestAllyInfo { + id: string; + name: string; + pokemon: ServerPokemon[]; +} export interface BattleRequestActivePokemon { moves: { name: string, @@ -60,6 +65,7 @@ export interface BattleMoveRequest { requestType: 'move'; rqid: number; side: BattleRequestSideInfo; + ally?: BattleRequestAllyInfo; active: (BattleRequestActivePokemon | null)[]; noCancel?: boolean; targetable?: boolean; @@ -67,6 +73,7 @@ export interface BattleMoveRequest { export interface BattleSwitchRequest { requestType: 'switch'; rqid: number; + ally?: BattleRequestAllyInfo; side: BattleRequestSideInfo; forceSwitch: boolean[]; noCancel?: boolean; @@ -75,6 +82,7 @@ export interface BattleTeamRequest { requestType: 'team'; rqid: number; side: BattleRequestSideInfo; + ally?: BattleRequestAllyInfo; maxTeamSize?: number; maxChosenTeamSize?: number; chosenTeamSize?: number; @@ -84,6 +92,7 @@ export interface BattleWaitRequest { requestType: 'wait'; rqid: number; side: undefined; + ally: undefined; noCancel?: boolean; } export type BattleRequest = BattleMoveRequest | BattleSwitchRequest | BattleTeamRequest | BattleWaitRequest; @@ -449,6 +458,7 @@ export class BattleChoiceBuilder { choiceType: isTeamPreview ? 'team' : 'switch', targetPokemon: 0, }; + if (choice === 'notMine') throw new Error(`You cannot decide for your partner!`); if (/^[0-9]+$/.test(choice)) { // Parse a one-based move index. current.targetPokemon = parseInt(choice, 10); @@ -562,6 +572,12 @@ export class BattleChoiceBuilder { battle.parseHealth(serverPokemon.condition, serverPokemon); } } + if (request.ally) { + for (const serverPokemon of request.ally.pokemon) { + battle.parseDetails(serverPokemon.ident.substr(4), serverPokemon.ident, serverPokemon.details, serverPokemon); + battle.parseHealth(serverPokemon.condition, serverPokemon); + } + } if (request.requestType === 'team' && !request.chosenTeamSize) { request.chosenTeamSize = 1; if (battle.gameType === 'doubles') { diff --git a/play.pokemonshowdown.com/src/panel-battle.tsx b/play.pokemonshowdown.com/src/panel-battle.tsx index cb788651d..493ca4aa4 100644 --- a/play.pokemonshowdown.com/src/panel-battle.tsx +++ b/play.pokemonshowdown.com/src/panel-battle.tsx @@ -425,6 +425,9 @@ class BattlePanel extends PSRoomPanel { room.battle.setViewpoint(request.side.id); room.side = request.side; } + if (request.ally) { + room.battle.myAllyPokemon = request.ally.pokemon; + } room.request = request; room.choices = new BattleChoiceBuilder(request); @@ -753,6 +756,14 @@ class BattlePanel extends PSRoomPanel { tooltip: `switchpokemon|${i}`, }); })} + {request.ally?.pokemon?.map((serverPokemon, i) => { + return this.renderPokemonButton({ + pokemon: serverPokemon, + cmd: `/switch notMine`, + disabled: true, + tooltip: `allypokemon|${i}`, + }); + })} ; } renderTeamPreviewChooser(request: | BattleTeamRequest, choices: BattleChoiceBuilder) {