Files
xiao/commands/games-sp/pokemon-advantage.js
T
2025-09-13 00:02:49 -04:00

204 lines
8.0 KiB
JavaScript

const Command = require('../../framework/Command');
const { PermissionFlagsBits } = require('discord.js');
const { createCanvas, loadImage } = require('@napi-rs/canvas');
const request = require('node-superfetch');
const { stripIndents } = require('common-tags');
const { greyscale, silhouette } = require('../../util/Canvas');
const path = require('path');
const advantages = require('../../assets/json/pokemon-advantage');
module.exports = class PokemonAdvantageCommand extends Command {
constructor(client) {
super(client, {
name: 'pokemon-advantage',
aliases: ['pokemon-adv', 'pokémon-advantage', 'pokémon-adv', 'pkmn-advantage', 'pkmn-adv'],
group: 'games-sp',
description: 'Guess which Pokémon has the type advantage.',
throttling: {
usages: 2,
duration: 10
},
clientPermissions: [PermissionFlagsBits.AttachFiles],
game: true,
credit: [
{
name: 'Pokémon',
url: 'https://www.pokemon.com/us/',
reason: 'Images, Original Game'
},
{
name: 'PokéAPI',
url: 'https://pokeapi.co/',
reason: 'API'
},
{
name: 'Serebii.net',
url: 'https://www.serebii.net/index2.shtml',
reason: 'Images'
},
{
name: 'DaFont',
url: 'https://www.dafont.com/',
reason: 'Pokemon Solid Font',
reasonURL: 'https://www.dafont.com/pokemon.font'
},
{
name: 'wavebeem',
url: 'https://github.com/wavebeem',
reason: 'Type Advantage Data',
reasonURL: 'https://github.com/wavebeem/pkmn.help/blob/master/src/data.ts'
}
]
});
}
async run(msg) {
const num1 = Math.floor(Math.random() * (this.client.pokemon.pokemonCount + 1));
const pkmn1 = await this.client.pokemon.fetch(num1);
const num2 = Math.floor(Math.random() * (this.client.pokemon.pokemonCount + 1));
const pkmn2 = await this.client.pokemon.fetch(num2);
await pkmn1.fetchDefaultVariety();
await pkmn2.fetchDefaultVariety();
const attachment = await this.createImage(pkmn1, pkmn2, null);
const answer = this.calculateAdvantage(pkmn1, pkmn2);
const answerAttachment = await this.createImage(pkmn1, pkmn2, answer);
await msg.reply(stripIndents`
**You have 15 seconds, who\'s got the type advantage?**
_If the Pokémon are evenly matched, type \`even\`._
`, { files: [attachment] });
const msgs = await msg.channel.awaitMessages({
filter: res => res.author.id === msg.author.id,
max: 1,
time: 15000
});
if (!msgs.size) return msg.reply(`Time! It's **${answer.name}**!`, { files: [answerAttachment] });
const guess = msgs.first().content.toLowerCase();
const slug = this.client.pokemon.makeSlug(guess);
if (answer === true) {
if (guess === 'even') return msg.reply('Nice! These two are even!', { files: [answerAttachment] });
return msg.reply('Nope! These two are even!', { files: [answerAttachment] });
}
if (!answer.names.includes(guess) && answer.slug !== slug) {
return msg.reply(`Nope! It's **${answer.name}**!`, { files: [answerAttachment] });
}
return msg.reply(`Nice! It's **${answer.name}**!`, { files: [answerAttachment] });
}
async createImage(pokemon1, pokemon2, winner) {
const name = `${pokemon1.id}${pokemon2.id}-${winner ? winner.id : 'none'}.png`;
const image1 = await request.get(pokemon1.spriteImageURL);
const image2 = await request.get(pokemon2.spriteImageURL);
const bg = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'pokemon-advantage', 'bg.png'));
const pkmn1 = await loadImage(image1.body);
const pkmn2 = await loadImage(image2.body);
const canvas = createCanvas(bg.width, bg.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(bg, 0, 0);
const silhouetteCanvas1 = createCanvas(pkmn1.width, pkmn1.height);
const silhouetteCtx1 = silhouetteCanvas1.getContext('2d');
silhouetteCtx1.drawImage(pkmn1, 0, 0);
silhouette(silhouetteCtx1, 0, 0, pkmn1.width, pkmn1.height);
const silhouetteCanvas2 = createCanvas(pkmn2.width, pkmn2.height);
const silhouetteCtx2 = silhouetteCanvas2.getContext('2d');
silhouetteCtx2.drawImage(pkmn2, 0, 0);
silhouette(silhouetteCtx2, 0, 0, pkmn2.width, pkmn2.height);
if (winner) {
const stars = await loadImage(
path.join(__dirname, '..', '..', 'assets', 'images', 'pokemon-advantage', 'stars.png')
);
if (winner === true) {
ctx.drawImage(stars, 20, 0, 200, 200);
ctx.drawImage(stars, 250, 0, 200, 200);
ctx.globalAlpha = 0.5;
ctx.drawImage(silhouetteCanvas1, 36, 17, 175, 175);
ctx.drawImage(silhouetteCanvas2, 256, 17, 175, 175);
ctx.globalAlpha = 1;
ctx.drawImage(pkmn1, 41, 12, 175, 175);
ctx.drawImage(pkmn2, 261, 12, 175, 175);
} else if (winner.id === pokemon1.id) {
ctx.drawImage(stars, 20, 0, 200, 200);
const greyCanvas = createCanvas(pkmn2.width, pkmn2.height);
const greyCtx = greyCanvas.getContext('2d');
greyCtx.drawImage(pkmn2, 0, 0);
greyscale(greyCtx, 0, 0, pkmn2.width, pkmn2.height);
ctx.globalAlpha = 0.5;
ctx.drawImage(silhouetteCanvas1, 36, 17, 175, 175);
ctx.drawImage(silhouetteCanvas2, 256, 17, 175, 175);
ctx.globalAlpha = 1;
ctx.drawImage(greyCanvas, 261, 12, 175, 175);
ctx.drawImage(pkmn1, 41, 12, 175, 175);
} else if (winner.id === pokemon2.id) {
ctx.drawImage(stars, 250, 0, 200, 200);
const greyCanvas = createCanvas(pkmn1.width, pkmn1.height);
const greyCtx = greyCanvas.getContext('2d');
greyCtx.drawImage(pkmn1, 0, 0);
greyscale(greyCtx, 0, 0, pkmn1.width, pkmn1.height);
ctx.globalAlpha = 0.5;
ctx.drawImage(silhouetteCanvas1, 36, 17, 175, 175);
ctx.drawImage(silhouetteCanvas2, 256, 17, 175, 175);
ctx.globalAlpha = 1;
ctx.drawImage(greyCanvas, 41, 12, 175, 175);
ctx.drawImage(pkmn2, 261, 12, 175, 175);
}
} else {
ctx.globalAlpha = 0.5;
ctx.drawImage(silhouetteCanvas1, 36, 17, 175, 175);
ctx.drawImage(silhouetteCanvas2, 256, 17, 175, 175);
ctx.globalAlpha = 1;
ctx.drawImage(pkmn1, 41, 12, 175, 175);
ctx.drawImage(pkmn2, 261, 12, 175, 175);
}
ctx.font = this.client.fonts.get('Pokemon Solid.ttf').toCanvasString(30);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.lineWidth = 8;
ctx.strokeStyle = 'black';
ctx.globalAlpha = 0.5;
ctx.strokeText(pokemon1.name, 123, 255, 175);
ctx.strokeText(pokemon2.name, 343, 255, 175);
ctx.globalAlpha = 1;
ctx.strokeStyle = '#3c5aa6';
ctx.fillStyle = '#ffcb05';
ctx.strokeText(pokemon1.name, 128, 250, 175);
ctx.fillText(pokemon1.name, 128, 250, 175);
ctx.strokeText(pokemon2.name, 348, 250, 175);
ctx.fillText(pokemon2.name, 348, 250, 175);
return { attachment: canvas.toBuffer('image/png'), name };
}
calculateAdvantage(pkmn1, pkmn2) {
if (pkmn1.id === pkmn2.id) return null;
if (pkmn1.missingno) return pkmn1;
if (pkmn2.missingno) return pkmn2;
const types1 = pkmn1.varieties.find(variety => variety.default).types;
const types2 = pkmn2.varieties.find(variety => variety.default).types;
if (types1[0] === types2[0] && types1[1] === types2[1]) return true;
const firstEffectives1 = advantages.data[types1[0]];
const firstEffectives2 = types1[1] ? advantages.data[types1[1]] : null;
const secndEffectives1 = advantages.data[types2[0]];
const secndEffectives2 = types2[1] ? advantages.data[types2[1]] : null;
let firstResult = 0;
let secndResult = 0;
firstResult += this.calculateSingleAdvantage(types2, firstEffectives1);
if (firstEffectives2) {
firstResult += this.calculateSingleAdvantage(types2, firstEffectives2);
} else {
firstResult += this.calculateSingleAdvantage(types2, firstEffectives1);
}
secndResult += this.calculateSingleAdvantage(types1, secndEffectives1);
if (secndEffectives2) {
secndResult += this.calculateSingleAdvantage(types1, secndEffectives2);
} else {
secndResult += this.calculateSingleAdvantage(types1, secndEffectives1);
}
if (firstResult === secndResult) return true;
return firstResult > secndResult ? pkmn1 : pkmn2;
}
calculateSingleAdvantage(types, advs) {
const x1 = advs[advantages.types.indexOf(types[0])];
const x2 = types[1] ? advs[advantages.types.indexOf(types[1])] : 1;
return x1 * x2;
}
};