a43ccf49-0da8-9821-08c7-70ff263e80d1_script.lsl 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. //
  2. // The line above should be left blank to avoid script errors in OpenSim.
  3. /* Sloodle quiz chair
  4. Copyright (c) 2006-9 Sloodle (various contributors)
  5. Released under the GNU GPL
  6. This files lists all the status codes we use for sloodle.
  7. They have been written in LSL format so that you can plunk them into your source
  8. code if needed.
  9. Contributors:
  10. Edmund Edgar
  11. Paul Preibisch
  12. */
  13. integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651;
  14. integer doRepeat = 0; // whether we should run through the questions again when we're done
  15. integer doDialog = 1; // whether we should ask the questions using dialog rather than chat
  16. integer doPlaySound = 1; // whether we should play sound
  17. integer doRandomize = 1; // whether we should ask the questions in random order
  18. string sloodleserverroot = "";
  19. integer sloodlecontrollerid = 0;
  20. string sloodlepwd = "";
  21. integer sloodlemoduleid = 0;
  22. integer sloodleobjectaccessleveluse = 0; // Who can use this object?
  23. integer sloodleobjectaccesslevelctrl = 0; // Who can control this object?
  24. integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
  25. integer isconfigured = FALSE; // Do we have all the configuration data we need?
  26. integer eof = FALSE; // Have we reached the end of the configuration data?
  27. integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
  28. integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343; // an arbitrary channel the sloodle scripts will use to talk to each other. Doesn't atter what it is, as long as the same thing is set in the sloodle_slave script.
  29. integer SLOODLE_CHANNEL_AVATAR_IGNORE = -1639279999;
  30. integer SLOODLE_CHANNEL_QUIZ_START_FOR_AVATAR = -1639271102; //Tells us to start a quiz for the avatar, if possible.; Ordinary quiz chair will have a second script that detects and avatar sitting on it and sends it. Awards-integrated version waits for a game ID to be set before doing this.
  31. integer SLOODLE_CHANNEL_QUIZ_STARTED_FOR_AVATAR = -1639271103; //Sent by main quiz script to tell UI scripts that quiz has started for avatar with key
  32. integer SLOODLE_CHANNEL_QUIZ_COMPLETED_FOR_AVATAR = -1639271104; //Sent by main quiz script to tell UI scripts that quiz has finished for avatar with key, with x/y correct in string
  33. integer SLOODLE_CHANNEL_QUESTION_ASKED_AVATAR = -1639271105; //Sent by main quiz script to tell UI scripts that question has been asked to avatar with key. String contains question ID + "|" + question text
  34. integer SLOODLE_CHANNEL_QUESTION_ANSWERED_AVATAR = -1639271106; //Sent by main quiz script to tell UI scripts that question has been answered by avatar with key. String contains selected option ID + "|" + option text + "|"
  35. integer SLOODLE_CHANNEL_QUIZ_LOADING_QUESTION = -1639271107;
  36. integer SLOODLE_CHANNEL_QUIZ_LOADED_QUESTION = -1639271108;
  37. integer SLOODLE_CHANNEL_QUIZ_LOADING_QUIZ = -1639271109;
  38. integer SLOODLE_CHANNEL_QUIZ_LOADED_QUIZ = -1639271110;
  39. integer SLOODLE_CHANNEL_QUIZ_GO_TO_STARTING_POSITION = -1639271111;
  40. integer SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT = -1639271125; // Tells the question handler scripts to ask the question with the ID in str to the avatar with key VIA CHAT.
  41. integer SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG = -1639271126; // Tells the question handler scripts to ask the question with the ID in str to the avatar with key VIA DIALOG.
  42. integer SLOODLE_CHANNEL_ANSWER_SCORE_FOR_AVATAR = -1639271113; // Tells anyone who might be interested that we scored the answer. Score in string, avatar in key.
  43. integer SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_DEFAULT = -1639271114; //mod quiz script is in state DEFAULT
  44. integer SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_READY = -1639271115; //mod quiz script is in state READY
  45. integer SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_LOAD_QUIZ_FOR_USER = -1639271116; //mod quiz script is in state CHECK_QUIZ
  46. integer SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_QUIZZING = -1639271117; //mod quiz script is in state quizzing
  47. integer SLOODLE_CHANNEL_QUIZ_NO_PERMISSION_USE= -1639271118; //user has tried to use the chair but doesnt have permission to do so.
  48. integer SLOODLE_CHANNEL_QUIZ_STOP_FOR_AVATAR = -1639271119; //Tells us to STOP a quiz for the avatar
  49. integer SLOODLE_CHANNEL_QUIZ_SUCCESS_NOTHING_MORE_TO_DO_WITH_AVATAR= -1639271122;
  50. integer SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR= -1639271123;
  51. integer SLOODLE_CHANNEL_QUIZ_ERROR_INVALID_QUESION = -1639271121; //
  52. integer SLOODLE_CHANNEL_QUIZ_ERROR_ATTEMPTS_LEFT= -1639271123; //
  53. integer SLOODLE_CHANNEL_QUIZ_ERROR_NO_QUESTIONS= -1639271124; //
  54. ///// TRANSLATION /////
  55. // Link message channels
  56. integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
  57. // Translation output methods
  58. string SLOODLE_TRANSLATE_WHISPER = "whisper"; // 1 output parameter: chat channel number
  59. string SLOODLE_TRANSLATE_SAY = "say"; // 1 output parameter: chat channel number
  60. string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay"; // No output parameters
  61. string SLOODLE_TRANSLATE_DIALOG = "dialog"; // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
  62. string SLOODLE_TRANSLATE_LOAD_URL = "loadurl"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  63. string SLOODLE_TRANSLATE_IM = "instantmessage"; // Recipient avatar should be identified in link message keyval. No output parameters.
  64. integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
  65. integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
  66. integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
  67. string SLOODLE_OBJECT_TYPE = "quiz-1.0";
  68. string SLOODLE_EOF = "sloodleeof";
  69. string sloodle_quiz_url = "/mod/sloodle/mod/quiz-1.0/linker.php";
  70. key httpquizquery = NULL_KEY;
  71. float request_timeout = 20.0;
  72. string sloodlehttpvars;
  73. // ID and name of the current quiz
  74. integer quizid = -1;
  75. string quizname = "";
  76. // This stores the list of question ID's (global ID's)
  77. list question_ids = [];
  78. integer num_questions = 0;
  79. // Identifies the active question number (index into question_ids list)
  80. // (Next question will always be this value +1)
  81. integer active_question = -1;
  82. // Avatar currently using this cahir
  83. key sitter = NULL_KEY;
  84. // The position where we started. The Chair will use this to get the lowest vertical position it used.
  85. vector startingposition;
  86. // Stores the number of questions the user got correct on a given attempt
  87. integer num_correct = 0;
  88. ///// FUNCTIONS /////
  89. /******************************************************************************************************************************
  90. * sloodle_error_code -
  91. * Author: Paul Preibisch
  92. * Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
  93. * The error_messages script hears this, translates the status code and sends an instant message to the avuuid
  94. * Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
  95. * Params: avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
  96. * Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
  97. * Params: a message from the server to use if there is none listed in the linker script.
  98. *******************************************************************************************************************************/
  99. sloodle_error_code(string method, key avuuid,integer statuscode, string msg){
  100. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode+"|"+(string)msg, NULL_KEY);
  101. } sloodle_debug(string msg)
  102. {
  103. llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
  104. }
  105. /******************************************************************************************************************************
  106. * clearUserQuizData-
  107. * Description - resets the quiz chair data. Used if a user jumps off a quiz chair. Resets data for next user
  108. *******************************************************************************************************************************/
  109. clearUserQuizData(){
  110. quizname = "";
  111. question_ids = [];
  112. num_questions = 0;
  113. num_correct=0;
  114. active_question = -1;
  115. sitter=NULL_KEY;
  116. }
  117. // Configure by receiving a linked message from another script in the object
  118. // Returns TRUE if the object has all the data it needs
  119. integer sloodle_handle_command(string str){
  120. list bits = llParseString2List(str,["|"],[]);
  121. integer numbits = llGetListLength(bits);
  122. string name = llList2String(bits,0);
  123. string value1 = "";
  124. string value2 = "";
  125. if (numbits > 1) value1 = llList2String(bits,1);
  126. if (numbits > 2) value2 = llList2String(bits,2);
  127. if (name == "set:sloodleserverroot") sloodleserverroot = value1;
  128. else if (name == "set:sloodlepwd") {
  129. // The password may be a single prim password, or a UUID and a password
  130. if (value2 != "") {
  131. sloodlepwd = value1 + "|" + value2;
  132. }
  133. else {
  134. sloodlepwd = value1;
  135. }
  136. }
  137. else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
  138. else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
  139. else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
  140. else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
  141. else if (name == "set:sloodlerepeat") doRepeat = (integer)value1;
  142. else if (name == "set:sloodlerandomize") doRandomize = (integer)value1;
  143. else if (name == "set:sloodledialog") doDialog = (integer)value1;
  144. else if (name == "set:sloodleplaysound") doPlaySound = (integer)value1;
  145. else if (name == SLOODLE_EOF) eof = TRUE;
  146. return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
  147. }
  148. // Checks if the given agent is permitted to user this object
  149. // Returns TRUE if so, or FALSE if not
  150. integer sloodle_check_access_use(key id)
  151. {
  152. // Check the access mode
  153. if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
  154. return llSameGroup(id);
  155. } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
  156. return TRUE;
  157. }
  158. // Assume it's owner mode
  159. return (id == llGetOwner());
  160. }
  161. // Report completion to the user
  162. finish_quiz()
  163. {
  164. sloodle_translation_request(SLOODLE_TRANSLATE_IM, [0], "complete", [llKey2Name(sitter), (string)num_correct + "/" + (string)num_questions], sitter, "quiz");
  165. //move_to_start(); // Taking this out here leaves the quiz chair at its final position until the user stands up.
  166. // Notify the server that the attempt was finished
  167. string body = sloodlehttpvars;
  168. body += "&finishattempt=1";
  169. llHTTPRequest(sloodleserverroot + sloodle_quiz_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  170. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_COMPLETED_FOR_AVATAR, (string)num_correct + "/" + (string)num_questions, sitter);
  171. }
  172. // Send a translation request link message
  173. sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch){
  174. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
  175. }
  176. ///// ----------- /////
  177. ///// STATES /////
  178. default
  179. {
  180. state_entry()
  181. {
  182. // Starting again with a new configuration
  183. llSetText("", <0.0,0.0,0.0>, 0.0);
  184. isconfigured = FALSE;
  185. eof = FALSE;
  186. // Reset our configuration data
  187. sloodleserverroot = "";
  188. sloodlepwd = "";
  189. sloodlecontrollerid = 0;
  190. sloodlemoduleid = 0;
  191. sloodleobjectaccessleveluse = 0;
  192. sloodleserveraccesslevel = 0;
  193. doRepeat = 1;
  194. doDialog = 1;
  195. doPlaySound = 1;
  196. doRandomize = 1;
  197. //tell other scripts we are in the default state.
  198. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_DEFAULT,llGetScriptName(), NULL_KEY);
  199. }
  200. link_message( integer sender_num, integer num, string str, key id)
  201. {
  202. // Check the channel for configuration messages
  203. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  204. // Split the message into lines
  205. list lines = llParseString2List(str, ["\n"], []);
  206. integer numlines = llGetListLength(lines);
  207. integer i = 0;
  208. for (i=0; i < numlines; i++) {
  209. isconfigured = sloodle_handle_command(llList2String(lines, i));
  210. }
  211. // If we've got all our data AND reached the end of the configuration data (eof), then move on
  212. if (eof == TRUE) {
  213. if (isconfigured == TRUE) {
  214. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
  215. state ready;
  216. } else {
  217. // Go all configuration but, it's not complete... request reconfiguration
  218. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
  219. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
  220. eof = FALSE;
  221. }
  222. }
  223. }
  224. }
  225. touch_start(integer num_detected)
  226. {
  227. //let the administrator request re-configuration if we get stuck in this state
  228. // Attempt to request a reconfiguration
  229. if (llDetectedKey(0) == llGetOwner()) {
  230. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
  231. }
  232. }
  233. }
  234. // Ready state - waiting for a user to climb aboard!
  235. state ready
  236. {
  237. state_entry()
  238. {
  239. // Clear existing data
  240. clearUserQuizData();
  241. //tell other scripts we are in the ready state
  242. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_READY, "", NULL_KEY);
  243. // This is now handled by a separate poseball
  244. // llSitTarget(<0,0,.5>, ZERO_ROTATION);
  245. }
  246. // Wait for the script that handles the sitting to tell us that somebody has sat on us.
  247. // Normally a sit will immediately produce a link message
  248. // But variations on the script may do things differently,
  249. // eg. the awards script doesn't want to start the quiz until it's got a Game ID
  250. link_message(integer sender_num, integer num, string str, key id)
  251. {
  252. if (num == SLOODLE_CHANNEL_QUIZ_START_FOR_AVATAR) {
  253. sitter = id;
  254. // Make sure the given avatar is allowed to use this object
  255. if (!sloodle_check_access_use(sitter)) {
  256. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [llKey2Name(sitter)], NULL_KEY, "");
  257. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_NO_PERMISSION_USE, "", sitter);
  258. sitter = NULL_KEY;
  259. return;
  260. }
  261. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "starting", [llKey2Name(sitter)], NULL_KEY, "quiz");
  262. state load_quiz_for_user;
  263. }
  264. }
  265. on_rez(integer par)
  266. {
  267. llResetScript();
  268. }
  269. state_exit()
  270. {
  271. llSetTimerEvent(0.0);
  272. }
  273. }
  274. // Fetching the general quiz data from the server
  275. state load_quiz_for_user
  276. {
  277. state_entry()
  278. {
  279. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_LOAD_QUIZ_FOR_USER, "", sitter);
  280. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "fetchingquiz", [], NULL_KEY, "quiz");
  281. // Request the quiz data from Moodle
  282. sloodlehttpvars = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  283. sloodlehttpvars += "&sloodlepwd=" + sloodlepwd;
  284. sloodlehttpvars += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  285. sloodlehttpvars += "&sloodleuuid=" + (string)sitter;
  286. sloodlehttpvars += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  287. sloodlehttpvars += "&sloodleavname=" + llEscapeURL(llKey2Name(sitter));
  288. httpquizquery = llHTTPRequest(sloodleserverroot + sloodle_quiz_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], sloodlehttpvars);
  289. llSetTimerEvent(0.0);
  290. llSetTimerEvent((float)request_timeout);
  291. }
  292. state_exit()
  293. {
  294. llSetTimerEvent(0.0);
  295. }
  296. timer()
  297. {
  298. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
  299. state ready;
  300. }
  301. link_message(integer sender_num, integer num, string str, key id) {
  302. if (num == SLOODLE_CHANNEL_QUIZ_STOP_FOR_AVATAR){
  303. state ready;
  304. }
  305. }
  306. http_response(key id, integer status, list meta, string body)
  307. {
  308. // Is this the response we are expecting?
  309. if (id != httpquizquery) return;
  310. httpquizquery = NULL_KEY;
  311. llSetTimerEvent(0.0);
  312. // Make sure the response was OK
  313. if (status != 200) {
  314. sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status, ""); //send message to error_message.lsl
  315. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);//todo add to dia
  316. state ready;//todo add to dia
  317. }
  318. // Split the response into several lines
  319. list lines = llParseString2List(body, ["\n"], []);
  320. integer numlines = llGetListLength(lines);
  321. body = "";
  322. list statusfields = llParseStringKeepNulls(llList2String(lines,0), ["|"], []);
  323. integer statuscode = (integer)llStringTrim(llList2String(statusfields, 0), STRING_TRIM);
  324. // Was it an error code?
  325. if (statuscode == -10301) {
  326. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noattemptsleft", [llKey2Name(sitter)], NULL_KEY, "");
  327. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);//todo add to dia
  328. state ready;
  329. return;
  330. } else if (statuscode == -10302) {
  331. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noquestions", [], NULL_KEY, "");
  332. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);
  333. state ready;
  334. return;
  335. } else if (statuscode <= 0) {
  336. //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
  337. string msg;
  338. if (numlines > 1) {
  339. msg = llList2String(lines, 1);
  340. }
  341. sloodle_debug(msg);
  342. //Sloodle 2.0 Change - output custom errorcode to other scripts
  343. sloodle_error_code(SLOODLE_TRANSLATE_IM, sitter,statuscode, msg); //send message to error_message.lsl
  344. // Check if an error message was reported
  345. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);//add to dia
  346. state ready;
  347. return;
  348. }
  349. // We shouldn't need the status line anymore... get rid of it
  350. statusfields = [];
  351. // Go through each line of the response
  352. integer i;
  353. for (i = 1; i < numlines; i++) {
  354. // Extract and parse the current line
  355. string thislinestr = llList2String(lines, i);
  356. list thisline = llParseString2List(thislinestr,["|"],[]);
  357. string rowtype = llList2String( thisline, 0 );
  358. // Check what type of line this is
  359. if ( rowtype == "quiz" ) {
  360. // Get the quiz ID and name
  361. quizid = (integer)llList2String(thisline, 4);
  362. quizname = llList2String(thisline, 2);
  363. } else if ( rowtype == "quizpages" ) {
  364. // Extract the list of questions ID's
  365. list question_ids_str = llCSV2List(llList2String(thisline, 3));
  366. num_questions = llGetListLength(question_ids_str);
  367. integer qiter = 0;
  368. question_ids = [];
  369. // Store all our question IDs
  370. for (qiter = 0; qiter < num_questions; qiter++) {
  371. question_ids += [(integer)llList2String(question_ids_str, qiter)];
  372. }
  373. // Are we to randomize the order of the questions?
  374. if (doRandomize) question_ids = llListRandomize(question_ids, 1);
  375. active_question = 0;
  376. }
  377. }
  378. // Make sure we have all the data we need
  379. if (quizname == "" || num_questions == 0) {
  380. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noquestions", [], NULL_KEY, "quiz");
  381. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);//add to dia
  382. state ready;//todo add to dia
  383. return;
  384. }
  385. // Report the status to the user
  386. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "ready", [quizname], NULL_KEY, "quiz");
  387. state quizzing;
  388. }
  389. on_rez(integer par)
  390. {
  391. llResetScript();
  392. }
  393. }
  394. // Running the quiz
  395. state quizzing
  396. {
  397. on_rez(integer param)
  398. {
  399. llResetScript();
  400. }
  401. state_entry()
  402. {
  403. llSetText("", <0.0,0.0,0.0>, 0.0);
  404. num_correct = 0;
  405. //tell other scripts we are quizzing
  406. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_QUIZZING, "", sitter);
  407. // Make sure we have some questions
  408. if (num_questions == 0) {
  409. sloodle_debug("No questions - cannot run quiz.");
  410. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter);//add to dia
  411. state ready;//todo add to dia
  412. return;
  413. }
  414. // Start from the beginning
  415. active_question = 0;
  416. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_STARTED_FOR_AVATAR, (string)quizid+"|"+quizname, sitter );
  417. if (doDialog==1){ //1 = true
  418. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  419. }else
  420. if (doDialog==0){ //0= false
  421. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  422. }
  423. llSetTimerEvent( 10.0 ); // The other script should let us know that it's heard us and asked the question. If it doesn't, we'll keep on retrying until it hears us, if it ever does.
  424. }
  425. link_message(integer sender_num, integer num, string str, key id)
  426. {
  427. if (num == SLOODLE_CHANNEL_QUIZ_STOP_FOR_AVATAR){
  428. state ready;
  429. }
  430. else
  431. if (num == SLOODLE_CHANNEL_QUIZ_ERROR_INVALID_QUESION) {//TODO add to dia
  432. //send message it is done with avatar
  433. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_FAILURE_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter );//TODO add to dia
  434. //go to state READY
  435. state ready;//todo add to dia
  436. }else
  437. if (num == SLOODLE_CHANNEL_ANSWER_SCORE_FOR_AVATAR) {
  438. float scorechange = (integer)str;
  439. if (sitter != id) {
  440. return;
  441. }
  442. // Advance to the next question
  443. active_question++;
  444. if(scorechange>0) num_correct++; // SAL added this
  445. // Are we are at the end of the quiz?
  446. if (active_question >= num_questions) {
  447. // Yes - finish off
  448. finish_quiz();
  449. // Do we want to repeat the quiz?
  450. if (!doRepeat) {
  451. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_SUCCESS_NOTHING_MORE_TO_DO_WITH_AVATAR, "", sitter );//TODO add to dia
  452. }
  453. state quizzing;
  454. return;
  455. }
  456. if (doDialog==1){ //1 = true
  457. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  458. }else
  459. if (doDialog==0){ //0= false
  460. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  461. }
  462. } else if (num == SLOODLE_CHANNEL_QUESTION_ASKED_AVATAR) {
  463. // Cancel the timer that we used to make sure the question script heard us and asked its question.
  464. // At this point the question script should ask the question then wait for a response.
  465. // If it doesn't get one, nothing will happen until the sitter touches us, and we'll ask the question script to fetch and ask the question again.
  466. llSetTimerEvent(0.0);
  467. } else if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  468. // Is it a reset command?
  469. if (str == "do:reset") {
  470. llResetScript();
  471. }
  472. return;
  473. }
  474. // TODO: What happens if loading the question fails?
  475. }
  476. state_exit()
  477. {
  478. llSetTimerEvent(0.0);
  479. }
  480. timer()
  481. {
  482. llSetTimerEvent( 0.0 );
  483. if (active_question > -1) {
  484. if (doDialog==1){ //1 = true
  485. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  486. }else
  487. if (doDialog==0){ //0= false
  488. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  489. }
  490. llSetTimerEvent( 10.0 ); // The other script should let us know that it's heard us and answered the question. If it doesn't, we'll keep on retrying until it hears us, if it ever does.
  491. }
  492. }
  493. touch_start(integer num)
  494. {
  495. if ((active_question + 1) < num_questions) {
  496. if (llDetectedKey(0) == sitter) {
  497. if (doDialog==1){ //1 = true
  498. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  499. }else
  500. if (doDialog==0){ //0= false
  501. llMessageLinked( LINK_SET, SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT, llList2String(question_ids, active_question)+"|"+sloodleserverroot+sloodle_quiz_url+"|"+sloodlehttpvars,sitter );//todo add to dia
  502. }
  503. }
  504. }
  505. }
  506. }
  507. // Please leave the following line intact to show where the script lives in Git:
  508. // SLOODLE LSL Script Git Location: mod/quiz-1.0/objects/default/assets/sloodle_mod_quiz-1.0.lslp