'use strict';
/** @type {typeof import('../../lib/fs').FS} */
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
const DISHES_FILE = 'config/chat-plugins/thecafe-foodfight.json';
const FOODFIGHT_COOLDOWN = 5 * 60 * 1000;
const thecafe = /** @type {ChatRoom} */ (Rooms.get('thecafe'));
/** @type {{[k: string]: string[]}} */
let dishes = {};
try {
dishes = require(`../../${DISHES_FILE}`);
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') throw e;
}
if (!dishes || typeof dishes !== 'object') dishes = {};
function saveDishes() {
FS(DISHES_FILE).write(JSON.stringify(dishes));
}
/**
* Used instead of Dex.packTeam to generate more human-readable output.
* @param {AnyObject[]} team
* @param {string[]} ingredients
*/
function stringifyTeam(team, ingredients) {
let output = '';
for (let i = 0; i < team.length; i++) {
const mon = team[i];
output += `${ingredients[i]} (${mon.species}) @ ${mon.item}
`;
output += `Ability: ${mon.ability}
`;
if (mon.happiness !== 255) output += `Happiness: ${mon.happiness}
`;
let evs = [];
for (const stat in mon.evs) {
if (mon.evs[stat]) evs.push(`${mon.evs[stat]} ${stat}`);
}
if (evs.length) output += `EVs: ${evs.join(' / ')}
`;
output += `${mon.nature} Nature
`;
let ivs = [];
for (const stat in mon.ivs) {
if (mon.ivs[stat] !== 31) ivs.push(`${mon.ivs[stat]} ${stat}`);
}
if (ivs.length) output += `IVs: ${ivs.join(' / ')}
`;
output += /** @type {string[]} */ (mon.moves).map(move => `- ${move}
`).join('');
output += '
';
}
return output;
}
/**
* @param {string} [generator]
*/
function generateTeam(generator = '') {
let potentialPokemon = Object.keys(Dex.data.Pokedex).filter(mon => {
const template = Dex.getTemplate(mon);
return template.baseSpecies === template.species;
});
let speciesClause = true;
switch (generator) {
case 'ou':
potentialPokemon = potentialPokemon.filter(mon => {
const template = Dex.getTemplate(mon);
return template.tier === 'OU';
}).concat(potentialPokemon.filter(mon => {
// There is probably a better way to get the ratios right, oh well.
const template = Dex.getTemplate(mon);
return template.tier === 'OU' || template.tier === 'UU';
}));
break;
case 'ag':
potentialPokemon = potentialPokemon.filter(mon => {
const template = Dex.getTemplate(mon);
const unviable = template.tier === 'NFE' || template.tier === 'PU' || template.tier === '(PU)' || template.tier.startsWith("LC");
const illegal = template.tier === 'Unreleased' || template.tier === 'Illegal' || template.tier.startsWith("CAP");
return !(unviable || illegal);
});
speciesClause = false;
break;
default:
potentialPokemon = potentialPokemon.filter(mon => {
const template = Dex.getTemplate(mon);
const op = template.tier === 'AG' || template.tier === 'Uber';
const unviable = template.tier === 'Illegal' || template.tier.includes("LC");
return !(op || unviable);
});
potentialPokemon.push('miltank', 'miltank', 'miltank', 'miltank'); // 5x chance for miltank for flavor purposes.
}
/** @type {string[]} */
const team = [];
while (team.length < 6) {
const randIndex = Math.floor(Math.random() * potentialPokemon.length);
const potentialMon = potentialPokemon[randIndex];
if (team.includes(potentialMon)) continue;
team.push(potentialMon);
if (speciesClause) potentialPokemon.splice(randIndex, 1);
}
return team.map(mon => Dex.getTemplate(mon).species);
}
/**
* @return {[string, string[]]}
*/
function generateDish() {
const keys = Object.keys(dishes);
const entry = dishes[keys[Math.floor(Math.random() * keys.length)]].slice();
const dish = entry.splice(0, 1)[0];
const ingredients = [];
while (ingredients.length < 6) {
ingredients.push(entry.splice(Math.floor(Math.random() * entry.length), 1)[0]);
}
return [dish, ingredients];
}
/** @type {ChatCommands} */
const commands = {
foodfight(target, room, user) {
if (room !== thecafe) return this.errorReply("This command is only available in The Café.");
if (!Object.keys(dishes).length) return this.errorReply("No dishes found. Add some dishes first.");
// @ts-ignore
if (user.foodfight && user.foodfight.timestamp + FOODFIGHT_COOLDOWN > Date.now()) return this.errorReply("Please wait a few minutes before using this command again.");
target = toID(target);
let team, importable;
const [dish, ingredients] = generateDish();
if (!target) {
const bfTeam = Dex.generateTeam('gen7bssfactory');
importable = stringifyTeam(bfTeam, ingredients);
team = /** @type {PokemonSet[]} */ (bfTeam).map(val => val.species);
} else {
team = generateTeam(target);
}
// @ts-ignore
user.foodfight = {team: team, dish: dish, ingredients: ingredients, timestamp: Date.now()};
const importStr = importable ? `
| Your dish is: ${dish} | ||||||
|---|---|---|---|---|---|---|
| Team | ${team.map(mon => `||||||
| Ingredients | ${ingredients.map(ingredient => `${ingredient} | `).join('')}|||||
| ${self ? `Your` : `${this.targetUsername}'s`} dish is: ${targetUser.foodfight.dish} | ||||||
|---|---|---|---|---|---|---|
| Team | ${targetUser.foodfight.team.map(mon => `||||||
| Ingredients | ${targetUser.foodfight.ingredients.map(ingredient => `${ingredient} | `).join('')}|||||
Access denied
There are no dishes in the database.
`; } else { buf += `Dishes | Ingredients |
|---|