diff --git a/config/formats.js b/config/formats.js index 9b885ba4e4..e5448a62f0 100644 --- a/config/formats.js +++ b/config/formats.js @@ -353,6 +353,116 @@ exports.Formats = [ return problems; } }, + { + // Get it? They're Han Chinese! + name: "[Seasonal] Han vs Hun", + section: "OM of the Month", + + team: 'randomSeasonalMulan', + ruleset: ['HP Percentage Mod', 'Sleep Clause Mod', 'Cancel Mod'], + onBegin: function () { + this.add('message', "General Shang! The Huns are marching towards the Imperial City! Train your recruits quickly and make your stand!"); + this.seasonal.songCount = 0; + this.seasonal.song = [ + "Let's get down to business, to defeat the Huns!", "Did they send me daughters, when I asked for sons?", + "You're the saddest bunch I ever met.", "But you can bet, before we're through...", "Mister, I'll make a man out of you!", + "Tranquil as a forest, but on fire within.", "Once you find your center, you are sure to win!", + "You're a spineless, pale, pathetic lot, and you haven't got a clue.", "Somehow, I'll make a man out of you!", + "I'm never gonna catch my breath...", "Say goodbye to those who knew me...", "Boy, was I a fool in school for cutting gym...", + "This guy's got them scared to death!", "Hope he doesn't see right through me...", "Now I really wish I knew how to swim...", + "We must be swift as a coursing river!", "With all the force of a great typhoon!", "With all the strength of a raging fire!", + "Mysterious as the dark side of the moon!", "Time is racing towards us, 'til the Huns arrive.", + "Heed my every order, and you might survive!", "You're unsuited for the rage of war.", "So pack up, go home, you're through.", + "How could I make a man out of you?", "We must be swift as a coursing river!", "With all the force of a great typhoon!", + "With all the strength of a raging fire!", "Mysterious as the dark side of the moon!" + ]; + this.seasonal.verses = {4: true, 8: true, 14: true, 18: true, 23: true, 27: true}; + this.seasonal.morale = 0; + }, + onModifyMove: function (move) { + if (move.id === 'sing') { + move.name = "Train Recruits"; + move.accuracy = 100; + move.target = "self"; + move.onTryHit = function (target, source, move) { + if (this.seasonal.songCount < this.seasonal.song.length) { + this.add('-message', '"' + this.seasonal.song[this.seasonal.songCount] + '"'); + if (this.seasonal.verses[this.seasonal.songCount]) { + this.add('-message', "Because of the difficult training, the new recruits are more experienced!"); + if (this.seasonal.songCount === 27) { + this.add('-message', "The recruits are now fully trained!"); + } + if (source.name !== 'Li Shang' && source.name !== 'Mushu') { + var boosts = (this.seasonal.morale % 2 ? {def: 1, spd: 1} : {atk: 1, spa: 1}); + this.boost(boosts, source, source, move); + } + this.seasonal.morale++; + } + this.seasonal.songCount++; + } else { + this.add('-message', "The soldiers cannot be trained further!"); + } + return null; + }; + } else if (move.id === 'octazooka') { + move.name = "Fire Rocket"; + move.category = 'Physical'; + move.basePower = 180; + move.type = '???'; + move.accuracy = 90; + delete move.secondaries; + move.ignoreOffense = true; // Fireworks not affected by boosts from morale + move.onTry = function (source, target) { + // If the soldier is inexperienced, the rocket can explode in their face. 50% chance at 0 morale, 33% at 1, 17% at 2, 0% afterwards. + if (source.name !== 'Li Shang' && (this.random(6) > (this.seasonal.morale + 2))) { + this.add('-message', "But " + source.name + "'s inexperience caused the rocket to backfire!"); + this.damage(Math.ceil(source.maxhp / 8), source, source, "the explosion", true); + return null; + } + }; + } else if (move.id === 'sacredfire') { + // Sorry, Sacred Fire's burn chance is too good for this format, since mostly Physical attackers + delete move.secondaries; + } + }, + onSwitchIn: function (pokemon) { + this.seasonal.morale = this.seasonal.morale || 0; + if (pokemon.name in {'Mulan': 1, 'Yao': 1, 'Ling': 1, 'Chien-Po': 1}) { + var offense = Math.ceil(this.seasonal.morale / 2) - 1; + var defense = Math.floor(this.seasonal.morale / 2); + this.boost({atk: offense, spa: offense, def: defense, spd: defense}, pokemon, pokemon, this.getMove('sing')); + } + + // Make Mushu Dragon/Fire type. + if (pokemon.name === 'Mushu') { + pokemon.addType('Fire'); + this.add('-start', pokemon, 'typeadd', 'Fire', '[from] ' + pokemon); + } + }, + onResidual: function () { + if (this.seasonal.songCount < this.seasonal.song.length) { + this.add('-message', '"' + this.seasonal.song[this.seasonal.songCount] + '"'); + var pokemon = null; + if (this.seasonal.verses[this.seasonal.songCount]) { + this.add('-message', "Because of the difficult training, the new recruits are more experienced!"); + if (this.seasonal.songCount === 27) { + this.add('-message', "The recruits are now fully trained!"); + } + if (this.p1.active[0].name in {'Mulan': 1, 'Yao': 1, 'Ling': 1, 'Chien-Po': 1}) { + pokemon = this.p1.active[0]; + } else if (this.p2.active[0].name in {'Mulan': 1, 'Yao': 1, 'Ling': 1, 'Chien-Po': 1}) { + pokemon = this.p2.active[0]; + } + if (pokemon && pokemon.hp) { + var boosts = (this.seasonal.morale % 2 ? {def: 1, spd: 1} : {atk: 1, spa: 1}); + this.boost(boosts, pokemon, pokemon, this.getMove('sing')); + } + this.seasonal.morale++; + } + this.seasonal.songCount++; + } + } + }, { name: "CAP", section: "Other Metagames", diff --git a/data/scripts.js b/data/scripts.js index ef2584edb7..52ed0abd8d 100644 --- a/data/scripts.js +++ b/data/scripts.js @@ -2701,5 +2701,121 @@ exports.BattleScripts = { level: level, shiny: (Math.random() * (template.id === 'missingno' ? 4 : 1024) <= 1) }; + }, + randomSeasonalMulanTeam: function (side) { + var armySide = 'china'; + var team = []; + var pokemon = ''; + var template = {}; + var set = {}; + var megaCount = 0; + var pokemonLeft = 0; + + // If the other team has been chosen, we get its opposing force. + if (this.seasonal && this.seasonal.side) { + armySide = (this.seasonal.side === 'hun' ? 'china' : 'hun'); + } else { + // First team being generated, pick a armySide at random. + armySide = (Math.random() > 0.5 ? 'china' : 'hun'); + this.seasonal = {'side': armySide}; + } + + if (armySide === 'china') { + var chinese = [ + 'accelgor', 'bisharp', 'gallade', 'hitmonchan', 'hitmonlee', 'hitmontop', 'infernape', 'lucario', 'machoke', 'medicham', + 'medicham', 'mienshao', 'pangoro', 'sawk', 'scrafty', 'scizor', 'throh', 'ursaring', 'vigoroth', 'weavile', 'zangoose' + ].randomize(); + + var weakCount = {}; + + // Add the members of the army. + var names = ["Li Shang", "Mulan", "Yao", "Ling"]; + for (var i = 0; i < chinese.length && pokemonLeft < 4; i++) { + var mainWeakness = {}; + pokemon = chinese[i]; + template = this.getTemplate(pokemon); + + // We don't want too many Fighting or Flying weaknesses, since those moves will be common + // Hard limit it to two, since after factoring in Chien-Po we might have a lot of common weakness + var mainWeakness = {}; + if (Tools.getEffectiveness('Flying', template) > 0) mainWeakness['Flying'] = true; + if (Tools.getEffectiveness('Fighting', template) > 0) mainWeakness['Fighting'] = true; + if (mainWeakness['Fighting'] && weakCount['Fighting'] >= 2) continue; + else if (mainWeakness['Flying'] && weakCount['Flying'] >= 2) continue; + else { + for (var type in mainWeakness) { + if (type in weakCount) { + weakCount[type]++; + } else { + weakCount[type] = 1; + } + } + } + + set = this.randomSet(template, pokemonLeft, !!megaCount); + if (this.getItem(set.item).megaStone) megaCount++; + set.species = toId(set.name); + set.name = names[pokemonLeft]; + set.gender = (set.name === "Mulan" ? 'F' : 'M'); + set.moves[4] = 'sing'; + set.moves[5] = 'octazooka'; + team.push(set); + pokemonLeft++; + } + + // Chien Po is very large, so he samples from a different pool of Pokemon + pokemon = ['blastoise', 'snorlax', 'golem', 'lickilicky', 'poliwrath', 'hariyama', 'magmortar'][this.random(7)]; + template = this.getTemplate(pokemon); + set = this.randomSet(template, 4, !!megaCount); + if (this.getItem(set.item).megaStone) megaCount++; + set.species = toId(set.name); + set.name = "Chien-Po"; + set.gender = 'M'; + set.moves[4] = 'sing'; + set.moves[5] = 'octazooka'; + team.push(set); + + // Add Eddie Murphy-- I mean, Mushu, to the team as a Dragonair. + template = this.getTemplate('dragonair'); + template.randomBattleMoves = ['dragondance', 'outrage', 'aquatail', 'waterfall', 'fusionbolt', 'extremespeed', 'dracometeor', 'dragonascent']; + set = this.randomSet(template, 5); + set.species = toId(set.name); + set.name = "Mushu"; + set.gender = 'M'; + set.ability = "Turboblaze"; + set.moves[4] = 'sing'; + set.moves[5] = 'sacredfire'; + team.push(set); + } else { + var huns = [ + 'aggron', 'chesnaught', 'conkeldurr', 'drapion', 'electivire', 'emboar', 'exploud', 'feraligatr', 'granbull', + 'haxorus', 'machamp', 'nidoking', 'rhyperior', 'swampert', 'tyranitar' + ].randomize(); + + for (var i = 0; i < huns.length && pokemonLeft < 5; i++) { + pokemon = huns[pokemonLeft]; + template = this.getTemplate(pokemon); + set = this.randomSet(template, pokemonLeft, !!megaCount); + if (this.getItem(set.item).megaStone) megaCount++; + set.species = toId(set.name); + if (i === 0) { + set.name = "Shan Yu"; + } else { + set.name = "Hun " + template.species; + } + set.gender = 'M'; + team.push(set); + pokemonLeft++; + } + + // Add Hayabusa the falcon. + pokemon = ['fearow', 'pidgeot', 'staraptor', 'honchkrow', 'aerodactyl', 'archeops', 'braviary', 'noivern'][this.random(8)]; + template = this.getTemplate(pokemon); + set = this.randomSet(template, 5, !!megaCount); + set.species = toId(set.name); + set.name = "Hayabusa"; + team.push(set); + } + return team; } };