diff --git a/README.md b/README.md index 63a91920..28179fda 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ things, I'm not taking any chances. 22. Start Xiao up! ## Commands -Total: 511 +Total: 510 ### Utility: @@ -480,7 +480,6 @@ Total: 511 * **wanted:** Draws an image or a user's avatar over a wanted poster. * **wild-pokemon:** Draws an image or a user's avatar over a wild Pokémon appearance. * **you-died:** Sends a "You Died" screen over an image or a user's avatar. -* **yu-gi-oh-gen:** Draws an image or a user's avatar on a Yu-Gi-Oh! Trading Card with the text of your choice. ### Image Text Manipulation: @@ -1257,11 +1256,6 @@ Total: 511 - [Jackster Productions](https://www.fontspace.com/jackster-productions) ([Pokemon GB Font](https://www.fontspace.com/pokemon-gb-font-f9621)) * **you-died:** - [FromSoftware](https://www.fromsoftware.jp/ww/) (Image, Original "Dark Souls" Game) -* **yu-gi-oh-gen:** - - [Konami](https://www.konami.com/en/) ([Images, Original "Yu-Gi-Oh!" Game](https://www.yugioh-card.com/en/)) - - [sl777123](https://www.deviantart.com/sl777123) ([Card Base Templates](https://www.deviantart.com/sl777123/gallery/64574029/templates)) - - [icycatelf](https://www.deviantart.com/icycatelf) ([Level/Rank Star Image](https://www.deviantart.com/icycatelf/art/Level-Star-Template-PSD-607344453)) - - [bushin](https://www.cardmaker.net/profile/220983-bushin/) ([Fonts](https://www.cardmaker.net/forums/topic/308603-fonts-for-yu-gi-oh-card-making-with-multilingual-support/)) * **ace-attorney:** - [Capcom](http://www.capcom.com/us/) ([Images, Original "Ace Attorney" Game](http://www.ace-attorney.com/)) - [Enkidulga](https://www.dafont.com/profile.php?user=736583) ([Ace Attorney Font](https://www.dafont.com/ace-attorney.font)) diff --git a/assets/fonts/Matrix Book.ttf b/assets/fonts/Matrix Book.ttf deleted file mode 100644 index c0bd7686..00000000 Binary files a/assets/fonts/Matrix Book.ttf and /dev/null differ diff --git a/assets/fonts/Matrix Small Caps.ttf b/assets/fonts/Matrix Small Caps.ttf deleted file mode 100644 index 73adbeb9..00000000 Binary files a/assets/fonts/Matrix Small Caps.ttf and /dev/null differ diff --git a/assets/fonts/Stone Serif LT Italic.ttf b/assets/fonts/Stone Serif LT Italic.ttf deleted file mode 100644 index 2f9fcc71..00000000 Binary files a/assets/fonts/Stone Serif LT Italic.ttf and /dev/null differ diff --git a/assets/fonts/Stone Serif Small Caps.ttf b/assets/fonts/Stone Serif Small Caps.ttf deleted file mode 100644 index 27cebf3d..00000000 Binary files a/assets/fonts/Stone Serif Small Caps.ttf and /dev/null differ diff --git a/assets/fonts/Stone Serif.ttf b/assets/fonts/Stone Serif.ttf deleted file mode 100644 index 7875cbae..00000000 Binary files a/assets/fonts/Stone Serif.ttf and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/dark.png b/assets/images/yu-gi-oh-gen/atrs/dark.png deleted file mode 100644 index e661dcbc..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/dark.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/divine.png b/assets/images/yu-gi-oh-gen/atrs/divine.png deleted file mode 100644 index a24545c2..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/divine.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/earth.png b/assets/images/yu-gi-oh-gen/atrs/earth.png deleted file mode 100644 index 893b8d74..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/earth.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/fire.png b/assets/images/yu-gi-oh-gen/atrs/fire.png deleted file mode 100644 index 9f0c515b..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/fire.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/laugh.png b/assets/images/yu-gi-oh-gen/atrs/laugh.png deleted file mode 100644 index bf5a2167..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/laugh.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/light.png b/assets/images/yu-gi-oh-gen/atrs/light.png deleted file mode 100644 index 829e5ef8..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/light.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/spell.png b/assets/images/yu-gi-oh-gen/atrs/spell.png deleted file mode 100644 index a6385056..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/spell.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/trap.png b/assets/images/yu-gi-oh-gen/atrs/trap.png deleted file mode 100644 index b8849566..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/trap.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/water.png b/assets/images/yu-gi-oh-gen/atrs/water.png deleted file mode 100644 index b1f65907..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/water.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/atrs/wind.png b/assets/images/yu-gi-oh-gen/atrs/wind.png deleted file mode 100644 index 3fc80471..00000000 Binary files a/assets/images/yu-gi-oh-gen/atrs/wind.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/effect.png b/assets/images/yu-gi-oh-gen/bases/effect.png deleted file mode 100644 index fddc2525..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/effect.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/fusion.png b/assets/images/yu-gi-oh-gen/bases/fusion.png deleted file mode 100644 index 4e8a5849..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/fusion.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/link.png b/assets/images/yu-gi-oh-gen/bases/link.png deleted file mode 100644 index f5296129..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/link.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/normal.png b/assets/images/yu-gi-oh-gen/bases/normal.png deleted file mode 100644 index 4b8a35b8..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/normal.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/ritual.png b/assets/images/yu-gi-oh-gen/bases/ritual.png deleted file mode 100644 index c135c93f..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/ritual.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/spell.png b/assets/images/yu-gi-oh-gen/bases/spell.png deleted file mode 100644 index 4ed33e80..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/spell.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/synchro.png b/assets/images/yu-gi-oh-gen/bases/synchro.png deleted file mode 100644 index 03b706bb..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/synchro.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/token.png b/assets/images/yu-gi-oh-gen/bases/token.png deleted file mode 100644 index ddf30e88..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/token.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/trap.png b/assets/images/yu-gi-oh-gen/bases/trap.png deleted file mode 100644 index a561db60..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/trap.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/bases/xyz.png b/assets/images/yu-gi-oh-gen/bases/xyz.png deleted file mode 100644 index 0c4a64cb..00000000 Binary files a/assets/images/yu-gi-oh-gen/bases/xyz.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/level.png b/assets/images/yu-gi-oh-gen/level.png deleted file mode 100644 index 59966f9f..00000000 Binary files a/assets/images/yu-gi-oh-gen/level.png and /dev/null differ diff --git a/assets/images/yu-gi-oh-gen/rank.png b/assets/images/yu-gi-oh-gen/rank.png deleted file mode 100644 index e1cc6f87..00000000 Binary files a/assets/images/yu-gi-oh-gen/rank.png and /dev/null differ diff --git a/commands/edit-image/yu-gi-oh-gen.js b/commands/edit-image/yu-gi-oh-gen.js deleted file mode 100644 index 10e4ce63..00000000 --- a/commands/edit-image/yu-gi-oh-gen.js +++ /dev/null @@ -1,327 +0,0 @@ -const Command = require('../../framework/Command'); -const { PermissionFlagsBits } = require('discord.js'); -const { createCanvas, loadImage } = require('canvas'); -const request = require('node-superfetch'); -const path = require('path'); -const { stripIndents } = require('common-tags'); -const { list, firstUpperCase } = require('../../util/Util'); -const { wrapText } = require('../../util/Canvas'); -const types = ['monster', 'spell', 'trap']; -const monsterTypes = ['normal', 'effect', 'ritual', 'fusion', 'synchro', 'xyz', 'link', 'token']; -const atrs = ['dark', 'divine', 'earth', 'fire', 'laugh', 'light', 'water', 'wind']; - -module.exports = class YuGiOhGenCommand extends Command { - constructor(client) { - super(client, { - name: 'yu-gi-oh-gen', - aliases: ['ygo-gen', 'yu-gi-oh-generator', 'ygo-generator'], - group: 'edit-image', - memberName: 'yu-gi-oh-gen', - description: 'Draws an image or a user\'s avatar on a Yu-Gi-Oh! Trading Card with the text of your choice.', - throttling: { - usages: 2, - duration: 10 - }, - clientPermissions: [PermissionFlagsBits.AttachFiles], - credit: [ - { - name: 'Konami', - url: 'https://www.konami.com/en/', - reason: 'Images, Original "Yu-Gi-Oh!" Game', - reasonURL: 'https://www.yugioh-card.com/en/' - }, - { - name: 'sl777123', - url: 'https://www.deviantart.com/sl777123', - reason: 'Card Base Templates', - reasonURL: 'https://www.deviantart.com/sl777123/gallery/64574029/templates' - }, - { - name: 'icycatelf', - url: 'https://www.deviantart.com/icycatelf', - reason: 'Level/Rank Star Image', - reasonURL: 'https://www.deviantart.com/icycatelf/art/Level-Star-Template-PSD-607344453' - }, - { - name: 'bushin', - url: 'https://www.cardmaker.net/profile/220983-bushin/', - reason: 'Fonts', - // eslint-disable-next-line max-len - reasonURL: 'https://www.cardmaker.net/forums/topic/308603-fonts-for-yu-gi-oh-card-making-with-multilingual-support/' - } - ], - args: [ - { - key: 'type', - type: 'string', - oneOf: types, - parse: type => type.toLowerCase() - }, - { - key: 'image', - type: 'image-or-avatar', - default: msg => msg.author.displayAvatarURL({ extension: 'png', size: 1024 }) - } - ] - }); - } - - async run(msg, { type, image }) { - const id = Math.floor(Math.random() * 100000000); - const setID = Math.floor(Math.random() * 1000); - const monsterType = await this.determineMonsterType(msg, type); - if (!monsterType) return msg.say('Aborted card creation.'); - const name = await this.determineName(msg); - if (!name) return msg.say('Aborted card creation.'); - const attribute = await this.determineAttribute(msg, type); - if (!attribute) return msg.say('Aborted card creation.'); - const species = await this.determineType(msg, type); - if (!species) return msg.say('Aborted card creation.'); - const effect = await this.determineEffect(msg, monsterType); - if (!effect) return msg.say('Aborted card creation.'); - const level = await this.determineLevel(msg, type, monsterType); - if (!level) return msg.say('Aborted card creation.'); - const atk = await this.determineAttack(msg, type); - if (!atk) return msg.say('Aborted card creation.'); - const def = await this.determineDefense(msg, type, monsterType); - if (!def) return msg.say('Aborted card creation.'); - const base = await loadImage( - path.join(__dirname, '..', '..', 'assets', 'images', 'yu-gi-oh-gen', 'bases', `${monsterType}.png`) - ); - const atr = await loadImage( - path.join(__dirname, '..', '..', 'assets', 'images', 'yu-gi-oh-gen', 'atrs', `${attribute}.png`) - ); - const { body } = await request.get(image); - const data = await loadImage(body); - const canvas = createCanvas(base.width, base.height); - const ctx = canvas.getContext('2d'); - ctx.fillStyle = 'white'; - ctx.fillRect(0, 0, base.width, base.height); - ctx.drawImage(this.squareImage(data), 98, 217, 617, 617); - ctx.drawImage(base, 0, 0); - ctx.drawImage(atr, 686, 55 + (monsterType === 'link' ? 4 : 0), 70, 70); - if (level > 0) { - const levelToUse = monsterType === 'xyz' ? 'rank' : 'level'; - const levelI = await loadImage( - path.join(__dirname, '..', '..', 'assets', 'images', 'yu-gi-oh-gen', `${levelToUse}.png`) - ); - for (let i = 0; i < level; i++) { - let levelX; - if (monsterType === 'xyz') levelX = 76 + (50 * i) + (5 * i); - else levelX = 686 - (50 * i) - (5 * i); - ctx.drawImage(levelI, levelX, 141, 50, 50); - } - } - ctx.fillStyle = monsterType === 'xyz' || monsterType === 'link' ? 'white' : 'black'; - ctx.textBaseline = 'top'; - ctx.font = this.client.fonts.get('Matrix Small Caps.ttf').toCanvasString(87); - ctx.fillText(name, 60, 63, 620); - ctx.fillStyle = 'black'; - if (type === 'monster') { - ctx.font = this.client.fonts.get('Stone Serif Small Caps.ttf').toCanvasString(31); - let typeStr = `[ ${firstUpperCase(species)} / ${firstUpperCase(monsterType)}`; - if (monsterType !== 'normal' && monsterType !== 'effect' && monsterType !== 'token') { - typeStr += ' / Effect'; - } - typeStr += ' ]'; - ctx.fillText(typeStr, 60, 894); - ctx.font = this.client.fonts.get('Stone Serif.ttf').toCanvasString(29); - ctx.fillText(atk.padStart(4, ' '), 514, 1085); - if (monsterType === 'link') ctx.fillText(def, 722, 1085); - else ctx.fillText(def.padStart(4, ' '), 675, 1085); - } else if (type === 'spell') { - ctx.font = this.client.fonts.get('Stone Serif Small Caps.ttf').toCanvasString(35); - ctx.fillText('[ Spell Card ]', 479, 141); - } else if (type === 'trap') { - ctx.font = this.client.fonts.get('Stone Serif Small Caps.ttf').toCanvasString(35); - ctx.fillText('[ Trap Card ]', 489, 141); - } - const font = monsterType === 'normal' ? 'Stone Serif LT Italic.ttf' : 'Matrix Book.ttf'; - ctx.font = this.client.fonts.get(font).toCanvasString(27); - const wrappedEffect = wrapText(ctx, effect, 690); - const trimmed = wrappedEffect.slice(0, type === 'monster' ? 4 : 6); - ctx.fillText(trimmed.join('\n'), 63, 933 - (type === 'monster' ? 0 : 34)); - ctx.font = this.client.fonts.get('Stone Serif.ttf').toCanvasString(22); - ctx.fillStyle = monsterType === 'xyz' ? 'white' : 'black'; - ctx.fillText(id.toString().padStart(8, '0'), 43, 1128); - ctx.fillText(`XIAO-EN${setID.toString().padStart(3, '0')}`, 589 - (monsterType === 'link' ? 58 : 0), 849); - return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'yu-gi-oh-gen.png' }] }); - } - - squareImage(image) { - const dimensions = image.width <= image.height ? image.width : image.height; - const canvas = createCanvas(dimensions, dimensions); - const ctx = canvas.getContext('2d'); - ctx.drawImage(image, (canvas.width / 2) - (image.width / 2), 0); - return canvas; - } - - async determineMonsterType(msg, type) { - if (type !== 'monster') return type; - await msg.reply(stripIndents` - What kind of monster do you want to make? Either ${list(monsterTypes, 'or')}. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const filter = res => { - if (res.author.id !== msg.author.id) return false; - return res.content.toLowerCase() === 'cancel' || monsterTypes.includes(res.content.toLowerCase()); - }; - const msgs = await msg.channel.awaitMessages({ - filter, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res.toLowerCase(); - } - - async determineName(msg, monsterType) { - if (monsterType === 'token') return 'Token'; - await msg.reply(stripIndents` - What name should your card have? - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const msgs = await msg.channel.awaitMessages({ - filter: res => res.author.id === msg.author.id, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } - - async determineAttribute(msg, type) { - if (type !== 'monster') return type; - await msg.reply(stripIndents` - What attribute should your monster be? Either ${list(atrs, 'or')}. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const filter = res => { - if (res.author.id !== msg.author.id) return false; - return res.content.toLowerCase() === 'cancel' || atrs.includes(res.content.toLowerCase()); - }; - const msgs = await msg.channel.awaitMessages({ - filter, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res.toLowerCase(); - } - - async determineType(msg, type) { - if (type !== 'monster') return type; - await msg.reply(stripIndents` - What type should your monster be? For example, "Dragon". - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const msgs = await msg.channel.awaitMessages({ - filter: res => res.author.id === msg.author.id, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } - - async determineEffect(msg, monsterType) { - if (monsterType === 'token') return 'This card can be used as any Token.'; - await msg.reply(stripIndents` - What effect should your card have? - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const msgs = await msg.channel.awaitMessages({ - filter: res => res.author.id === msg.author.id, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } - - async determineLevel(msg, type, monsterType) { - if (type !== 'monster' || monsterType === 'link') return -1; - await msg.reply(stripIndents` - What ${monsterType === 'xyz' ? 'rank' : 'level'} should your monster be? From 0-12. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const filter = res => { - if (res.author.id !== msg.author.id) return false; - if (res.content.toLowerCase() === 'cancel') return true; - const int = Number.parseInt(res.content, 10); - return int >= 0 && int <= 12; - }; - const msgs = await msg.channel.awaitMessages({ - filter, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } - - async determineAttack(msg, type) { - if (type !== 'monster') return -1; - await msg.reply(stripIndents` - How much attack should your monster have? From 0-9999. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - const filter = res => { - if (res.author.id !== msg.author.id) return false; - if (res.content.toLowerCase() === 'cancel') return true; - const int = Number.parseInt(res.content, 10); - return int >= 0 && int <= 9999; - }; - const msgs = await msg.channel.awaitMessages({ - filter, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } - - async determineDefense(msg, type, monsterType) { - if (type !== 'monster') return -1; - if (monsterType === 'link') { - await msg.reply(stripIndents` - What link rating should your monster have? From 0-8. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - } else { - await msg.reply(stripIndents` - How much defense should your monster have? From 0-9999. - Respond with \`cancel\` to cancel the command. The command will automatically be cancelled in 60 seconds. - `); - } - const filter = res => { - if (res.author.id !== msg.author.id) return false; - if (res.content.toLowerCase() === 'cancel') return true; - const int = Number.parseInt(res.content, 10); - return int >= 0 && int <= (monsterType === 'link' ? 8 : 9999); - }; - const msgs = await msg.channel.awaitMessages({ - filter, - max: 1, - time: 60000 - }); - if (!msgs.size) return null; - const res = msgs.first().content; - if (res.toLowerCase() === 'cancel') return null; - return res; - } -};