// ==UserScript==
// @name Sauce's Showdown Music Mod
// @namespace https://github.com/OpenSauce04/ssmm-showdown/
// @version 0.4
// @description A replacement of the Pokemon Showdown battle music with many other tracks from the Pokemon series
// @author OpenSauce
// @match https://play.pokemonshowdown.com/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @license AGPL-3.0; https://github.com/smogon/pokemon-showdown-client/blob/master/LICENSE
// ==/UserScript==
// == PART 1 ==
var
BattleBGM = function () {
function BattleBGM(url, loopstart, loopend) {
this.sound = void 0;
this.url = void 0;
this.timer = undefined;
this.loopstart = void 0;
this.loopend = void 0;
this.isPlaying = false;
this.isActuallyPlaying = false;
this.willRewind = true;
this.url = url;
this.loopstart = loopstart;
this.loopend = loopend;
}
var _proto = BattleBGM.prototype;
_proto.
play = function play() {
this.willRewind = true;
this.resume();
};
_proto.
resume = function resume() {
this.isPlaying = true;
this.actuallyResume();
};
_proto.
pause = function pause() {
this.isPlaying = false;
this.actuallyPause();
BattleBGM.update();
};
_proto.
stop = function stop() {
this.pause();
this.willRewind = true;
};
_proto.
destroy = function destroy() {
BattleSound.deleteBgm(this);
this.pause();
};
_proto.
actuallyResume = function actuallyResume() {
if (this !== BattleSound.currentBgm()) return;
if (this.isActuallyPlaying) return;
if (!this.sound) this.sound = BattleSound.getSoundSpecial(this.url);
if (!this.sound) return;
if (this.willRewind) this.sound.currentTime = 0;
this.willRewind = false;
this.isActuallyPlaying = true;
this.sound.volume = BattleSound.bgmVolume / 100;
this.sound.play();
this.updateTime();
};
_proto.
actuallyPause = function actuallyPause() {
if (!this.isActuallyPlaying) return;
this.isActuallyPlaying = false;
this.sound.pause();
this.updateTime();
};
_proto.
updateTime = function updateTime() {
var _this = this;
clearTimeout(this.timer);
this.timer = undefined;
if (this !== BattleSound.currentBgm()) return;
if (!this.sound) return;
var progress = this.sound.currentTime * 1000;
if (progress > this.loopend - 1000) {
this.sound.currentTime -= (this.loopend - this.loopstart) / 1000;
}
this.timer = setTimeout(function () {
_this.updateTime();
}, Math.max(this.loopend - progress, 1));
};
BattleBGM.
update = function update() {
var current = BattleSound.currentBgm();
for (var _i = 0, _BattleSound$bgm =
BattleSound.bgm; _i < _BattleSound$bgm.length; _i++) {
var bgm = _BattleSound$bgm[_i];
if (bgm.isPlaying) {
if (bgm === current) {
bgm.actuallyResume();
} else {
bgm.actuallyPause();
}
}
}
};
return BattleBGM;
}();
// == PART 2 ==
var BattleSound = new (function () {
function _class2() {
this.
soundCache = {};
this.
bgm = [];
this.
effectVolume = 50;
this.
bgmVolume = 50;
this.
muted = false;
}
var _proto2 = _class2.prototype;
_proto2.
getSound = function getSound(url) {
if (!window.HTMLAudioElement) return;
if (this.soundCache[url]) return this.soundCache[url];
try {
var sound = document.createElement('audio');
sound.src = 'https://' + Config.routes.client + '/' + url;
sound.volume = this.effectVolume / 100;
this.soundCache[url] = sound;
return sound;
} catch (_unused) {
console.log(_unused)
}
};
_proto2.
getSoundSpecial = function getSoundSpecial(url) {
if (!window.HTMLAudioElement) return;
if (this.soundCache[url]) return this.soundCache[url];
try {
var sound = document.createElement('audio');
sound.src = url;
sound.volume = this.effectVolume / 100;
this.soundCache[url] = sound;
return sound;
} catch (_unused) {
console.log(_unused)
}
};
_proto2.
playEffect = function playEffect(url) {
this.playSound(url, this.muted ? 0 : this.effectVolume);
};
_proto2.
playSound = function playSound(url, volume) {
if (!volume) return;
var effect = this.getSound(url);
if (effect) {
effect.volume = volume / 100;
effect.play();
}
};
_proto2.
loadBgm = function loadBgm(url, loopstart, loopend, replaceBGM) {
if (replaceBGM) {
replaceBGM.stop();
this.deleteBgm(replaceBGM);
}
var bgm = new BattleBGM(url, loopstart, loopend);
this.bgm.push(bgm);
return bgm;
};
_proto2.
deleteBgm = function deleteBgm(bgm) {
var soundIndex = BattleSound.bgm.indexOf(bgm);
if (soundIndex >= 0) BattleSound.bgm.splice(soundIndex, 1);
};
_proto2.
currentBgm = function currentBgm() {
if (!this.bgmVolume || this.muted) return false;
for (var _i2 = 0, _this$bgm =
this.bgm; _i2 < _this$bgm.length; _i2++) {
var bgm = _this$bgm[_i2];
if (bgm.isPlaying) return bgm;
}
return null;
};
_proto2.
setMute = function setMute(muted) {
muted = !!muted;
if (this.muted === muted) return;
this.muted = muted;
BattleBGM.update();
};
_proto2.
loudnessPercentToAmplitudePercent = function loudnessPercentToAmplitudePercent(loudnessPercent) {
var decibels = 10 * Math.log(loudnessPercent / 100) / Math.log(2);
return Math.pow(10, decibels / 20) * 100;
};
_proto2.
setBgmVolume = function setBgmVolume(bgmVolume) {
this.bgmVolume = this.loudnessPercentToAmplitudePercent(bgmVolume);
BattleBGM.update();
};
_proto2.
setEffectVolume = function setEffectVolume(effectVolume) {
this.effectVolume = this.loudnessPercentToAmplitudePercent(effectVolume);
};
return _class2;
}())();
// == PART 3 ==
BattleScene = function () {
function BattleScene(battle, $frame, $logFrame) {
this.battle = void 0;
this.animating = true;
this.acceleration = 1;
this.gen = 7;
this.mod = '';
this.activeCount = 1;
this.numericId = 0;
this.$frame = void 0;
this.$battle = null;
this.$options = null;
this.log = void 0;
this.$terrain = null;
this.$weather = null;
this.$bgEffect = null;
this.$bg = null;
this.$sprite = null;
this.$sprites = [null, null];
this.$spritesFront = [null, null];
this.$stat = null;
this.$fx = null;
this.$leftbar = null;
this.$rightbar = null;
this.$turn = null;
this.$messagebar = null;
this.$delay = null;
this.$hiddenMessage = null;
this.$tooltips = null;
this.tooltips = void 0;
this.sideConditions = [{}, {}];
this.preloadDone = 0;
this.preloadNeeded = 0;
this.bgm = null;
this.backdropImage = '';
this.bgmNum = 0;
this.preloadCache = {};
this.messagebarOpen = false;
this.customControls = false;
this.interruptionCount = 1;
this.curWeather = '';
this.curTerrain = '';
this.timeOffset = 0;
this.pokemonTimeOffset = 0;
this.minDelay = 0;
this.activeAnimations = $();
this.battle = battle;
$frame.addClass('battle');
this.$frame = $frame;
this.log = new BattleLog($logFrame[0], this);
this.log.battleParser.pokemonName = function (pokemonId) {
if (!pokemonId) return '';
if (battle.ignoreNicks || battle.ignoreOpponent) {
var pokemon = battle.getPokemon(pokemonId);
if (pokemon) return pokemon.speciesForme;
}
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 + '???';
};
var numericId = 0;
if (battle.id) {
numericId = parseInt(battle.id.slice(battle.id.lastIndexOf('-') + 1), 10);
if (this.battle.id.includes('digimon')) this.mod = 'digimon';
}
if (!numericId) {
numericId = Math.floor(Math.random() * 1000000);
}
this.numericId = numericId;
this.tooltips = new BattleTooltips(battle);
this.tooltips.listen($frame[0]);
this.preloadEffects();
}
var _proto = BattleScene.prototype;
_proto.
reset = function reset() {
this.updateGen();
if (this.$options) {
this.log.reset();
} else {
this.$options = $('<div class="battle-options"></div>');
$(this.log.elem).prepend(this.$options);
}
this.$frame.empty();
this.$battle = $('<div class="innerbattle"></div>');
this.$frame.append(this.$battle);
this.$bg = $('<div class="backdrop" style="background-image:url(' + Dex.resourcePrefix + this.backdropImage + ');display:block;opacity:0.8"></div>');
this.$terrain = $('<div class="weather"></div>');
this.$weather = $('<div class="weather"></div>');
this.$bgEffect = $('<div></div>');
this.$sprite = $('<div></div>');
this.$sprites = [$('<div></div>'), $('<div></div>')];
this.$spritesFront = [$('<div></div>'), $('<div></div>')];
this.$sprite.append(this.$sprites[1]);
this.$sprite.append(this.$spritesFront[1]);
this.$sprite.append(this.$spritesFront[0]);
this.$sprite.append(this.$sprites[0]);
this.$stat = $('<div role="complementary" aria-label="Active Pokemon"></div>');
this.$fx = $('<div></div>');
this.$leftbar = $('<div class="leftbar" role="complementary" aria-label="Your Team"></div>');
this.$rightbar = $('<div class="rightbar" role="complementary" aria-label="Opponent\'s Team"></div>');
this.$turn = $('<div></div>');
this.$messagebar = $('<div class="messagebar message"></div>');
this.$delay = $('<div></div>');
this.$hiddenMessage = $('<div class="message" style="position:absolute;display:block;visibility:hidden"></div>');
this.$tooltips = $('<div class="tooltips"></div>');
this.$battle.append(this.$bg);
this.$battle.append(this.$terrain);
this.$battle.append(this.$weather);
this.$battle.append(this.$bgEffect);
this.$battle.append(this.$sprite);
this.$battle.append(this.$stat);
this.$battle.append(this.$fx);
this.$battle.append(this.$leftbar);
this.$battle.append(this.$rightbar);
this.$battle.append(this.$turn);
this.$battle.append(this.$messagebar);
this.$battle.append(this.$delay);
this.$battle.append(this.$hiddenMessage);
this.$battle.append(this.$tooltips);
if (!this.animating) {
this.$battle.append('<div class="seeking"><strong>seeking...</strong></div>');
}
this.messagebarOpen = false;
this.timeOffset = 0;
this.pokemonTimeOffset = 0;
this.curTerrain = '';
this.curWeather = '';
this.log.battleParser.perspective = this.battle.mySide.sideid;
this.resetSides(true);
};
_proto.
animationOff = function animationOff() {
this.$battle.append('<div class="seeking"><strong>seeking...</strong></div>');
this.stopAnimation();
this.animating = false;
this.$messagebar.empty().css({
opacity: 0,
height: 0
});
};
_proto.
stopAnimation = function stopAnimation() {
this.interruptionCount++;
this.$battle.find(':animated').finish();
this.$fx.empty();
};
_proto.
animationOn = function animationOn() {
if (this.animating) return;
$.fx.off = false;
this.animating = true;
this.$battle.find('.seeking').remove();
this.updateSidebars();
for (var _i = 0, _this$battle$sides =
this.battle.sides; _i < _this$battle$sides.length; _i++) {
var side = _this$battle$sides[_i];
for (var _i2 = 0, _side$pokemon =
side.pokemon; _i2 < _side$pokemon.length; _i2++) {
var pokemon = _side$pokemon[_i2];
pokemon.sprite.reset(pokemon);
}
}
this.updateWeather(true);
this.resetTurn();
this.resetSideConditions();
};
_proto.
pause = function pause() {
var _this = this;
this.stopAnimation();
this.updateBgm();
if (this.battle.turn > 0) {
this.$frame.append('<div class="playbutton"><button name="play"><i class="fa fa-play icon-play"></i> Resume</button></div>');
} else {
this.$frame.append('<div class="playbutton"><button name="play"><i class="fa fa-play"></i> Play</button><br /><br /><button name="play-muted" class="startsoundchooser" style="font-size:10pt;display:none">Play (music off)</button></div>');
this.$frame.find('div.playbutton button[name=play-muted]').click(function () {
_this.setMute(true);
_this.battle.play();
});
}
this.$frame.find('div.playbutton button[name=play]').click(function () {
return _this.battle.play();
});
};
_proto.
resume = function resume() {
this.$frame.find('div.playbutton').remove();
this.updateBgm();
};
_proto.
setMute = function setMute(muted) {
BattleSound.setMute(muted);
};
_proto.
wait = function wait(time) {
if (!this.animating) return;
this.timeOffset += time;
};
_proto.
addSprite = function addSprite(sprite) {
if (sprite.$el) this.$sprites[+sprite.isFrontSprite].append(sprite.$el);
};
_proto.
showEffect = function showEffect(effect, start, end, transition, after) {
if (typeof effect === 'string') effect = BattleEffects[effect];
if (!start.time) start.time = 0;
if (!end.time) end.time = start.time + 500;
start.time += this.timeOffset;
end.time += this.timeOffset;
if (!end.scale && end.scale !== 0 && start.scale) end.scale = start.scale;
if (!end.xscale && end.xscale !== 0 && start.xscale) end.xscale = start.xscale;
if (!end.yscale && end.yscale !== 0 && start.yscale) end.yscale = start.yscale;
end = Object.assign({}, start, end);
var startpos = this.pos(start, effect);
var endpos = this.posT(end, effect, transition, start);
var $effect = $('<img src="' + effect.url + '" style="display:block;position:absolute" />');
this.$fx.append($effect);
$effect = this.$fx.children().last();
if (start.time) {
$effect.css(Object.assign({}, startpos, {
opacity: 0
}));
$effect.delay(start.time).animate({
opacity: startpos.opacity
},
1);
} else {
$effect.css(startpos);
}
$effect.animate(endpos, end.time - start.time);
if (after === 'fade') {
$effect.animate({
opacity: 0
},
100);
}
if (after === 'explode') {
if (end.scale) end.scale *= 3;
if (end.xscale) end.xscale *= 3;
if (end.yscale) end.yscale *= 3;
end.opacity = 0;
var endendpos = this.pos(end, effect);
$effect.animate(endendpos, 200);
}
this.waitFor($effect);
};
_proto.
backgroundEffect = function backgroundEffect(bg, duration) {
var opacity = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
var delay = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
var $effect = $('<div class="background"></div>');
$effect.css({
background: bg,
display: 'block',
opacity: 0
});
this.$bgEffect.append($effect);
$effect.delay(delay).animate({
opacity: opacity
},
250).delay(duration - 250);
$effect.animate({
opacity: 0
},
250);
};
_proto.
pos = function pos(loc, obj) {
loc = Object.assign({
x: 0,
y: 0,
z: 0,
scale: 1,
opacity: 1
},
loc);
if (!loc.xscale && loc.xscale !== 0) loc.xscale = loc.scale;
if (!loc.yscale && loc.yscale !== 0) loc.yscale = loc.scale;
var left = 210;
var top = 245;
var scale = obj.gen === 5 ?
2.0 - loc.z / 200 :
1.5 - 0.5 * (loc.z / 200);
if (scale < .1) scale = .1;
left += (410 - 190) * (loc.z / 200);
top += (135 - 245) * (loc.z / 200);
left += Math.floor(loc.x * scale);
top -= Math.floor(loc.y * scale);
var width = Math.floor(obj.w * scale * loc.xscale);
var height = Math.floor(obj.h * scale * loc.yscale);
var hoffset = Math.floor((obj.h - (obj.y || 0) * 2) * scale * loc.yscale);
left -= Math.floor(width / 2);
top -= Math.floor(hoffset / 2);
var pos = {
left: left,
top: top,
width: width,
height: height,
opacity: loc.opacity
};
if (loc.display) pos.display = loc.display;
return pos;
};
_proto.
posT = function posT(loc, obj, transition, oldLoc) {
var pos = this.pos(loc, obj);
var oldPos = oldLoc ? this.pos(oldLoc, obj) : null;
var transitionMap = {
left: 'linear',
top: 'linear',
width: 'linear',
height: 'linear',
opacity: 'linear'
};
if (transition === 'ballistic') {
transitionMap.top = pos.top < oldPos.top ? 'ballisticUp' : 'ballisticDown';
}
if (transition === 'ballisticUnder') {
transitionMap.top = pos.top < oldPos.top ? 'ballisticDown' : 'ballisticUp';
}
if (transition === 'ballistic2') {
transitionMap.top = pos.top < oldPos.top ? 'quadUp' : 'quadDown';
}
if (transition === 'ballistic2Back') {
transitionMap.top = loc.z > 0 ? 'quadUp' : 'quadDown';
}
if (transition === 'ballistic2Under') {
transitionMap.top = pos.top < oldPos.top ? 'quadDown' : 'quadUp';
}
if (transition === 'swing') {
transitionMap.left = 'swing';
transitionMap.top = 'swing';
transitionMap.width = 'swing';
transitionMap.height = 'swing';
}
if (transition === 'accel') {
transitionMap.left = 'quadDown';
transitionMap.top = 'quadDown';
transitionMap.width = 'quadDown';
transitionMap.height = 'quadDown';
}
if (transition === 'decel') {
transitionMap.left = 'quadUp';
transitionMap.top = 'quadUp';
transitionMap.width = 'quadUp';
transitionMap.height = 'quadUp';
}
return {
left: [pos.left, transitionMap.left],
top: [pos.top, transitionMap.top],
width: [pos.width, transitionMap.width],
height: [pos.height, transitionMap.height],
opacity: [pos.opacity, transitionMap.opacity]
};
};
_proto.
waitFor = function waitFor(elem) {
this.activeAnimations = this.activeAnimations.add(elem);
};
_proto.
startAnimations = function startAnimations() {
this.$fx.empty();
this.activeAnimations = $();
this.timeOffset = 0;
this.minDelay = 0;
};
_proto.
finishAnimations = function finishAnimations() {
if (this.minDelay || this.timeOffset) {
this.$delay.delay(Math.max(this.minDelay, this.timeOffset));
this.activeAnimations = this.activeAnimations.add(this.$delay);
}
if (!this.activeAnimations.length) return undefined;
return this.activeAnimations.promise();
};
_proto.
preemptCatchup = function preemptCatchup() {
this.log.preemptCatchup();
};
_proto.
message = function message(_message) {
var _this2 = this;
if (!this.messagebarOpen) {
this.log.addSpacer();
if (this.animating) {
this.$messagebar.empty();
this.$messagebar.css({
display: 'block',
opacity: 0,
height: 'auto'
});
this.$messagebar.animate({
opacity: 1
},
this.battle.messageFadeTime / this.acceleration);
}
}
if (this.battle.hardcoreMode && _message.slice(0, 8) === '<small>(') {
_message = '';
}
if (_message && this.animating) {
this.$hiddenMessage.append('<p></p>');
var $message = this.$hiddenMessage.children().last();
$message.html(_message);
$message.css({
display: 'block',
opacity: 0
});
$message.animate({
height: 'hide'
},
1,
function () {
$message.appendTo(_this2.$messagebar);
$message.animate({
height: 'show',
'padding-bottom': 4,
opacity: 1
},
_this2.battle.messageFadeTime / _this2.acceleration);
});
this.waitFor($message);
}
this.messagebarOpen = true;
};
_proto.
maybeCloseMessagebar = function maybeCloseMessagebar(args, kwArgs) {
if (this.log.battleParser.sectionBreak(args, kwArgs)) {
if (!this.messagebarOpen) return false;
this.closeMessagebar();
return true;
}
return false;
};
_proto.
closeMessagebar = function closeMessagebar() {
if (this.messagebarOpen) {
this.messagebarOpen = false;
if (this.animating) {
this.$messagebar.delay(this.battle.messageShownTime / this.acceleration).animate({
opacity: 0
},
this.battle.messageFadeTime / this.acceleration);
this.waitFor(this.$messagebar);
}
return true;
}
return false;
};
_proto.
runMoveAnim = function runMoveAnim(moveid, participants) {
if (!this.animating) return;
var animEntry = BattleMoveAnims[moveid];
if (this.acceleration >= 3) {
var targetsSelf = !participants[1] || participants[0] === participants[1];
var isSpecial = !targetsSelf && this.battle.dex.moves.get(moveid).category === 'Special';
animEntry = BattleOtherAnims[targetsSelf ? 'fastanimself' : isSpecial ? 'fastanimspecial' : 'fastanimattack'];
} else if (!animEntry) {
animEntry = BattleMoveAnims['tackle'];
}
animEntry.anim(this, participants.map(function (p) {
return p.sprite;
}));
};
_proto.
runOtherAnim = function runOtherAnim(moveid, participants) {
if (!this.animating) return;
BattleOtherAnims[moveid].anim(this, participants.map(function (p) {
return p.sprite;
}));
};
_proto.
runStatusAnim = function runStatusAnim(moveid, participants) {
if (!this.animating) return;
BattleStatusAnims[moveid].anim(this, participants.map(function (p) {
return p.sprite;
}));
};
_proto.
runResidualAnim = function runResidualAnim(moveid, pokemon) {
if (!this.animating) return;
BattleMoveAnims[moveid].residualAnim(this, [pokemon.sprite]);
};
_proto.
runPrepareAnim = function runPrepareAnim(moveid, attacker, defender) {
if (!this.animating || this.acceleration >= 3) return;
var moveAnim = BattleMoveAnims[moveid];
if (!moveAnim.prepareAnim) return;
moveAnim.prepareAnim(this, [attacker.sprite, defender.sprite]);
};
_proto.
updateGen = function updateGen() {
var _this$battle$nearSide;
var gen = this.battle.gen;
if (Dex.prefs('nopastgens')) gen = 6;
if (Dex.prefs('bwgfx') && gen > 5) gen = 5;
this.gen = gen;
this.activeCount = ((_this$battle$nearSide = this.battle.nearSide) == null ? void 0 : _this$battle$nearSide.active.length) || 1;
var isSPL = typeof this.battle.rated === 'string' && this.battle.rated.startsWith("Smogon Premier League");
var bg;
if (isSPL) {
if (gen <= 1) bg = 'fx/bg-gen1-spl.png';
else
if (gen <= 2) bg = 'fx/bg-gen2-spl.png';
else
if (gen <= 3) bg = 'fx/bg-gen3-spl.png';
else
if (gen <= 4) bg = 'fx/bg-gen4-spl.png';
else
bg = 'fx/bg-spl.png';
this.setBgm(-101);
} else {
if (gen <= 1) bg = 'fx/bg-gen1.png?';
else
if (gen <= 2) bg = 'fx/bg-gen2.png?';
else
if (gen <= 3) bg = 'fx/' + BattleBackdropsThree[this.numericId % BattleBackdropsThree.length] + '?';
else
if (gen <= 4) bg = 'fx/' + BattleBackdropsFour[this.numericId % BattleBackdropsFour.length];
else
if (gen <= 5) bg = 'fx/' + BattleBackdropsFive[this.numericId % BattleBackdropsFive.length];
else
bg = 'sprites/gen6bgs/' + BattleBackdrops[this.numericId % BattleBackdrops.length];
}
this.backdropImage = bg;
if (this.$bg) {
this.$bg.css('background-image', 'url(' + Dex.resourcePrefix + '' + this.backdropImage + ')');
}
};
_proto.
getDetailsText = function getDetailsText(pokemon) {
var _pokemon$side;
var name = (_pokemon$side = pokemon.side) != null && _pokemon$side.isFar && (
this.battle.ignoreOpponent || this.battle.ignoreNicks) ? pokemon.speciesForme : pokemon.name;
if (name !== pokemon.speciesForme) {
name += ' (' + pokemon.speciesForme + ')';
}
if (pokemon === pokemon.side.active[0]) {
name += ' (active)';
} else if (pokemon.fainted) {
name += ' (fainted)';
} else {
var statustext = '';
if (pokemon.hp !== pokemon.maxhp) {
statustext += pokemon.getHPText();
}
if (pokemon.status) {
if (statustext) statustext += '|';
statustext += pokemon.status;
}
if (statustext) {
name += ' (' + statustext + ')';
}
}
return BattleLog.escapeHTML(name);
};
_proto.
getSidebarHTML = function getSidebarHTML(side, posStr) {
var noShow = this.battle.hardcoreMode && this.battle.gen < 7;
var speciesOverage = this.battle.speciesClause ? Infinity : Math.max(side.pokemon.length - side.totalPokemon, 0);
var sidebarIcons =
[];
var speciesTable = [];
var zoroarkRevealed = false;
var hasIllusion = false;
if (speciesOverage) {
for (var i = 0; i < side.pokemon.length; i++) {
var species = side.pokemon[i].getBaseSpecies().baseSpecies;
if (speciesOverage && speciesTable.includes(species)) {
for (var _i3 = 0; _i3 <
sidebarIcons.length; _i3++) {
var sidebarIcon = sidebarIcons[_i3];
if (side.pokemon[sidebarIcon[1]].getBaseSpecies().baseSpecies === species) {
sidebarIcon[0] = 'pokemon-illusion';
}
}
hasIllusion = true;
speciesOverage--;
} else {
sidebarIcons.push(['pokemon', i]);
speciesTable.push(species);
if (['Zoroark', 'Zorua'].includes(species)) {
zoroarkRevealed = true;
}
}
}
} else {
for (var _i4 = 0; _i4 < side.pokemon.length; _i4++) {
sidebarIcons.push(['pokemon', _i4]);
}
}
if (!zoroarkRevealed && hasIllusion && sidebarIcons.length < side.totalPokemon) {
sidebarIcons.push(['pseudo-zoroark', null]);
}
while (sidebarIcons.length < side.totalPokemon) {
sidebarIcons.push(['unrevealed', null]);
}
while (sidebarIcons.length < 6) {
sidebarIcons.push(['empty', null]);
}
var pokemonhtml = '';
for (var _i5 = 0; _i5 < sidebarIcons.length; _i5++) {
var _sidebarIcons$_i = sidebarIcons[_i5],
iconType = _sidebarIcons$_i[0],
pokeIndex = _sidebarIcons$_i[1];
var poke = pokeIndex !== null ? side.pokemon[pokeIndex] : null;
var tooltipCode = " class=\"picon has-tooltip\" data-tooltip=\"pokemon|" + side.n + "|" + pokeIndex + (iconType === 'pokemon-illusion' ? '|illusion' : '') + "\"";
if (iconType === 'empty') {
pokemonhtml += "<span class=\"picon\" style=\"" + Dex.getPokemonIcon('pokeball-none') + "\"></span>";
} else if (noShow) {
if (poke != null && poke.fainted) {
pokemonhtml += "<span" + tooltipCode + " style=\"" + Dex.getPokemonIcon('pokeball-fainted') + "\" aria-label=\"Fainted\"></span>";
} else if (poke != null && poke.status) {
pokemonhtml += "<span" + tooltipCode + " style=\"" + Dex.getPokemonIcon('pokeball-statused') + "\" aria-label=\"Statused\"></span>";
} else {
pokemonhtml += "<span" + tooltipCode + " style=\"" + Dex.getPokemonIcon('pokeball') + "\" aria-label=\"Non-statused\"></span>";
}
} else if (iconType === 'pseudo-zoroark') {
pokemonhtml += "<span class=\"picon\" style=\"" + Dex.getPokemonIcon('zoroark') + "\" title=\"Unrevealed Illusion user\" aria-label=\"Unrevealed Illusion user\"></span>";
} else if (!poke) {
pokemonhtml += "<span class=\"picon\" style=\"" + Dex.getPokemonIcon('pokeball') + "\" title=\"Not revealed\" aria-label=\"Not revealed\"></span>";
} else if (!poke.ident && this.battle.teamPreviewCount && this.battle.teamPreviewCount < side.pokemon.length) {
var details = this.getDetailsText(poke);
pokemonhtml += "<span" + tooltipCode + " style=\"" + Dex.getPokemonIcon(poke, !side.isFar) + (";opacity:0.6\" aria-label=\"" + details + "\"></span>");
} else {
var _details = this.getDetailsText(poke);
pokemonhtml += "<span" + tooltipCode + " style=\"" + Dex.getPokemonIcon(poke, !side.isFar) + ("\" aria-label=\"" + _details + "\"></span>");
}
if (_i5 % 3 === 2) pokemonhtml += "</div><div class=\"teamicons\">";
}
pokemonhtml = '<div class="teamicons">' + pokemonhtml + '</div>';
var ratinghtml = side.rating ? " title=\"Rating: " + BattleLog.escapeHTML(side.rating) + "\"" : "";
var faded = side.name ? "" : " style=\"opacity: 0.4\"";
return "<div class=\"trainer trainer-" + posStr + "\"" + faded + "><strong>" + BattleLog.escapeHTML(side.name) + "</strong><div class=\"trainersprite\"" + ratinghtml + " style=\"background-image:url(" + Dex.resolveAvatar(side.avatar) + ")\"></div>" + pokemonhtml + "</div>";
};
_proto.
updateSidebar = function updateSidebar(side) {
if (this.battle.gameType === 'freeforall') {
this.updateLeftSidebar();
this.updateRightSidebar();
} else if (side === this.battle.nearSide || side === this.battle.nearSide.ally) {
this.updateLeftSidebar();
} else {
this.updateRightSidebar();
}
};
_proto.
updateLeftSidebar = function updateLeftSidebar() {
var side = this.battle.nearSide;
if (side.ally) {
var side2 = side.ally;
this.$leftbar.html(this.getSidebarHTML(side, 'near2') + this.getSidebarHTML(side2, 'near'));
} else if (this.battle.sides.length > 2) {
var _side = this.battle.sides[side.n === 0 ? 3 : 2];
this.$leftbar.html(this.getSidebarHTML(_side, 'near2') + this.getSidebarHTML(side, 'near'));
} else {
this.$leftbar.html(this.getSidebarHTML(side, 'near'));
}
};
_proto.
updateRightSidebar = function updateRightSidebar() {
var side = this.battle.farSide;
if (side.ally) {
var side2 = side.ally;
this.$rightbar.html(this.getSidebarHTML(side, 'far2') + this.getSidebarHTML(side2, 'far'));
} else if (this.battle.sides.length > 2) {
var _side2 = this.battle.sides[side.n === 0 ? 3 : 2];
this.$rightbar.html(this.getSidebarHTML(_side2, 'far2') + this.getSidebarHTML(side, 'far'));
} else {
this.$rightbar.html(this.getSidebarHTML(side, 'far'));
}
};
_proto.
updateSidebars = function updateSidebars() {
this.updateLeftSidebar();
this.updateRightSidebar();
};
_proto.
updateStatbars = function updateStatbars() {
for (var _i6 = 0, _this$battle$sides2 =
this.battle.sides; _i6 < _this$battle$sides2.length; _i6++) {
var side = _this$battle$sides2[_i6];
for (var _i7 = 0, _side$active =
side.active; _i7 < _side$active.length; _i7++) {
var active = _side$active[_i7];
if (active) active.sprite.updateStatbar(active);
}
}
};
_proto.
resetSides = function resetSides(skipEmpty) {
if (!skipEmpty) {
for (var _i8 = 0, _this$$sprites =
this.$sprites; _i8 < _this$$sprites.length; _i8++) {
var $spritesContainer = _this$$sprites[_i8];
$spritesContainer.empty();
}
}
for (var _i9 = 0, _this$battle$sides3 =
this.battle.sides; _i9 < _this$battle$sides3.length; _i9++) {
var _side$missedPokemon, _side$missedPokemon$s;
var side = _this$battle$sides3[_i9];
side.z = side.isFar ? 200 : 0;
(_side$missedPokemon = side.missedPokemon) == null ? void 0 : (_side$missedPokemon$s = _side$missedPokemon.sprite) == null ? void 0 : _side$missedPokemon$s.destroy();
side.missedPokemon = {
sprite: new PokemonSprite(null, {
x: side.leftof(-100),
y: side.y,
z: side.z,
opacity: 0
},
this, side.isFar)
};
side.missedPokemon.sprite.isMissedPokemon = true;
}
if (this.battle.sides.length > 2 && this.sideConditions.length === 2) {
this.sideConditions.push({}, {});
}
this.rebuildTooltips();
};
_proto.
rebuildTooltips = function rebuildTooltips() {
var tooltipBuf = '';
var tooltips = this.battle.gameType === 'freeforall' ? {
p2b: {
top: 70,
left: 250,
width: 80,
height: 100,
tooltip: 'activepokemon|1|1'
},
p2a: {
top: 90,
left: 390,
width: 100,
height: 100,
tooltip: 'activepokemon|1|0'
},
p1a: {
top: 200,
left: 130,
width: 120,
height: 160,
tooltip: 'activepokemon|0|0'
},
p1b: {
top: 200,
left: 350,
width: 150,
height: 160,
tooltip: 'activepokemon|0|1'
}
} : {
p2c: {
top: 70,
left: 250,
width: 80,
height: 100,
tooltip: 'activepokemon|1|2'
},
p2b: {
top: 85,
left: 320,
width: 90,
height: 100,
tooltip: 'activepokemon|1|1'
},
p2a: {
top: 90,
left: 390,
width: 100,
height: 100,
tooltip: 'activepokemon|1|0'
},
p1a: {
top: 200,
left: 130,
width: 120,
height: 160,
tooltip: 'activepokemon|0|0'
},
p1b: {
top: 200,
left: 250,
width: 150,
height: 160,
tooltip: 'activepokemon|0|1'
},
p1c: {
top: 200,
left: 350,
width: 150,
height: 160,
tooltip: 'activepokemon|0|2'
}
};
for (var _id in tooltips) {
var layout = tooltips[_id];
tooltipBuf += "<div class=\"has-tooltip\" style=\"position:absolute;";
tooltipBuf += "top:" + layout.top + "px;left:" + layout.left + "px;width:" + layout.width + "px;height:" + layout.height + "px;";
tooltipBuf += "\" data-id=\"" + _id + "\" data-tooltip=\"" + layout.tooltip + "\" data-ownheight=\"1\"></div>";
}
this.$tooltips.html(tooltipBuf);
};
_proto.
teamPreview = function teamPreview() {
var newBGNum = 0;
for (var siden = 0; siden < 2 || this.battle.gameType === 'multi' && siden < 4; siden++) {
var side = this.battle.sides[siden];
var spriteIndex = +this.battle.sidesSwitched ^ siden % 2;
var textBuf = '';
var buf = '';
var buf2 = '';
this.$sprites[spriteIndex].empty();
var ludicoloCount = 0;
var lombreCount = 0;
for (var i = 0; i < side.pokemon.length; i++) {
var pokemon = side.pokemon[i];
if (pokemon.speciesForme === 'Xerneas-*') {
pokemon.speciesForme = 'Xerneas-Neutral';
}
if (pokemon.speciesForme === 'Ludicolo') ludicoloCount++;
if (pokemon.speciesForme === 'Lombre') lombreCount++;
var spriteData = Dex.getSpriteData(pokemon, !!spriteIndex, {
gen: this.gen,
noScale: true,
mod: this.mod
});
var y = 0;
var x = 0;
if (spriteIndex) {
y = 48 + 50 + 3 * (i + 6 - side.pokemon.length);
x = 48 + 180 + 50 * (i + 6 - side.pokemon.length);
} else {
y = 48 + 200 + 3 * i;
x = 48 + 100 + 50 * i;
}
if (textBuf) textBuf += ' / ';
textBuf += pokemon.speciesForme;
var _url = spriteData.url;
buf += '<img src="' + _url + '" width="' + spriteData.w + '" height="' + spriteData.h + '" style="position:absolute;top:' + Math.floor(y - spriteData.h / 2) + 'px;left:' + Math.floor(x - spriteData.w / 2) + 'px" />';
buf2 += '<div style="position:absolute;top:' + (y + 45) + 'px;left:' + (x - 40) + 'px;width:80px;font-size:10px;text-align:center;color:#FFF;">';
var gender = pokemon.gender;
if (gender === 'M' || gender === 'F') {
buf2 += "<img src=\"" + Dex.fxPrefix + "gender-" + gender.toLowerCase() + ".png\" alt=\"" + gender + "\" width=\"7\" height=\"10\" class=\"pixelated\" style=\"margin-bottom:-1px\" /> ";
}
if (pokemon.level !== 100) {
buf2 += '<span style="text-shadow:#000 1px 1px 0,#000 1px -1px 0,#000 -1px 1px 0,#000 -1px -1px 0"><small>L</small>' + pokemon.level + '</span>';
}
if (pokemon.item === '(mail)') {
buf2 += ' <img src="' + Dex.resourcePrefix + 'fx/mail.png" width="8" height="10" alt="F" style="margin-bottom:-1px" />';
} else if (pokemon.item) {
buf2 += ' <img src="' + Dex.resourcePrefix + 'fx/item.png" width="8" height="10" alt="F" style="margin-bottom:-1px" />';
}
buf2 += '</div>';
}
side.totalPokemon = side.pokemon.length;
if (textBuf) {
this.log.addDiv('chat battle-history',
'<strong>' + BattleLog.escapeHTML(side.name) + '\'s team:</strong> <em style="color:#445566;display:block;">' + BattleLog.escapeHTML(textBuf) + '</em>');
}
this.$sprites[spriteIndex].html(buf + buf2);
if (!newBGNum) {
if (ludicoloCount >= 2) {
newBGNum = -3;
} else if (ludicoloCount + lombreCount >= 2) {
newBGNum = -2;
}
}
}
if (newBGNum !== 0) {
this.setBgm(newBGNum);
}
this.wait(1000);
this.updateSidebars();
};
_proto.
showJoinButtons = function showJoinButtons() {
if (!this.battle.joinButtons) return;
if (this.battle.ended || this.battle.rated) return;
if (!this.battle.p1.name) {
this.$battle.append('<div class="playbutton1"><button name="joinBattle">Join Battle</button></div>');
}
if (!this.battle.p2.name) {
this.$battle.append('<div class="playbutton2"><button name="joinBattle">Join Battle</button></div>');
}
};
_proto.
hideJoinButtons = function hideJoinButtons() {
if (!this.battle.joinButtons) return;
this.$battle.find('.playbutton1, .playbutton2').remove();
};
_proto.
pseudoWeatherLeft = function pseudoWeatherLeft(pWeather) {
var buf = '<br />' + Dex.moves.get(pWeather[0]).name;
if (!pWeather[1] && pWeather[2]) {
pWeather[1] = pWeather[2];
pWeather[2] = 0;
}
if (this.battle.gen < 7 && this.battle.hardcoreMode) return buf;
if (pWeather[2]) {
return buf + ' <small>(' + pWeather[1] + ' or ' + pWeather[2] + ' turns)</small>';
}
if (pWeather[1]) {
return buf + ' <small>(' + pWeather[1] + ' turn' + (pWeather[1] === 1 ? '' : 's') + ')</small>';
}
return buf;
};
_proto.
sideConditionLeft = function sideConditionLeft(cond, isFoe, all) {
if (!cond[2] && !cond[3] && !all) return '';
var buf = "<br />" + (isFoe && !all ? "Foe's " : "") + Dex.moves.get(cond[0]).name;
if (this.battle.gen < 7 && this.battle.hardcoreMode) return buf;
if (!cond[2] && !cond[3]) return buf;
if (!cond[2] && cond[3]) {
cond[2] = cond[3];
cond[3] = 0;
}
if (!cond[3]) {
return buf + ' <small>(' + cond[2] + ' turn' + (cond[2] === 1 ? '' : 's') + ')</small>';
}
return buf + ' <small>(' + cond[2] + ' or ' + cond[3] + ' turns)</small>';
};
_proto.
weatherLeft = function weatherLeft() {
if (this.battle.gen < 7 && this.battle.hardcoreMode) return '';
var weatherhtml = "";
if (this.battle.weather) {
var weatherNameTable = {
sunnyday: 'Sun',
desolateland: 'Intense Sun',
raindance: 'Rain',
primordialsea: 'Heavy Rain',
sandstorm: 'Sandstorm',
hail: 'Hail',
deltastream: 'Strong Winds'
};
weatherhtml = "" + (weatherNameTable[this.battle.weather] || this.battle.weather);
if (this.battle.weatherMinTimeLeft !== 0) {
weatherhtml += " <small>(" + this.battle.weatherMinTimeLeft + " or " + this.battle.weatherTimeLeft + " turns)</small>";
} else if (this.battle.weatherTimeLeft !== 0) {
weatherhtml += " <small>(" + this.battle.weatherTimeLeft + " turn" + (this.battle.weatherTimeLeft === 1 ? '' : 's') + ")</small>";
}
var nullifyWeather = this.battle.abilityActive(['Air Lock', 'Cloud Nine']);
weatherhtml = "" + (nullifyWeather ? '<s>' : '') + weatherhtml + (nullifyWeather ? '</s>' : '');
}
for (var _i10 = 0, _this$battle$pseudoWe =
this.battle.pseudoWeather; _i10 < _this$battle$pseudoWe.length; _i10++) {
var pseudoWeather = _this$battle$pseudoWe[_i10];
weatherhtml += this.pseudoWeatherLeft(pseudoWeather);
}
return weatherhtml;
};
_proto.
sideConditionsLeft = function sideConditionsLeft(side, all) {
var buf = "";
for (var _id2 in side.sideConditions) {
buf += this.sideConditionLeft(side.sideConditions[_id2], side.isFar, all);
}
return buf;
};
_proto.
upkeepWeather = function upkeepWeather() {
var isIntense = ['desolateland', 'primordialsea', 'deltastream'].includes(this.curWeather);
this.$weather.animate({
opacity: 1.0
},
300).animate({
opacity: isIntense ? 0.9 : 0.5
},
300);
};
_proto.
updateWeather = function updateWeather(instant) {
var _this3 = this;
if (!this.animating) return;
var isIntense = false;
var weather = this.battle.weather;
if (this.battle.abilityActive(['Air Lock', 'Cloud Nine'])) {
weather = '';
}
var terrain = '';
for (var _i11 = 0, _this$battle$pseudoWe2 =
this.battle.pseudoWeather; _i11 < _this$battle$pseudoWe2.length; _i11++) {
var pseudoWeatherData = _this$battle$pseudoWe2[_i11];
var pwid = toID(pseudoWeatherData[0]);
switch (pwid) {
case 'electricterrain':
case 'grassyterrain':
case 'mistyterrain':
case 'psychicterrain':
terrain = pwid;
break;
default:
if (!terrain) terrain = 'pseudo';
break;
}
}
if (weather === 'desolateland' || weather === 'primordialsea' || weather === 'deltastream') {
isIntense = true;
}
var weatherhtml = this.weatherLeft();
for (var _i12 = 0, _this$battle$sides4 =
this.battle.sides; _i12 < _this$battle$sides4.length; _i12++) {
var side = _this$battle$sides4[_i12];
weatherhtml += this.sideConditionsLeft(side);
}
if (weatherhtml) weatherhtml = "<br />" + weatherhtml;
if (instant) {
this.$weather.html('<em>' + weatherhtml + '</em>');
if (this.curWeather === weather && this.curTerrain === terrain) return;
this.$terrain.attr('class', terrain ? 'weather ' + terrain + 'weather' : 'weather');
this.curTerrain = terrain;
this.$weather.attr('class', weather ? 'weather ' + weather + 'weather' : 'weather');
this.$weather.css('opacity', isIntense || !weather ? 0.9 : 0.5);
this.curWeather = weather;
return;
}
if (weather !== this.curWeather) {
this.$weather.animate({
opacity: 0
},
this.curWeather ? 300 : 100,
function () {
_this3.$weather.html('<em>' + weatherhtml + '</em>');
_this3.$weather.attr('class', weather ? 'weather ' + weather + 'weather' : 'weather');
_this3.$weather.animate({
opacity: isIntense || !weather ? 0.9 : 0.5
}, 300);
});
this.curWeather = weather;
} else {
this.$weather.html('<em>' + weatherhtml + '</em>');
}
if (terrain !== this.curTerrain) {
this.$terrain.animate({
top: 360,
opacity: 0
},
this.curTerrain ? 400 : 1,
function () {
_this3.$terrain.attr('class', terrain ? 'weather ' + terrain + 'weather' : 'weather');
_this3.$terrain.animate({
top: 0,
opacity: 1
}, 400);
});
this.curTerrain = terrain;
}
};
_proto.
resetTurn = function resetTurn() {
if (this.battle.turn <= 0) {
this.$turn.html('');
return;
}
this.$turn.html('<div class="turn has-tooltip" data-tooltip="field" data-ownheight="1">Turn ' + this.battle.turn + '</div>');
};
_proto.
incrementTurn = function incrementTurn() {
if (!this.animating) return;
var turn = this.battle.turn;
if (turn <= 0) return;
var $prevTurn = this.$turn.children();
var $newTurn = $('<div class="turn has-tooltip" data-tooltip="field" data-ownheight="1">Turn ' + turn + '</div>');
$newTurn.css({
opacity: 0,
left: 160
});
this.$turn.append($newTurn);
$newTurn.animate({
opacity: 1,
left: 110
},
500).animate({
opacity: .4
},
1500);
$prevTurn.animate({
opacity: 0,
left: 60
},
500,
function () {
$prevTurn.remove();
});
this.updateAcceleration();
this.wait(500 / this.acceleration);
};
_proto.
updateAcceleration = function updateAcceleration() {
if (this.battle.turnsSinceMoved > 2) {
this.acceleration = (this.battle.messageFadeTime < 150 ? 2 : 1) * Math.min(this.battle.turnsSinceMoved - 1, 3);
} else {
this.acceleration = this.battle.messageFadeTime < 150 ? 2 : 1;
if (this.battle.messageFadeTime < 50) this.acceleration = 3;
}
};
_proto.
addPokemonSprite = function addPokemonSprite(pokemon) {
var sprite = new PokemonSprite(Dex.getSpriteData(pokemon, pokemon.side.isFar, {
gen: this.gen,
mod: this.mod
}), {
x: pokemon.side.x,
y: pokemon.side.y,
z: pokemon.side.z,
opacity: 0
},
this, pokemon.side.isFar);
if (sprite.$el) this.$sprites[+pokemon.side.isFar].append(sprite.$el);
return sprite;
};
_proto.
addSideCondition = function addSideCondition(siden, id, instant) {
if (!this.animating) return;
var side = this.battle.sides[siden];
var spriteIndex = +side.isFar;
switch (id) {
case 'auroraveil':
var auroraveil = new Sprite(BattleEffects.auroraveil, {
display: 'block',
x: side.x,
y: side.y,
z: side.behind(-14),
xscale: 1,
yscale: 0,
opacity: 0.1
},
this);
this.$spritesFront[spriteIndex].append(auroraveil.$el);
this.sideConditions[siden][id] = [auroraveil];
auroraveil.anim({
opacity: 0.7,
time: instant ? 0 : 400
}).
anim({
opacity: 0.3,
time: instant ? 0 : 300
});
break;
case 'reflect':
var reflect = new Sprite(BattleEffects.reflect, {
display: 'block',
x: side.x,
y: side.y,
z: side.behind(-17),
xscale: 1,
yscale: 0,
opacity: 0.1
},
this);
this.$spritesFront[spriteIndex].append(reflect.$el);
this.sideConditions[siden][id] = [reflect];
reflect.anim({
opacity: 0.7,
time: instant ? 0 : 400
}).
anim({
opacity: 0.3,
time: instant ? 0 : 300
});
break;
case 'safeguard':
var safeguard = new Sprite(BattleEffects.safeguard, {
display: 'block',
x: side.x,
y: side.y,
z: side.behind(-20),
xscale: 1,
yscale: 0,
opacity: 0.1
},
this);
this.$spritesFront[spriteIndex].append(safeguard.$el);
this.sideConditions[siden][id] = [safeguard];
safeguard.anim({
opacity: 0.7,
time: instant ? 0 : 400
}).
anim({
opacity: 0.3,
time: instant ? 0 : 300
});
break;
case 'lightscreen':
var lightscreen = new Sprite(BattleEffects.lightscreen, {
display: 'block',
x: side.x,
y: side.y,
z: side.behind(-23),
xscale: 1,
yscale: 0,
opacity: 0.1
},
this);
this.$spritesFront[spriteIndex].append(lightscreen.$el);
this.sideConditions[siden][id] = [lightscreen];
lightscreen.anim({
opacity: 0.7,
time: instant ? 0 : 400
}).
anim({
opacity: 0.3,
time: instant ? 0 : 300
});
break;
case 'mist':
var mist = new Sprite(BattleEffects.mist, {
display: 'block',
x: side.x,
y: side.y,
z: side.behind(-27),
xscale: 1,
yscale: 0,
opacity: 0.1
},
this);
this.$spritesFront[spriteIndex].append(mist.$el);
this.sideConditions[siden][id] = [mist];
mist.anim({
opacity: 0.7,
time: instant ? 0 : 400
}).
anim({
opacity: 0.3,
time: instant ? 0 : 300
});
break;
case 'stealthrock':
var rock1 = new Sprite(BattleEffects.rock1, {
display: 'block',
x: side.leftof(-40),
y: side.y - 10,
z: side.z,
opacity: 0.5,
scale: 0.2
},
this);
var rock2 = new Sprite(BattleEffects.rock2, {
display: 'block',
x: side.leftof(-20),
y: side.y - 40,
z: side.z,
opacity: 0.5,
scale: 0.2
},
this);
var rock3 = new Sprite(BattleEffects.rock1, {
display: 'block',
x: side.leftof(30),
y: side.y - 20,
z: side.z,
opacity: 0.5,
scale: 0.2
},
this);
var rock4 = new Sprite(BattleEffects.rock2, {
display: 'block',
x: side.leftof(10),
y: side.y - 30,
z: side.z,
opacity: 0.5,
scale: 0.2
},
this);
this.$spritesFront[spriteIndex].append(rock1.$el);
this.$spritesFront[spriteIndex].append(rock2.$el);
this.$spritesFront[spriteIndex].append(rock3.$el);
this.$spritesFront[spriteIndex].append(rock4.$el);
this.sideConditions[siden][id] = [rock1, rock2, rock3, rock4];
break;
case 'gmaxsteelsurge':
var surge1 = new Sprite(BattleEffects.greenmetal1, {
display: 'block',
x: side.leftof(-30),
y: side.y - 20,
z: side.z,
opacity: 0.5,
scale: 0.8
},
this);
var surge2 = new Sprite(BattleEffects.greenmetal2, {
display: 'block',
x: side.leftof(35),
y: side.y - 15,
z: side.z,
opacity: 0.5,
scale: 0.8
},
this);
var surge3 = new Sprite(BattleEffects.greenmetal1, {
display: 'block',
x: side.leftof(50),
y: side.y - 10,
z: side.z,
opacity: 0.5,
scale: 0.8
},
this);
this.$spritesFront[spriteIndex].append(surge1.$el);
this.$spritesFront[spriteIndex].append(surge2.$el);
this.$spritesFront[spriteIndex].append(surge3.$el);
this.sideConditions[siden][id] = [surge1, surge2, surge3];
break;
case 'spikes':
var spikeArray = this.sideConditions[siden]['spikes'];
if (!spikeArray) {
spikeArray = [];
this.sideConditions[siden]['spikes'] = spikeArray;
}
var levels = this.battle.sides[siden].sideConditions['spikes'][1];
if (spikeArray.length < 1 && levels >= 1) {
var spike1 = new Sprite(BattleEffects.caltrop, {
display: 'block',
x: side.x - 25,
y: side.y - 40,
z: side.z,
scale: 0.3
},
this);
this.$spritesFront[spriteIndex].append(spike1.$el);
spikeArray.push(spike1);
}
if (spikeArray.length < 2 && levels >= 2) {
var spike2 = new Sprite(BattleEffects.caltrop, {
display: 'block',
x: side.x + 30,
y: side.y - 45,
z: side.z,
scale: .3
},
this);
this.$spritesFront[spriteIndex].append(spike2.$el);
spikeArray.push(spike2);
}
if (spikeArray.length < 3 && levels >= 3) {
var spike3 = new Sprite(BattleEffects.caltrop, {
display: 'block',
x: side.x + 50,
y: side.y - 40,
z: side.z,
scale: .3
},
this);
this.$spritesFront[spriteIndex].append(spike3.$el);
spikeArray.push(spike3);
}
break;
case 'toxicspikes':
var tspikeArray = this.sideConditions[siden]['toxicspikes'];
if (!tspikeArray) {
tspikeArray = [];
this.sideConditions[siden]['toxicspikes'] = tspikeArray;
}
var tspikeLevels = this.battle.sides[siden].sideConditions['toxicspikes'][1];
if (tspikeArray.length < 1 && tspikeLevels >= 1) {
var tspike1 = new Sprite(BattleEffects.poisoncaltrop, {
display: 'block',
x: side.x + 5,
y: side.y - 40,
z: side.z,
scale: 0.3
},
this);
this.$spritesFront[spriteIndex].append(tspike1.$el);
tspikeArray.push(tspike1);
}
if (tspikeArray.length < 2 && tspikeLevels >= 2) {
var tspike2 = new Sprite(BattleEffects.poisoncaltrop, {
display: 'block',
x: side.x - 15,
y: side.y - 35,
z: side.z,
scale: .3
},
this);
this.$spritesFront[spriteIndex].append(tspike2.$el);
tspikeArray.push(tspike2);
}
break;
case 'stickyweb':
var web = new Sprite(BattleEffects.web, {
display: 'block',
x: side.x + 15,
y: side.y - 35,
z: side.z,
opacity: 0.4,
scale: 0.7
},
this);
this.$spritesFront[spriteIndex].append(web.$el);
this.sideConditions[siden][id] = [web];
break;
}
};
_proto.
removeSideCondition = function removeSideCondition(siden, id) {
if (!this.animating) return;
if (this.sideConditions[siden][id]) {
for (var _i13 = 0, _this$sideConditions$ =
this.sideConditions[siden][id]; _i13 < _this$sideConditions$.length; _i13++) {
var sprite = _this$sideConditions$[_i13];
sprite.destroy();
}
delete this.sideConditions[siden][id];
}
};
_proto.
resetSideConditions = function resetSideConditions() {
for (var siden = 0; siden < this.sideConditions.length; siden++) {
for (var _id3 in this.sideConditions[siden]) {
this.removeSideCondition(siden, _id3);
}
for (var _id4 in this.battle.sides[siden].sideConditions) {
this.addSideCondition(siden, _id4, true);
}
}
};
_proto.
typeAnim = function typeAnim(pokemon, types) {
var result = BattleLog.escapeHTML(types).split('/').map(function (type) {
return (
'<img src="' + Dex.resourcePrefix + 'sprites/types/' + type + '.png" alt="' + type + '" class="pixelated" />');
}).
join(' ');
this.resultAnim(pokemon, result, 'neutral');
};
_proto.
resultAnim = function resultAnim(pokemon, result, type) {
if (!this.animating) return;
var $effect = $('<div class="result ' + type + 'result"><strong>' + result + '</strong></div>');
this.$fx.append($effect);
$effect.delay(this.timeOffset).css({
display: 'block',
opacity: 0,
top: pokemon.sprite.top - 5,
left: pokemon.sprite.left - 75
}).
animate({
opacity: 1
},
1);
$effect.animate({
opacity: 0,
top: pokemon.sprite.top - 65
},
1000, 'swing');
this.wait(this.acceleration < 2 ? 350 : 250);
pokemon.sprite.updateStatbar(pokemon);
if (this.acceleration < 3) this.waitFor($effect);
};
_proto.
abilityActivateAnim = function abilityActivateAnim(pokemon, result) {
if (!this.animating) return;
this.$fx.append('<div class="result abilityresult"><strong>' + result + '</strong></div>');
var $effect = this.$fx.children().last();
$effect.delay(this.timeOffset).css({
display: 'block',
opacity: 0,
top: pokemon.sprite.top + 15,
left: pokemon.sprite.left - 75
}).
animate({
opacity: 1
},
1);
$effect.delay(800).animate({
opacity: 0
},
400, 'swing');
this.wait(100);
pokemon.sprite.updateStatbar(pokemon);
if (this.acceleration < 3) this.waitFor($effect);
};
_proto.
damageAnim = function damageAnim(pokemon, damage) {
if (!this.animating) return;
if (!pokemon.sprite.$statbar) return;
pokemon.sprite.updateHPText(pokemon);
var $hp = pokemon.sprite.$statbar.find('div.hp');
var w = pokemon.hpWidth(150);
var hpcolor = BattleScene.getHPColor(pokemon);
var callback;
if (hpcolor === 'y') {
callback = function () {
$hp.addClass('hp-yellow');
};
}
if (hpcolor === 'r') {
callback = function () {
$hp.addClass('hp-yellow hp-red');
};
}
if (damage === '100%' && pokemon.hp > 0) damage = '99%';
this.resultAnim(pokemon, this.battle.hardcoreMode ? 'Damage' : '−' + damage, 'bad');
$hp.animate({
width: w,
'border-right-width': w ? 1 : 0
},
350, callback);
};
_proto.
healAnim = function healAnim(pokemon, damage) {
if (!this.animating) return;
if (!pokemon.sprite.$statbar) return;
pokemon.sprite.updateHPText(pokemon);
var $hp = pokemon.sprite.$statbar.find('div.hp');
var w = pokemon.hpWidth(150);
var hpcolor = BattleScene.getHPColor(pokemon);
var callback;
if (hpcolor === 'g') {
callback = function () {
$hp.removeClass('hp-yellow hp-red');
};
}
if (hpcolor === 'y') {
callback = function () {
$hp.removeClass('hp-red');
};
}
this.resultAnim(pokemon, this.battle.hardcoreMode ? 'Heal' : '+' + damage, 'good');
$hp.animate({
width: w,
'border-right-width': w ? 1 : 0
},
350, callback);
};
_proto.
removeEffect = function removeEffect(pokemon, id, instant) {
return pokemon.sprite.removeEffect(id, instant);
};
_proto.
addEffect = function addEffect(pokemon, id, instant) {
return pokemon.sprite.addEffect(id, instant);
};
_proto.
animSummon = function animSummon(pokemon, slot, instant) {
return pokemon.sprite.animSummon(pokemon, slot, instant);
};
_proto.
animUnsummon = function animUnsummon(pokemon, instant) {
return pokemon.sprite.animUnsummon(pokemon, instant);
};
_proto.
animDragIn = function animDragIn(pokemon, slot) {
return pokemon.sprite.animDragIn(pokemon, slot);
};
_proto.
animDragOut = function animDragOut(pokemon) {
return pokemon.sprite.animDragOut(pokemon);
};
_proto.
updateStatbar = function updateStatbar(pokemon, updatePrevhp, updateHp) {
return pokemon.sprite.updateStatbar(pokemon, updatePrevhp, updateHp);
};
_proto.
updateStatbarIfExists = function updateStatbarIfExists(pokemon, updatePrevhp, updateHp) {
return pokemon.sprite.updateStatbarIfExists(pokemon, updatePrevhp, updateHp);
};
_proto.
animTransform = function animTransform(pokemon, isCustomAnim, isPermanent) {
return pokemon.sprite.animTransform(pokemon, isCustomAnim, isPermanent);
};
_proto.
clearEffects = function clearEffects(pokemon) {
return pokemon.sprite.clearEffects();
};
_proto.
removeTransform = function removeTransform(pokemon) {
return pokemon.sprite.removeTransform();
};
_proto.
animFaint = function animFaint(pokemon) {
return pokemon.sprite.animFaint(pokemon);
};
_proto.
animReset = function animReset(pokemon) {
return pokemon.sprite.animReset();
};
_proto.
anim = function anim(pokemon, end, transition) {
return pokemon.sprite.anim(end, transition);
};
_proto.
beforeMove = function beforeMove(pokemon) {
return pokemon.sprite.beforeMove();
};
_proto.
afterMove = function afterMove(pokemon) {
return pokemon.sprite.afterMove();
};
_proto.
setFrameHTML = function setFrameHTML(html) {
this.customControls = true;
this.$frame.html(html);
};
_proto.
setControlsHTML = function setControlsHTML(html) {
this.customControls = true;
var $controls = this.$frame.parent().children('.battle-controls');
$controls.html(html);
};
_proto.
preloadImage = function preloadImage(url) {
var _this4 = this;
var token = url.replace(/\.(gif|png)$/, '').replace(/\//g, '-');
if (this.preloadCache[token]) {
return;
}
this.preloadNeeded++;
this.preloadCache[token] = new Image();
this.preloadCache[token].onload = function () {
_this4.preloadDone++;
};
this.preloadCache[token].src = url;
};
_proto.
preloadEffects = function preloadEffects() {
for (var i in BattleEffects) {
if (i === 'alpha' || i === 'omega') continue;
var _url2 = BattleEffects[i].url;
if (_url2) this.preloadImage(_url2);
}
this.preloadImage(Dex.resourcePrefix + 'sprites/ani/substitute.gif');
this.preloadImage(Dex.resourcePrefix + 'sprites/ani-back/substitute.gif');
};
_proto.
rollBgm = function rollBgm() {
this.setBgm(1 + this.numericId % 6);
};
_proto.
setBgm = function setBgm(bgmNum) {
if (this.bgmNum === bgmNum) return;
this.bgmNum = bgmNum;
switch (bgmNum) {
case -1:
this.bgm = BattleSound.loadBgm('https://play.pokemonshowdown.com/audio/bw2-homika-dogars.mp3', 1661, 68131, this.bgm);
break;
case -2:
this.bgm = BattleSound.loadBgm('https://play.pokemonshowdown.com/audio/xd-miror-b.mp3', 9000, 57815, this.bgm);
break;
case -3:
this.bgm = BattleSound.loadBgm('https://play.pokemonshowdown.com/audio/colosseum-miror-b.mp3', 896, 47462, this.bgm);
break;
case -101:
this.bgm = BattleSound.loadBgm('https://play.pokemonshowdown.com/audio/spl-elite4.mp3', 3962, 152509, this.bgm);
break;
case 1:
this.bgm = BattleSound.loadBgm('https://github.com/OpenSauce04/ssmm-showdown/raw/master/music/xy-elite4.mp3', 133673, 261675, this.bgm);
break;
case 2:
this.bgm = BattleSound.loadBgm('https://github.com/OpenSauce04/ssmm-showdown/raw/master/music/bw-n-final.mp3', 42532, 129714, this.bgm);
break;
case 3:
this.bgm = BattleSound.loadBgm('https://github.com/OpenSauce04/ssmm-showdown/raw/master/music/bdsp-giratina.mp3', 60527, 164162, this.bgm);
break;
case 4:
this.bgm = BattleSound.loadBgm('https://github.com/OpenSauce04/ssmm-showdown/raw/master/music/b2w2-plasma.mp3', 264410, 438982, this.bgm);
break;
case 5:
this.bgm = BattleSound.loadBgm('https://github.com/OpenSauce04/ssmm-showdown/raw/master/music/bdsp-galactic-admin.mp3', 119450, 176991, this.bgm);
break;
case 6:
default:
this.bgm = BattleSound.loadBgm('https://play.pokemonshowdown.com/audio/sm-trainer.mp3', 8323, 89230, this.bgm);
break;
}
this.updateBgm();
};
_proto.
updateBgm = function updateBgm() {
var nowPlaying =
this.battle.turn >= 0 && !this.battle.ended && !this.battle.paused;
if (nowPlaying) {
if (!this.bgm) this.rollBgm();
this.bgm.resume();
} else if (this.bgm) {
this.bgm.pause();
}
};
_proto.
resetBgm = function resetBgm() {
if (this.bgm) this.bgm.stop();
};
_proto.
destroy = function destroy() {
this.log.destroy();
if (this.$frame) this.$frame.empty();
if (this.bgm) {
this.bgm.destroy();
this.bgm = null;
}
this.battle = null;
};
BattleScene.
getHPColor = function getHPColor(pokemon) {
var ratio = pokemon.hp / pokemon.maxhp;
if (ratio > 0.5) return 'g';
if (ratio > 0.2) return 'y';
return 'r';
};
return BattleScene;
}();