diff --git a/play.pokemonshowdown.com/js/client-teambuilder.js b/play.pokemonshowdown.com/js/client-teambuilder.js
index fd2593e4fd..98decadcbf 100644
--- a/play.pokemonshowdown.com/js/client-teambuilder.js
+++ b/play.pokemonshowdown.com/js/client-teambuilder.js
@@ -1375,10 +1375,10 @@
// moves
if (!set.moves) set.moves = [];
buf += '
';
// stats
diff --git a/play.pokemonshowdown.com/js/storage.js b/play.pokemonshowdown.com/js/storage.js
index 8ca36a79bf..e0f02a3529 100644
--- a/play.pokemonshowdown.com/js/storage.js
+++ b/play.pokemonshowdown.com/js/storage.js
@@ -812,6 +812,20 @@ Storage.packTeam = function (team) {
if (moveid.substr(0, 11) === 'hiddenpower' && moveid.length > 11) hasHP = true;
}
+ // move PP ups
+ if (set.movePPUps) {
+ var PPUps = '';
+ var showPPUps = false;
+ for (var j = 0; j < set.movePPUps.length; j++) {
+ if (j) PPUps += ',';
+ if (set.movePPUps[j] < 3) {
+ PPUps += set.movePPUps[j];
+ showPPUps = true;
+ }
+ }
+ if (showPPUps) buf += ';' + PPUps;
+ }
+
// nature
buf += '|' + (set.nature || '');
@@ -883,7 +897,7 @@ Storage.fastUnpackTeam = function (buf) {
if (!buf) return [];
var team = [];
- var i = 0, j = 0;
+ var i = 0, j = 0, k = 0;
while (true) {
var set = {};
@@ -913,10 +927,23 @@ Storage.fastUnpackTeam = function (buf) {
i = j + 1;
// moves
- j = buf.indexOf('|', i);
+ j = buf.indexOf(';', i);
+ k = buf.indexOf('|', i);
+ if (j < 0 || j > k) j = k;
set.moves = buf.substring(i, j).split(',');
i = j + 1;
+ // move PP ups
+ if (buf.charAt(j) === ';') {
+ j = buf.indexOf('|', i);
+ set.movePPUps = buf.substring(i, j).split(',');
+ for (var index = 0; index < set.movePPUps.length; index++) {
+ set.movePPUps[index] = parseInt(set.movePPUps[index], 10);
+ if (!set.movePPUps[index]) set.movePPUps[index] = 3;
+ }
+ i = j + 1;
+ }
+
// nature
j = buf.indexOf('|', i);
set.nature = buf.substring(i, j);
@@ -1000,7 +1027,7 @@ Storage.unpackTeam = function (buf) {
if (!buf) return [];
var team = [];
- var i = 0, j = 0;
+ var i = 0, j = 0, k = 0;
while (true) {
var set = {};
@@ -1029,12 +1056,29 @@ Storage.unpackTeam = function (buf) {
i = j + 1;
// moves
- j = buf.indexOf('|', i);
+ j = buf.indexOf(';', i);
+ k = buf.indexOf('|', i);
+ if (j < 0 || j > k) {
+ j = k;
+ if (j < 0) return null;
+ }
set.moves = buf.substring(i, j).split(',').map(function (moveid) {
return Dex.moves.get(moveid).name;
});
i = j + 1;
+ // move PP ups
+ if (buf.charAt(j) === ';') {
+ j = buf.indexOf('|', i);
+ if (j < 0) return null;
+ set.movePPUps = buf.substring(i, j).split(',');
+ for (var index = 0; index < set.movePPUps.length; index++) {
+ set.movePPUps[index] = parseInt(set.movePPUps[index], 10);
+ if (isNaN(set.movePPUps[index])) set.movePPUps[index] = 3;
+ }
+ i = j + 1;
+ }
+
// nature
j = buf.indexOf('|', i);
set.nature = buf.substring(i, j);
@@ -1344,7 +1388,15 @@ Storage.importTeam = function (buffer, teams) {
if (line === 'Frustration' && curSet.happiness === undefined) {
curSet.happiness = 0;
}
- curSet.moves.push(line);
+ var moveAndPPUps = line.split(' (PP Ups: ', 2);
+ curSet.moves.push(moveAndPPUps[0]);
+ if (!curSet.movePPUps) curSet.movePPUps = [];
+ if (moveAndPPUps[1]) moveAndPPUps[1] = moveAndPPUps[1].charAt(0);
+ if (isNaN(moveAndPPUps[1])) {
+ curSet.movePPUps.push(3);
+ } else {
+ curSet.movePPUps.push(parseInt(moveAndPPUps[1], 10));
+ }
}
}
if (teams && teams.length && typeof teams[teams.length - 1].team !== 'string') {
@@ -1493,7 +1545,11 @@ Storage.exportTeam = function (team, gen, hidestats) {
move = move.substr(0, 13) + '[' + move.substr(13) + ']';
}
if (move) {
- text += '- ' + move + " \n";
+ text += '- ' + move;
+ if (curSet.movePPUps && !isNaN(curSet.movePPUps[j]) && curSet.movePPUps[j] < 3) {
+ text += " (PP Ups: " + curSet.movePPUps[j] + ")";
+ }
+ text += " \n";
}
}
text += "\n";
diff --git a/play.pokemonshowdown.com/src/battle-tooltips.ts b/play.pokemonshowdown.com/src/battle-tooltips.ts
index ebeb171361..4e8a748dc7 100644
--- a/play.pokemonshowdown.com/src/battle-tooltips.ts
+++ b/play.pokemonshowdown.com/src/battle-tooltips.ts
@@ -2517,6 +2517,8 @@ interface PokemonSet {
/** Defaults to no ability (error in Gen 3+) */
ability?: string;
moves: string[];
+ /** Defaults to 3 */
+ movePPUps?: number[];
/** Defaults to no nature (error in Gen 3+) */
nature?: NatureName;
/** Defaults to random legal gender, NOT subject to gender ratios */
diff --git a/play.pokemonshowdown.com/src/panel-teamdropdown.tsx b/play.pokemonshowdown.com/src/panel-teamdropdown.tsx
index 0794f16cab..e343bc2674 100644
--- a/play.pokemonshowdown.com/src/panel-teamdropdown.tsx
+++ b/play.pokemonshowdown.com/src/panel-teamdropdown.tsx
@@ -41,6 +41,14 @@ class PSTeambuilder {
}
}
+ if (set.movePPUps && set.movePPUps.some(n => n < 3)) {
+ const PPUps = set.movePPUps.map(n => {
+ if (n === 3) return '';
+ return n.toString();
+ });
+ buf += ';' + PPUps.join(',');
+ }
+
// nature
buf += '|' + (set.nature || '');
@@ -140,11 +148,19 @@ class PSTeambuilder {
species.abilities[parts[3] as '0' || '0'] || (parts[3] === '' ? '' : '!!!ERROR!!!') :
Dex.abilities.get(parts[3]).name;
- // moves
- set.moves = parts[4].split(',').map(moveid =>
+ // moves and PP ups
+ const [moves, PPUps] = parts[4].split(';', 2);
+ set.moves = moves.split(',').map(moveid =>
Dex.moves.get(moveid).name
);
+ if (PPUps) {
+ set.movePPUps = PPUps.split(',').map(n => {
+ if (!n) return 3;
+ return parseInt(n, 10);
+ });
+ }
+
// nature
set.nature = parts[5] as NatureName;
if (set.nature as any === 'undefined') set.nature = undefined;
@@ -224,14 +240,19 @@ class PSTeambuilder {
text += `Ability: ${set.ability} \n`;
}
if (set.moves) {
- for (let move of set.moves) {
+ for (let i = 0; i < set.moves.length; i++) {
+ let move = set.moves[i];
+ let PPUps = ``;
if (move.substr(0, 13) === 'Hidden Power ') {
const hpType = move.slice(13);
move = move.slice(0, 13);
move = `${move}[${hpType}]`;
}
+ if (set.movePPUps && !isNaN(set.movePPUps[i]) && set.movePPUps[i] < 3) {
+ PPUps = ` (PP Ups: ${set.movePPUps[i]})`;
+ }
if (move) {
- text += `- ${move} \n`;
+ text += `- ${move}${PPUps} \n`;
}
}
}
@@ -395,9 +416,10 @@ class PSTeambuilder {
if (line !== 'undefined') set.nature = line as NatureName;
} else if (line.charAt(0) === '-' || line.charAt(0) === '~') {
line = line.slice(line.charAt(1) === ' ' ? 2 : 1);
- if (line.startsWith('Hidden Power [')) {
- const hpType = line.slice(14, -1) as TypeName;
- line = 'Hidden Power ' + hpType;
+ let [move, PPUps] = line.split(' (PP Ups: ');
+ if (move.startsWith('Hidden Power [')) {
+ const hpType = move.slice(14, -1) as TypeName;
+ move = 'Hidden Power ' + hpType;
if (!set.ivs && Dex.types.isName(hpType)) {
set.ivs = {hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31};
const hpIVs = Dex.types.get(hpType).HPivs || {};
@@ -406,6 +428,8 @@ class PSTeambuilder {
}
}
}
+ if (!set.movePPUps) set.movePPUps = [];
+ set.movePPUps.push(parseInt(PPUps?.charAt(0), 10) || 3);
if (line === 'Frustration' && set.happiness === undefined) {
set.happiness = 0;
}