{ "version": 3, "sources": ["../../../../server/chat-plugins/scavenger-games.ts"], "sourcesContent": ["/**\r\n * Scavengers Games Plugin\r\n * Pokemon Showdown - http://pokemonshowdown.com/\r\n *\r\n * This plugin stores the different possible game modes and twists that take place in scavengers room\r\n *\r\n * @license MIT license\r\n */\r\n\r\nimport {ScavengerHunt, ScavengerHuntPlayer} from './scavengers';\r\nimport {Utils} from '../../lib';\r\n\r\nexport type TwistEvent = (this: ScavengerHunt, ...args: any[]) => void;\r\ninterface Twist {\r\n\tname: string;\r\n\tid: string;\r\n\tisGameMode?: true;\r\n\tdesc?: string;\r\n\t[eventid: string]: string | number | TwistEvent | boolean | undefined;\r\n}\r\n\r\ntype GameModeFunction = (this: ScavengerGameTemplate, ...args: any[]) => void;\r\ninterface GameMode {\r\n\tname: string;\r\n\tid: string;\r\n\tmod: Twist;\r\n\tround?: number;\r\n\tleaderboard?: true;\r\n\tteamAnnounce?: GameModeFunction;\r\n\tgetPlayerTeam?: GameModeFunction;\r\n\tadvanceTeam?: GameModeFunction;\r\n\t[k: string]: any;\r\n}\r\n\r\nfunction toSeconds(time: string) {\r\n\t// hhmmss => ss\r\n\tconst parts = time.split(':').reverse();\r\n\treturn parts.map((value, index) => parseInt(value) * Math.pow(60, index)).reduce((a, b) => a + b);\r\n}\r\n\r\nclass Leaderboard {\r\n\tdata: {[userid: string]: AnyObject};\r\n\r\n\tconstructor() {\r\n\t\tthis.data = {};\r\n\t}\r\n\r\n\taddPoints(name: string, aspect: string, points: number, noUpdate?: boolean) {\r\n\t\tconst userid: string = toID(name);\r\n\r\n\t\tif (!userid || userid === 'constructor' || !points) return this;\r\n\t\tif (!this.data[userid]) this.data[userid] = {name: name};\r\n\r\n\t\tif (!this.data[userid][aspect]) this.data[userid][aspect] = 0;\r\n\t\tthis.data[userid][aspect] += points;\r\n\r\n\t\tif (!noUpdate) this.data[userid].name = name; // always keep the last used name\r\n\r\n\t\treturn this; // allow chaining\r\n\t}\r\n\r\n\tvisualize(sortBy: string): Promise<({rank: number} & AnyObject)[]>;\r\n\tvisualize(sortBy: string, userid: string): Promise<({rank: number} & AnyObject) | undefined>;\r\n\tvisualize(sortBy: string, userid?: string) {\r\n\t\t// FIXME: this is not how promises work\r\n\t\t// return a promise for async sorting - make this less exploitable\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tlet lowestScore = Infinity;\r\n\t\t\tlet lastPlacement = 1;\r\n\r\n\t\t\tconst ladder = Utils.sortBy(\r\n\t\t\t\tObject.entries(this.data).filter(([u, bit]) => sortBy in bit),\r\n\t\t\t\t([u, bit]) => -bit[sortBy]\r\n\t\t\t).map(([u, bit], i) => {\r\n\t\t\t\tif (bit[sortBy] !== lowestScore) {\r\n\t\t\t\t\tlowestScore = bit[sortBy];\r\n\t\t\t\t\tlastPlacement = i + 1;\r\n\t\t\t\t}\r\n\t\t\t\treturn {\r\n\t\t\t\t\trank: lastPlacement,\r\n\t\t\t\t\t...bit,\r\n\t\t\t\t} as {rank: number} & AnyObject;\r\n\t\t\t}); // identify ties\r\n\t\t\tif (userid) {\r\n\t\t\t\tconst rank = ladder.find(entry => toID(entry.name) === userid);\r\n\t\t\t\tresolve(rank);\r\n\t\t\t} else {\r\n\t\t\t\tresolve(ladder);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tasync htmlLadder(): Promise {\r\n\t\tconst data = await this.visualize('points');\r\n\t\tconst display = `
${data.map(line =>\r\n\t\t\t``).join('')\r\n\t\t}
RankNamePoints
${line.rank}${line.name}${line.points}
`;\r\n\t\treturn display;\r\n\t}\r\n}\r\n\r\nconst TWISTS: {[k: string]: Twist} = {\r\n\tperfectscore: {\r\n\t\tname: 'Perfect Score',\r\n\t\tid: 'perfectscore',\r\n\t\tdesc: \"Players who finish the hunt without submitting a single wrong answer get a shoutout!\",\r\n\r\n\t\tonLeave(player) {\r\n\t\t\tif (!this.leftGame) this.leftGame = [];\r\n\t\t\tthis.leftGame.push(player.id);\r\n\t\t},\r\n\r\n\t\tonSubmitPriority: 1,\r\n\t\tonSubmit(player, value) {\r\n\t\t\tconst currentQuestion = player.currentQuestion;\r\n\r\n\t\t\tif (!player.answers) player.answers = {};\r\n\t\t\tif (!player.answers[currentQuestion]) player.answers[currentQuestion] = [];\r\n\r\n\t\t\tif (player.answers[currentQuestion].includes(value)) return;\r\n\r\n\t\t\tplayer.answers[currentQuestion].push(value);\r\n\t\t},\r\n\r\n\t\tonComplete(player, time, blitz) {\r\n\t\t\tconst isPerfect = !this.leftGame?.includes(player.id) &&\r\n\t\t\t\tObject.values(player.answers).every((attempts: any) => attempts.length <= 1);\r\n\t\t\treturn {name: player.name, time, blitz, isPerfect};\r\n\t\t},\r\n\r\n\t\tonAfterEndPriority: 1,\r\n\t\tonAfterEnd(isReset) {\r\n\t\t\tif (isReset) return;\r\n\t\t\tconst perfect = this.completed.filter(entry => entry.isPerfect).map(entry => entry.name);\r\n\t\t\tif (perfect.length) {\r\n\t\t\t\tthis.announce(Utils.html`${Chat.toListString(perfect)} ${perfect.length > 1 ? 'have' : 'has'} completed the hunt without a single wrong answer!`);\r\n\t\t\t}\r\n\t\t},\r\n\t},\r\n\r\n\tbonusround: {\r\n\t\tname: 'Bonus Round',\r\n\t\tid: 'bonusround',\r\n\t\tdesc: \"Players can choose whether or not they choose to complete the 4th question.\",\r\n\r\n\t\tonAfterLoad() {\r\n\t\t\tif (this.questions.length === 3) {\r\n\t\t\t\tthis.announce('This twist requires at least four questions. Please reset the hunt and make it again.');\r\n\t\t\t\tthis.huntLocked = true;\r\n\t\t\t} else {\r\n\t\t\t\tthis.questions[this.questions.length - 1].hint += ' (You may choose to skip this question using ``/scavenge skip``.)';\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonAnySubmit(player) {\r\n\t\t\tif (this.huntLocked) {\r\n\t\t\t\tplayer.sendRoom('The hunt was not set up correctly. Please wait for the host to reset the hunt and create a new one.');\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonSubmitPriority: 1,\r\n\t\tonSubmit(player, value) {\r\n\t\t\tconst currentQuestion = player.currentQuestion;\r\n\r\n\t\t\tif (value === 'skip' && currentQuestion + 1 === this.questions.length) {\r\n\t\t\t\tplayer.sendRoom('You have opted to skip the current question.');\r\n\t\t\t\tplayer.skippedQuestion = true;\r\n\t\t\t\tthis.onComplete(player);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonComplete(player, time, blitz) {\r\n\t\t\tconst noSkip = !player.skippedQuestion;\r\n\t\t\treturn {name: player.name, time, blitz, noSkip};\r\n\t\t},\r\n\r\n\t\tonAfterEndPriority: 1,\r\n\t\tonAfterEnd(isReset) {\r\n\t\t\tif (isReset) return;\r\n\t\t\tconst noSkip = this.completed.filter(entry => entry.noSkip).map(entry => entry.name);\r\n\t\t\tif (noSkip.length) {\r\n\t\t\t\tthis.announce(Utils.html`${Chat.toListString(noSkip)} ${noSkip.length > 1 ? 'have' : 'has'} completed the hunt without skipping the last question!`);\r\n\t\t\t}\r\n\t\t},\r\n\t},\r\n\r\n\tincognito: {\r\n\t\tname: 'Incognito',\r\n\t\tid: 'incognito',\r\n\t\tdesc: \"Upon answering the last question correctly, the player's finishing time will not be announced in the room! Results will only be known at the end of the hunt.\",\r\n\r\n\t\tonCorrectAnswer(player, value) {\r\n\t\t\tif (player.currentQuestion + 1 >= this.questions.length) {\r\n\t\t\t\tthis.runEvent('PreComplete', player);\r\n\r\n\t\t\t\tplayer.sendRoom(`Congratulations! You have gotten the correct answer.`);\r\n\t\t\t\tplayer.sendRoom(`This is a special style where finishes aren't announced! To see your placement, wait for the hunt to end. Until then, it's your secret that you finished!`);\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonPreComplete(player) {\r\n\t\t\tconst now = Date.now();\r\n\t\t\tconst time = Chat.toDurationString(now - this.startTime, {hhmmss: true});\r\n\t\t\tconst canBlitz = this.completed.length < 3;\r\n\r\n\t\t\tconst blitz = now - this.startTime <= 60000 && canBlitz &&\r\n\t\t\t\t(this.room.settings.scavSettings?.blitzPoints?.[this.gameType] || this.gameType === 'official');\r\n\r\n\t\t\tconst result = this.runEvent('Complete', player, time, blitz) || {name: player.name, time, blitz};\r\n\r\n\t\t\tthis.preCompleted = this.preCompleted ? [...this.preCompleted, result] : [result];\r\n\t\t\tplayer.completed = true;\r\n\t\t\tplayer.destroy();\r\n\t\t},\r\n\r\n\t\tonEnd() {\r\n\t\t\tthis.completed = this.preCompleted || [];\r\n\t\t},\r\n\t},\r\n\r\n\tspamfilter: {\r\n\t\tname: 'Spam Filter',\r\n\t\tid: 'spamfilter',\r\n\r\n\t\tdesc: 'Every wrong answer adds 30 seconds to your final time!',\r\n\r\n\t\tonIncorrectAnswer(player: ScavengerHuntPlayer, value: string) {\r\n\t\t\tif (!player.incorrect) player.incorrect = [];\r\n\t\t\tconst id = `${player.currentQuestion}-${value}`;\r\n\t\t\tif (player.incorrect.includes(id)) return;\r\n\r\n\t\t\tplayer.incorrect.push(id);\r\n\t\t},\r\n\r\n\t\tonComplete(player, time, blitz) {\r\n\t\t\tconst seconds = toSeconds(time);\r\n\t\t\tif (!player.incorrect) return {name: player.name, total: seconds, blitz, time, original_time: time};\r\n\r\n\t\t\tconst total = seconds + (30 * player.incorrect.length);\r\n\t\t\tconst finalTime = Chat.toDurationString(total * 1000, {hhmmss: true});\r\n\t\t\tif (total > 60) blitz = false;\r\n\r\n\t\t\treturn {name: player.name, total, blitz, time: finalTime, original_time: time};\r\n\t\t},\r\n\r\n\t\tonConfirmCompletion(player, time, blitz, place, result) {\r\n\t\t\tblitz = result.blitz;\r\n\t\t\ttime = result.time;\r\n\t\t\tconst deductionMessage = player.incorrect?.length ?\r\n\t\t\t\tChat.count(player.incorrect, 'incorrect guesses', 'incorrect guess') :\r\n\t\t\t\t\"Perfect!\";\r\n\t\t\treturn `${Utils.escapeHTML(player.name)} has finished the hunt! (Final Time: ${time} - ${deductionMessage}${(blitz ? \" - BLITZ\" : \"\")})`;\r\n\t\t},\r\n\r\n\t\tonEnd() {\r\n\t\t\tUtils.sortBy(this.completed, entry => entry.total);\r\n\t\t},\r\n\t},\r\n\r\n\tblindincognito: {\r\n\t\tname: 'Blind Incognito',\r\n\t\tid: 'blindincognito',\r\n\t\tdesc: \"Upon completing the last question, neither you nor other players will know if the last question is correct! You may be in for a nasty surprise when the hunt ends!\",\r\n\r\n\t\tonAnySubmit(player, value) {\r\n\t\t\tif (player.precompleted) {\r\n\t\t\t\tplayer.sendRoom(`That may or may not be the right answer - if you aren't confident, you can try again!`);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonCorrectAnswer(player, value) {\r\n\t\t\tif (player.currentQuestion + 1 >= this.questions.length) {\r\n\t\t\t\tthis.runEvent('PreComplete', player);\r\n\r\n\t\t\t\tplayer.sendRoom(`That may or may not be the right answer - if you aren't confident, you can try again!`);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonIncorrectAnswer(player, value) {\r\n\t\t\tif (player.currentQuestion + 1 >= this.questions.length) {\r\n\t\t\t\tplayer.sendRoom(`That may or may not be the right answer - if you aren't confident, you can try again!`);\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonPreComplete(player) {\r\n\t\t\tconst now = Date.now();\r\n\t\t\tconst time = Chat.toDurationString(now - this.startTime, {hhmmss: true});\r\n\t\t\tconst canBlitz = this.completed.length < 3;\r\n\r\n\t\t\tconst blitz = now - this.startTime <= 60000 && canBlitz &&\r\n\t\t\t\t(this.room.settings.scavSettings?.blitzPoints?.[this.gameType] || this.gameType === 'official');\r\n\r\n\t\t\tconst result = this.runEvent('Complete', player, time, blitz) || {name: player.name, time, blitz};\r\n\r\n\t\t\tthis.preCompleted = this.preCompleted ? [...this.preCompleted, result] : [result];\r\n\t\t\tplayer.precompleted = true;\r\n\t\t},\r\n\r\n\t\tonEnd() {\r\n\t\t\tthis.completed = this.preCompleted || [];\r\n\t\t},\r\n\t},\r\n\r\n\ttimetrial: {\r\n\t\tname: 'Time Trial',\r\n\t\tid: 'timetrial',\r\n\t\tdesc: \"Time starts when the player starts the hunt!\",\r\n\r\n\t\tonAfterLoad() {\r\n\t\t\tif (this.questions.length === 3) {\r\n\t\t\t\tthis.announce('This twist requires at least four questions. Please reset the hunt and make it again.');\r\n\t\t\t\tthis.huntLocked = true;\r\n\t\t\t}\r\n\t\t\tthis.altIps = {};\r\n\t\t\tthis.startTimes = {};\r\n\t\t},\r\n\r\n\t\tonJoin(user: User) {\r\n\t\t\tif (!Config.noipchecks) {\r\n\t\t\t\tconst altIp = user.ips.find(ip => this.altIps[ip] && this.altsIps[ip].id !== user.id);\r\n\t\t\t\tif (altIp) {\r\n\t\t\t\t\tuser.sendTo(this.room, `You already have started the hunt as ${this.altIps[altIp].name}.`);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!this.startTimes[user.id]) this.startTimes[user.id] = Date.now();\r\n\t\t\tif (this.addPlayer(user)) {\r\n\t\t\t\tthis.cacheUserIps(user);\r\n\t\t\t\tdelete this.leftHunt[user.id];\r\n\t\t\t\tuser.sendTo(this.room, \"You joined the scavenger hunt! Use the command /scavenge to answer.\");\r\n\t\t\t\tthis.onSendQuestion(user);\r\n\t\t\t} else {\r\n\t\t\t\tuser.sendTo(this.room, \"You have already joined the hunt.\");\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t},\r\n\r\n\t\tonLeave(user) {\r\n\t\t\tfor (const ip of user.ips) {\r\n\t\t\t\tthis.altIps[ip] = {id: user.id, name: user.name};\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonAnySubmit(player) {\r\n\t\t\tif (this.huntLocked) {\r\n\t\t\t\tplayer.sendRoom('The hunt was not set up correctly. Please wait for the host to reset the hunt and create a new one.');\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonComplete(player, time, blitz) {\r\n\t\t\tconst now = Date.now();\r\n\t\t\tconst takenTime = Chat.toDurationString(now - this.startTimes[player.id], {hhmmss: true});\r\n\t\t\tconst result = {name: player.name, id: player.id, time: takenTime, blitz};\r\n\t\t\tthis.completed.push(result);\r\n\t\t\tconst place = Utils.formatOrder(this.completed.length);\r\n\r\n\t\t\tthis.announce(\r\n\t\t\t\tUtils.html`${result.name} is the ${place} player to finish the hunt! (${takenTime}${(blitz ? \" - BLITZ\" : \"\")})`\r\n\t\t\t);\r\n\t\t\tUtils.sortBy(this.completed, entry => entry.time);\r\n\r\n\t\t\tplayer.destroy(); // remove from user.games;\r\n\t\t\treturn true;\r\n\t\t},\r\n\t},\r\n\r\n\tscavengersfeud: {\r\n\t\tid: 'scavengersfeud',\r\n\t\tname: 'Scavengers Feud',\r\n\t\tdesc: 'After completing the hunt, players will guess what the most common incorrect answer for each question is.',\r\n\t\tonAfterLoad() {\r\n\t\t\tthis.guesses = {};\r\n\t\t\tthis.incorrect = this.questions.map(() => ({}));\r\n\r\n\t\t\tthis.questions.push({\r\n\t\t\t\thint: 'Please enter what you think are the most common incorrect answers to each question. (Enter your guesses in the order of the previous questions, and separate them with a comma)',\r\n\t\t\t\tanswer: ['Any'],\r\n\t\t\t\tspoilers: [],\r\n\t\t\t});\r\n\t\t},\r\n\r\n\t\tonIncorrectAnswer(player: ScavengerHuntPlayer, value: string) {\r\n\t\t\tconst curr = player.currentQuestion;\r\n\r\n\t\t\tif (!this.incorrect[curr][value]) this.incorrect[curr][value] = [];\r\n\t\t\tif (this.incorrect[curr][value].includes(player.id)) return;\r\n\r\n\t\t\tthis.incorrect[curr][value].push(player.id);\r\n\t\t},\r\n\r\n\t\tonSubmitPriority: 1,\r\n\t\tonSubmit(player, jumble, value) {\r\n\t\t\tconst currentQuestion = player.currentQuestion;\r\n\r\n\t\t\tif (currentQuestion + 1 === this.questions.length) {\r\n\t\t\t\tthis.guesses[player.id] = value.split(',').map((part: string) => toID(part));\r\n\r\n\t\t\t\tthis.onComplete(player);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonEnd() {\r\n\t\t\tthis.questions = this.questions.slice(0, -1); // remove the automatically added last question.\r\n\t\t},\r\n\r\n\t\tonAfterEnd(isReset) {\r\n\t\t\tif (isReset) return;\r\n\r\n\t\t\tconst buffer = [];\r\n\t\t\tfor (const [idx, data] of this.incorrect.entries()) {\r\n\t\t\t\t// collate the data for each question\r\n\t\t\t\tlet collection = [];\r\n\t\t\t\tfor (const str in data) {\r\n\t\t\t\t\tcollection.push({count: data[str].length, value: str});\r\n\t\t\t\t}\r\n\t\t\t\tcollection = collection.sort((a, b) => b.count - a.count);\r\n\t\t\t\tconst maxValue = collection[0]?.count || 0;\r\n\r\n\t\t\t\tconst matches = collection\r\n\t\t\t\t\t.filter(pair => pair.count === maxValue)\r\n\t\t\t\t\t.map(pair => pair.value);\r\n\r\n\t\t\t\tconst matchedPlayers = [];\r\n\t\t\t\tfor (const playerid in this.guesses) {\r\n\t\t\t\t\tconst guesses = this.guesses[playerid];\r\n\t\t\t\t\tif (matches.includes(guesses[idx])) matchedPlayers.push(playerid);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// display the data\r\n\t\t\t\tconst matchDisplay = matches.length ? matches.join(', ') : 'No wrong answers!';\r\n\t\t\t\tconst playerDisplay = matches.length ?\r\n\t\t\t\t\tmatchedPlayers.length ? `- ${matchedPlayers.join(', ')}` : '- No one guessed correctly!' :\r\n\t\t\t\t\t'';\r\n\t\t\t\tbuffer.push(`Q${idx + 1}: ${matchDisplay} ${playerDisplay}`);\r\n\t\t\t}\r\n\r\n\t\t\tthis.announce(`

Most common incorrect answers:

${buffer.join('
')}`);\r\n\t\t},\r\n\t},\r\n\r\n\tminesweeper: {\r\n\t\tid: 'minesweeper',\r\n\t\tname: 'Minesweeper',\r\n\t\tdesc: 'The huntmaker can add incorrect \\'mines\\' to the hunt - they get points every time a player scavenges it, and players that dodge all the mines in the hunt get points.',\r\n\t\tonAfterLoad() {\r\n\t\t\tthis.guesses = this.questions.map(() => []);\r\n\t\t\tthis.mines = [];\r\n\t\t\tfor (const question of this.questions) {\r\n\t\t\t\tthis.mines.push(question.answer.filter(ans => ans.startsWith('!')));\r\n\t\t\t\tquestion.answer = question.answer.filter(ans => !ans.startsWith('!'));\r\n\t\t\t}\r\n\t\t\tif ((this.mines as string[][]).some(mineSet => mineSet.length === 0)) {\r\n\t\t\t\tthis.announce('This twist requires at least one mine for each question. Please reset the hunt and make it again.');\r\n\t\t\t\tthis.huntLocked = true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonEditQuestion(questionNumber: number, questionAnswer: string, value: string) {\r\n\t\t\tif (questionAnswer === 'question') questionAnswer = 'hint';\r\n\t\t\tif (!['hint', 'answer'].includes(questionAnswer)) return false;\r\n\r\n\t\t\tlet answer: string[] = [];\r\n\t\t\tif (questionAnswer === 'answer') {\r\n\t\t\t\tanswer = value.split(';').map(p => p.trim());\r\n\t\t\t}\r\n\r\n\t\t\tif (!questionNumber || questionNumber < 1 || questionNumber > this.questions.length || (!answer && !value)) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tquestionNumber--; // indexOf starts at 0\r\n\r\n\t\t\tif (questionAnswer === 'answer') {\r\n\t\t\t\t// These two lines are the only difference from the original\r\n\t\t\t\tthis.mines[questionNumber] = answer.filter(ans => ans.startsWith('!'));\r\n\t\t\t\tthis.questions[questionNumber].answer = answer.filter(ans => !ans.startsWith('!'));\r\n\t\t\t} else {\r\n\t\t\t\tthis.questions[questionNumber].hint = value;\r\n\t\t\t}\r\n\r\n\t\t\tthis.announce(`The ${questionAnswer} for question ${questionNumber + 1} has been edited.`);\r\n\t\t\tif (questionAnswer === 'hint') {\r\n\t\t\t\tfor (const p in this.playerTable) {\r\n\t\t\t\t\tthis.playerTable[p].onNotifyChange(questionNumber);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t},\r\n\r\n\t\tonAnySubmit(player) {\r\n\t\t\tif (this.huntLocked) {\r\n\t\t\t\tplayer.sendRoom('The hunt was not set up correctly. Please wait for the host to reset the hunt and create a new one.');\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonIncorrectAnswer(player: ScavengerHuntPlayer, value: string) {\r\n\t\t\tconst curr = player.currentQuestion;\r\n\r\n\t\t\tif (!this.guesses[curr][player.id]) this.guesses[curr][player.id] = new Set();\r\n\t\t\tthis.guesses[curr][player.id].add(toID(value));\r\n\r\n\t\t\tthrow new Chat.ErrorMessage(\"That is not the answer - try again!\");\r\n\t\t},\r\n\r\n\t\tonShowEndBoard(endedBy?: User) {\r\n\t\t\tconst sliceIndex = this.gameType === 'official' ? 5 : 3;\r\n\t\t\tconst hosts = Chat.toListString(this.hosts.map(h => `${Utils.escapeHTML(h.name)}`));\r\n\r\n\t\t\tconst mines: {mine: string, users: string[]}[][] = [];\r\n\r\n\t\t\tfor (let index = 0; index < this.mines.length; index++) {\r\n\t\t\t\tmines[index] = [];\r\n\t\t\t\tfor (const mine of this.mines[index]) {\r\n\t\t\t\t\tmines[index].push({mine: mine.substr(1), users: []});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor (const player of Object.values(this.playerTable)) {\r\n\t\t\t\tif (player.mines) {\r\n\t\t\t\t\tfor (const {index, mine} of player.mines) {\r\n\t\t\t\t\t\tmines[index].find(obj => obj.mine === mine)?.users.push(player.name);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor (const mineSet of mines) mineSet.sort();\r\n\r\n\t\t\tthis.announce(\r\n\t\t\t\t`The ${this.gameType ? `${this.gameType} ` : \"\"}scavenger hunt by ${hosts} was ended ${(endedBy ? \"by \" + Utils.escapeHTML(endedBy.name) : \"automatically\")}.
` +\r\n\t\t\t\t`${this.completed.slice(0, sliceIndex).map((p, i) => `${Utils.formatOrder(i + 1)} place: ${Utils.escapeHTML(p.name)} [${p.time}].
`).join(\"\")}` +\r\n\t\t\t\t`${this.completed.length > sliceIndex ? `Consolation Prize: ${this.completed.slice(sliceIndex).map(e => `${Utils.escapeHTML(e.name)} [${e.time}]`).join(', ')}
` : ''}
` +\r\n\t\t\t\t`
Solution:
` +\r\n\t\t\t\t`${this.questions.map((q, i) => (\r\n\t\t\t\t\t`${i + 1}) ${Chat.formatText(q.hint)} [${Utils.escapeHTML(q.answer.join(' / '))}]
` +\r\n\t\t\t\t\t`
Mines: ${mines[i].map(({mine, users}) => Utils.escapeHTML(`${mine}: ${users.join(' / ') || '-'}`)).join('
')}
`\r\n\t\t\t\t)).join(\"
\")}` +\r\n\t\t\t\t`
`\r\n\t\t\t);\r\n\t\t\treturn true;\r\n\t\t},\r\n\r\n\t\tonEnd(isReset) {\r\n\t\t\tif (isReset) return;\r\n\t\t\tfor (const [q, guessObj] of this.guesses.entries()) {\r\n\t\t\t\tconst mines: string[] = this.mines[q];\r\n\t\t\t\tfor (const [playerId, guesses] of Object.entries(guessObj)) {\r\n\t\t\t\t\tconst player = this.playerTable[playerId];\r\n\t\t\t\t\tif (!player.mines) player.mines = [];\r\n\t\t\t\t\t(player.mines as {index: number, mine: string}[]).push(...mines\r\n\t\t\t\t\t\t.filter(mine => (guesses as Set).has(toID(mine)))\r\n\t\t\t\t\t\t.map(mine => ({index: q, mine: mine.substr(1)})));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonAfterEndPriority: 1,\r\n\t\tonAfterEnd(isReset) {\r\n\t\t\tif (isReset) return;\r\n\t\t\tconst noMines = [];\r\n\t\t\tfor (const {name} of this.completed) {\r\n\t\t\t\tconst player = this.playerTable[toID(name)];\r\n\t\t\t\tif (!player) continue;\r\n\t\t\t\tif (!player.mines?.length) noMines.push(name);\r\n\t\t\t}\r\n\t\t\tif (noMines.length) {\r\n\t\t\t\tthis.announce(Utils.html`${Chat.toListString(noMines)} ${noMines.length > 1 ? 'have' : 'has'} completed the hunt without hitting a single mine!`);\r\n\t\t\t\t// Points are awarded manually\r\n\t\t\t}\r\n\t\t},\r\n\t},\r\n};\r\n\r\nconst MODES: {[k: string]: GameMode | string} = {\r\n\tko: 'kogames',\r\n\tkogames: {\r\n\t\tname: 'KO Games',\r\n\t\tid: 'kogames',\r\n\r\n\t\tmod: {\r\n\t\t\tname: 'KO Games',\r\n\t\t\tid: 'KO Games',\r\n\t\t\tisGameMode: true,\r\n\r\n\t\t\tonLoad() {\r\n\t\t\t\tthis.allowRenames = false; // don't let people change their name in the middle of the hunt.\r\n\t\t\t},\r\n\r\n\t\t\tonJoin(user: User) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (game.playerlist && !game.playerlist.includes(user.id)) {\r\n\t\t\t\t\tuser.sendTo(this.room, 'You are not allowed to join this scavenger hunt.');\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonAfterEnd() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (!this.completed.length) {\r\n\t\t\t\t\tthis.announce('No one has completed the hunt - the round has been void.');\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgame.round++;\r\n\r\n\t\t\t\t// elimination\r\n\t\t\t\tif (!game.playerlist) {\r\n\t\t\t\t\tgame.playerlist = this.completed.map(entry => toID(entry.name));\r\n\t\t\t\t\tthis.announce(`Round ${game.round} - ${Chat.toListString(this.completed.map(p => `${p.name}`))} have successfully completed the last hunt and have moved on to the next round!`);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlet eliminated = [];\r\n\t\t\t\t\tconst completed = this.completed.map(entry => toID(entry.name)) as string[];\r\n\t\t\t\t\tif (completed.length === game.playerlist.length) {\r\n\t\t\t\t\t\teliminated.push(completed.pop()); // eliminate one\r\n\t\t\t\t\t\tgame.playerlist = game.playerlist.filter(userid => completed.includes(userid));\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\teliminated = game.playerlist.filter(userid => !completed.includes(userid));\r\n\t\t\t\t\t\tfor (const username of eliminated) {\r\n\t\t\t\t\t\t\tconst userid = toID(username);\r\n\t\t\t\t\t\t\tgame.playerlist = game.playerlist.filter(pid => pid !== userid);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.announce(`Round ${game.round} - ${Chat.toListString(eliminated.map(n => `${n}`))} ${Chat.plural(eliminated, 'have', 'has')} been eliminated! ${Chat.toListString(game.playerlist.map(p => `${this.playerTable[p].name}`))} have successfully completed the last hunt and have moved on to the next round!`);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// process end of game\r\n\t\t\t\tif (game.playerlist.length === 1) {\r\n\t\t\t\t\tconst winningUser = Users.get(game.playerlist[0]);\r\n\t\t\t\t\tconst winner = winningUser ? winningUser.name : game.playerlist[0];\r\n\r\n\t\t\t\t\tthis.announce(`Congratulations to the winner - ${winner}!`);\r\n\t\t\t\t\tgame.destroy();\r\n\t\t\t\t} else if (!game.playerlist.length) {\r\n\t\t\t\t\tthis.announce('Everyone has been eliminated! Better luck next time!');\r\n\t\t\t\t\tgame.destroy();\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t},\r\n\r\n\t\tround: 0,\r\n\t\tplayerlist: null,\r\n\t},\r\n\r\n\tscav: 'scavengergames',\r\n\tscavgames: 'scavengergames',\r\n\tscavengergames: {\r\n\t\tname: 'Scavenger Games',\r\n\t\tid: 'scavengergames',\r\n\r\n\t\tmod: {\r\n\t\t\tname: 'Scavenger Games',\r\n\t\t\tid: 'scavengergames',\r\n\t\t\tisGameMode: true,\r\n\r\n\t\t\tonLoad() {\r\n\t\t\t\tthis.allowRenames = false; // don't let people change their name in the middle of the hunt.\r\n\t\t\t\tthis.setTimer(1);\r\n\t\t\t},\r\n\r\n\t\t\tonJoin(user) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (game.playerlist && !game.playerlist.includes(user.id)) {\r\n\t\t\t\t\tuser.sendTo(this.room, 'You are not allowed to join this scavenger hunt.');\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonAfterEnd() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (!this.completed.length) {\r\n\t\t\t\t\tthis.announce('No one has completed the hunt - the round has been void.');\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tgame.round++;\r\n\r\n\t\t\t\tlet eliminated: string[] = [];\r\n\t\t\t\tif (!game.playerlist) {\r\n\t\t\t\t\tgame.playerlist = this.completed.map(entry => toID(entry.name) as string);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconst completed = this.completed.map(entry => toID(entry.name) as string);\r\n\t\t\t\t\teliminated = game.playerlist.filter(userid => !completed.includes(userid));\r\n\t\t\t\t\tfor (const username of eliminated) {\r\n\t\t\t\t\t\tconst userid = toID(username);\r\n\t\t\t\t\t\tgame.playerlist = game.playerlist.filter(pid => pid !== userid);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.announce(`Round ${game.round} - ${Chat.toListString(eliminated.map(n => `${n}`))} ${eliminated.length ? `${Chat.plural(eliminated, 'have', 'has')} been eliminated!` : ''} ${Chat.toListString(game.playerlist.map(p => `${this.playerTable[p].name}`))} have successfully completed the last hunt and have moved on to the next round!`);\r\n\r\n\t\t\t\t// process end of game\r\n\t\t\t\tif (game.playerlist.length === 1) {\r\n\t\t\t\t\tconst winningUser = Users.get(game.playerlist[0]);\r\n\t\t\t\t\tconst winner = winningUser ? winningUser.name : game.playerlist[0];\r\n\r\n\t\t\t\t\tthis.announce(`Congratulations to the winner - ${winner}!`);\r\n\t\t\t\t\tgame.destroy();\r\n\t\t\t\t} else if (!game.playerlist.length) {\r\n\t\t\t\t\tthis.announce('Everyone has been eliminated! Better luck next time!');\r\n\t\t\t\t\tgame.destroy();\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t},\r\n\r\n\t\tround: 0,\r\n\t\tplayerlist: null,\r\n\t},\r\n\r\n\tpr: 'pointrally',\r\n\tpointrally: {\r\n\t\tname: 'Point Rally',\r\n\t\tid: 'pointrally',\r\n\r\n\t\tpointDistribution: [50, 40, 32, 25, 20, 15, 10],\r\n\r\n\t\tmod: {\r\n\t\t\tname: 'Point Rally',\r\n\t\t\tid: 'pointrally',\r\n\t\t\tisGameMode: true,\r\n\r\n\t\t\tonLoad() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tthis.announce(`Round ${++game.round}`);\r\n\t\t\t},\r\n\r\n\t\t\tasync onAfterEnd() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tfor (const [i, completed] of this.completed.map(e => e.name).entries()) {\r\n\t\t\t\t\tconst points = (game.pointDistribution[i] ||\r\n\t\t\t\t\t\tgame.pointDistribution[game.pointDistribution.length - 1]);\r\n\t\t\t\t\tgame.leaderboard.addPoints(completed, 'points', points);\r\n\t\t\t\t}\r\n\t\t\t\t// post leaderboard\r\n\t\t\t\tconst room = this.room;\r\n\t\t\t\tconst html = await game.leaderboard.htmlLadder() as string;\r\n\t\t\t\troom.add(`|raw|${html}`).update();\r\n\t\t\t},\r\n\t\t},\r\n\t\tround: 0,\r\n\t\tleaderboard: true,\r\n\t},\r\n\r\n\tjs: 'jumpstart',\r\n\tjump: 'jumpstart',\r\n\tjumpstart: {\r\n\t\tname: 'Jump Start',\r\n\t\tid: 'jumpstart',\r\n\r\n\t\tjumpstart: [60, 40, 30, 20, 10],\r\n\t\tround: 0,\r\n\t\tmod: {\r\n\t\t\tname: 'Jump Start',\r\n\t\t\tid: 'jumpstart',\r\n\t\t\tisGameMode: true,\r\n\r\n\t\t\tonLoad() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (game.round === 0) return;\r\n\t\t\t\tconst maxTime = Math.max(...game.jumpstart);\r\n\r\n\t\t\t\tthis.jumpstartTimers = [];\r\n\t\t\t\tthis.answerLock = true;\r\n\r\n\t\t\t\tfor (const [i, time] of game.jumpstart.entries()) {\r\n\t\t\t\t\tif (!game.completed[i]) break;\r\n\r\n\t\t\t\t\tthis.jumpstartTimers[i] = setTimeout(() => {\r\n\t\t\t\t\t\tconst target = game.completed.shift();\r\n\t\t\t\t\t\tif (!target) return;\r\n\r\n\t\t\t\t\t\tconst staffHost = Users.get(this.staffHostId);\r\n\t\t\t\t\t\tconst targetUser = Users.get(target);\r\n\r\n\t\t\t\t\t\tif (targetUser) {\r\n\t\t\t\t\t\t\tif (staffHost) staffHost.sendTo(this.room, `${targetUser.name} has received their first hint early.`);\r\n\t\t\t\t\t\t\ttargetUser.sendTo(\r\n\t\t\t\t\t\t\t\tthis.room,\r\n\t\t\t\t\t\t\t\t`|raw|The first hint to the next hunt is: ${Chat.formatText(this.questions[0].hint)}`\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\ttargetUser.sendTo(\r\n\t\t\t\t\t\t\t\tthis.room,\r\n\t\t\t\t\t\t\t\t`|notify|Early Hint|The first hint to the next hunt is: ${Chat.formatText(this.questions[0].hint)}`\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}, (maxTime - time) * 1000 + 5000);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// when the jump starts are all given to eligible players\r\n\t\t\t\tthis.jumpstartTimers[this.jumpstartTimers.length] = setTimeout(() => {\r\n\t\t\t\t\tthis.answerLock = false;\r\n\t\t\t\t\tconst message = this.getCreationMessage(true);\r\n\t\t\t\t\tthis.room.add(message).update();\r\n\t\t\t\t\tthis.announce('You may start guessing!');\r\n\t\t\t\t\tthis.startTime = Date.now();\r\n\t\t\t\t}, 1000 * (maxTime + 5));\r\n\t\t\t},\r\n\r\n\t\t\tonJoin(user) {\r\n\t\t\t\tif (this.answerLock) {\r\n\t\t\t\t\tuser.sendTo(this.room, `The hunt is not open for guesses yet!`);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonViewHunt(user) {\r\n\t\t\t\tif (this.answerLock && !(this.hosts.some(h => h.id === user.id) || user.id === this.staffHostId)) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonCreateCallback() {\r\n\t\t\t\tif (this.answerLock) {\r\n\t\t\t\t\treturn `|raw|
${['official', 'unrated'].includes(this.gameType) ? 'An' : 'A'} ${this.gameType} ` +\r\n\t\t\t\t\t\t`Scavenger Hunt by ${Utils.escapeHTML(Chat.toListString(this.hosts.map(h => h.name)))} ` +\r\n\t\t\t\t\t\t`has been started${(this.hosts.some(h => h.id === this.staffHostId) ? '' : ` by ${Utils.escapeHTML(this.staffHostName)}`)}.` +\r\n\t\t\t\t\t\t`
The first hint is currently being handed out to early finishers.`;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonEnd(reset) {\r\n\t\t\t\tif (this.jumpstartTimers) {\r\n\t\t\t\t\tfor (const timer of this.jumpstartTimers) {\r\n\t\t\t\t\t\tclearTimeout(timer);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tif (!reset) {\r\n\t\t\t\t\tif (game.round === 0) {\r\n\t\t\t\t\t\tgame.completed = this.completed.map(entry => toID(entry.name));\r\n\t\t\t\t\t\tgame.round++;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tgame.destroy();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t},\r\n\t},\r\n\r\n\tts: 'teamscavs',\r\n\ttscav: 'teamscavs',\r\n\tteamscavengers: 'teamscavs',\r\n\tteamscavs: {\r\n\t\tname: 'Team Scavs',\r\n\t\tid: 'teamscavs',\r\n\t\t/* {\r\n\t\t\t[team\r\n\t\t\tname: string]: {\r\n\t\t\t name: string[],\r\n\t\t\t players: UserID[],\r\n\t\t\t answers: string[],\r\n\t\t\t question: number,\r\n\t\t\t completed: boolean\r\n\t\t\t}\r\n\t\t } */\r\n\t\tteams: {},\r\n\r\n\t\tteamAnnounce(player: ScavengerHuntPlayer | User, message: string) {\r\n\t\t\tconst team = this.getPlayerTeam(player);\r\n\r\n\t\t\tfor (const userid of team.players) {\r\n\t\t\t\tconst user = Users.getExact(userid);\r\n\t\t\t\tif (!user?.connected) continue; // user is offline\r\n\r\n\t\t\t\tuser.sendTo(this.room, `|raw|
${message}
`);\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tgetPlayerTeam(player: ScavengerHuntPlayer | User) {\r\n\t\t\tconst game = this.room.scavgame!;\r\n\t\t\tfor (const teamID in game.teams) {\r\n\t\t\t\tconst team = game.teams[teamID];\r\n\t\t\t\tif (team.players.includes(player.id)) {\r\n\t\t\t\t\treturn team;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t},\r\n\r\n\t\tadvanceTeam(answerer: ScavengerHuntPlayer, isFinished?: boolean) {\r\n\t\t\tconst hunt = this.room.getGame(ScavengerHunt)!;\r\n\r\n\t\t\tconst team = this.getPlayerTeam(answerer);\r\n\r\n\t\t\tteam.question++;\r\n\t\t\tconst question = hunt.getQuestion(team.question);\r\n\t\t\tfor (const userid of team.players) {\r\n\t\t\t\tconst user = Users.getExact(userid);\r\n\t\t\t\tif (!user) continue;\r\n\r\n\t\t\t\tuser.sendTo(this.room, question);\r\n\t\t\t}\r\n\t\t\tteam.answers = [];\r\n\t\t},\r\n\r\n\t\tmod: {\r\n\t\t\tname: 'Team Scavs',\r\n\t\t\tid: 'teamscavs',\r\n\t\t\tisGameMode: true,\r\n\r\n\t\t\tonLoad() {\r\n\t\t\t\t// don't let people change their name in the middle of the hunt.\r\n\t\t\t\tthis.allowRenames = false;\r\n\t\t\t},\r\n\r\n\t\t\tonViewHunt(user) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tconst team = game.getPlayerTeam(user);\r\n\t\t\t\tconst player = this.playerTable[user.id];\r\n\r\n\t\t\t\tif (!player || !team) return;\r\n\r\n\t\t\t\tif (player.currentQuestion !== team.question - 1) player.currentQuestion = team.question - 1;\r\n\t\t\t\tif (team.completed) player.completed = true;\r\n\t\t\t},\r\n\r\n\t\t\tonSendQuestion(player) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tconst team = game.getPlayerTeam(player);\r\n\r\n\t\t\t\tif (!team) return;\r\n\r\n\t\t\t\tif (player.currentQuestion !== team.question - 1) player.currentQuestion = team.question - 1;\r\n\t\t\t\tif (team.completed) {\r\n\t\t\t\t\tplayer.completed = true;\r\n\t\t\t\t\tplayer.sendRoom('Your team has already completed the hunt!');\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonConnect(user) {\r\n\t\t\t\tconst player = this.playerTable[user.id];\r\n\t\t\t\tif (!player) return;\r\n\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tconst team = game.getPlayerTeam(player);\r\n\r\n\t\t\t\tif (team) {\r\n\t\t\t\t\tif (player.currentQuestion !== team.question - 1) player.currentQuestion = team.question - 1;\r\n\t\t\t\t\tif (team.completed) player.completed = true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonJoin(user) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tconst team = game.getPlayerTeam(user);\r\n\t\t\t\tif (!team) {\r\n\t\t\t\t\tuser.sendTo(this.room, 'You are not allowed to join this scavenger hunt as you are not on any of the teams.');\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonAfterLoadPriority: -9999,\r\n\t\t\tonAfterLoad() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\r\n\t\t\t\tif (Object.keys(game.teams).length === 0) {\r\n\t\t\t\t\tthis.announce('Teams have not been set up yet. Please reset the hunt.');\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\t// -1 so that blind incog takes precedence of this\r\n\t\t\tonCorrectAnswerPriority: -1,\r\n\t\t\tonCorrectAnswer(player, value) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\r\n\t\t\t\tif (player.currentQuestion + 1 < this.questions.length) {\r\n\t\t\t\t\tgame.teamAnnounce(\r\n\t\t\t\t\t\tplayer,\r\n\t\t\t\t\t\tUtils.html`${player.name} has gotten the correct answer (${value}) for question #${player.currentQuestion + 1}.`\r\n\t\t\t\t\t);\r\n\t\t\t\t\tgame.advanceTeam(player);\r\n\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\r\n\t\t\tonAnySubmit(player, value) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\r\n\t\t\t\tconst team = game.getPlayerTeam(player);\r\n\r\n\t\t\t\tif (!team) return true; // handle players who get kicked during the hunt.\r\n\r\n\t\t\t\tif (player.currentQuestion !== team.question - 1) player.currentQuestion = team.question - 1;\r\n\t\t\t\tif (team.completed) player.completed = true;\r\n\r\n\t\t\t\tif (player.completed) return;\r\n\r\n\t\t\t\tif (team.answers.includes(value)) return;\r\n\t\t\t\tgame.teamAnnounce(player, Utils.html`${player.name} has guessed \"${value}\".`);\r\n\t\t\t\tteam.answers.push(value);\r\n\t\t\t},\r\n\r\n\t\t\tonCompletePriority: 2,\r\n\t\t\tonComplete(player, time, blitz) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\r\n\t\t\t\tconst team = game.getPlayerTeam(player);\r\n\t\t\t\treturn {name: team.name, time, blitz};\r\n\t\t\t},\r\n\r\n\t\t\t// workaround that gives the answer after verifying that completion should not be hidden\r\n\t\t\tonConfirmCompletion(player, time, blitz) {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tconst team = game.getPlayerTeam(player);\r\n\t\t\t\tteam.completed = true;\r\n\t\t\t\tteam.question++;\r\n\r\n\t\t\t\tgame.teamAnnounce(\r\n\t\t\t\t\tplayer,\r\n\t\t\t\t\tUtils.html`${player.name} has gotten the correct answer for question #${player.currentQuestion}. Your team has completed the hunt!`\r\n\t\t\t\t);\r\n\t\t\t},\r\n\r\n\t\t\tonEnd() {\r\n\t\t\t\tconst game = this.room.scavgame!;\r\n\t\t\t\tfor (const teamID in game.teams) {\r\n\t\t\t\t\tconst team = game.teams[teamID];\r\n\t\t\t\t\tteam.answers = [];\r\n\t\t\t\t\tteam.question = 1;\r\n\t\t\t\t\tteam.completed = false;\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t},\r\n\t},\r\n};\r\n\r\nexport class ScavengerGameTemplate {\r\n\troom: Room;\r\n\tplayerlist: null | string[];\r\n\ttimer: NodeJS.Timer | null;\r\n\r\n\t[k: string]: any;\r\n\tconstructor(room: Room) {\r\n\t\tthis.room = room;\r\n\t\tthis.playerlist = null;\r\n\t\tthis.timer = null;\r\n\t}\r\n\r\n\tdestroy(force?: boolean) {\r\n\t\tif (this.timer) clearTimeout(this.timer);\r\n\t\tconst game = this.room.getGame(ScavengerHunt);\r\n\t\tif (force && game) game.onEnd(false);\r\n\t\tthis.room.scavgame = null;\r\n\t}\r\n\r\n\teliminate(userid: string) {\r\n\t\tif (!this.playerlist?.includes(userid)) return false;\r\n\t\tthis.playerlist = this.playerlist.filter(pid => pid !== userid);\r\n\r\n\t\tif (this.leaderboard) delete this.leaderboard.data[userid];\r\n\t\treturn true;\r\n\t}\r\n\r\n\tannounce(msg: string) {\r\n\t\tthis.room.add(`|raw|
${msg}
`).update();\r\n\t}\r\n}\r\n\r\nconst LoadGame = function (room: Room, gameid: string) {\r\n\tlet game = MODES[gameid];\r\n\tif (!game) return false; // invalid id\r\n\tif (typeof game === 'string') game = MODES[game];\r\n\r\n\tconst base = new ScavengerGameTemplate(room);\r\n\r\n\tconst scavgame = Object.assign(base, Utils.deepClone(game));\r\n\r\n\t// initialize leaderboard if required\r\n\tif (scavgame.leaderboard) {\r\n\t\tscavgame.leaderboard = new Leaderboard();\r\n\t}\r\n\treturn scavgame;\r\n};\r\n\r\nexport const ScavMods = {\r\n\tLoadGame,\r\n\ttwists: TWISTS,\r\n\tmodes: MODES,\r\n};\r\n"], "mappings": "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", "names": [] }