From 6ac189235cd3419e585963908549a63db22a5908 Mon Sep 17 00:00:00 2001 From: Niels Simenon Date: Fri, 12 Nov 2021 16:43:20 +0100 Subject: [PATCH] Added ping and duck, showing category in trivia. --- config/default.js | 5 ++- src/app.js | 46 ++++++++++++++--------- src/games/duck.js | 89 +++++++++++++++++++++++++++++++++++++++++++++ src/games/ping.js | 10 +++++ src/games/trivia.js | 4 +- 5 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 src/games/duck.js create mode 100644 src/games/ping.js diff --git a/config/default.js b/config/default.js index 5b6d5ef..1377909 100644 --- a/config/default.js +++ b/config/default.js @@ -20,10 +20,13 @@ module.exports = { color: 'var(--message-56)', }, channels: ['GamesNight'], - games: ['mash', 'trivia'], + games: ['mash', 'trivia', 'ping', 'duck'], trivia: { mode: 'first', // first or timeout rounds: 10, timeout: 30, }, + duck: { + interval: [10, 3600], // seconds + }, }; diff --git a/src/app.js b/src/app.js index 7c98efd..ee0779f 100644 --- a/src/app.js +++ b/src/app.js @@ -47,7 +47,9 @@ async function getWsId(httpSession) { return res.body; } -async function setPoints(gameKey, user, value, mode = 'add') { +async function setPoints(defaultKey, user, value, { mode = 'add', key }) { + const gameKey = key || defaultKey; + if (!user) { logger.warn(`Failed to set ${gameKey} points for missing user`); return; @@ -70,14 +72,14 @@ async function setPoints(gameKey, user, value, mode = 'add') { await fs.writeFile(`./points-${instance}.json`, JSON.stringify(points, null, 4)); } -function getPoints(game, { user, room }) { - const userPoints = points[game.key]?.[`${user.id}:${user.username}`]; +function getPoints(game, { user, room, command }) { + const userPoints = (points[command] || points[game.key])?.[`${user.id}:${user.username}`]; game.sendMessage(`You have scored **${userPoints || 0}** points in ${game.name}, @${user.username}`, room.id); } -function getLeaderboard(game, { user, room }) { - const leaderboard = points[game.key]; +function getLeaderboard(game, { user, room, command }) { + const leaderboard = points[command] || points[game.key]; if (!leaderboard || Object.keys(leaderboard).length === 0) { game.sendMessage(`No points scored in ${game.name} yet!`, room.id); @@ -138,12 +140,12 @@ function onMessage(message, bot, games) { const room = bot.rooms[message.roomId]; if (['leaderboard', 'lead', 'leader', 'leaders', 'scoreboard', 'best'].includes(subcommand) && games[command]) { - getLeaderboard(games[command], { user, room }); + getLeaderboard(games[command], { user, room, command }); return; } if (['points', 'score'].includes(subcommand) && games[command]) { - getPoints(games[command], { user, room }); + getPoints(games[command], { user, room, command }); return; } @@ -151,13 +153,14 @@ function onMessage(message, bot, games) { const args = message.body.split(/\s+/).slice(1); const game = games[command]; - if (game) { + if (game && game.onCommand) { if (user) { user.points = points[game.key]?.[`${user.id}:${user.username}`] || 0; } - games[command].onCommand(args, { + game.onCommand(args, { ...game, + command, subcommand, bot, message, @@ -214,18 +217,25 @@ function getGames(bot) { }); }; - const setGamePoints = (userId, score, mode) => setPoints(key, userId, score, mode); + const setGamePoints = (userId, score, options) => setPoints(key, userId, score, options); + + const curatedGame = { + ...game, + ...(key.game && key), + name: game.name || key, + key, + sendMessage, + setPoints: setGamePoints, + }; + + if (game.onStart) { + game.onStart({ ...curatedGame, bot }); + } return { ...acc, - [key]: { - ...game, - ...(key.game && key), - name: game.name || key, - key, - sendMessage, - setPoints: setGamePoints, - }, + [key]: curatedGame, + ...game.commands?.reduce((commandAcc, command) => ({ ...commandAcc, [command]: curatedGame }), {}), }; }, {}); diff --git a/src/games/duck.js b/src/games/duck.js new file mode 100644 index 0000000..30627f9 --- /dev/null +++ b/src/games/duck.js @@ -0,0 +1,89 @@ +'use strict'; + +const config = require('config'); + +const ducks = new Map(); +let shots = new Map(); + +function launchDuck(context) { + ducks.delete(context.room?.id); + shots = new Map(); + + const interval = Array.isArray(config.duck.interval) + ? ((Math.random() * (config.duck.interval[1] - config.duck.interval[0])) + config.duck.interval[0]) * 1000 + : config.duck.interval * 1000; + + setTimeout(() => { + if (context.bot.rooms.length === 0) { + return; + } + + const rooms = Object.values(context.bot.rooms); + const room = rooms[Math.floor(Math.random() * rooms.length)]; + + ducks.set(room.id, new Date()); + context.sendMessage('Quack! :duck:', room.id); + }, interval); +} + +function onCommand(args, context) { + const duck = ducks.get(context.room.id); + + if (!duck) { + context.sendMessage(`There is no duck, what are you shooting at, @${context.user.username}?!`, context.room.id); + return; + } + + const hit = Math.random() > 0.3; + const time = ((new Date().getTime() - duck.getTime()) / 1000).toFixed(3); + + if (context.command === 'bang') { + if (hit) { + context.sendMessage(`You shot a duck in **${time} seconds**, @${context.user.username}`, context.room.id); + launchDuck(context); + + context.setPoints(context.user, 1, { key: 'bang' }); + + return; + } + + const messages = [ + `How could you miss *that*, @${context.user.username}...?!`, + `Better luck next time, @${context.user.username}.`, + `The duck got away, @${context.user.username}`, + `Channeling Gareth Southgate, @${context.user.username}? You missed!`, + ]; + + shots.set(context.user.id, new Date()); + context.sendMessage(messages[Math.floor(Math.random() * messages.length)], context.room.id); + + return; + } + + if (['bef', 'befriend'].includes(context.command)) { + if (hit) { + context.sendMessage(`You befriended a duck in **${time} seconds**, @${context.user.username}`, context.room.id); + launchDuck(context); + + context.setPoints(context.user, 1, { key: 'befriend' }); + + return; + } + + const messages = [ + `The duck does not want to be your friend right now, @${context.user.username}`, + `The duck would like some time for itself, @${context.user.username}`, + `The duck isn't in the mood right now, @${context.user.username}`, + ]; + + shots.set(context.user.id, new Date()); + context.sendMessage(messages[Math.floor(Math.random() * messages.length)], context.room.id); + } +} + +module.exports = { + name: 'Duck', + commands: ['bang', 'bef', 'befriend'], + onStart: launchDuck, + onCommand, +}; diff --git a/src/games/ping.js b/src/games/ping.js new file mode 100644 index 0000000..4634d2a --- /dev/null +++ b/src/games/ping.js @@ -0,0 +1,10 @@ +'use strict'; + +function onCommand(args, context) { + context.sendMessage(`Pong, @${context.user.username}!`, context.room.id); +} + +module.exports = { + name: 'Ping', + onCommand, +}; diff --git a/src/games/trivia.js b/src/games/trivia.js index 2dae114..2839733 100644 --- a/src/games/trivia.js +++ b/src/games/trivia.js @@ -50,7 +50,7 @@ async function playRound(context, round = 0) { const question = game.questions[round]; - context.sendMessage(`**Question ${round + 1}/${game.questions.length}**: ${question.question}`, context.room.id); + context.sendMessage(`**Question ${round + 1}/${game.questions.length}** (${question.category}): ${question.question}`, context.room.id); context.logger.info(`Trivia asked "${question.question}" with answer: ${question.answer}`); try { @@ -163,7 +163,7 @@ function onCommand(args, context) { } async function onMessage(message, context) { - if (!game) { + if (!game || context.user.id === config.user.id) { return; }