PokeBattle.commands ?= {} Commands = {} desc = (description) -> desc.lastDescription = description makeCommand = (commandNames..., func) -> for commandName in commandNames Commands[commandName] = func # Generate description description = "" if commandNames.length > 1 aliases = commandNames[1...].map((n) -> "/#{n}").join(', ') description += " Also #{aliases}. " description += desc.lastDescription # TODO: Hardcoded user level HelpDescriptions['1'][commandNames[0]] = description delete desc.lastDescription parseCommand = (line) -> [ commandName, args... ] = line.split(/\s+/) if commandName[0] == '/' # It's a command. Remove leading slash commandName = commandName[1...] args = args.join(' ').split(/,/g) return [commandName, args] return null PokeBattle.commands.execute = (room, line) -> result = parseCommand(line) return false if !result [commandName, args] = result command = Commands[commandName] if !command # Fall-through to server. return false command(room, args...) return true desc 'Displays a list of all commands.' makeCommand "commands", "help", "h", (room) -> user = room.get('users').get(PokeBattle.username) for level, descriptions of HelpDescriptions level = Number(level) continue if user.get('authority') < level message = [] # TODO: Hardcoded levels authLevels = {1: "USER", 2: "DRIVER", 3: "MOD", 4: "ADMIN", 5: "OWNER"} humanLevel = authLevels[level] message.push("#{humanLevel} COMMANDS:") for name, description of descriptions message.push("/#{name}: #{description}") message = message.join("
") room.announce('success', message) true desc 'Opens the challenge for a specific user. Usage: /challenge username' makeCommand "challenge", "chall", "c", (room, username) -> if !username PokeBattle.events.trigger("errorMessage", "Usage: /challenge username") return message = PokeBattle.messages.add(id: username) message.openChallenge(username) desc 'Private messages a certain user. Usage: /message username, message' makeCommand "message", "msg", "pm", "whisper", "w", (room, username, messages...) -> username = username?.trim() if !username PokeBattle.events.trigger("errorMessage", "Usage: /message username, msg") return message = PokeBattle.messages.add(id: username) if messages.length > 0 text = messages.join(',') PokeBattle.primus.send('privateMessage', message.id, text) else # The PM is opened without a message. message.trigger('open', message) desc 'Clears the chat.' makeCommand "clear", (room) -> room.clear() desc 'Displays a Pokemon\'s PokeBattle value, or displays all Pokemon at or under a particular PBV. Usage: /pbv pkmn1, pkmn2, OR /pbv number' makeCommand "pbv", (room, pokemon...) -> pbv = Number(pokemon[0]) if !isNaN(pbv) messages = findPokemonAtPBV(pbv) else messages = findTotalPBV(pokemon) if messages.length == 0 room.announce('error', "PBV error: Enter valid Pokemon or PBV.") else room.announce('success', "PBV: #{messages.join('; ')}") findPokemonAtPBV = (pbv) -> messages = [] counter = 0 for speciesName, formes of window.Generations.XY.FormeData for formeName, formeData of formes if formeData.pokeBattleValue <= pbv counter += 1 dexEntry = "pokemon/#{slugify(speciesName)}/#{slugify(formeName)}" icon = pokemonIcon(speciesName, formeName) formattedName = formatName(speciesName, formeName) messages.push("#{linkToDex(dexEntry, icon + formattedName)}: #{formeData.pokeBattleValue}") if messages.length > 10 messages = _.sample(messages, 10) messages.push(linkToDex("pokemon/?pbv=<#{pbv + 1}", "See more Pokemon »")) if messages.length > 0 plural = if messages.length == 1 then "is" else "are" messages.unshift("There #{plural} #{counter} Pokemon with a PBV of #{pbv} or less") messages findTotalPBV = (pokemon) -> pokemon = _(pokemon).map(findPokemon) messages = [] total = 0 for array in pokemon continue unless array [speciesName, formeName] = array pbv = PokeBattle.PBV.determinePBV(window.Generations.XY, species: speciesName, forme: formeName) total += pbv dexEntry = "pokemon/#{slugify(speciesName)}/#{slugify(formeName)}" icon = pokemonIcon(speciesName, formeName) formattedName = formatName(speciesName, formeName) messages.push("#{linkToDex(dexEntry, icon + formattedName)}: #{pbv}") messages.push("Total: #{total}") if messages.length > 1 messages desc 'Looks up information about a Pokemon, move, item, or ability.' makeCommand "data", "dex", (room, query) -> if (pokemon = findPokemon(query)) message = dataPokemon(pokemon) else if (item = findItem(query)) message = dataItem(item) else if (move = findMove(query)) message = dataMove(move) else if (ability = findAbility(query)) message = dataAbility(ability) else room.announce("error", "Data error: Enter a valid Pokemon, item, move, or ability.") return room.announce('success', message) dataPokemon = (pokemon) -> [speciesName, formeName] = pokemon [speciesSlug, formeSlug] = [slugify(speciesName), slugify(formeName)] forme = window.Generations.XY.FormeData[speciesName][formeName] {types, abilities, hiddenAbility, stats, pokeBattleValue} = forme # Format abilities abilities = _.clone(abilities) abilities.push(hiddenAbility) if hiddenAbility? abilities = _(abilities).map((a) -> linkToDex("abilities/#{slugify(a)}", a)) abilities = abilities.join('/') abilities += " (H)" if hiddenAbility? # Format types, stats, and icon types = _(types).map (t) -> linkToDex("types/#{slugify(t)}", "#{t}") statNames = [ 'HP', 'Attack', 'Defense', 'Sp.Attack', 'Sp.Defense', 'Speed'] stats = [ stats.hp, stats.attack, stats.defense, stats.specialAttack, stats.specialDefense, stats.speed ] statsText = _.map(_.zip(statNames, stats), (a) -> a.join(': ')).join(' / ') # Build data message = """#{pokemonIcon(speciesName, formeName, "left")}

