Trivia files are text files which use the same format as
HamFon's Trivia Bot. Each line of the file is defined as follows.
- The first character of the line defines what the line's separator is.
- The first token of the line is the category.
- The second token is the best answer.
- The remaining tokens until the first double separator, are other possible answers.
- Between the first double separator and either the end of the line or the second double separator, is the question.
- Remaining tokens separated by any separators are extra parameters, which are not used as of yet.
For example, all of the following lines are valid.
NPC Code:
/Sports&Leisure/Indianapolis Motor Speedway/Indianapolis/Indy//Where is Gasoline Alley?
/GraalOnline/Classic iPhone/Classic//What was the first successful iPhone Graal server?//parameters/that/are/not/used/(yet)
\Graal\graalonline.com/downloads\\Where can you download the GraalOnline client?
Some example trivia files are available
here.
All trivia text files should be placed in trivia/ .
The (npcserver) requires read rights to the trivia files.
r trivia/*
By default, chat commands are:
!trivia [rounds] (staff rights required)
!stoptrivia - stop the trivia (staff rights required)
!leader - who is winning the current game
!points - how many points you have this game
!correct - how many correct answers you have this game
To join a game, or answer a question, you just say an answer. If it is a correct answer, you should see something like this...
(trivia Stefan ftw?)
Note that answers are not case or context sensitive. If an answer is Billie Jean, and someone says "It might be billie jean, but idk!", that would be considered a correct answer.
npc script:
PHP Code:
function onCreated() {
join("trivia");
loadTriviaFile("your_trivia_file.txt"); // located at trivia/your_trivia_file.txt
showcharacter();
this.head = "head19.png";
this.body = "body2.png";
this.dir = 2;
this.colors[0] = "orange";
this.colors[1] = "darkgreen";
this.colors[2] = "brown";
this.colors[3] = "red";
this.colors[4] = "green";
}
class "trivia":
PHP Code:
const DEFAULT_ROUNDS = 10;
const START_MESSAGE = "Starting %1$s rounds of trivia! Get ready!";
const STOP_MESSAGE = "Stopping the trivia.";
const CATEGORY_MESSAGE = "The next question is categorized as '%1$s'.";
const CORRECT_ANSWER_MESSAGE = "The first correct answer was given by '%1$s'! (%2$s seconds)";
const NO_CORRECT_ANSWER_MESSAGE = "Nobody was able to give a correct answer!";
const CORRECT_MESSAGE = "The correct answer was '%1$s'.";
const LEADER_MESSAGE = "Currently, '%1$s' is in the lead, with %2$s points!";
const ROUNDS_REMAINING_MESSAGE = "There are %1$s rounds remaining in this trivia game.";
const WINNER_MESSAGE = "This trivia game's winner is '%1$s'!";
const MESSAGE_TIMEOUT = 5;
const TRIVIA_TIMEOUT = 30;
const TRIVIA_POINTS = 50;
/**
events
*/
function onCreated() {
stopTrivia();
}
function onPlayerChats() {
temp.tokens = player.chat.tokenize();
switch (temp.tokens[0].lower()) {
case "!trivia":
if (player.communityname in serveroptions.staff.tokenize(","))
startTrivia(temp.tokens[1]);
break;
case "!stoptrivia":
if (player.communityname in serveroptions.staff.tokenize(","))
stopTrivia();
break;
case "!leader":
player.chat = getLeaderNick();
break;
case "!points":
player.chat = this.triviaPlayers.(@player.account).points;
break;
case "!correct":
player.chat = this.triviaPlayers.(@player.account).correctAnswers;
break;
default:
if (this.roundStarted)
triviaAnswer();
break;
}
}
function onRoundStart() {
this.triviaIndex = int(random(0, this.trivia.size()));
this.chat = format2(CATEGORY_MESSAGE, {this.trivia[this.triviaIndex].category});
scheduleevent(MESSAGE_TIMEOUT, "onAskQuestion", NULL);
}
function onAskQuestion() {
this.chat = this.trivia[this.triviaIndex].question;
this.questionTime = timevar2;
scheduleevent(TRIVIA_TIMEOUT, "onTriviaTimeout", NULL);
this.roundStarted = true;
}
function onTriviaTimeout() {
this.roundStarted = false;
this.chat = NO_CORRECT_ANSWER_MESSAGE;
scheduleevent(MESSAGE_TIMEOUT, "onAnnounceAnswer", NULL);
}
function onAnnounceAnswer() {
this.chat = format2(CORRECT_MESSAGE, {this.trivia[this.triviaIndex].answers[0]});
scheduleevent(MESSAGE_TIMEOUT, "onAnnounceLeader", NULL);
}
function onAnnounceLeader() {
if (this.leaderAccount != NULL)
this.chat = format2(LEADER_MESSAGE, {getLeaderNick(), this.triviaPlayers.(@this.leaderAccount).points});
scheduleevent(MESSAGE_TIMEOUT, "onRoundEnd", NULL);
}
function onRoundEnd() {
if (--this.rounds > 0) {
this.chat = format2(ROUNDS_REMAINING_MESSAGE, {this.rounds});
scheduleevent(MESSAGE_TIMEOUT, "onRoundStart", NULL);
} else {
if (this.leaderAccount == NULL) {
stopTrivia();
} else {
this.chat = format2(WINNER_MESSAGE, {getLeaderNick()});
scheduleevent(MESSAGE_TIMEOUT, "onStopTrivia", NULL);
}
}
}
function onClearChat() {
this.chat = "";
}
function onStopTrivia() {
stopTrivia();
}
/**
functions
*/
function loadTriviaFile(temp.s) {
this.trivia = "";
temp.lines.loadlines("trivia/" @ temp.s);
for (temp.line: temp.lines) {
if (temp.line.trim() == "")
continue;
temp.separator = temp.line.substring(0, 1);
temp.sepPositions = temp.line.positions(temp.separator @ temp.separator);
temp.obj = new TStaticVar();
if (temp.sepPositions.size() > 1) {
temp.obj.question = temp.line.substring(temp.sepPositions[0] + 2, temp.sepPositions[1]);
temp.obj.params = temp.line.substring(temp.sepPositions[1] + 2).tokenize(temp.separator);
} else {
temp.obj.question = temp.line.substring(temp.sepPositions[0] + 2);
}
temp.tokens = temp.line.substring(0, temp.sepPositions[0]).tokenize(temp.separator);
temp.obj.category = temp.tokens[0];
temp.obj.answers = temp.tokens.subarray(1);
this.trivia.add(temp.obj);
}
if (this.trivia.size() == 0) {
this.chat = "Unable to load trivia data. Make sure the specified file exists, and is a valid trivia text file.";
this.triviaLoaded = false;
} else {
this.chat = "Trivia loaded!";
this.triviaLoaded = true;
}
}
function startTrivia(temp.rounds) {
if (this.triviaStarted)
stopTrivia();
if (!this.triviaLoaded)
return;
if (temp.rounds <= 0)
temp.rounds = DEFAULT_ROUNDS;
this.rounds = temp.rounds;
cancelevents("onClearChat");
this.chat = format2(START_MESSAGE, {temp.rounds});
if (this.triviaPlayers != NULL)
this.triviaPlayers.destroy();
this.triviaPlayers = new TStaticVar();
this.leaderAccount = "";
scheduleevent(5, "onRoundStart", NULL);
this.triviaStarted = true;
}
function stopTrivia() {
if (this.triviaStarted)
this.chat = STOP_MESSAGE;
scheduleevent(MESSAGE_TIMEOUT, "onClearChat", NULL);
cancelevents("onTriviaUpdate");
cancelevents("onRoundStart");
cancelevents("onAskQuestion");
cancelevents("onTriviaTimeout");
cancelevents("onAnnounceAnswer");
cancelevents("onAnnounceLeader");
cancelevents("onRoundEnd");
cancelevents("onStopTrivia");
this.triviaStarted = false;
}
function triviaAnswer() {
if (this.triviaPlayers.(@player.account) == NULL)
this.triviaPlayers.(@player.account) = new TStaticVar();
for (temp.answer: this.trivia[this.triviaIndex].answers) {
if (player.chat.lower().pos(temp.answer.lower()) == -1)
continue;
this.roundStarted = false;
this.triviaPlayers.(@player.account).correctAnswers++;
this.triviaPlayers.(@player.account).points += TRIVIA_POINTS;
this.chat = format2(CORRECT_ANSWER_MESSAGE, {player.nick, int(timevar2 - this.questionTime)});
if (this.triviaPlayers.(@player.account).points > this.triviaPlayers.(@this.leaderAccount).points)
this.leaderAccount = player.account;
cancelevents("onTriviaTimeout");
scheduleevent(MESSAGE_TIMEOUT, "onAnnounceAnswer", NULL);
return;
}
}
function getLeaderNick() {
temp.pl = findplayer(this.leaderAccount);
if (temp.pl == NULL)
temp.pl = new TServerPlayer(@this.leaderAccount);
temp.leaderNick = temp.pl.nick;
temp.pl.destroy();
return temp.leaderNick;
}
Please report any bugs you find, and comment with any ideas you have, so I can improve it for anyone that might use this.
Enjoy!