Auto Timer Duration: ${timerDuration} minutes Auto Dequeue: {
completed: AnyObject[];
leftHunt: {[userid: string]: 1 | undefined};
hosts: FakeUser[];
+ isHTML: boolean;
modsList: string[];
mods: {[k: string]: ModEvent[]};
staffHostId: string;
@@ -338,14 +340,16 @@ export class ScavengerHunt extends Rooms.RoomGame {
readonly checkChat = true;
[k: string]: any; // for purposes of adding new temporary properties for the purpose of twists.
- constructor(
+ constructor({room, staffHost, hosts, gameType, questions, isHTML, mod}:
+ {
room: Room,
staffHost: User | FakeUser,
hosts: FakeUser[],
gameType: GameTypes,
questions: (string | string[])[],
- mod?: string | string[]
- ) {
+ isHTML?: boolean,
+ mod?: string | string[],
+ }) {
super(room);
this.allowRenames = true;
@@ -362,6 +366,8 @@ export class ScavengerHunt extends Rooms.RoomGame {
this.hosts = hosts;
+ this.isHTML = !!isHTML;
+
this.modsList = [];
this.mods = {};
@@ -430,6 +436,10 @@ export class ScavengerHunt extends Rooms.RoomGame {
this.runEvent('Connect', user, connection);
}
+ formatOutput(text: string): string {
+ return this.isHTML ? text : Chat.formatText(text);
+ }
+
getCreationMessage(newHunt?: boolean): string {
const message = this.runEvent('CreateCallback');
if (message) return message;
@@ -443,8 +453,8 @@ export class ScavengerHunt extends Rooms.RoomGame {
const huntType = `${article} ${newHunt ? 'new ' : ''}${this.gameType}`;
return `|raw|${huntType} scavenger hunt by ${hosts} has been started${staffHost}. ` +
- `
` +
- `
Hint #1: ${Chat.formatText(this.questions[0].hint)}` +
+ `
` +
+ `Hint #1: ${this.formatOutput(this.questions[0].hint)} ` +
`
` +
`(To answer, use
/scavenge ANSWER )
`;
}
@@ -614,16 +624,16 @@ export class ScavengerHunt extends Rooms.RoomGame
{
};
const finalHint = current.number === this.questions.length ? "Final " : "";
- return `|raw|` +
- `${finalHint}Hint #${current.number}: ` +
- `${
- Chat.formatText(current.question.hint) +
+ return `|raw|` +
+ `${finalHint}Hint #${current.number}: ` +
+ `${
+ this.formatOutput(current.question.hint) +
(showHints && current.question.spoilers.length ?
`Extra Hints: ${
current.question.spoilers.map(p => `- ${p}`).join(' ')
} ` :
``)
- }
` +
+ }` +
`
`;
}
@@ -654,19 +664,19 @@ export class ScavengerHunt extends Rooms.RoomGame {
user.sendTo(
this.room,
- `|raw|` +
- `# Hint Answer ` +
+ `|raw|` +
+ `# Hint Answer ` +
this.questions.slice(0, qLimit).map((q, i) => (
`${
i + 1
- } ${
- Chat.formatText(q.hint) +
+ } ${
+ this.formatOutput(q.hint) +
(q.spoilers.length ?
`Extra Hints: ${
q.spoilers.map(s => `- ${s}`).join(' ')
} ` :
``)
- }
${
+ } ${
i + 1 >= qLimit ?
`` :
Utils.escapeHTMLForceWrap(q.answer.join(' ; '))
@@ -710,8 +720,8 @@ export class ScavengerHunt extends Rooms.RoomGame {
`The ${this.gameType ? `${this.gameType} ` : ""}scavenger hunt by ${hosts} was ended ${(endedBy ? "by " + Utils.escapeHTML(endedBy.name) : "automatically")}. ` +
`${this.completed.slice(0, sliceIndex).map((p, i) => `${Utils.formatOrder(i + 1)} place: ${Utils.escapeHTML(p.name)} [${p.time}] . `).join("")}` +
`${this.completed.length > sliceIndex ? `Consolation Prize: ${this.completed.slice(sliceIndex).map(e => `${Utils.escapeHTML(e.name)} [${e.time}] `).join(', ')} ` : ''} ` +
- `Solution: ` +
- `${this.questions.map((q, i) => `${i + 1}) ${Chat.formatText(q.hint)} [${Utils.escapeHTML(q.answer.join(' / '))} ] `).join(" ")}` +
+ `Solution: ` +
+ `${this.questions.map((q, i) => `${i + 1}) ${this.formatOutput(q.hint)} [${Utils.escapeHTML(q.answer.join(' / '))} ] `).join(" ")}` +
` `
);
}
@@ -731,6 +741,7 @@ export class ScavengerHunt extends Rooms.RoomGame {
hosts: next.hosts,
questions: correctlyFormattedQuestions,
staffHostId: 'scavengermanager',
+ isHTML: next.isHTML,
staffHostName: 'Scavenger Manager',
gameType: 'unrated',
});
@@ -821,16 +832,20 @@ export class ScavengerHunt extends Rooms.RoomGame {
const next = room.settings.scavQueue.shift()!;
const duration = room.settings.scavSettings?.defaultScavTimer || DEFAULT_TIMER_DURATION;
room.game = new ScavengerHunt(
- room,
- {id: next.staffHostId, name: next.staffHostName},
- next.hosts,
- next.gameType,
- next.questions
+ {
+ room: room,
+ staffHost: {id: next.staffHostId, name: next.staffHostName},
+ hosts: next.hosts,
+ gameType: next.gameType,
+ questions: next.questions,
+ isHTML: next.isHTML,
+ }
);
const game = room.getGame(ScavengerHunt);
if (game) {
game.setTimer(duration); // auto timer for queue'd games.
room.add(`|c|~|[ScavengerManager] A scavenger hunt by ${Chat.toListString(next.hosts.map(h => h.name))} has been automatically started. It will automatically end in ${duration} minutes.`).update(); // highlight the users with "hunt by"
+ this.modlog('SCAV NEW', null, `${game.gameType.toUpperCase()}: creators - ${game.hosts.map(h => h.id)}`);
}
// update the saved queue.
@@ -1016,7 +1031,7 @@ export class ScavengerHuntPlayer extends Rooms.RoomGamePlayer {
onNotifyChange(num: number) {
this.game.runEvent('NotifyChange', this, num);
if (num === this.currentQuestion) {
- this.sendRoom(`|raw|The hint has been changed to: ${Chat.formatText(this.game.questions[num].hint)}`);
+ this.sendRoom(`|raw|The hint has been changed to: ${this.game.formatOutput(this.game.questions[num].hint)}
`);
}
}
@@ -1339,6 +1354,20 @@ const ScavengerCommands: Chat.ChatCommands = {
forcecreate: 'create',
forcecreateunrated: 'create',
createrecycled: 'create',
+
+ createhtmltwist: 'create',
+ createhtmltwistofficial: 'create',
+ createhtmltwistmini: 'create',
+ createhtmltwistpractice: 'create',
+ createhtmltwistunrated: 'create',
+ createhtmlpractice: 'create',
+ createhtmlofficial: 'create',
+ createhtmlunrated: 'create',
+ createhtmlmini: 'create',
+ forcecreatehtml: 'create',
+ forcecreatehtmlunrated: 'create',
+ createhtmlrecycled: 'create',
+ createhtml: 'create',
create(target, room, user, connection, cmd) {
room = this.requireRoom();
if (!getScavsRoom(room)) {
@@ -1359,6 +1388,8 @@ const ScavengerCommands: Chat.ChatCommands = {
gameType = 'recycled';
}
+ const isHTML = cmd.includes('html');
+
let mod;
let questions = target;
@@ -1410,7 +1441,17 @@ const ScavengerCommands: Chat.ChatCommands = {
const res = ScavengerHunt.parseQuestions(params);
if (res.err) return this.errorReply(res.err);
- room.game = new ScavengerHunt(room, user, hosts, gameType, res.result, mod);
+ room.game = new ScavengerHunt(
+ {
+ room: room,
+ staffHost: user,
+ hosts: hosts,
+ gameType: gameType,
+ questions: res.result,
+ isHTML: isHTML,
+ mod: mod,
+ }
+ );
this.privateModAction(`A new scavenger hunt was created by ${user.name}.`);
this.modlog('SCAV NEW', null, `${gameType.toUpperCase()}: creators - ${hosts.map(h => h.id)}`);
@@ -1526,6 +1567,7 @@ const ScavengerCommands: Chat.ChatCommands = {
const hunt: QueuedHunt = {
hosts: game.hosts,
questions: [],
+ isHTML: game.isHTML,
staffHostId: game.staffHostId,
staffHostName: game.StaffHostName,
gameType: game.gameType,
@@ -1699,6 +1741,10 @@ const ScavengerCommands: Chat.ChatCommands = {
queueunrated: 'queue',
queuerated: 'queue',
queuerecycled: 'queue',
+ queuehtmlunrated: 'queue',
+ queuehtmlrated: 'queue',
+ queuehtmlrecycled: 'queue',
+ queuehtml: 'queue',
queue(target, room, user) {
room = this.requireRoom();
if (!getScavsRoom(room)) {
@@ -1714,6 +1760,8 @@ const ScavengerCommands: Chat.ChatCommands = {
return this.parse('/scavhelp staff');
}
+ const isHTML = this.cmd.includes('html');
+
this.checkCan('mute', null, room);
if (this.cmd === 'queuerecycled') {
@@ -1736,6 +1784,7 @@ const ScavengerCommands: Chat.ChatCommands = {
room.settings.scavQueue.push({
hosts: next.hosts,
questions: correctlyFormattedQuestions,
+ isHTML: isHTML,
staffHostId: 'scavengermanager',
staffHostName: 'Scavenger Manager',
gameType: 'unrated',
@@ -1755,6 +1804,7 @@ const ScavengerCommands: Chat.ChatCommands = {
room.settings.scavQueue.push({
hosts: hosts,
questions: results.result,
+ isHTML: isHTML,
staffHostId: user.id,
staffHostName: user.name,
gameType: (this.cmd.includes('unrated') ? 'unrated' : 'regular'),
@@ -1811,11 +1861,14 @@ const ScavengerCommands: Chat.ChatCommands = {
const next = room.settings.scavQueue.splice(huntId, 1)[0];
room.game = new ScavengerHunt(
- room,
- {id: next.staffHostId, name: next.staffHostName},
- next.hosts,
- next.gameType,
- next.questions
+ {
+ room: room,
+ staffHost: {id: next.staffHostId, name: next.staffHostName},
+ hosts: next.hosts,
+ gameType: next.gameType,
+ questions: next.questions,
+ isHTML: next.isHTML,
+ }
);
if (huntId) this.sendReply(`|uhtmlchange|scav-queue|${formatQueue(room.settings.scavQueue, user, room)}`);
@@ -2501,6 +2554,7 @@ export const commands: Chat.ChatCommands = {
// old game aliases
scavenge: ScavengerCommands.guess,
startpracticehunt: 'starthunt',
+ startofficial: 'starthunt',
startofficialhunt: 'starthunt',
startminihunt: 'starthunt',
startunratedhunt: 'starthunt',
@@ -2515,6 +2569,24 @@ export const commands: Chat.ChatCommands = {
forcestartunrated: 'starthunt',
forcestartpractice: 'starthunt',
+ starthtmlpracticehunt: 'starthunt',
+ starthtmlofficial: 'starthunt',
+ starthtmlofficialhunt: 'starthunt',
+ starthtmlminihunt: 'starthunt',
+ starthtmlunratedhunt: 'starthunt',
+ starthtmlrecycledhunt: 'starthunt',
+ starthtmltwisthunt: 'starthunt',
+ starthtmltwistofficial: 'starthunt',
+ starthtmltwistpractice: 'starthunt',
+ starthtmltwistmini: 'starthunt',
+ starthtmltwistunrated: 'starthunt',
+
+ forcehtmlstarthunt: 'starthunt',
+ forcehtmlstartunrated: 'starthunt',
+ forcehtmlstartpractice: 'starthunt',
+
+ starthtmlhunt: 'starthunt',
+
starthunt: ScavengerCommands.create,
joinhunt: ScavengerCommands.join,
leavehunt: ScavengerCommands.leave,
@@ -2580,7 +2652,9 @@ export const commands: Chat.ChatCommands = {
"- /teamscavshelp: Explains the team scavs plugin.",
" As a room driver (%) , you can also use the following Scavengers commands:",
"- /scav queue (unrated) [host(s)] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | ...: Queue a scavenger hunt to be started after the current hunt is finished.",
+ "- /scav queuehtml (unrated) [host(s)] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | ...: Queue a scavenger hunt that uses HTML to be started after the current hunt is finished.",
"- /start(official/practice/mini/unrated)hunt [host] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | ...: Create a new (official/practice/mini/unrated) scavenger hunt and start it immediately.",
+ "- /starthtml(official/practice/mini/unrated)hunt [host] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | ...: Create a new (official/practice/mini/unrated) scavenger hunt that uses HTML and start it immediately.",
"- /scav viewqueue (or /scav queue): Look at the list of queued scavenger hunts. Now also includes the option to remove hunts from the queue.",
"- /resethunt: Reset the current scavenger hunt without revealing the hints and answers, nor giving out points.",
"- /resethunttoqueue: Reset the ongoing scavenger hunt without revealing the hints and answers, nor giving out points. Then, add it directly to the queue.",