' +
@@ -730,12 +738,25 @@
var pokemon = switchables[i];
pokemon.name = pokemon.ident.substr(4);
var tooltipArgs = 'switchpokemon|' + i;
- if (pokemon.fainted || i < this.battle.nearSide.active.length || this.choice.switchFlags[i] || trapped) {
+ if (pokemon.fainted || i < this.battle.pokemonControlled || this.choice.switchFlags[i] || trapped) {
party += '
';
}
}
+ if (this.battle.mySide.ally) party += this.displayAllyParty();
+ return party;
+ },
+ displayAllyParty: function () {
+ var party = '';
+ if (!this.battle.mySide.ally) return;
+ var allyParty = this.battle.myAllyPokemon;
+ for (var i = 0; i < allyParty.length; i++) {
+ var pokemon = allyParty[i];
+ pokemon.name = pokemon.ident.substr(4);
+ var tooltipArgs = 'allypokemon|' + i;
+ party += '
';
+ }
return party;
},
updateSwitchControls: function (type) {
@@ -760,7 +781,7 @@
// TODO? hpbar
requestTitle += "Which Pokémon will it switch in for?";
var controls = '
`;
}
pokemonhtml = '
' + pokemonhtml + '
';
+ const ratinghtml = side.rating ? ` title="Rating: ${BattleLog.escapeHTML(side.rating)}"` : ``;
+ let posStr = side.isFar ? 'far' : 'near';
+ if (isAlly) posStr += '2';
+ return `
${BattleLog.escapeHTML(side.name)}${pokemonhtml}
`;
+ }
+ updateSidebar(side: Side) {
+ if (side.n > 1) side = side.ally;
const $sidebar = (side.isFar ? this.$rightbar : this.$leftbar);
+ let sidebarhtml = this.getSidebarHTML(side) + (side.ally ? this.getSidebarHTML(side.ally, true) : '');
if (side.name) {
- const ratinghtml = side.rating ? ` title="Rating: ${BattleLog.escapeHTML(side.rating)}"` : ``;
- $sidebar.html(`
${BattleLog.escapeHTML(side.name)}${pokemonhtml}
`);
+ $sidebar.html(sidebarhtml);
$sidebar.find('.trainer').css('opacity', 1);
} else {
$sidebar.find('.trainer').css('opacity', 0.4);
}
}
updateSidebars() {
- for (const side of this.battle.sides) this.updateSidebar(side);
+ this.updateSidebar(this.battle.nearSide);
+ this.updateSidebar(this.battle.farSide);
}
updateStatbars() {
for (const side of this.battle.sides) {
@@ -713,17 +721,33 @@ class BattleScene {
}
}
- teamPreviewEnd() {
- for (let siden = 0; siden < 2; siden++) {
- this.$sprites[siden].empty();
- this.battle.sides[siden].updateSprites();
+ resetSides(skipEmpty?: boolean) {
+ if (!skipEmpty) {
+ for (const $spritesContainer of this.$sprites) {
+ $spritesContainer.empty();
+ }
+ }
+ for (const side of this.battle.sides) {
+ side.z = (side.isFar ? 200 : 0);
+ side.missedPokemon?.sprite?.destroy();
+
+ side.missedPokemon = {
+ sprite: new PokemonSprite(null, {
+ x: side.leftof(-100),
+ y: side.y,
+ z: side.z,
+ opacity: 0,
+ }, this, side.isFar),
+ } as any;
+
+ side.missedPokemon.sprite.isMissedPokemon = true;
}
}
teamPreview() {
let newBGNum = 0;
- for (let siden = 0; siden < 2; siden++) {
- const side = this.battle.sides[siden];
- const spriteIndex = +this.battle.sidesSwitched ^ siden;
+ for (let siden = 0; siden < 2 || (this.battle.gameType === 'multi' && siden < 4); siden++) {
+ let side = this.battle.sides[siden];
+ const spriteIndex = +this.battle.sidesSwitched ^ (siden % 2);
let textBuf = '';
let buf = '';
let buf2 = '';
@@ -1426,20 +1450,6 @@ class BattleScene {
afterMove(pokemon: Pokemon) {
return pokemon.sprite.afterMove();
}
- updateSpritesForSide(side: Side) {
- side.missedPokemon?.sprite?.destroy();
-
- side.missedPokemon = {
- sprite: new PokemonSprite(null, {
- x: side.leftof(-100),
- y: side.y,
- z: side.z,
- opacity: 0,
- }, this, side.isFar),
- } as any;
-
- side.missedPokemon.sprite.isMissedPokemon = true;
- }
// Misc
/////////////////////////////////////////////////////////////////////
diff --git a/src/battle-scene-stub.ts b/src/battle-scene-stub.ts
index 31005f6f5..9f58dc1b3 100644
--- a/src/battle-scene-stub.ts
+++ b/src/battle-scene-stub.ts
@@ -42,8 +42,9 @@ class BattleSceneStub {
runStatusAnim(moveid: ID, participants: Pokemon[]): void { }
startAnimations(): void { }
teamPreview(): void { }
- teamPreviewEnd(): void { }
+ resetSides(): void { }
updateGen(): void { }
+ getSidebarHTML(side: Side) { }
updateSidebar(side: Side): void { }
updateSidebars(): void { }
updateStatbars(): void { }
@@ -68,7 +69,6 @@ class BattleSceneStub {
anim(pokemon: Pokemon, end: ScenePos, transition?: string) { }
beforeMove(pokemon: Pokemon) { }
afterMove(pokemon: Pokemon) { }
- updateSpritesForSide(side: Side) { }
unlink(userid: string, showRevealButton = false) { }
}
diff --git a/src/battle-text-parser.ts b/src/battle-text-parser.ts
index 4dbb33483..cbfa22b7e 100644
--- a/src/battle-text-parser.ts
+++ b/src/battle-text-parser.ts
@@ -12,16 +12,20 @@ declare const BattleText: {[id: string]: {[templateName: string]: string}};
type Args = [string, ...string[]];
type KWArgs = {[kw: string]: string};
+type SideID = 'p1' | 'p2' | 'p3' | 'p4';
class BattleTextParser {
p1 = "Player 1";
p2 = "Player 2";
- perspective: 0 | 1;
+ p3 = "Player 3";
+ p4 = "Player 4";
+ perspective: SideID;
gen = 7;
+ turn = 0;
curLineSection: 'break' | 'preMajor' | 'major' | 'postMajor' = 'break';
lowercaseRegExp: RegExp | null | undefined = undefined;
- constructor(perspective: 0 | 1 = 0) {
+ constructor(perspective: SideID = 'p1') {
this.perspective = perspective;
}
@@ -226,7 +230,7 @@ class BattleTextParser {
pokemonName = (pokemon: string) => {
if (!pokemon) return '';
- if (!pokemon.startsWith('p1') && !pokemon.startsWith('p2')) return `???pokemon:${pokemon}???`;
+ if (!pokemon.startsWith('p')) return `???pokemon:${pokemon}???`;
if (pokemon.charAt(3) === ':') return pokemon.slice(4).trim();
else if (pokemon.charAt(2) === ':') return pokemon.slice(3).trim();
return `???pokemon:${pokemon}???`;
@@ -234,14 +238,11 @@ class BattleTextParser {
pokemon(pokemon: string) {
if (!pokemon) return '';
- let side;
- switch (pokemon.slice(0, 2)) {
- case 'p1': side = 0; break;
- case 'p2': side = 1; break;
- default: return `???pokemon:${pokemon}???`;
- }
+ let side = pokemon.slice(0, 2);
+ if (!['p1', 'p2', 'p3', 'p4'].includes(side)) return `???pokemon:${pokemon}???`;
const name = this.pokemonName(pokemon);
- const template = BattleText.default[side === this.perspective ? 'pokemon' : 'opposingPokemon'];
+ const isNear = side === this.perspective || side === BattleTextParser.allyID(side as SideID);
+ const template = BattleText.default[isNear ? 'pokemon' : 'opposingPokemon'];
return template.replace('[NICKNAME]', name);
}
@@ -257,20 +258,30 @@ class BattleTextParser {
side = side.slice(0, 2);
if (side === 'p1') return this.p1;
if (side === 'p2') return this.p2;
+ if (side === 'p3') return this.p3;
+ if (side === 'p4') return this.p4;
return `???side:${side}???`;
}
- team(side: string, isFar: 0 | 1 = 0) {
+ static allyID(sideid: SideID): SideID | '' {
+ if (sideid === 'p1') return 'p3';
+ if (sideid === 'p2') return 'p4';
+ if (sideid === 'p3') return 'p1';
+ if (sideid === 'p4') return 'p2';
+ return '';
+ }
+
+ team(side: string, isFar: boolean = false) {
side = side.slice(0, 2);
- if (side === (this.perspective === isFar ? 'p1' : 'p2')) {
- return BattleText.default.team;
+ if (side === this.perspective || side === BattleTextParser.allyID(side as SideID)) {
+ return isFar ? BattleText.default.team : BattleText.default.opposingTeam;
}
- return BattleText.default.opposingTeam;
+ return !isFar ? BattleText.default.team : BattleText.default.opposingTeam;
}
own(side: string) {
side = side.slice(0, 2);
- if (side === (this.perspective === 0 ? 'p1' : 'p2')) {
+ if (side === this.perspective) {
return 'OWN';
}
return '';
@@ -278,7 +289,7 @@ class BattleTextParser {
party(side: string) {
side = side.slice(0, 2);
- if (side === (this.perspective === 0 ? 'p1' : 'p2')) {
+ if (side === this.perspective || side === BattleTextParser.allyID(side as SideID)) {
return BattleText.default.party;
}
return BattleText.default.opposingParty;
@@ -347,7 +358,7 @@ class BattleTextParser {
switch (cmd) {
case 'done' : case 'turn':
return 'break';
- case 'move' : case 'cant': case 'switch': case 'drag': case 'upkeep': case 'start': case '-mega':
+ case 'move' : case 'cant': case 'switch': case 'drag': case 'upkeep': case 'start': case '-mega': case '-candynamax':
return 'major';
case 'switchout': case 'faint':
return 'preMajor';
@@ -409,6 +420,10 @@ class BattleTextParser {
this.p1 = name;
} else if (side === 'p2' && name) {
this.p2 = name;
+ } else if (side === 'p3' && name) {
+ this.p3 = name;
+ } else if (side === 'p4' && name) {
+ this.p4 = name;
}
return '';
}
@@ -421,6 +436,7 @@ class BattleTextParser {
case 'turn': {
const [, num] = args;
+ this.turn = Number.parseInt(num, 10);
return this.template('turn').replace('[NUMBER]', num) + '\n';
}
@@ -529,6 +545,18 @@ class BattleTextParser {
return line1 + template.replace('[POKEMON]', this.pokemon(pokemon)).replace('[MOVE]', move);
}
+ case '-candynamax': {
+ let [, side] = args;
+ const own = this.own(side);
+ let template = '';
+ if (this.turn === 1) {
+ if (own) template = this.template('canDynamax', own);
+ } else {
+ template = this.template('canDynamax', own);
+ }
+ return template.replace('[TRAINER]', this.trainer(side));
+ }
+
case 'message': {
let [, message] = args;
return '' + message + '\n';
@@ -609,7 +637,7 @@ class BattleTextParser {
const id = BattleTextParser.effectId(ability);
if (id === 'unnerve') {
const template = this.template('start', ability);
- return line1 + template.replace('[TEAM]', this.team(pokemon.slice(0, 2), 1));
+ return line1 + template.replace('[TEAM]', this.team(pokemon.slice(0, 2), true));
}
let templateId = 'start';
if (id === 'anticipation' || id === 'sturdy') templateId = 'activate';
diff --git a/src/battle-tooltips.ts b/src/battle-tooltips.ts
index 11a88203e..920e99916 100644
--- a/src/battle-tooltips.ts
+++ b/src/battle-tooltips.ts
@@ -271,11 +271,11 @@ class BattleTooltips {
case 'zmove':
case 'maxmove': { // move|MOVE|ACTIVEPOKEMON|[GMAXMOVE]
let move = this.battle.dex.getMove(args[1]);
- let index = parseInt(args[2], 10);
- let pokemon = this.battle.nearSide.active[index];
- let serverPokemon = this.battle.myPokemon![index];
+ let teamIndex = parseInt(args[2], 10);
+ let pokemon = this.battle.nearSide.active[teamIndex + this.battle.pokemonControlled * Math.floor(this.battle.mySide!.n / 2)];
let gmaxMove = args[3] ? this.battle.dex.getMove(args[3]) : undefined;
if (!pokemon) return false;
+ let serverPokemon = this.battle.myPokemon![teamIndex];
buf = this.showMoveTooltip(move, type, pokemon, serverPokemon, gmaxMove);
break;
}
@@ -307,6 +307,22 @@ class BattleTooltips {
let sideIndex = parseInt(args[1], 10);
let side = this.battle.sides[+this.battle.sidesSwitched ^ sideIndex];
let activeIndex = parseInt(args[2], 10);
+ if (this.battle.gameType === 'multi') {
+ if (activeIndex >= side.active.length) return;
+ if (activeIndex && side.sideid !== 'p3' && side.sideid !== 'p4') side = side.ally;
+ if (!activeIndex && (side.sideid === 'p3' || side.sideid === 'p4')) side = side.ally;
+ let pokemon = side.active[activeIndex];
+ if (!pokemon) return;
+ let serverPokemon = null;
+ if (side === this.battle.mySide && this.battle.myPokemon) {
+ serverPokemon = this.battle.myPokemon[0];
+ } else if (side === this.battle.mySide!.ally && this.battle.myAllyPokemon) {
+ serverPokemon = this.battle.myAllyPokemon[0];
+ }
+ if (!pokemon) return false;
+ buf = this.showPokemonTooltip(pokemon, serverPokemon, true);
+ break;
+ }
let pokemon = side.active[activeIndex];
let serverPokemon = null;
if (sideIndex === 0 && this.battle.myPokemon) {
@@ -319,16 +335,30 @@ class BattleTooltips {
case 'switchpokemon': { // switchpokemon|POKEMON
// mouse over switchable pokemon
// serverPokemon definitely exists, sidePokemon maybe
- let side = this.battle.mySide;
+ // let side = this.battle.mySide;
let activeIndex = parseInt(args[1], 10);
let pokemon = null;
- if (activeIndex < side.active.length) {
+ /* if (activeIndex < side.active.length && activeIndex < this.battle.pokemonControlled) {
pokemon = side.active[activeIndex];
- }
+ if (pokemon && pokemon.side === side.ally) pokemon = null;
+ } */
let serverPokemon = this.battle.myPokemon![activeIndex];
buf = this.showPokemonTooltip(pokemon, serverPokemon);
break;
}
+ case 'allypokemon': { // allypokemon|POKEMON
+ // mouse over ally's pokemon in multi battles
+ // serverPokemon definitely exists, sidePokemon maybe
+ // let side = this.battle.mySide.ally;
+ let activeIndex = parseInt(args[1], 10);
+ let pokemon = null;
+ /*if (activeIndex < side.pokemon.length) {
+ pokemon = side.pokemon[activeIndex] || side.ally ? side.ally.pokemon[activeIndex] : null;
+ }*/
+ let serverPokemon = this.battle.myAllyPokemon ? this.battle.myAllyPokemon[activeIndex] : null;
+ buf = this.showPokemonTooltip(pokemon, serverPokemon);
+ break;
+ }
case 'field': {
buf = this.showFieldTooltip();
break;
@@ -1838,8 +1868,8 @@ class BattleTooltips {
// this will only be available if the ability announced itself in some way
let allyAbility = Dex.getAbility(ally.ability).name;
// otherwise fall back on the original set data sent from the server
- if (!allyAbility && this.battle.myPokemon) {
- allyAbility = Dex.getAbility(this.battle.myPokemon[ally.slot].ability).name;
+ if (!allyAbility && this.battle.myAllyPokemon) {
+ allyAbility = Dex.getAbility(this.battle.myAllyPokemon[ally.slot].ability).name;
}
return allyAbility;
}
diff --git a/src/battle.ts b/src/battle.ts
index bc58cc38c..9befe4ac1 100644
--- a/src/battle.ts
+++ b/src/battle.ts
@@ -577,9 +577,11 @@ class Side {
battle: Battle;
name = '';
id = '';
+ sideid: SideID;
n: number;
isFar: boolean;
foe: Side = null!;
+ ally: Side = null!;
avatar: string = 'unknown';
rating: string = '';
totalPokemon = 6;
@@ -597,11 +599,11 @@ class Side {
/** [effectName, levels, minDuration, maxDuration] */
sideConditions: {[id: string]: [string, number, number, number]} = {};
- constructor(battle: Battle, n: number, isOpp?: boolean) {
+ constructor(battle: Battle, n: number) {
this.battle = battle;
this.n = n;
- this.isFar = isOpp || !!n;
- this.updateSprites();
+ this.sideid = ['p1', 'p2', 'p3', 'p4'][n] as SideID;
+ this.isFar = !!(n % 2);
}
rollTrainerSprites() {
@@ -630,13 +632,8 @@ class Side {
}
reset() {
this.clearPokemon();
- this.updateSprites();
this.sideConditions = {};
}
- updateSprites() {
- this.z = (this.isFar ? 200 : 0);
- this.battle.scene.updateSpritesForSide(this);
- }
setAvatar(avatar: string) {
this.avatar = avatar;
}
@@ -1026,13 +1023,17 @@ class Battle {
pseudoWeather = [] as WeatherState[];
weatherTimeLeft = 0;
weatherMinTimeLeft = 0;
- mySide: Side = null!;
+ mySide: Side | null = null;
nearSide: Side = null!;
farSide: Side = null!;
p1: Side = null!;
p2: Side = null!;
+ p3?: Side = null!;
+ p4?: Side = null!;
+ pokemonControlled = 0;
+ sides: Side[] = null!;
myPokemon: ServerPokemon[] | null = null;
- sides: [Side, Side] = [null!, null!];
+ myAllyPokemon: ServerPokemon[] | null = null;
lastMove = '';
gen = 8;
@@ -1040,7 +1041,7 @@ class Battle {
teamPreviewCount = 0;
speciesClause = false;
tier = '';
- gameType: 'singles' | 'doubles' | 'triples' = 'singles';
+ gameType: 'singles' | 'doubles' | 'triples' | 'multi' = 'singles';
rated: string | boolean = false;
isBlitz = false;
endLastTurnPending = false;
@@ -1154,6 +1155,7 @@ class Battle {
if (side) side.reset();
}
this.myPokemon = null;
+ this.myAllyPokemon = null;
// DOM state
this.scene.reset();
@@ -1176,6 +1178,8 @@ class Battle {
this.farSide = null!;
this.p1 = null!;
this.p2 = null!;
+ this.p3 = null!;
+ this.p4 = null!;
}
log(args: Args, kwArgs?: KWArgs, preempt?: boolean) {
@@ -1192,14 +1196,16 @@ class Battle {
setSidesSwitched(sidesSwitched: boolean) {
this.sidesSwitched = sidesSwitched;
if (this.sidesSwitched) {
- this.nearSide = this.mySide = this.p2;
+ this.nearSide = this.p2;
this.farSide = this.p1;
} else {
- this.nearSide = this.mySide = this.p1;
+ this.nearSide = this.p1;
this.farSide = this.p2;
}
this.nearSide.isFar = false;
+ if (this.nearSide.ally) this.nearSide.ally.isFar = false;
this.farSide.isFar = true;
+ if (this.farSide.ally) this.farSide.ally.isFar = true;
// nothing else should need updating - don't call this function after sending out pokemon
}
@@ -2824,7 +2830,7 @@ class Battle {
this.scene.afterMove(poke);
break;
}
- case '-hint': case '-message': {
+ case '-hint': case '-message': case '-candynamax': {
this.log(args, kwArgs);
break;
}
@@ -2940,23 +2946,15 @@ class Battle {
let siden = -1;
let slot = -1; // if there is an explicit slot for this pokemon
- let slotChart: {[k: string]: number} = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5};
- if (name.substr(0, 4) === 'p2: ' || name === 'p2') {
- siden = this.p2.n;
- name = name.substr(4);
- } else if (name.substr(0, 4) === 'p1: ' || name === 'p1') {
- siden = this.p1.n;
- name = name.substr(4);
- } else if (name.substr(0, 2) === 'p2' && name.substr(3, 2) === ': ') {
- slot = slotChart[name.substr(2, 1)];
- siden = this.p2.n;
- name = name.substr(5);
- pokemonid = 'p2: ' + name;
- } else if (name.substr(0, 2) === 'p1' && name.substr(3, 2) === ': ') {
- slot = slotChart[name.substr(2, 1)];
- siden = this.p1.n;
- name = name.substr(5);
- pokemonid = 'p1: ' + name;
+ if (/^p[1-9]($|: )/.test(name)) {
+ siden = parseInt(name.charAt(1), 10) - 1;
+ name = name.slice(4);
+ } else if (/^p[1-9][a-f]: /.test(name)) {
+ const slotChart: {[k: string]: number} = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5};
+ siden = parseInt(name.charAt(1), 10) - 1;
+ slot = slotChart[name.charAt(2)];
+ name = name.slice(5);
+ pokemonid = `p${siden + 1}: ${name}`;
}
return {name, siden, slot, pokemonid};
}
@@ -3035,8 +3033,10 @@ class Battle {
return null;
}
getSide(sidename: string): Side {
- if (sidename === 'p1' || sidename.substr(0, 3) === 'p1:') return this.p1;
- if (sidename === 'p2' || sidename.substr(0, 3) === 'p2:') return this.p2;
+ if (sidename === 'p1' || sidename.startsWith('p1:')) return this.p1;
+ if (sidename === 'p2' || sidename.startsWith('p2:')) return this.p2;
+ if ((sidename === 'p3' || sidename.startsWith('p3:')) && this.p3) return this.p3;
+ if ((sidename === 'p4' || sidename.startsWith('p4:')) && this.p4) return this.p4;
if (this.nearSide.id === sidename) return this.nearSide;
if (this.farSide.id === sidename) return this.farSide;
if (this.nearSide.name === sidename) return this.nearSide;
@@ -3071,9 +3071,9 @@ class Battle {
runMajor(args: Args, kwArgs: KWArgs, preempt?: boolean) {
switch (args[0]) {
case 'start': {
- this.scene.teamPreviewEnd();
this.nearSide.active[0] = null;
this.farSide.active[0] = null;
+ this.scene.resetSides();
this.start();
break;
}
@@ -3103,8 +3103,22 @@ class Battle {
this.gameType = args[1] as any;
switch (args[1]) {
default:
- this.nearSide.active = [null];
- this.farSide.active = [null];
+ for (const side of this.sides) side.active = [null];
+ break;
+ case 'multi':
+ this.pokemonControlled = 1;
+ this.p3 = new Side(this, 2);
+ this.p4 = new Side(this, 3);
+ this.p3.foe = this.p4.ally = this.p2;
+ this.p3.ally = this.p4.foe = this.p1;
+ this.p1.ally = this.p3;
+ this.p2.ally = this.p4;
+ this.p3.isFar = this.p1.isFar;
+ this.p4.isFar = this.p2.isFar;
+ this.sides = [this.p1, this.p2, this.p3, this.p4];
+ // intentionally sync p1/p3 and p2/p4's active arrays
+ this.p1.active = this.p3.active = [null, null];
+ this.p2.active = this.p4.active = [null, null];
break;
case 'doubles':
this.nearSide.active = [null, null];
@@ -3116,7 +3130,9 @@ class Battle {
this.farSide.active = [null, null, null];
break;
}
+ if (!this.pokemonControlled) this.pokemonControlled = this.nearSide.active.length;
this.scene.updateGen();
+ this.scene.resetSides();
break;
}
case 'rule': {
@@ -3221,9 +3237,9 @@ class Battle {
side.setName(args[2]);
if (args[3]) side.setAvatar(args[3]);
if (args[4]) side.rating = args[4];
- this.scene.updateSidebar(side);
if (this.joinButtons) this.scene.hideJoinButtons();
this.log(args);
+ this.scene.updateSidebar(side);
break;
}
case 'teamsize': {
diff --git a/src/panel-battle.tsx b/src/panel-battle.tsx
index 71ca6f937..b0538a4a1 100644
--- a/src/panel-battle.tsx
+++ b/src/panel-battle.tsx
@@ -10,6 +10,8 @@ type BattleDesc = {
minElo?: number | string,
p1?: string,
p2?: string,
+ p3?: string,
+ p4?: string,
};
class BattlesRoom extends PSRoom {
diff --git a/style/battle.css b/style/battle.css
index c6533c645..9e45ac0af 100644
--- a/style/battle.css
+++ b/style/battle.css
@@ -315,11 +315,22 @@ License: GPLv2
position: absolute;
left: 0;
right: 0;
- bottom: 102px;
+ bottom: 75px;
}
-.rightbar .trainer {
+
+.trainer-near {
+ bottom: 75px;
+}
+.trainer-far {
bottom: 232px;
}
+.trainer-near2 {
+ bottom: 232px;
+}
+.trainer-far2 {
+ bottom: 75px;
+}
+
.trainer strong {
display: block;
font-size: 8pt;
diff --git a/style/client.css b/style/client.css
index ea713352f..094b1aa73 100644
--- a/style/client.css
+++ b/style/client.css
@@ -1851,6 +1851,13 @@ a.ilink.yours {
width: 640px;
background: #EEF2F5;
}
+.ps-room .ally-pokemon {
+ position: absolute;
+ top: 280px;
+ left: 0;
+ width: 640px;
+ background: #EEF2F5;
+}
.battle-chat-toggle {
display: none;
}
@@ -1946,6 +1953,7 @@ a.ilink.yours {
left: 0;
display: block;
}
+.allyTeam button,
.shiftselect button,
.moveselect button,
.switchselect button {
@@ -1970,6 +1978,7 @@ a.ilink.yours {
color: #445588;
cursor: default;
}
+.allyparty button,
.switchmenu button {
position: relative;
display: block;
@@ -1982,11 +1991,14 @@ a.ilink.yours {
white-space: pre;
overflow: hidden;
}
+.allyparty button .picon,
.switchmenu button .picon {
float: left;
margin: -6px -3px -6px -4px;
opacity: 0.8;
}
+
+.allyparty button .hpbar,
.switchmenu button .hpbar {
position: absolute;
display: block;
@@ -2000,6 +2012,7 @@ a.ilink.yours {
/* The declaration order of these three hpbar* classes is significant. */
+.allyparty button .hpbar span,
.switchmenu button .hpbar span {
display: block;
height: 1px;
@@ -2007,10 +2020,14 @@ a.ilink.yours {
border-top: 1px solid #3C0;
border-radius: 1px;
}
+
+.allyparty button .hpbar-yellow span,
.switchmenu button .hpbar-yellow span {
border-top-color: #a5aa53;
background-color: #a2a822;
}
+
+.allyparty button .hpbar-red span,
.switchmenu button .hpbar-red span {
border-top-color: #faa;
background-color: #f55;
@@ -2018,6 +2035,7 @@ a.ilink.yours {
/****************/
+.allyparty button .status,
.switchmenu button .status {
position: absolute;
display: block;
@@ -2098,13 +2116,14 @@ a.ilink.yours {
background: #E5E5E5;
color: black;
}
-
+.allyparty,
.switchmenu,
.movemenu {
display: block;
margin-right: -10px;
padding-left: 4px;
}
+.allyparty button,
.switchmenu button,
.movemenu button {
position: relative;
@@ -2122,12 +2141,14 @@ a.ilink.yours {
background: #e3e3e3;
background: linear-gradient(to bottom, #f6f6f6, #e3e3e3);
}
+.allyparty button:hover,
.switchmenu button:hover,
.movemenu button:hover {
background: #cfcfcf;
background: linear-gradient(to bottom, #f2f2f2, #cfcfcf);
border-color: #606060;
}
+.allyparty button:active,
.switchmenu button:active,
.movemenu button:active,
.switchmenu button.pressed,
@@ -2135,6 +2156,8 @@ a.ilink.yours {
background: linear-gradient(to bottom, #cfcfcf, #f2f2f2);
}
+.allyparty button.disabled,
+.allyparty button:disabled,
.switchmenu button.disabled,
.switchmenu button:disabled,
.movemenu button:disabled {
@@ -2181,6 +2204,7 @@ a.ilink.yours {
display: none;
padding: 0 75px 0 85px;
}
+ .allyparty,
.switchmenu {
display: none;
max-width: 325px;
@@ -2192,6 +2216,7 @@ a.ilink.yours {
left: 20px;
bottom: 20px;
}
+ .allyTeam,
.switchselect {
position: absolute;
right: 20px;