Files
2024-04-06 18:16:23 -04:00

106 lines
3.0 KiB
JavaScript

const { Collection } = require('@discordjs/collection');
const path = require('path');
const { stripIndents } = require('common-tags');
const Player = require('./Player');
const { shuffle, reactIfAble } = require('../../util/Util');
const { AudioPlayerStatus } = require('@discordjs/voice');
const { SUCCESS_EMOJI_ID } = process.env;
module.exports = class Game {
constructor(client, channel, connection) {
Object.defineProperty(this, 'client', { value: client });
this.name = 'mafia';
this.players = new Collection();
this.channel = channel;
this.connection = connection;
this.turn = 1;
}
determineRoles(playerCount) {
const roles = ['detective', 'mafia', 'mafia'];
for (let i = 0; i < (playerCount - 3); i++) roles.push('innocent');
return shuffle(roles);
}
async generate(list) {
const roles = this.determineRoles(list.length);
let i = 0;
for (const user of list) {
try {
await user.send(`You are ${roles[i] === 'detective' ? 'the' : 'a part of the'} **${roles[i]}**.`);
} catch {
await this.channel.send(
`${user}, I couldn't send a DM to you. Please open your DMs and use the \`me\` command to see your role.`
);
}
const player = new Player(this, user, roles[i]);
this.players.set(user.id, player);
i++;
}
return this.players;
}
playAudio(id) {
this.connection.play(
path.join(__dirname, '..', '..', 'assets', 'sounds', 'mafia', `${id}.mp3`), { volume: 2 }
);
return new Promise((res, rej) => {
this.dispatcher.once(AudioPlayerStatus.Idle, () => res(true));
this.dispatcher.once('error', err => rej(err));
});
}
async getVotes(playersArr) {
await this.channel.send(stripIndents`
Who do you think is a Mafia member? Please type the number.
${playersArr.map((p, i) => `**${i + 1}.** ${p.user.tag}`).join('\n')}
`);
const voted = [];
const filter = res => {
if (!this.players.some(p => p.user.id === res.author.id)) return false;
if (voted.includes(res.author.id)) return false;
if (!playersArr[Number.parseInt(res.content, 10) - 1]) return false;
voted.push(res.author.id);
reactIfAble(res, res.author, SUCCESS_EMOJI_ID, '✅');
return true;
};
const votes = await this.channel.awaitMessages({
filter,
max: this.players.size,
time: 90000
});
if (!votes.size) return null;
return votes;
}
getHanged(votes, playersArr) {
const counts = new Collection();
for (const vote of votes.values()) {
const player = this.players.get(playersArr[Number.parseInt(vote.content, 10) - 1].id);
if (counts.has(player.id)) {
++counts.get(player.id).votes;
} else {
counts.set(player.id, {
id: player.id,
votes: 1,
user: player.user
});
}
}
return counts.sort((a, b) => b.votes - a.votes).first();
}
get shouldEnd() {
return this.players.size < 4 && !this.players.some(p => p.role === 'mafia');
}
get voiceChannel() {
return this.connection.channel;
}
get dispatcher() {
return this.client.dispatchers.get(this.channel.guild.id);
}
};