/* License: GPLv2 */ // par: -webkit-filter: sepia(100%) hue-rotate(373deg) saturate(592%); // -webkit-filter: sepia(100%) hue-rotate(22deg) saturate(820%) brightness(29%); // psn: -webkit-filter: sepia(100%) hue-rotate(618deg) saturate(285%); // brn: -webkit-filter: sepia(100%) hue-rotate(311deg) saturate(469%); // slp: -webkit-filter: grayscale(100%); // frz: -webkit-filter: sepia(100%) hue-rotate(154deg) saturate(759%) brightness(23%); $.extend($.easing, { ballisticUp: function (x, t, b, c, d) { return -3 * x * x + 4 * x; }, ballisticDown: function (x, t, b, c, d) { x = 1 - x; return 1 - (-3 * x * x + 4 * x); }, quadUp: function (x, t, b, c, d) { x = 1 - x; return 1 - (x * x); }, quadDown: function (x, t, b, c, d) { return x * x; } }); function BattleSoundLibrary() { // options this.effectVolume = 50; this.bgmVolume = 50; this.muted = false; // effects this.effectCache = {}; this.loadEffect = function(url) { if (this.effectCache[url] && this.effectCache[url] !== this.soundPlaceholder) { return this.effectCache[url]; } try { this.effectCache[url] = soundManager.createSound({ id: url, url: Tools.resourcePrefix + url, volume: this.effectVolume }); } catch (e) {} if (!this.effectCache[url]) { this.effectCache[url] = this.soundPlaceholder; } return this.effectCache[url]; }; this.playEffect = function(url) { if (!this.muted) this.loadEffect(url).setVolume(this.effectVolume).play(); }; // bgm this.bgmCache = {}; this.bgm = null; this.loadBgm = function(url, loopstart, loopend) { if (this.bgmCache[url]) { if (this.bgmCache[url] !== this.soundPlaceholder || loopstart === undefined) { return this.bgmCache[url]; } } try { this.bgmCache[url] = soundManager.createSound({ id: url, url: Tools.resourcePrefix + url, volume: this.bgmVolume }); } catch (e) {} if (!this.bgmCache[url]) { // couldn't load // suppress crash return this.bgmCache[url] = this.soundPlaceholder; } this.bgmCache[url].onposition(loopend, function() { this.setPosition(loopstart); }); return this.bgmCache[url]; }; this.playBgm = function(url, loopstart, loopstop) { if (this.bgm === this.loadBgm(url, loopstart, loopstop)) { if (!this.bgm.paused && this.bgm.playState) { return; } } else { this.stopBgm(); } try { this.bgm = this.loadBgm(url, loopstart, loopstop).setVolume(this.bgmVolume); if (!this.muted) { if (this.bgm.paused) { this.bgm.resume(); } else { this.bgm.play(); } } } catch(e) {} }; this.pauseBgm = function() { if (this.bgm) { this.bgm.pause(); } }; this.stopBgm = function() { if (this.bgm) { this.bgm.stop(); this.bgm = null; } }; // setting this.setMute = function(muted) { muted = !!muted; if (this.muted == muted) return; this.muted = muted; if (muted) { if (this.bgm) this.bgm.pause(); } else { if (this.bgm) this.bgm.play(); } }; this.setBgmVolume = function(bgmVolume) { this.bgmVolume = bgmVolume; if (this.bgm) { try { this.bgm.setVolume(bgmVolume); } catch (e) {} } }; this.setEffectVolume = function(effectVolume) { this.effectVolume = effectVolume; }; // misc this.soundPlaceholder = { play: function(){ return this; }, pause: function(){ return this; }, stop: function(){ return this; }, resume: function(){ return this; }, setVolume: function(){ return this; } }; } var BattleSound = new BattleSoundLibrary(); function Pokemon(species) { var selfP = this; this.atk = 0; this.def = 0; this.spa = 0; this.spd = 0; this.spe = 0; this.atkStat = 0; this.defStat = 0; this.spaStat = 0; this.spdStat = 0; this.speStat = 0; this.boosts = {}; this.hp = 0; this.maxhp = 0; this.hpcolor = ''; this.moves = []; this.ability = ''; this.item = ''; this.species = species; this.side = null; this.fainted = false; this.zerohp = false; this.status = ''; this.statusStage = 0; this.volatiles = {}; this.turnstatuses = {}; this.movestatuses = {}; this.lastmove = ''; this.name = ''; this.species = ''; this.id = ''; this.statbarElem = null; this.getHPColor = function () { if (selfP.hpcolor) return selfP.hpcolor; var ratio = selfP.hp / selfP.maxhp; if (ratio > 0.5) return 'g'; if (ratio > 0.2) return 'y'; return 'r'; }; this.getHPColorClass = function () { switch (selfP.getHPColor()) { case 'y': return ' hpbar-yellow'; case 'r': return ' hpbar-red'; } return ''; }; var epsilon = 0.5/714; this.getPixelRange = function (pixels, color) { if (pixels === 0) { return [0, 0]; } else if (pixels === 1) { return [0 + epsilon, 2/48 - epsilon]; } else if (pixels === 9) { if (color === 'y') { // ratio is > 0.2 return [0.2 + epsilon, 10/48 - epsilon]; } else { // ratio is <= 0.2 return [9/48, 0.2]; } } else if (pixels === 24) { if (color === 'g') { // ratio is > 0.5 return [0.5 + epsilon, 25/48 - epsilon]; } else { // ratio is exactly 0.5 return [0.5, 0.5]; } } else if (pixels === 48) { return [1, 1]; } else { return [pixels/48, (pixels + 1)/48 - epsilon]; } }; this.getFormattedRange = function (range, precision, separator) { if (range[0] === range[1]) { var percentage = Math.abs(range[0] * 100); if (Math.floor(percentage) === percentage) { return percentage + '%'; } return percentage.toFixed(precision) + '%'; } var lower, upper; if (precision === 0) { lower = Math.floor(range[0] * 100); upper = Math.ceil(range[1] * 100); } else { lower = (range[0] * 100).toFixed(precision); upper = (range[1] * 100).toFixed(precision); } return lower + separator + upper + '%'; }; this.getDamageRange = function (damage) { if (damage[1] !== 48) { var ratio = damage[0] / damage[1]; return [ratio, ratio]; } else if (damage[3] === undefined) { // wrong pixel damage. // this case exists for backward compatibility only. return [damage[2] / 100, damage[2] / 100]; } // pixel damage var oldrange = selfP.getPixelRange(damage[3], damage[4]); var newrange = selfP.getPixelRange(damage[3] + damage[0], selfP.hpcolor); if (damage[0] === 0) { // no change in displayed pixel width return [0, newrange[1] - newrange[0]]; } if (oldrange[0] < newrange[0]) { // swap order var r = oldrange; oldrange = newrange; newrange = r; } return [oldrange[0] - newrange[1], oldrange[1] - newrange[0]]; }; // returns [delta, denominator, percent(, oldnum, oldcolor)] or false this.healthParse = function (hpstring, parsedamage, heal) { if (!hpstring || !hpstring.length) return false; var parenIndex = hpstring.lastIndexOf('('); if (parenIndex >= 0) { // old style damage and health reporting if (parsedamage) { var damage = parseFloat(hpstring); // unusual check preseved for backward compatbility if (isNaN(damage)) damage = 50; if (heal) { selfP.hp += selfP.maxhp * damage / 100; if (selfP.hp > selfP.maxhp) selfP.hp = selfP.maxhp; } else { selfP.hp -= selfP.maxhp * damage / 100; } // parse the absolute health information var ret = this.healthParse(hpstring); if (ret && (ret[1] === 100)) { // support for old replays with nearest-100th damage and health return [damage, 100, damage]; } // complicated expressions preserved for backward compatibility var percent = Math.round(Math.ceil(damage * 48 / 100) / 48 * 100); var pixels = Math.ceil(damage * 48 / 100); return [pixels, 48, percent]; } if (hpstring.substr(hpstring.length-1) !== ')') { return false; } hpstring = hpstring.substr(parenIndex+1, hpstring.length-parenIndex-2); } var hp = hpstring.split(' '); var status = hp[1]; hp = hp[0]; var oldhp = (selfP.zerohp || selfP.fainted) ? 0 : (selfP.hp || 1); var oldmaxhp = selfP.maxhp; var oldwidth = selfP.hpWidth(100); var oldcolor = selfP.hpcolor; // hp parse selfP.hpcolor = ''; if (hp === '0' || hp === '0.0') { selfP.hp = 0; selfP.zerohp = true; } else if (hp.indexOf('/') > 0) { var hp = hp.split('/'); if (isNaN(parseFloat(hp[0])) || isNaN(parseFloat(hp[1]))) { return false; } selfP.hp = parseFloat(hp[0]); selfP.maxhp = parseFloat(hp[1]); if (oldmaxhp === 0) { // max hp not known before parsing this message oldmaxhp = oldhp = selfP.maxhp; } if (selfP.hp > selfP.maxhp) selfP.hp = selfP.maxhp; var colorchar = hp[1].substr(hp[1].length - 1); if ((colorchar === 'y') || (colorchar === 'g')) { selfP.hpcolor = colorchar; } if (!selfP.hp) { selfP.zerohp = true; } } else if (!isNaN(parseFloat(hp))) { selfP.hp = selfP.maxhp * parseFloat(hp) / 100; } // status parse if (!status) { selfP.status = ''; } else if (status === 'par' || status === 'brn' || status === 'slp' || status === 'frz' || status === 'tox') { selfP.status = status; } else if (status === 'psn' && selfP.status !== 'tox') { selfP.status = status; } else if (status === 'fnt') { selfP.hp = 0; selfP.zerohp = true; selfP.fainted = true; } var oldnum = oldhp ? (Math.floor(oldhp / oldmaxhp * selfP.maxhp) || 1) : 0; var delta = selfP.hp - oldnum; var deltawidth = selfP.hpWidth(100) - oldwidth; return [delta, selfP.maxhp, deltawidth, oldnum, oldcolor]; }; this.checkDetails = function(details, ident) { if (details === selfP.details) return true; if (selfP.details.indexOf('-*') >= 0) { selfP.needsReplace = true; details = details.replace(/-[A-Za-z0-9]+(, |$)/, '$1'); return (details === selfP.details.replace(/-[A-Za-z0-9*]+(, |$)/, '$1')); } return false; }; this.getIdent = function() { if (selfP.side.active.length === 1) return selfP.ident; var slots = ['a','b','c','d','e','f']; return selfP.ident.substr(0,2) + slots[selfP.slot] + selfP.ident.substr(2); }; this.removeVolatile = function (volatile) { if (!selfP.hasVolatile(volatile)) return; if (volatile === 'formechange') { selfP.sprite.removeTransform(); } if (selfP.volatiles[volatile][1]) selfP.volatiles[volatile][1].remove(); delete selfP.volatiles[volatile]; }; this.addVolatile = function (volatile) { var self = selfP.side.battle; if (selfP.hasVolatile(volatile)) return; selfP.volatiles[volatile] = [volatile, null]; if (volatile === 'leechseed') { selfP.side.battle.spriteElemsFront[selfP.side.n].append(''); var curelem = selfP.side.battle.spriteElemsFront[selfP.side.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfP.sprite.x - 30, y: selfP.sprite.y - 40, z: selfP.sprite.z, scale: .2, opacity: .6 }, BattleEffects.energyball)); var elem = curelem; selfP.side.battle.spriteElemsFront[selfP.side.n].append(''); curelem = selfP.side.battle.spriteElemsFront[selfP.side.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfP.sprite.x + 40, y: selfP.sprite.y - 35, z: selfP.sprite.z, scale: .2, opacity: .6 }, BattleEffects.energyball)); elem = elem.add(curelem); selfP.side.battle.spriteElemsFront[selfP.side.n].append(''); curelem = selfP.side.battle.spriteElemsFront[selfP.side.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfP.sprite.x + 20, y: selfP.sprite.y - 25, z: selfP.sprite.z, scale: .2, opacity: .6 }, BattleEffects.energyball)); elem = elem.add(curelem); selfP.volatiles[volatile][1] = elem; } }; this.hasVolatile = function (volatile) { return !!selfP.volatiles[volatile]; }; this.removeTurnstatus = function (volatile) { if (!selfP.hasTurnstatus(volatile)) return; if (selfP.turnstatuses[volatile][1]) selfP.turnstatuses[volatile][1].remove(); delete selfP.turnstatuses[volatile]; }; this.addTurnstatus = function (volatile) { volatile = toId(volatile); var self = selfP.side.battle; if (selfP.hasTurnstatus(volatile)) { if (volatile === 'protect' || volatile === 'magiccoat') { selfP.turnstatuses[volatile][1].css(self.pos({ x: selfP.sprite.x, y: selfP.sprite.y, z: selfP.sprite.behind(-15), xscale: 1 * 1.2, yscale: .7 * 1.2, opacity: 1 }, BattleEffects.none), 300).animate(self.pos({ x: selfP.sprite.x, y: selfP.sprite.y, z: selfP.sprite.behind(-15), xscale: 1, yscale: .7, opacity: .4 }, BattleEffects.none), 300); } return; } selfP.turnstatuses[volatile] = [volatile, null]; if (volatile === 'protect' || volatile === 'magiccoat') { selfP.side.battle.spriteElemsFront[selfP.side.n].append('
'; } pokemonhtml = '
' + pokemonhtml + '
'; if (selfS.n === 1) { if (selfS.initialized) self.rightbarElem.html('
' + Tools.escapeHTML(selfS.name) + '
' + pokemonhtml + '
').find('.trainer').css('opacity',1); else self.rightbarElem.find('.trainer').css('opacity',0.4); } else { if (selfS.initialized) self.leftbarElem.html('
' + Tools.escapeHTML(selfS.name) + '
' + pokemonhtml + '
').find('.trainer').css('opacity',1); else self.leftbarElem.find('.trainer').css('opacity',0.4); } }; this.addSideCondition = function (condition) { condition = toId(condition); if (selfS.sideConditions[condition]) { if (condition === 'spikes' || condition === 'toxicspikes') { selfS.sideConditions[condition][2]++; if (condition === 'spikes' && selfS.sideConditions[condition][2] == 2) { self.spriteElemsFront[selfS.n].append(''); curelem = self.spriteElemsFront[selfS.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfS.x + 50, y: selfS.y - 40, z: selfS.z, scale: .3 }, BattleEffects.caltrop)); selfS.sideConditions['spikes'][1] = selfS.sideConditions['spikes'][1].add(curelem); } else if (condition === 'spikes') { self.spriteElemsFront[selfS.n].append(''); curelem = self.spriteElemsFront[selfS.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfS.x + 30, y: selfS.y - 45, z: selfS.z, scale: .3 }, BattleEffects.caltrop)); selfS.sideConditions['spikes'][1] = selfS.sideConditions['spikes'][1].add(curelem); } else if (condition === 'toxicspikes') { self.spriteElemsFront[selfS.n].append(''); curelem = self.spriteElemsFront[selfS.n].children().last(); curelem.css(self.pos({ display: 'block', x: selfS.x - 15, y: selfS.y - 35, z: selfS.z, scale: .3 }, BattleEffects.poisoncaltrop)); selfS.sideConditions['toxicspikes'][1] = selfS.sideConditions['toxicspikes'][1].add(curelem); } } return; } var elem, curelem; switch (condition) { case 'reflect': self.spriteElemsFront[selfS.n].append('