/** * Chat plug-ins * Pokemon Showdown - http://pokemonshowdown.com/ * * These are chat plugins - small programs to enhance the chat rooms on Pokemon Showdown. * Plugins are objects inside the plugins object. The objects are expected to have data values and a commands object inside. * The data object saves the data relevant to the plugin, like scores. * The commands object is used to import the commands onto the chat commands. * It's very important not to add plug-in commands with the same name as existing commands. * * @license MIT license */ var plugins = exports.plugins = { /** * Scavenger hunts plugin. Only works in a room with the id 'scavengers'. * This game shows a hint. Once a player submits the correct answer, they move on to the next hint. * You finish upon correctly answering the third hint. * In an official hunt, the first three to finish within 60 seconds achieve blitz. */ scavengers: { status: 'off', blitz: null, hintOne: '', answerOne: '', hintTwo: '', answerTwo: '', hintThree: '', answerThree: '', participants: {}, finished: [], result: null, commands: { scavenger: 'scavengers', scavengers: function (target, room, user) { return this.parse('/join scavengers'); }, startofficialhunt: 'starthunt', starthunt: function (target, room, user, connection, cmd) { if (room.id !== 'scavengers') return; if (!this.can('mute', null, room)) return false; if (plugins.scavengers.status === 'on') return this.sendReply('There is already an active scavenger hunt.'); var targets = target.split(','); if (!targets[0] || !targets[1] || !targets[2] || !targets[3] || !targets[4] || !targets[5] || targets[6]) { return this.sendReply('You must specify three hints and three answers.'); } plugins.scavengers.status = 'on'; if (cmd === 'startofficialhunt') { if (!this.can('ban', null, room)) return false; plugins.scavengers.blitz = setTimeout(function () { plugins.scavengers.blitz = null; }, 60000); } plugins.scavengers.hintOne = targets[0].trim(); plugins.scavengers.answerOne = toId(targets[1]); plugins.scavengers.hintTwo = targets[2].trim(); plugins.scavengers.answerTwo = toId(targets[3]); plugins.scavengers.hintThree = targets[4].trim(); plugins.scavengers.answerThree = toId(targets[5]); var result = (cmd === 'startofficialhunt' ? 'An official' : 'A new') + ' Scavenger Hunt has been started by ' + Tools.escapeHTML(user.name) + '! The first hint is: ' + Tools.escapeHTML(plugins.scavengers.hintOne); Rooms.rooms.scavengers.addRaw('
' + result + '
'); }, joinhunt: function (target, room, user) { if (room.id !== 'scavengers') return; if (plugins.scavengers.status !== 'on') return this.sendReply('There is no active scavenger hunt.'); if (user.userid in plugins.scavengers.participants) return this.sendReply('You are already participating in the current scavenger hunt.'); plugins.scavengers.participants[user.userid] = {room: 0}; this.sendReply('You joined the scavenger hunt! Use the command /scavenge to answer. The first hint is: ' + plugins.scavengers.hintOne); }, scavenge: function (target, room, user) { if (room.id !== 'scavengers') return; if (plugins.scavengers.status !== 'on') return this.sendReply('There is no active scavenger hunt.'); if (!plugins.scavengers.participants[user.userid]) return this.sendReply('You are not participating in the current scavenger hunt. Use the command /joinhunt to participate.'); if (plugins.scavengers.participants[user.userid].room >= 3) return this.sendReply('You have already finished!'); target = toId(target); var room = plugins.scavengers.participants[user.userid].room; if (plugins.scavengers[{0:'answerOne', 1:'answerTwo', 2:'answerThree'}[room]] === target) { plugins.scavengers.participants[user.userid].room++; room++; if (room < 3) { var hints = {1:'hintTwo', 2:'hintThree'}; this.sendReply('Well done! Your ' + (room === 1 ? 'second' : 'final') + ' hint is: ' + plugins.scavengers[hints[room]]); } else { plugins.scavengers.finished.push(user.name); var position = plugins.scavengers.finished.length; var result = '' + Tools.escapeHTML(user.name) + ' has finished the hunt '; result += (position === 1) ? 'and is the winner!' : (position === 2) ? 'in 2nd place!' : (position === 3) ? 'in 3rd place!' : 'in ' + position + 'th place!'; result += (position < 4 && plugins.scavengers.blitz ? ' [BLITZ]' : ''); Rooms.rooms.scavengers.addRaw('
' + result + '
'); } } else { this.sendReply('That is not the answer - try again!'); } }, scavengerhint: 'scavengerstatus', scavengerstatus: function (target, room, user) { if (room.id !== 'scavengers') return; if (plugins.scavengers.status !== 'on') return this.sendReply('There is no active scavenger hunt.'); if (!plugins.scavengers.participants[user.userid]) return this.sendReply('You are not participating in the current scavenger hunt. Use the command /joinhunt to participate.'); if (plugins.scavengers.participants[user.userid].room >= 3) return this.sendReply('You have finished the current scavenger hunt.'); var hints = {0:'hintOne', 1:'hintTwo', 2:'hintThree'}; var room = plugins.scavengers.participants[user.userid].room; this.sendReply('You are on hint number ' + (room + 1) + ': ' + plugins.scavengers[hints[room]]); }, endhunt: function (target, room, user) { if (room.id !== 'scavengers') return; if (!this.can('mute', null, room)) return false; if (plugins.scavengers.status !== 'on') return this.sendReply('There is no active scavenger hunt.'); var winner = plugins.scavengers.finished[0]; var second = plugins.scavengers.finished[1]; var third = plugins.scavengers.finished[2]; var consolation = plugins.scavengers.finished.slice(3).join(', '); var result = 'The Scavenger Hunt was ended by ' + Tools.escapeHTML(user.name) + '. '; if (winner) { result += '
Winner: ' + Tools.escapeHTML(winner) + '.'; if (second) result += ' Second place: ' + Tools.escapeHTML(second) + '.'; if (third) result += ' Third place: ' + Tools.escapeHTML(third) + '.'; if (consolation) result += ' Consolation prize to: ' + Tools.escapeHTML(consolation) + '.'; } else { result += 'No user has completed the hunt.'; } result += '
Solution: ' + Tools.escapeHTML(plugins.scavengers.answerOne) + ', ' + Tools.escapeHTML(plugins.scavengers.answerTwo) + ', ' + Tools.escapeHTML(plugins.scavengers.answerThree) + '.'; plugins.scavengers.result = result; this.parse('/resethunt'); }, resethunt: function (target, room, user) { if (room.id !== 'scavengers') return; if (!this.can('mute', null, room)) return false; if (plugins.scavengers.status !== 'on') return this.sendReply('There is no active scavenger hunt.'); plugins.scavengers.status = 'off'; if (plugins.scavengers.blitz) clearTimeout(plugins.scavengers.blitz); plugins.scavengers.blitz = null; plugins.scavengers.hintOne = ''; plugins.scavengers.answerOne = ''; plugins.scavengers.hintTwo = ''; plugins.scavengers.answerTwo = ''; plugins.scavengers.hintThree = ''; plugins.scavengers.answerThree = ''; plugins.scavengers.participants = {}; plugins.scavengers.finished = []; if (plugins.scavengers.result) { Rooms.rooms.scavengers.addRaw('
' + plugins.scavengers.result + '
'); } else { Rooms.rooms.scavengers.addRaw('
The Scavenger Hunt was reset by ' + Tools.escapeHTML(user.name) + '.
'); } plugins.scavengers.result = null; }, scavengershelp: 'scavengerhelp', scavengerhelp: function (target, room, user) { if (room.id !== 'scavengers') return; if (!this.canBroadcast()) return; this.sendReplyBox( 'Player commands:
' + '- /scavengers - Join the scavengers room
' + '- /joinhunt - Join the current scavenger hunt
' + '- /scavenge guess - Attempt to answer the hint
' + '- /scavengerstatus - Get your current game status
' + '
' + 'Staff commands:
' + '- /starthunt hint, answer, hint, answer, hint, answer - Start a new scavenger hunt (Requires: % @ # & ~)
' + '- /startofficialhunt hint, answer, hint, answer, hint, answer - Start an official hunt with 60 seconds blitz period (Requires: @ # & ~)
' + '- /endhunt - Finish the current hunt and announce the winners (Requires: % @ # & ~)
' + '- /resethunt - Reset the scavenger hunt to mint status (Requires: % @ # & ~)' ); } } }, /** * The Studio: Artist of the Day Plugin * This is a daily activity where users get to nominate an artist to be Artist of the day, and it's randomly selected * Only works in a room with the id "The Studio" */ studio: { commands: { startaotd: function () { return this.parse('/toggleaotd on'); }, endaotd: function () { return this.parse('/toggleaotd off'); }, taotd: 'toggleaotd', toggleaotd: function (target, room, user) { if (room.id !== 'thestudio') return this.sendReply("This command can only be used in The Studio."); if (!this.canTalk()) return; if (!this.can('mute', null, room)) return; if (!target) { return this.sendReply("/toggleaotd [on / off] - If on, this will start AOTD, if off, this will no longer allow people to use /naotd."); } if (target === 'on') { if (room.aotdOn == true) return this.sendReply("The Artist of the Day has already started."); room.addRaw( '
' + '

Artist of the Day has started!

' + "

(Started by " + Tools.escapeHTML(user.name) + ")

" + "

Use /naotd [artist] to nominate an artist!

" + '
' ); room.aotdOn = true; this.logModCommand("Artist of the Day was started by " + Tools.escapeHTML(user.name) + "."); } if (target === 'off') { if (!room.aotdOn) return this.sendReply("The Artist of the Day has already ended."); room.addRaw("Nominations are over! (Turned off by " + Tools.escapeHTML(user.name) + ")"); room.aotdOn = false; } }, aotdfaq: 'aotdhelp', aotdhelp: function (target, room) { if (!this.canBroadcast()) return; if (room.id !== 'thestudio') return this.sendReply("This command can only be used in The Studio."); this.sendReplyBox( "

Artist of the Day:

" + "

This is a room activity for The Studio where users nominate artists for the title of 'Artist of the Day'.

" + '

' + "Command List:" + '

' + '

' + "

More information on Artist of the Day and these commands.

" ); }, nominateartistoftheday: 'naotd', naotd: function (target, room, user) { if (room.id !== 'thestudio') return this.sendReply("This command can only be used in The Studio."); if (!room.aotdOn) return this.sendReply("The Artist of the Day has already been chosen."); if (!target) return this.sendReply("/naotd [artist] - Nominates an artist for Artist of the Day."); if (target.length > 25) return this.sendReply("This Artist's name is too long; it cannot exceed 25 characters."); if (!this.canTalk()) return; room.addRaw(Tools.escapeHTML(user.name) + "'s nomination for Artist of the Day is: " + Tools.escapeHTML(target) + ""); }, artistoftheday: 'aotd', aotd: function (target, room, user) { if (room.id !== 'thestudio') return this.sendReply("This command can only be used in The Studio."); if (!target) { if (!this.canBroadcast()) return; this.sendReplyBox("The current Artist of the Day is: " + Tools.escapeHTML(room.aotd) + ""); return; } if (!this.canTalk()) return; if (target.length > 25) return this.sendReply("This Artist\'s name is too long; it cannot exceed 25 characters."); if (!this.can('mute', null, room)) return; room.aotd = target; room.addRaw( '
' + "

The Artist of the Day is now " + Tools.escapeHTML(target) + "

" + "

(Set by " + Tools.escapeHTML(user.name) + ".)

" + "

This Artist will be posted on our Artist of the Day page.

" + '
' ); room.aotdOn = false; this.logModCommand("The Artist of the Day was changed to " + Tools.escapeHTML(target) + " by " + Tools.escapeHTML(user.name) + "."); } } }, /** * The Happy Place: Quote of the Day Plugin * This is a command that allows a room owner to set an inspirational "quote" of the day. * Others may braodcast this at any time to remind the room of such. * Only works in a room with the id "The Happy Place" * Credits: panpawn, TalkTakesTime, Morfent, and sirDonovan */ happy: { quote: "", commands: { quoteoftheday: 'qotd', qotd: function (target, room, user) { if (room.id !== 'thehappyplace') return this.sendReply("This command can only be used in The Happy Place."); if (!this.canBroadcast()) return; if (!target) { if (!plugins.happy.quote) return this.sendReplyBox("The Quote of the Day has not been set."); return this.sendReplyBox("The current 'Inspirational Quote of the Day' is:
" + plugins.happy.quote); } if (!this.can('declare', null, room)) return false; if (target === 'off' || target === 'disable' || target === 'reset') { if (!plugins.happy.quote) return this.sendReply("The Quote of the Day has already been reset."); plugins.happy.quote = ""; this.sendReply("The Quote of the Day was reset by " + Tools.escapeHTML(user.name) + "."); this.logModCommand(user.name + " has reset the Quote of the Day."); return; } plugins.happy.quote = Tools.escapeHTML(target); room.addRaw( '
' + "

The 'Inspirational Quote of the Day' has been updated by " + Tools.escapeHTML(user.name) + ".

" + "

Quote: " + plugins.happy.quote + '

' + '
' ); this.logModCommand(Tools.escapeHTML(user.name) + " has updated the quote of the day to: " + plugins.happy.quote); } } } };