mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-10-02 07:42:12 -05:00
Client-side support for Multi Battles (#1649)
This commit is contained in:
committed by
GitHub
parent
576f773653
commit
1fe0b7eb85
@@ -7,7 +7,6 @@
|
||||
minMainWidth: 956,
|
||||
maxWidth: 1180,
|
||||
initialize: function (data) {
|
||||
this.me = {};
|
||||
this.choice = undefined;
|
||||
/** are move/switch/team-preview controls currently being shown? */
|
||||
this.controlsShown = false;
|
||||
@@ -335,6 +334,9 @@
|
||||
if (this.request) {
|
||||
// TODO: investigate when to do this
|
||||
this.updateSide();
|
||||
if (this.request.ally) {
|
||||
this.addAlly(this.request.ally);
|
||||
}
|
||||
|
||||
act = this.request.requestType;
|
||||
if (this.request.side) {
|
||||
@@ -382,7 +384,7 @@
|
||||
|
||||
if (this.request.forceSwitch !== true) {
|
||||
var faintedLength = _.filter(this.request.forceSwitch, function (fainted) {return fainted;}).length;
|
||||
var freedomDegrees = faintedLength - _.filter(switchables.slice(this.battle.nearSide.active.length), function (mon) {return !mon.fainted;}).length;
|
||||
var freedomDegrees = faintedLength - _.filter(switchables.slice(this.battle.pokemonControlled), function (mon) {return !mon.fainted;}).length;
|
||||
this.choice.freedomDegrees = Math.max(freedomDegrees, 0);
|
||||
this.choice.canSwitch = faintedLength - this.choice.freedomDegrees;
|
||||
}
|
||||
@@ -404,6 +406,9 @@
|
||||
done: 0,
|
||||
count: 1
|
||||
};
|
||||
if (this.battle.gameType === 'multi') {
|
||||
this.choice.count = 1;
|
||||
}
|
||||
if (this.battle.gameType === 'doubles') {
|
||||
this.choice.count = 2;
|
||||
}
|
||||
@@ -516,7 +521,8 @@
|
||||
}
|
||||
|
||||
var moveTarget = this.choice ? this.choice.moveTarget : '';
|
||||
var pos = this.choice.choices.length - (type === 'movetarget' ? 1 : 0);
|
||||
var pos = this.choice.choices.length;
|
||||
if (type === 'movetarget') pos--;
|
||||
|
||||
var hpRatio = switchables[pos].hp / switchables[pos].maxhp;
|
||||
|
||||
@@ -555,10 +561,12 @@
|
||||
if (type === 'movetarget') {
|
||||
requestTitle += 'At who? ';
|
||||
|
||||
var activePos = this.battle.mySide.n > 1 ? pos + this.battle.pokemonControlled : pos;
|
||||
|
||||
var targetMenus = ['', ''];
|
||||
var nearActive = this.battle.nearSide.active;
|
||||
var farActive = this.battle.farSide.active;
|
||||
var farSlot = farActive.length - 1 - pos;
|
||||
var farSlot = farActive.length - 1 - activePos;
|
||||
|
||||
for (var i = farActive.length - 1; i >= 0; i--) {
|
||||
var pokemon = farActive[i];
|
||||
@@ -587,9 +595,9 @@
|
||||
if (moveTarget === 'adjacentFoe') {
|
||||
disabled = true;
|
||||
} else if (moveTarget === 'normal' || moveTarget === 'adjacentAlly' || moveTarget === 'adjacentAllyOrSelf') {
|
||||
if (Math.abs(pos - i) > 1) disabled = true;
|
||||
if (Math.abs(activePos - i) > 1) disabled = true;
|
||||
}
|
||||
if (moveTarget !== 'adjacentAllyOrSelf' && pos == i) disabled = true;
|
||||
if (moveTarget !== 'adjacentAllyOrSelf' && activePos == i) disabled = true;
|
||||
|
||||
if (disabled) {
|
||||
targetMenus[1] += '<button disabled="disabled" style="visibility:hidden"></button> ';
|
||||
@@ -615,7 +623,8 @@
|
||||
var hasMoves = false;
|
||||
var moveMenu = '';
|
||||
var movebuttons = '';
|
||||
var typeValueTracker = new ModifiableValue(this.battle, this.battle.nearSide.active[pos], this.battle.myPokemon[pos]);
|
||||
var activePos = this.battle.mySide.n > 1 ? pos + this.battle.pokemonControlled : pos;
|
||||
var typeValueTracker = new ModifiableValue(this.battle, this.battle.nearSide.active[activePos], this.battle.myPokemon[pos]);
|
||||
var currentlyDynamaxed = (!canDynamax && maxMoves);
|
||||
for (var i = 0; i < curActive.moves.length; i++) {
|
||||
var moveData = curActive.moves[i];
|
||||
@@ -627,7 +636,7 @@
|
||||
if (move.id === 'Recharge') move.type = '–';
|
||||
if (name.substr(0, 12) === 'Hidden Power') name = 'Hidden Power';
|
||||
var moveType = this.tooltips.getMoveType(move, typeValueTracker)[0];
|
||||
var tooltipArgs = 'move|' + moveData.move + '|' + pos;
|
||||
var tooltipArgs = 'move|' + moveData.move + '|' + activePos;
|
||||
if (moveData.disabled) {
|
||||
movebuttons += '<button disabled="disabled" class="has-tooltip" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '">';
|
||||
} else {
|
||||
@@ -715,7 +724,6 @@
|
||||
'<div class="switchmenu">' + switchMenu + '</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
this.$controls.html(
|
||||
'<div class="controls">' +
|
||||
'<div class="whatdo">' + requestTitle + this.getTimerHTML() + '</div>' +
|
||||
@@ -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 += '<button class="disabled has-tooltip" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : trapped ? ',trapped' : i < this.battle.nearSide.active.length ? ',active' : '') + '" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '"><span class="picon" style="' + Dex.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + (pokemon.hp ? '<span class="' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
} else {
|
||||
party += '<button name="chooseSwitch" value="' + i + '" class="has-tooltip" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '"><span class="picon" style="' + Dex.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '<span class="' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
}
|
||||
}
|
||||
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 += '<button class="disabled has-tooltip" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + ',notMine' + '" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '"><span class="picon" style="' + Dex.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + (pokemon.hp ? '<span class="' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
}
|
||||
return party;
|
||||
},
|
||||
updateSwitchControls: function (type) {
|
||||
@@ -760,7 +781,7 @@
|
||||
// TODO? hpbar
|
||||
requestTitle += "Which Pokémon will it switch in for?";
|
||||
var controls = '<div class="switchmenu" style="display:block">';
|
||||
for (var i = 0; i < nearActive.length; i++) {
|
||||
for (var i = 0; i < this.battle.pokemonControlled; i++) {
|
||||
var pokemon = this.battle.myPokemon[i];
|
||||
var tooltipArgs = 'switchpokemon|' + i;
|
||||
if (pokemon && !pokemon.fainted || this.choice.switchOutFlags[i]) {
|
||||
@@ -789,8 +810,8 @@
|
||||
for (var i = 0; i < switchables.length; i++) {
|
||||
var pokemon = switchables[i];
|
||||
var tooltipArgs = 'switchpokemon|' + i;
|
||||
if (pokemon.fainted || i < this.battle.nearSide.active.length || this.choice.switchFlags[i]) {
|
||||
switchMenu += '<button class="disabled has-tooltip" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.nearSide.active.length ? ',active' : '') + '" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '">';
|
||||
if (pokemon.fainted || i < this.battle.pokemonControlled || this.choice.switchFlags[i]) {
|
||||
switchMenu += '<button class="disabled has-tooltip" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.pokemonControlled ? ',active' : '') + '" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '">';
|
||||
} else {
|
||||
switchMenu += '<button name="chooseSwitch" value="' + i + '" class="has-tooltip" data-tooltip="' + BattleLog.escapeHTML(tooltipArgs) + '">';
|
||||
}
|
||||
@@ -877,19 +898,20 @@
|
||||
}
|
||||
buf += leads.join(', ') + ' will be sent out first.<br />';
|
||||
} else if (this.choice.choices && this.request) {
|
||||
var nearActive = this.battle.nearSide.active;
|
||||
for (var i = 0; i < this.choice.choices.length; i++) {
|
||||
var myActive = this.battle.myPokemon;
|
||||
for (var i = 0; i < (this.battle.myPokemon || this.choice.choices.length); i++) {
|
||||
var parts = this.choice.choices[i].split(' ');
|
||||
switch (parts[0]) {
|
||||
case 'move':
|
||||
var move;
|
||||
myActive = this.battle.nearSide.active;
|
||||
if (this.request.active[i].maxMoves && !this.request.active[i].canDynamax) { // it's a max move
|
||||
move = this.request.active[i].maxMoves.maxMoves[parseInt(parts[1], 10) - 1].move;
|
||||
} else { // it's a normal move
|
||||
move = this.request.active[i].moves[parseInt(parts[1], 10) - 1].move;
|
||||
}
|
||||
var target = '';
|
||||
buf += nearActive[i].speciesForme + ' will ';
|
||||
buf += myActive[i].speciesForme + ' will ';
|
||||
if (parts.length > 2) {
|
||||
var targetPos = parts[2];
|
||||
if (targetPos === 'mega') {
|
||||
@@ -909,7 +931,7 @@
|
||||
var targetActive = this.battle.farSide.active;
|
||||
// Targeting your own side in doubles / triples
|
||||
if (targetPos < 0) {
|
||||
targetActive = nearActive;
|
||||
targetActive = myActive;
|
||||
targetPos = -targetPos;
|
||||
target += 'your ';
|
||||
}
|
||||
@@ -924,13 +946,13 @@
|
||||
break;
|
||||
case 'switch':
|
||||
buf += '' + this.battle.myPokemon[parts[1] - 1].speciesForme + ' will switch in';
|
||||
if (nearActive[i]) {
|
||||
buf += ', replacing ' + nearActive[i].speciesForme;
|
||||
if (myActive[i]) {
|
||||
buf += ', replacing ' + myActive[i].speciesForme;
|
||||
}
|
||||
buf += '.<br />';
|
||||
break;
|
||||
case 'shift':
|
||||
buf += nearActive[i].speciesForme + ' will shift position.<br />';
|
||||
buf += myActive[i].speciesForme + ' will shift position.<br />';
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1007,7 +1029,7 @@
|
||||
updateSideLocation: function (sideData) {
|
||||
if (!sideData.id) return;
|
||||
this.side = sideData.id;
|
||||
if (this.battle.sidesSwitched !== !!(this.side === 'p2')) {
|
||||
if (this.battle.sidesSwitched !== !!(this.side === 'p2' || this.side === 'p4')) {
|
||||
this.battle.switchSides();
|
||||
this.$chat = this.$chatFrame.find('.inner');
|
||||
}
|
||||
@@ -1015,6 +1037,14 @@
|
||||
updateSide: function () {
|
||||
var sideData = this.request.side;
|
||||
this.battle.myPokemon = sideData.pokemon;
|
||||
this.battle.mySide = this.battle[sideData.id];
|
||||
this.battle.nearSide = this.battle.sides[this.battle.mySide.n % 2];
|
||||
this.battle.farSide = this.battle.mySide.foe;
|
||||
this.battle.mySide.isFar = false;
|
||||
this.battle.farSide.isFar = true;
|
||||
if (this.battle.mySide.ally) this.battle.mySide.ally.isFar = false;
|
||||
if (this.battle.farSide.ally) this.battle.farSide.ally.isFar = true;
|
||||
this.battle.myPokemon = sideData.pokemon;
|
||||
for (var i = 0; i < sideData.pokemon.length; i++) {
|
||||
var pokemonData = sideData.pokemon[i];
|
||||
if (this.request.active && this.request.active[i]) pokemonData.canGmax = this.request.active[i].gigantamax || false;
|
||||
@@ -1027,6 +1057,20 @@
|
||||
pokemonData.getHPColor = Pokemon.prototype.getHPColor;
|
||||
}
|
||||
},
|
||||
addAlly: function (allyData) {
|
||||
this.battle.myAllyPokemon = allyData.pokemon;
|
||||
for (var i = 0; i < allyData.pokemon.length; i++) {
|
||||
var pokemonData = allyData.pokemon[i];
|
||||
this.battle.parseDetails(pokemonData.ident.substr(4), pokemonData.ident, pokemonData.details, pokemonData);
|
||||
this.battle.parseHealth(pokemonData.condition, pokemonData);
|
||||
pokemonData.hpDisplay = Pokemon.prototype.hpDisplay;
|
||||
pokemonData.getPixelRange = Pokemon.prototype.getPixelRange;
|
||||
pokemonData.getFormattedRange = Pokemon.prototype.getFormattedRange;
|
||||
pokemonData.getHPColorClass = Pokemon.prototype.getHPColorClass;
|
||||
pokemonData.getHPColor = Pokemon.prototype.getHPColor;
|
||||
pokemonData.side = this.battle.mySide.ally;
|
||||
}
|
||||
},
|
||||
|
||||
// buttons
|
||||
joinBattle: function () {
|
||||
@@ -1218,6 +1262,8 @@
|
||||
data = data.split(',');
|
||||
if (data[1] === 'fainted') {
|
||||
app.addPopupMessage("" + data[0] + " has no energy left to battle!");
|
||||
} else if (data[1] === 'notMine') {
|
||||
app.addPopupMessage("You cannot decide for your partner!");
|
||||
} else if (data[1] === 'trapped') {
|
||||
app.addPopupMessage("You are trapped and cannot select " + data[0] + "!");
|
||||
} else if (data[1] === 'active') {
|
||||
@@ -1241,20 +1287,20 @@
|
||||
var nearActive = this.battle.nearSide.active;
|
||||
|
||||
if (this.request.requestType === 'switch' && this.request.forceSwitch !== true) {
|
||||
while (choices.length < nearActive.length && !this.request.forceSwitch[choices.length]) {
|
||||
while (choices.length < this.battle.pokemonControlled && !this.request.forceSwitch[choices.length]) {
|
||||
choices.push('pass');
|
||||
}
|
||||
if (choices.length < nearActive.length) {
|
||||
if (choices.length < this.battle.pokemonControlled) {
|
||||
this.choice.type = 'switch2';
|
||||
this.updateControlsForPlayer();
|
||||
return true;
|
||||
}
|
||||
} else if (this.request.requestType === 'move') {
|
||||
while (choices.length < nearActive.length && !nearActive[choices.length]) {
|
||||
while (choices.length < this.battle.pokemonControlled && !nearActive[choices.length]) {
|
||||
choices.push('pass');
|
||||
}
|
||||
|
||||
if (choices.length < nearActive.length) {
|
||||
if (choices.length < this.battle.pokemonControlled) {
|
||||
this.choice.type = 'move2';
|
||||
this.updateControlsForPlayer();
|
||||
return true;
|
||||
@@ -1275,12 +1321,12 @@
|
||||
if (act === 'switch') {
|
||||
// Assert that the remaining Pokémon won't switch, even though
|
||||
// the player could have decided otherwise.
|
||||
for (var i = 0; i < this.battle.nearSide.active.length; i++) {
|
||||
for (var i = 0; i < this.battle.pokemonControlled; i++) {
|
||||
if (!this.choice.choices[i]) this.choice.choices[i] = 'pass';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.choice.choices.length >= (this.choice.count || this.battle.nearSide.active.length)) {
|
||||
if (this.choice.choices.length >= (this.choice.count || this.battle.pokemonControlled || this.request.active.length)) {
|
||||
this.sendDecision(this.choice.choices);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ class BattleScene {
|
||||
const pokemon = battle.getPokemon(pokemonId);
|
||||
if (pokemon) return pokemon.speciesForme;
|
||||
}
|
||||
if (!pokemonId.startsWith('p1') && !pokemonId.startsWith('p2')) return '???pokemon:' + pokemonId + '???';
|
||||
if (!pokemonId.startsWith('p')) return '???pokemon:' + pokemonId + '???';
|
||||
if (pokemonId.charAt(3) === ':') return pokemonId.slice(4).trim();
|
||||
else if (pokemonId.charAt(2) === ':') return pokemonId.slice(3).trim();
|
||||
return '???pokemon:' + pokemonId + '???';
|
||||
@@ -208,7 +208,9 @@ class BattleScene {
|
||||
this.curTerrain = '';
|
||||
this.curWeather = '';
|
||||
|
||||
this.log.battleParser!.perspective = this.battle.sidesSwitched ? 1 : 0;
|
||||
this.log.battleParser!.perspective = this.battle.mySide!.sideid;
|
||||
|
||||
this.resetSides(true);
|
||||
}
|
||||
|
||||
animationOff() {
|
||||
@@ -616,9 +618,7 @@ class BattleScene {
|
||||
}
|
||||
return BattleLog.escapeHTML(name);
|
||||
}
|
||||
|
||||
updateSidebar(side: Side) {
|
||||
if (!this.animating) return;
|
||||
getSidebarHTML(side: Side, isAlly?: boolean): string {
|
||||
let noShow = this.battle.hardcoreMode && this.battle.gen < 7;
|
||||
|
||||
let speciesOverage = this.battle.speciesClause ? Infinity : Math.max(side.pokemon.length - side.totalPokemon, 0);
|
||||
@@ -693,17 +693,25 @@ class BattleScene {
|
||||
if (i % 3 === 2) pokemonhtml += `</div><div class="teamicons">`;
|
||||
}
|
||||
pokemonhtml = '<div class="teamicons">' + pokemonhtml + '</div>';
|
||||
const ratinghtml = side.rating ? ` title="Rating: ${BattleLog.escapeHTML(side.rating)}"` : ``;
|
||||
let posStr = side.isFar ? 'far' : 'near';
|
||||
if (isAlly) posStr += '2';
|
||||
return `<div class="trainer trainer-${posStr}"><strong>${BattleLog.escapeHTML(side.name)}</strong><div class="trainersprite"${ratinghtml} style="background-image:url(${Dex.resolveAvatar(side.avatar)})"></div>${pokemonhtml}</div>`;
|
||||
}
|
||||
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(`<div class="trainer"><strong>${BattleLog.escapeHTML(side.name)}</strong><div class="trainersprite"${ratinghtml} style="background-image:url(${Dex.resolveAvatar(side.avatar)})"></div>${pokemonhtml}</div>`);
|
||||
$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
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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': {
|
||||
|
||||
@@ -10,6 +10,8 @@ type BattleDesc = {
|
||||
minElo?: number | string,
|
||||
p1?: string,
|
||||
p2?: string,
|
||||
p3?: string,
|
||||
p4?: string,
|
||||
};
|
||||
|
||||
class BattlesRoom extends PSRoom {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user