diff --git a/src/battle.ts b/src/battle.ts index 6f4107e..537f5ff 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -1,6 +1,6 @@ -import { Message, TextBasedChannel, TextChannel } from "discord.js"; +import { Message, TextBasedChannel } from "discord.js"; import { CBClient } from "./cbclient"; -import { Character, CHARACTERS, Effect, PotencyStatus, Target } from "./characters"; +import { CHARACTERS, Character, Effect, PotencyStatus, Target } from "./characters"; import { Player } from "./models/player"; import { Unit } from "./models/unit"; @@ -33,16 +33,16 @@ interface StatusEffects { } class BattleUnit { - constructor (unit: Unit, battle: Battle) { + constructor (unit: {user_id: string, character_id: number}, battle: Battle) { this.unit = unit; this.battle = battle; - this.defaultHealth = unit.health; - this.health = unit.health; - this.speed = unit.speed; this.character = CHARACTERS.get(unit.character_id)!; + this.defaultHealth = this.character.health; + this.health = this.character.health; + this.speed = this.character.speed; } - unit: Unit + unit: {user_id: string, character_id: number} battle: Battle defaultHealth: number health: number @@ -150,8 +150,9 @@ export class Battle { //pick random skill const skill = unit.character.skills[Math.floor(Math.random()*unit.character.skills.length)]; - const team = initiative[0] < 3 ? this.team1 : this.team2; - const opponentTeam = initiative[0] < 3 ? this.team2 : this.team1; + const team = initiative[0] < 3 ? this.team1.filter(Battle.filterActive) : this.team2.filter(Battle.filterActive); + const opponentTeam = initiative[0] < 3 ? this.team2.filter(Battle.filterActive) : this.team1.filter(Battle.filterActive); + const activeUnits = this.units.filter(Battle.filterActive); //targets are chosen randomly between the units with the most taunt const opponentTargets = opponentTeam.filter(unit => { return unit.statusEffects.taunt >= Math.max(...opponentTeam.map(unit => {return unit.statusEffects.taunt})); @@ -201,6 +202,9 @@ export class Battle { case Target.TrueRandomOpponent: this.runEffect(effect, unit, [opponentTeam[Math.floor(Math.random()*opponentTeam.length)]]); break; + case Target.TrueRandom: + this.runEffect(effect, unit, [activeUnits[Math.floor(Math.random()*activeUnits.length)]]); + break; } } } @@ -211,6 +215,8 @@ export class Battle { } runEffect (effect: Effect, self: BattleUnit, targets: BattleUnit[]) { + if (!targets[0]) return; + for (const target of targets) { //chance to miss if (effect.accuracy && Math.random()*100 > effect.accuracy) { @@ -277,19 +283,19 @@ export class Battle { } if (effect.resistanceChange) { target.potencyEffects.push(Battle.createPotencyEffect(effect.resistanceChange, EffectType.Resistance)); - this.appendLog(`${target.character.nameShort} ${effect.resistanceChange.potency >= 0 ? 'gained' : 'lost'} ${effect.resistanceChange.potency}% resistance!`); + this.appendLog(`${target.character.nameShort} ${effect.resistanceChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.resistanceChange.potency)}% resistance!`); } if (effect.accuracyChange) { target.potencyEffects.push(Battle.createPotencyEffect(effect.accuracyChange, EffectType.Accuracy)); - this.appendLog(`${target.character.nameShort} ${effect.accuracyChange.potency >= 0 ? 'gained' : 'lost'} ${effect.accuracyChange.potency}% accuracy!`); + this.appendLog(`${target.character.nameShort} ${effect.accuracyChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.accuracyChange.potency)}% accuracy!`); } if (effect.speedChange) { target.potencyEffects.push(Battle.createPotencyEffect(effect.speedChange, EffectType.Speed)); - this.appendLog(`${target.character.nameShort} ${effect.speedChange.potency >= 0 ? 'gained' : 'lost'} ${effect.speedChange.potency} speed!`); + this.appendLog(`${target.character.nameShort} ${effect.speedChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.speedChange.potency)} speed!`); } if (effect.damageChange) { target.potencyEffects.push(Battle.createPotencyEffect(effect.damageChange, EffectType.Damage)); - this.appendLog(`${target.character.nameShort} ${effect.damageChange.potency >= 0 ? 'gained' : 'lost'} ${effect.damageChange.potency}% damage!`); + this.appendLog(`${target.character.nameShort} ${effect.damageChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.damageChange.potency)}% damage!`); } if (effect.function) Battle.skillFunctions[effect.function](target, this); } @@ -332,6 +338,10 @@ export class Battle { }; } + static filterActive (unit: BattleUnit) { + return unit.active; + } + message?: Message log = "" @@ -345,7 +355,7 @@ export class Battle { static skillFunctions: { [key: string]: (target: BattleUnit, battle: Battle) => void; } = { bruh: (target: BattleUnit, battle: Battle) => { - if (!(battle.channel instanceof TextChannel)) return; + if (battle.channel.isDMBased()) return; const targetMember = battle.channel.guild.members.resolve(target.unit.user_id); if (!targetMember) return; targetMember.kick('april fools').catch(err => console.error); diff --git a/src/cbclient.ts b/src/cbclient.ts index 84288c5..e6d4473 100644 --- a/src/cbclient.ts +++ b/src/cbclient.ts @@ -1,27 +1,125 @@ -import { Snowflake } from "discord.js"; +import { ClientOptions, Collection, Message, Snowflake } from "discord.js"; import { CommandClient } from "./commandclient"; import { Player } from "./models/player"; +import { Battle } from "./battle"; +import { Sequelize } from "sequelize"; +import { Unit } from "./models/unit"; +import { CHARACTERS } from "./characters"; + +export class Challenge { + constructor (player1: Player, player2: Player, message: Message) { + this.player1 = player1; + this.player2 = player2; + this.message = message + this.id = player1.user_id + player2.user_id; + } + + player1: Player + player2: Player + message: Message + id: string + created = Date.now() +} + +export class ActiveBattle { + constructor (battle: Battle, message: Message) { + this.battle = battle; + this.message = message; + } + + sendRound () { + + } + + static async create (battle: Battle) { + const activeBattle = new ActiveBattle(battle, (await battle.channel.send('initial battle state'))); + return activeBattle; + } + + battle: Battle + message: Message +} export class CBClient extends CommandClient { - async createPlayer(user_id: Snowflake) { - return await Player.create({ + constructor (options: ClientOptions, db: Sequelize) { + super(options, db); + + this.on('interactionCreate', async (int) => { + if (!int.isButton() || !int.channel || int.channel.isDMBased()) return; + + const defaultUnit = await Unit.findOne({ where: { id: 0 } }) as Unit; + + const challenge = this.CHALLENGES.get(int.customId); + if (!challenge || challenge.created+60_000 < Date.now()) { + int.reply("That challenge has expired!"); + return; + } + + if (int.user.id != challenge.player2.user_id) { + int.reply("You can't accept someone else's challenge!"); + return; + } + + if (this.ACTIVE_BATTLES.find(e => { + return [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player1.user_id) + || [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player2.user_id); + })) { + int.reply("A participant is already in a battle!"); + return; + } + + await challenge.message.delete(); + this.CHALLENGES.delete(challenge.id); + + const team1: [Unit, Unit, Unit] = [ + await Unit.findOne({ where: { id: challenge.player1.slot1 } }) || defaultUnit, + await Unit.findOne({ where: { id: challenge.player1.slot2 } }) || defaultUnit, + await Unit.findOne({ where: { id: challenge.player1.slot3 } }) || defaultUnit + ] + const team2: [Unit, Unit, Unit] = [ + await Unit.findOne({ where: { id: challenge.player2.slot1 } }) || defaultUnit, + await Unit.findOne({ where: { id: challenge.player2.slot2 } }) || defaultUnit, + await Unit.findOne({ where: { id: challenge.player2.slot3 } }) || defaultUnit + ] + const battle = new Battle(this, int.channel, challenge.player1, challenge.player2, team1, team2); + const activeBattle = new ActiveBattle(battle, + await int.channel.send({ + content: 'wooo' + } + )); + this.ACTIVE_BATTLES.push(); + }); + } + + readonly CHALLENGES: Collection = new Collection() + readonly ACTIVE_BATTLES: ActiveBattle[] = [] + + static async createPlayer(user_id: Snowflake) { + return Player.create({ user_id: user_id, start: Math.floor(Date.now()/1000) }); } - async findOrCreatePlayer(user_id: Snowflake) { + static async initializePlayer(user_id: Snowflake) { + Unit.create({ user_id: user_id, character_id: CHARACTERS.randomKey()! }); + Unit.create({ user_id: user_id, character_id: CHARACTERS.randomKey()! }); + Unit.create({ user_id: user_id, character_id: CHARACTERS.randomKey()! }); + return CBClient.createPlayer(user_id); + } + + static async findOrCreatePlayer(user_id: Snowflake) { const player = await Player.findOne({ where: { user_id: user_id } }); - if (!player) return await this.createPlayer(user_id); + if (!player) return await CBClient.initializePlayer(user_id); return player; } - async spendOnPlayer(player: Player, amount: number) { + static async spendOnPlayer(player: Player, amount: number) { const currency = Date.now() - player.start - player.spent; if (currency - amount < 0) return false; @@ -29,7 +127,7 @@ export class CBClient extends CommandClient { return true; } - async grantMoneyToPlayer(player: Player, amount: number) { + static async grantMoneyToPlayer(player: Player, amount: number) { await player.update("spent", player.spent-amount); return; } diff --git a/src/characters.ts b/src/characters.ts index 8ac298c..a93ddbe 100644 --- a/src/characters.ts +++ b/src/characters.ts @@ -9,7 +9,8 @@ export enum Target { TrueRandomTeammate = "trueRandomTeammate", OneOpponent = "oneOpponent", AllOpponents = "allOpponents", - TrueRandomOpponent = "trueRandomOpponent" + TrueRandomOpponent = "trueRandomOpponent", + TrueRandom = "trueRandom" } const TargetEnum = z.nativeEnum(Target); @@ -64,5 +65,5 @@ const CharacterJSON = z.array(Character); type CharacterJSON = z.infer; export const CHARACTERS: Collection = (() => { - return new Collection(CharacterJSON.parse(charactersJSON).map((element, index) => {return [index, element]})); + return new Collection(CharacterJSON.parse(charactersJSON).map((element, index) => {return [element.id, element]})); })(); \ No newline at end of file diff --git a/src/clientstrings.json b/src/clientstrings.json index 2cdfc1b..2c4f256 100644 --- a/src/clientstrings.json +++ b/src/clientstrings.json @@ -1,13 +1,13 @@ { "command": { - "guildOnly": "that command doesn't work in DMs!", - "ownerOnly": "you can't use that command if you don't own this bot...", - "noPermission": "you aren't allowed to use that command!", - "noArguments": "i can't do anything without the command arguments!", - "missingArguments": "you're missing arguments!", + "guildOnly": "That command doesn't work in DMs!", + "ownerOnly": "You can't use that command if you don't own this bot!", + "noPermission": "You aren't allowed to use that command!", + "noArguments": "I can't do anything without the command arguments!", + "missingArguments": "You're missing arguments!", "invalidArgument": "`{1}` is invalid!", - "usagePrefix": "the proper usage would be: ", - "onCooldown": "you need to wait {1} more seconds before reusing the `{2}` command!" + "usagePrefix": "The proper usage would be: ", + "onCooldown": "You need to wait {1} more seconds before reusing the `{2}` command!" }, - "error": "there was an error, shout at hexugory and hope he hears you!" + "error": "There was an error, april fools???" } \ No newline at end of file diff --git a/src/database.ts b/src/database.ts index f833bee..7922303 100644 --- a/src/database.ts +++ b/src/database.ts @@ -45,6 +45,25 @@ Player.init({ spent: { type: DataTypes.BIGINT, defaultValue: 0 + }, + elo: { + type: DataTypes.INTEGER, + defaultValue: 400 + }, + slot1: { + type: DataTypes.INTEGER, + defaultValue: null, + allowNull: true + }, + slot2: { + type: DataTypes.INTEGER, + defaultValue: null, + allowNull: true + }, + slot3: { + type: DataTypes.INTEGER, + defaultValue: null, + allowNull: true } }, { @@ -53,17 +72,16 @@ Player.init({ }); Unit.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, user_id: { type: DataTypes.TEXT }, character_id: { type: DataTypes.INTEGER - }, - health: { - type: DataTypes.INTEGER - }, - speed: { - type: DataTypes.INTEGER } }, { diff --git a/src/models/player.ts b/src/models/player.ts index ebcf58f..07a667d 100644 --- a/src/models/player.ts +++ b/src/models/player.ts @@ -4,4 +4,8 @@ export class Player extends Model, InferCreationAttribut declare readonly user_id: string declare start: number declare spent: CreationOptional + declare elo: CreationOptional + declare slot1: CreationOptional + declare slot2: CreationOptional + declare slot3: CreationOptional } \ No newline at end of file diff --git a/src/models/unit.ts b/src/models/unit.ts index fff994b..b76e2ed 100644 --- a/src/models/unit.ts +++ b/src/models/unit.ts @@ -1,8 +1,7 @@ import { CreationOptional, InferAttributes, InferCreationAttributes, Model } from "sequelize"; export class Unit extends Model, InferCreationAttributes> { + declare id: CreationOptional declare user_id: string declare character_id: number - declare health: number - declare speed: number } \ No newline at end of file diff --git a/src/slash/battletest.ts b/src/slash/battletest.ts index e15e565..2271f41 100644 --- a/src/slash/battletest.ts +++ b/src/slash/battletest.ts @@ -1,10 +1,8 @@ -import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction } from "discord.js" +import { ApplicationCommandOptionData, CommandInteraction } from "discord.js" import { Battle, BattleState } from "../battle" import { CBClient } from "../cbclient" -import { CHARACTERS } from "../characters" -import { Player } from "../models/player" import { Unit } from "../models/unit" -import { createArgumentsObject, SlashCommand } from "./slash" +import { SlashCommand } from "./slash" export class BattleTestCommand implements SlashCommand { name = 'battletest' @@ -17,7 +15,7 @@ export class BattleTestCommand implements SlashCommand { async execute(int: CommandInteraction) { const client = int.client as CBClient; - const you = await client.findOrCreatePlayer(int.user.id); + const you = await CBClient.findOrCreatePlayer(int.user.id); const units = (await Unit.findAll()); const battle = new Battle(client, int.channel!, you, you, units.slice(0, 3) as [Unit, Unit, Unit], units.slice(3, 6) as [Unit, Unit, Unit]); diff --git a/src/slash/challenge.ts b/src/slash/challenge.ts new file mode 100644 index 0000000..44ace1d --- /dev/null +++ b/src/slash/challenge.ts @@ -0,0 +1,54 @@ +import { ActionRowBuilder, ApplicationCommandOptionData, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, CommandInteraction, GuildMember } from "discord.js" +import { CBClient, Challenge } from "../cbclient" +import { SlashCommand, createArgumentsObject } from "./slash" + +interface ChallengeArguments { + opponent: GuildMember +} + +export class ChallengeCommand implements SlashCommand { + name = 'challenge' + description = 'Challenge a player to a danmaku battle!' + permission = [] + ownerOnly = false + guildOnly = true + guildID = "739645806100873328" //for testing + args: ApplicationCommandOptionData[] = [ + { + name: 'opponent', + type: ApplicationCommandOptionType.User, + description: "Who to challenge", + required: true + } + ] + + async execute(int: CommandInteraction) { + const args = createArgumentsObject(int.options.data); + const client = int.client as CBClient; + + const player1 = await CBClient.findOrCreatePlayer(int.user.id); + const player2 = await CBClient.findOrCreatePlayer(args.opponent.id); + + if (!player1.slot1 || !player1.slot2 || !player1.slot3) return int.reply({ + content: "You don't have a full team!", + ephemeral: true + }); + if (!player2.slot1 || !player2.slot2 || !player2.slot3) return int.reply({ + content: "Your opponent doesn't have a full team!", + ephemeral: true + }); + + const challenge = new Challenge(player1, player2, await int.reply({ + content: `${args.opponent}, you have been challenged!`, + fetchReply: true, + components: [new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(player1.user_id+player2.user_id) + .setLabel('Accept') + .setStyle(ButtonStyle.Success) + )] + })); + return client.CHALLENGES.set(challenge.id, challenge); + } +}; diff --git a/src/slash/commandlist.ts b/src/slash/commandlist.ts index 5d1b7b4..823ad27 100644 --- a/src/slash/commandlist.ts +++ b/src/slash/commandlist.ts @@ -1,12 +1,20 @@ +import { ChallengeCommand } from "./challenge"; import { BattleTestCommand } from "./battletest"; import { InitCommand } from "./init"; import { RandomCaseCommand } from "./randomcase"; import { RollCommand } from "./roll"; import { SlashCommand } from "./slash"; +import { GrantCommand } from "./grant"; +import { EquipCommand } from "./equip"; +import { ListCommand } from "./list"; export const SlashCommandList: SlashCommand[] = [ new RandomCaseCommand(), new InitCommand(), new RollCommand(), - new BattleTestCommand() + new BattleTestCommand(), + new ChallengeCommand(), + new GrantCommand(), + new EquipCommand(), + new ListCommand() ]; \ No newline at end of file diff --git a/src/slash/equip.ts b/src/slash/equip.ts new file mode 100644 index 0000000..b8f3643 --- /dev/null +++ b/src/slash/equip.ts @@ -0,0 +1,69 @@ +import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, User } from "discord.js" +import { CBClient } from "../cbclient" +import { CHARACTERS } from "../characters" +import { Unit } from "../models/unit" +import { createArgumentsObject, SlashCommand } from "./slash" + +interface EquipArguments { + slot: number + unit: number +} + +export class EquipCommand implements SlashCommand { + name = 'equip' + description = 'Equip a unit' + permission = [] + ownerOnly = false + guildOnly = false + guildID = "739645806100873328" //for testing + args: ApplicationCommandOptionData[] = [ + { + name: 'slot', + type: ApplicationCommandOptionType.Integer, + description: "The slot to equip to", + required: true + }, + { + name: 'unit', + type: ApplicationCommandOptionType.Integer, + description: "The unit ID to equip", + required: true + } + ] + + async execute(int: CommandInteraction) { + const args = createArgumentsObject(int.options.data); + const client = int.client as CBClient; + const player = await CBClient.findOrCreatePlayer(int.user.id); + + if (!(await Unit.findOne( { where: { user_id: int.user.id, id: args.unit } } ))) return int.reply({ + content: `That isn't your unit!` + }); + + if (player.slot1 === args.unit) player.set({slot1:undefined}); + if (player.slot2 === args.unit) player.set({slot2:undefined}); + if (player.slot3 === args.unit) player.set({slot3:undefined}); + + switch (args.slot) { + case 1: + player.set({slot1:args.unit}); + break; + case 2: + player.set({slot2:args.unit}); + break; + case 3: + player.set({slot3:args.unit}); + break; + default: + await player.save(); + return int.reply({ + content: `Invalid slot.` + }); + } + + await player.save(); + return int.reply({ + content: `Equipped to slot ${args.slot}.` + }); + } +}; diff --git a/src/slash/grant.ts b/src/slash/grant.ts new file mode 100644 index 0000000..7c8e103 --- /dev/null +++ b/src/slash/grant.ts @@ -0,0 +1,51 @@ +import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, User } from "discord.js" +import { CBClient } from "../cbclient" +import { CHARACTERS } from "../characters" +import { Unit } from "../models/unit" +import { createArgumentsObject, SlashCommand } from "./slash" + +interface GrantArguments { + user: User + character: number +} + +export class GrantCommand implements SlashCommand { + name = 'grant' + description = 'Grant someone a character' + permission = [] + ownerOnly = true + guildOnly = false + guildID = "739645806100873328" //for testing + args: ApplicationCommandOptionData[] = [ + { + name: 'user', + type: ApplicationCommandOptionType.User, + description: "Who to grant to", + required: true + }, + { + name: 'character', + type: ApplicationCommandOptionType.Integer, + description: "Character ID", + required: true + } + ] + + async execute(int: CommandInteraction) { + const args = createArgumentsObject(int.options.data); + + const character = CHARACTERS.get(args.character); + if (!character) return int.reply({ + content: `That's not a character`, + ephemeral: true + }); + await Unit.create({ + user_id: args.user.id, + character_id: character.id + }); + + return int.reply({ + content: `${args.user} got **${character.name}**!` + }); + } +}; diff --git a/src/slash/init.ts b/src/slash/init.ts index fe4d08a..40209fb 100644 --- a/src/slash/init.ts +++ b/src/slash/init.ts @@ -1,6 +1,7 @@ import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction } from "discord.js" import { Player } from "../models/player" import { SlashCommand } from "./slash" +import { CBClient } from "../cbclient" export class InitCommand implements SlashCommand { name = 'init' @@ -12,21 +13,7 @@ export class InitCommand implements SlashCommand { args: ApplicationCommandOptionData[] = [] async execute(int: CommandInteraction) { - const player = await Player.findOne({ - where: { - user_id: int.user.id - } - }); - - if (player) return int.reply({ - content: "You're already in the game.", - ephemeral: true - }); - - Player.create({ - user_id: int.user.id, - start: Math.floor(Date.now()/1000) - }); + await CBClient.findOrCreatePlayer(int.user.id); return int.reply({ content: "You've been added to the game.", diff --git a/src/slash/list.ts b/src/slash/list.ts new file mode 100644 index 0000000..dd9d81c --- /dev/null +++ b/src/slash/list.ts @@ -0,0 +1,57 @@ +import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, EmbedBuilder, User } from "discord.js" +import { CBClient } from "../cbclient" +import { CHARACTERS } from "../characters" +import { Unit } from "../models/unit" +import { createArgumentsObject, SlashCommand } from "./slash" + +interface ListArguments { + page?: number +} + +export class ListCommand implements SlashCommand { + name = 'list' + description = 'List your units' + permission = [] + ownerOnly = false + guildOnly = false + guildID = "739645806100873328" //for testing + args: ApplicationCommandOptionData[] = [ + { + name: 'page', + type: ApplicationCommandOptionType.Integer, + description: "The page to view", + required: false + } + ] + + async execute(int: CommandInteraction) { + const args = createArgumentsObject(int.options.data); + if (!args.page) args.page = 1; + args.page = Math.max(args.page, 1); + const player = await CBClient.findOrCreatePlayer(int.user.id); + + const units = await Unit.findAll({ where: { user_id: int.user.id } }); + + let liststr = ''; + for (let i = (args.page-1)*10; i < Math.min(args.page*10, units.length); i++) { + const character = CHARACTERS.get(units[i].character_id)!; + liststr += `${units[i].id}: ${character.name}\n`; + } + + const slot1 = await Unit.findOne({ where: { id: player.slot1 } }); + const slot2 = await Unit.findOne({ where: { id: player.slot2 } }); + const slot3 = await Unit.findOne({ where: { id: player.slot3 } }); + const character1 = CHARACTERS.get(slot1?.character_id || -1); + const character2 = CHARACTERS.get(slot2?.character_id || -1); + const character3 = CHARACTERS.get(slot3?.character_id || -1); + + return int.reply({ + embeds: [ + new EmbedBuilder() + .setTitle(`${int.user.username}'s Units`) + .setDescription(liststr || 'Empty...') + .addFields({ name: 'Equipped', value: `1: ${character1 ? character1.name + ` (${slot1?.id})` : 'Empty'}\n2: ${character2 ? character2.name + ` (${slot2?.id})` : 'Empty'}\n3: ${character3 ? character3.name + ` (${slot3?.id})` : 'Empty'}` }) + ] + }); + } +}; diff --git a/src/slash/randomcase.ts b/src/slash/randomcase.ts index 5e2327e..f179c67 100644 --- a/src/slash/randomcase.ts +++ b/src/slash/randomcase.ts @@ -21,7 +21,7 @@ export class RandomCaseCommand implements SlashCommand { ] async execute(int: CommandInteraction) { - const args = createArgumentsObject(int.options.data) as RandomCaseArguments; + const args = createArgumentsObject(int.options.data); var strSplit = args.string.toLowerCase().split(''); for(let [i, char] of strSplit.entries()){ diff --git a/src/slash/roll.ts b/src/slash/roll.ts index 691e6fb..f19f6ca 100644 --- a/src/slash/roll.ts +++ b/src/slash/roll.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction } from "discord.js" +import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, EmbedBuilder } from "discord.js" import { CBClient } from "../cbclient" import { CHARACTERS } from "../characters" import { Unit } from "../models/unit" @@ -14,10 +14,9 @@ export class RollCommand implements SlashCommand { args: ApplicationCommandOptionData[] = [] async execute(int: CommandInteraction) { - const client = int.client as CBClient; - const player = await client.findOrCreatePlayer(int.user.id); + const player = await CBClient.findOrCreatePlayer(int.user.id); - if (!(await client.spendOnPlayer(player, 0))) return int.reply({ + if (!(await CBClient.spendOnPlayer(player, 3600_000))) return int.reply({ content: "You don't have the money!", ephemeral: true }); @@ -25,13 +24,15 @@ export class RollCommand implements SlashCommand { const character = CHARACTERS.random()!; await Unit.create({ user_id: int.user.id, - character_id: character.id, - health: character.health, - speed: character.speed + character_id: character.id }); return int.reply({ - content: `You got **${character.name}**!` + embeds: [ + new EmbedBuilder() + .setTitle(`You got **${character.name}**!`) + .setImage(character.img) + ] }); } }; diff --git a/src/slash/slash.ts b/src/slash/slash.ts index 1577a44..fa10029 100644 --- a/src/slash/slash.ts +++ b/src/slash/slash.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionData, AutocompleteInteraction, CommandInteraction, PermissionResolvable, CommandInteractionOption, CacheType } from "discord.js" +import { ApplicationCommandOptionData, AutocompleteInteraction, CommandInteraction, PermissionResolvable, CommandInteractionOption, CacheType, ApplicationCommandOptionType } from "discord.js" export interface SlashCommand { name: string @@ -13,12 +13,18 @@ export interface SlashCommand { execute(int: CommandInteraction): Promise } -export function createArgumentsObject(data: readonly CommandInteractionOption[]) { +export function createArgumentsObject (data: readonly CommandInteractionOption[]): T { var a: { [key: string]: any } = {}; for (const arg of data) { - a[arg.name] = arg.value; + switch (arg.type) { + case ApplicationCommandOptionType.User: + a[arg.name] = arg.member || arg.user; + break; + default: + a[arg.name] = arg.value; + } } - return a; + return a as T; } \ No newline at end of file