#{formatName(speciesName, formeName)}: #{types.join('')} | #{abilities}
#{statsText} | #{_(stats).reduce((a, b) -> a + b)} BST | PBV: #{pokeBattleValue} #{linkToDex("pokemon/#{speciesSlug}/#{formeSlug}", "See dex entry »")}

""" message dataItem = (itemName) -> item = window.Generations.XY.ItemData[itemName] message = "#{itemName}: #{item.description}" message += " Natural Gift is #{item.naturalGift.type} type and has #{item.naturalGift.power} base power." if item.naturalGift message += " Fling has #{item.flingPower} base power." if item.flingPower message += " Currently unreleased in Gen 6." if item.unreleased message dataMove = (moveName) -> move = window.Generations.XY.MoveData[moveName] type = linkToDex("types/#{slugify(move.type)}", "#{move.type}") category = """#{move.damage}""" target = """#{move.target}""" power = move.power || "—" acc = move.accuracy || "—" maxpp = Math.floor(move.pp * 8/5) if move.priority > 0 priority = "+#{move.priority}" else if move.priority < 0 priority = move.priority message = """#{moveName}: #{type} #{category} #{target} """ message += "Power: #{power} Acc: #{acc} PP: #{move.pp} (max #{maxpp})" message += "
" message += "Priority #{priority}. " if priority message += move.description message += " " message += linkToDex("moves/#{slugify(moveName)}", "See who learns this move »") message dataAbility = (abilityName) -> ability = window.Generations.XY.AbilityData[abilityName] message = """#{abilityName}: #{ability.description} #{linkToDex("abilities/#{slugify(abilityName)}", "See who obtains this ability »")}""" message # Finds the most lenient match possible. findPokemon = (pokemonName) -> pokemonName = normalize(pokemonName) for speciesName, speciesData of window.Generations.XY.FormeData for formeName of speciesData name = speciesName name += formeName unless formeName == 'default' name = normalize(name) name += name return [speciesName, formeName] if name.indexOf(pokemonName) != -1 # Return blank match null # Finds the most lenient match possible. findItem = (itemName) -> normalized = normalize(itemName) for name of window.Generations.XY.ItemData return name if normalized == normalize(name) # Return blank match null # Finds the most lenient match possible. findMove = (moveName) -> normalized = normalize(moveName) for name of window.Generations.XY.MoveData return name if normalized == normalize(name) # Return blank match null # Finds the most lenient match possible. findAbility = (abilityName) -> normalized = normalize(abilityName) for name of window.Generations.XY.AbilityData return name if normalized == normalize(name) # Return blank match null slugify = (str) -> str.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/\-{2,}/g, '-') normalize = (str) -> str.trim().toLowerCase().replace(/[^a-zA-Z0-9]+/g, '') formatName = (speciesName, formeName) -> if formeName == 'default' pokemonName = speciesName else pokemonName = speciesName pokemonName += ' ' pokemonName += formeName.split('-') .map((n) -> n[0].toUpperCase() + n[1...]) .join('-') return pokemonName linkToDex = (slug, text) -> "#{text}" pokemonIcon = (speciesName, formeName, classes="") -> style = window.PokemonIconBackground(speciesName, formeName) """"""