Greasy Fork 支持简体中文。

BvS_Daily (Non-ES6)

Assist in daily tasks

  1. // ==UserScript==
  2. // @name BvS_Daily (Non-ES6)
  3. // @namespace SirDuck36
  4. // @description Assist in daily tasks
  5. // @version 2019.05.25
  6. // @include http*://*animecubedgaming.com/billy/bvs*
  7. // @include http*://*animecubed.com/billy/bvs*
  8. // @grant GM_log
  9. // @grant GM_addStyle
  10. // ==/UserScript==
  11.  
  12. // ** NOTE ** - This version does NOT use ES6 features. For the other version please visit
  13. // https://greasyfork.org/en/scripts/2508-bvs-daily
  14. // 4.14.2011 Initial version by SirDuck36
  15. // 4.19.2011 Major overhaul of the API by SirDuck36
  16. // 4.20.2011 Minor updates and bug fixes from North
  17. // 4.20.2011 Updated ChangeSequence to include a task number
  18. // 4.20.2011 Bug fix for GoPage('glowslinging');
  19. // 4.21.2011 Added several new options for gopage function
  20. // 4.23.2011 Added sequences link -- suggested by WolfX
  21. // 4.23.2011 Add hotkeylock to left and right arrow hotkeys -- suggested by Skarn22
  22. // 4.23.2011 Added support for //@SequenceCode before first task -- suggested by North
  23. // 4.23.2011 Fixed editor window hide to remove lingering select box -- SirDuck36
  24. // 4.23.2011 Added functionality to hide daily window on desired pages -- SirDuck36
  25. // 6.12.2011 Bug fix for ChangeSequence function -- Skarn22
  26. // 6.19.2011 Add newline to ShowMsg and add pizzawitch to GoPage function -- SirDuck36
  27. // 9.28.2014 Added grant permissions -- Channel28
  28. // 11.7.2015 Fix a bug with flags when changing sequences. Thanks to Terrec -- Channel28
  29. // 11.8.2015 Small fix. Thanks to Terrec -- Channel28
  30. // 12.30.2015 Small fix regarding which key is to be pressed (Thanks to DTC) -- Channel28
  31. // 5.19.2017 Now https compatible -- Channel28
  32. // 2.04.2018 Now compatible with GreaseMonkey v4 (Thanks to Takumi) -- Channel28
  33. // 5.25.2019 Added GoPage destinations for Breakfast, Marketplace & Tattoo Parlor. Hiding/unhiding
  34. // of the window is remembered globally. This can be turned off by changing the
  35. // OptGlobalHide below. True to show and false to hide (Thanks to Chrobot) -- Channel28
  36. // Options
  37. // GlobalHide: if set, window's hidden/unhidden state is remembered globally
  38. // instead of per page.
  39. var OptGlobalHide = true;
  40. ////////////////////////////////////////////////////////////////////////
  41. /////////// LIBRARY CODE /////////////////
  42. ////////////////////////////////////////////////////////////////////////
  43. /*
  44. DOM Storage wrapper class (credits: http://userscripts.org/users/dtkarlsson)
  45. Constructor:
  46. var store = new DOMStorage({"session"|"local"}, [<namespace>]);
  47. Set item:
  48. store.setItem(<key>, <value>);
  49. Get item:
  50. store.getItem(<key>[, <default value>]);
  51. Remove item:
  52. store.removeItem(<key>);
  53. Get all keys in namespace as array:
  54. var array = store.keys();
  55. */
  56. function DOMStorage(type, namespace) {
  57. var my = this;
  58. if (typeof(type) != "string")
  59. type = "session";
  60. switch (type) {
  61. case "local": my.storage = localStorage; break;
  62. case "session": my.storage = sessionStorage; break;
  63. default: my.storage = sessionStorage;
  64. }
  65. if (!namespace || typeof(namespace) != "string")
  66. namespace = "Greasemonkey";
  67. my.ns = namespace + ".";
  68. my.setItem = function(key, val) {
  69. try {
  70. my.storage.setItem(escape(my.ns + key), val);
  71. }
  72. catch (e) {
  73. GM_log(e);
  74. }
  75. },
  76. my.getItem = function(key, def) {
  77. try {
  78. var val = my.storage.getItem(escape(my.ns + key));
  79. if (val)
  80. return val;
  81. else
  82. return def;
  83. }
  84. catch (e) {
  85. return def;
  86. }
  87. }
  88. // Kludge, avoid Firefox crash
  89. my.removeItem = function(key) {
  90. try {
  91. my.storage.setItem(escape(my.ns + key), null);
  92. }
  93. catch (e) {
  94. GM_log(e);
  95. }
  96. }
  97. // Return array of all keys in this namespace
  98. my.keys = function() {
  99. var arr = [];
  100. var i = 0;
  101. do {
  102. try {
  103. var key = unescape(my.storage.key(i));
  104. if (key.indexOf(my.ns) == 0 && my.storage.getItem(key))
  105. arr.push(key.slice(my.ns.length));
  106. }
  107. catch (e) {
  108. break;
  109. }
  110. i++;
  111. } while (true);
  112. return arr;
  113. }
  114. }
  115. // End DOM Storage Wrapper class
  116. // UI (credits: http://userscripts.org/users/dtkarlsson)
  117. function Window(id, storage)
  118. {
  119. var my = this;
  120. my.id = id;
  121. my.offsetX = 0;
  122. my.offsetY = 0;
  123. my.moving = false;
  124. // Window dragging events
  125. my.drag = function(event) {
  126. if (my.moving) {
  127. my.element.style.left = (event.clientX - my.offsetX)+'px';
  128. my.element.style.top = (event.clientY - my.offsetY)+'px';
  129. event.preventDefault();
  130. }
  131. }
  132. my.stopDrag = function(event) {
  133. if (my.moving) {
  134. my.moving = false;
  135. var x = parseInt(my.element.style.left);
  136. var y = parseInt(my.element.style.top);
  137. if(x < 0) x = 0;
  138. if(y < 0) y = 0;
  139. storage.setItem(my.id + ".coord.x", x);
  140. storage.setItem(my.id + ".coord.y", y);
  141. my.element.style.opacity = 1;
  142. window.removeEventListener('mouseup', my.stopDrag, true);
  143. window.removeEventListener('mousemove', my.drag, true);
  144. }
  145. }
  146. my.startDrag = function(event) {
  147. if (event.button != 0) {
  148. my.moving = false;
  149. return;
  150. }
  151. my.offsetX = event.clientX - parseInt(my.element.style.left);
  152. my.offsetY = event.clientY - parseInt(my.element.style.top);
  153. if (my.offsetY > 27)
  154. return;
  155. my.moving = true;
  156. my.element.style.opacity = 0.75;
  157. event.preventDefault();
  158. window.addEventListener('mouseup', my.stopDrag, true);
  159. window.addEventListener('mousemove', my.drag, true);
  160. }
  161. my.show = function()
  162. {
  163. this.element.style.visibility = 'visible';
  164. }
  165. my.hide = function()
  166. {
  167. this.element.style.visibility = 'hidden';
  168. }
  169. my.reset = function()
  170. {
  171. storage.setItem(my.id + ".coord.x", 6);
  172. storage.setItem(my.id + ".coord.y", 6);
  173. my.element.style.left = "6px";
  174. my.element.style.top = "6px";
  175. }
  176. my.element = document.createElement("div");
  177. my.element.id = id;
  178. document.body.appendChild(my.element);
  179. my.element.addEventListener('mousedown', my.startDrag, true);
  180. if (storage.getItem(my.id + ".coord.x"))
  181. my.element.style.left = storage.getItem(my.id + ".coord.x") + "px";
  182. else
  183. my.element.style.left = "6px";
  184. if (storage.getItem(my.id + ".coord.y"))
  185. my.element.style.top = storage.getItem(my.id + ".coord.y") + "px";
  186. else
  187. my.element.style.top = "6px";
  188. }
  189. // End UI Window implementation
  190. // Make infinite alerts less miserable
  191. var displayAlerts = true;
  192. function alert(msg) {
  193. if (displayAlerts) {
  194. if (!confirm(msg)) {
  195. displayAlerts = false;
  196. }
  197. }
  198. }
  199. ////////////////////////////////////////////////////////////////////////
  200. /////////// DATA STRUCTURES /////////////////
  201. ////////////////////////////////////////////////////////////////////////
  202. function dailyData()
  203. {
  204. // Save the storage object
  205. this.storage = new DOMStorage("local", "BvSDaily");
  206. this.namePlayer = document.evaluate("//input[@name='player' and @type='hidden']", document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue.value;
  207. // List of all sequences stored in memory
  208. this.sequenceList = "";
  209. // List of all pages on which the daily window is hidden
  210. this.hidePageList = "";
  211. // Global hide flag
  212. this.globalHide = false;
  213. // Name and task number of current sequence
  214. this.sequenceName = "";
  215. this.taskNum = 0;
  216. // Actual tasklist for this sequence
  217. this.taskList = new Array();
  218. // Array of string flags to save information... a flag is set if contained in the array
  219. // Crude but simple
  220. this.flagStr = "|";
  221. // Helper function to set a flag
  222. this.SetFlag = function(flagtext)
  223. {
  224. if (!this.TestFlag(flagtext))
  225. this.flagStr += flagtext + "|";
  226. }
  227. // Helper function to test for a flag
  228. this.TestFlag = function(flagtext)
  229. {
  230. if (this.flagStr.indexOf("|" + flagtext + "|") > -1)
  231. return true;
  232. else
  233. return false;
  234. }
  235. // Check whether a page is in the hidePageList
  236. this.TestHidePage = function(pageName)
  237. {
  238. if (OptGlobalHide)
  239. return this.globalHide;
  240. for (var i=0; i < this.hidePageList.length; i++)
  241. if (this.hidePageList[i] === pageName)
  242. return true;
  243. return false;
  244. }
  245. // Add a page to the hidePageList
  246. this.AddHidePage = function(pageName)
  247. {
  248. if (!this.TestHidePage(pageName))
  249. this.hidePageList.push(pageName);
  250. if (OptGlobalHide)
  251. this.globalHide = true;
  252. this.SaveState();
  253. }
  254. // Remove a page from the hidePageList
  255. this.RemoveHidePage = function(pageName)
  256. {
  257. this.globalHide = false;
  258. for (var i=0; i < this.hidePageList.length; i++)
  259. if (this.hidePageList[i] === pageName)
  260. {
  261. this.hidePageList.splice(i,1);
  262. break;
  263. }
  264. this.SaveState();
  265. }
  266. // Check whether a sequence name is in the sequence list
  267. this.TestSequence = function(sequenceName)
  268. {
  269. for (var i=0; i < this.sequenceList.length; i++)
  270. if (this.sequenceList[i] === sequenceName)
  271. return true;
  272. return false;
  273. }
  274. // Remove a sequence
  275. this.RemoveSequence = function(sequenceName)
  276. {
  277. // Remove sequence from sequence list
  278. for (var i=0; i<this.sequenceList.length; i++)
  279. if (this.sequenceList[i] === sequenceName)
  280. {
  281. // Remove this element from sequencelist
  282. this.sequenceList.splice(i,1);
  283. break;
  284. }
  285. this.SaveState();
  286. this.storage.removeItem("Daily_Sequence_" + sequenceName);
  287. }
  288. // Store a new or modified sequence
  289. this.SaveSequence = function(sequenceName, sequenceCode)
  290. {
  291. if (!this.TestSequence(sequenceName))
  292. {
  293. // Add sequenceName to sequenceList and save
  294. this.sequenceList.push(sequenceName);
  295. this.SaveState();
  296. }
  297. // Save the sequence code
  298. this.storage.setItem("Daily_Sequence_" + sequenceName, sequenceCode);
  299. // Update the daily window
  300. floatingDaily.Draw();
  301. }
  302. // Load and parse a given new sequence name
  303. this.LoadSequence = function(newSequenceName)
  304. {
  305. // Set the current sequence name and reinitialize taskList
  306. this.flagStr = this.storage.getItem(this.namePlayer + "_Daily_" + newSequenceName + "_Flags", "|");
  307. if (!(this.sequenceName === newSequenceName))
  308. {
  309. // Only reset the sequencename and tasknum if this is not the current sequence in use
  310. this.sequenceName = newSequenceName;
  311. this.taskNum = 1;
  312. }
  313. // Initialize empty tasklist
  314. this.taskList = new Array();
  315. // Load newSequenceName from memory and parse into this.taskList
  316. var strSequenceData = this.storage.getItem("Daily_Sequence_" + newSequenceName, "");
  317. if (!strSequenceData)
  318. return; // no sequence data to be loaded
  319. var sequenceData = strSequenceData.split("@NewTask");
  320. // Implementation of sequence code goes into task 0
  321. if (sequenceData[0].indexOf("@SequenceCode") > -1)
  322. this.taskList.push(new Task("SequenceCode", sequenceData[0]));
  323. else
  324. this.taskList.push(null);
  325. // Input the various tasks to be performed
  326. for (i=1; i < sequenceData.length; i++)
  327. {
  328. // Default taskname from a line such as "//@TaskName: Example Task Name"
  329. var taskname;
  330. var res = /@TaskName: (.+)(?=\r|\n)/.exec(sequenceData[i]);
  331. if (res)
  332. taskname = res[1];
  333. else
  334. taskname = "task " + i; // default taskname
  335. this.taskList.push(new Task(taskname, sequenceData[i]) );
  336. }
  337. // Add a final ending task which does nothing
  338. this.taskList.push(new Task("Done", "ShowMsg(\"Sequence Complete!\")"));
  339. }
  340. this.SaveState = function()
  341. {
  342. // Save the current state of this script (sequence name, task number, flags in use)
  343. this.storage.setItem("Daily_SequenceList", this.sequenceList.join("|") );
  344. this.storage.setItem("Daily_HidePageList", this.hidePageList.join("|") );
  345. this.storage.setItem("Daily_GlobalHide", this.globalHide);
  346. this.storage.setItem(this.namePlayer + "_DailyTaskNum", this.taskNum);
  347. this.storage.setItem(this.namePlayer + "_Daily_" + this.sequenceName + "_Flags", this.flagStr );
  348. this.storage.setItem(this.namePlayer + "_DailySequenceName", this.sequenceName);
  349. }
  350. this.LoadState = function()
  351. {
  352. // Load the previous state of this script (sequence name, task number, flags in use)
  353. this.sequenceList = this.storage.getItem("Daily_SequenceList", this.sequenceList ).split("|");
  354. this.hidePageList = this.storage.getItem("Daily_HidePageList", this.hidePageList ).split("|");
  355. this.globalHide = ('true' === this.storage.getItem("Daily_GlobalHide", 'false'));
  356. this.sequenceName = this.storage.getItem(this.namePlayer + "_DailySequenceName", "");
  357. if (this.sequenceName)
  358. {
  359. this.taskNum = parseInt( this.storage.getItem(this.namePlayer + "_DailyTaskNum", "0") );
  360. this.flagStr = this.storage.getItem(this.namePlayer + "_Daily_" + this.sequenceName + "_Flags", "|" );
  361. }
  362. // remove leading empty sequence strings
  363. // problem only occurs intially (I think)
  364. if (this.sequenceList[0] === "")
  365. {
  366. this.sequenceList.splice(0,1);
  367. this.SaveState();
  368. }
  369. if (this.hidePageList[0] === "")
  370. {
  371. this.hidePageList.splice(0,1);
  372. this.SaveState();
  373. }
  374. }
  375. // Load the current state
  376. this.LoadState();
  377. // Load the sequence corresponding to the current state
  378. this.LoadSequence(this.sequenceName);
  379. }
  380. // task object has a description to be shown and a function that gets called
  381. function Task(taskname, taskfun)
  382. {
  383. this.taskname = taskname;
  384. this.taskfun = taskfun;
  385. }
  386. function Jutsu(name, code)
  387. {
  388. this.name = name;
  389. this.code = code;
  390. }
  391. function Mission(name, jutsu, allyget, type, diff, succ)
  392. {
  393. this.name = name;
  394. this.jutsu = jutsu;
  395. this.type = type;
  396. this.diff = diff;
  397. this.succ = succ;
  398. this.allyget = allyget;
  399. }
  400. function Quest(name, code, numsteps, flag)
  401. {
  402. this.name = name;
  403. this.code = code;
  404. this.numsteps = numsteps;
  405. this.flag = flag;
  406. }
  407. ////////////////////////////////////////////////////////////////////////
  408. /////////// FLOATING WINDOWS ///////////////
  409. ////////////////////////////////////////////////////////////////////////
  410. function FloatingDaily()
  411. {
  412. this.window = new Window("floatingDaily", data.storage);
  413. // Add css style for report window
  414. this.window.element.style.border = "2px solid #000000";
  415. this.window.element.style.position = "fixed";
  416. this.window.element.style.zIndex = "100";
  417. this.window.element.style.color = "#000000";
  418. this.window.element.style.padding = "5";
  419. this.window.element.style.textAlign = "left";
  420. this.window.element.style.overflowX = "auto";
  421. this.window.element.style.overflowY = "auto";
  422. this.window.element.style.width = "200px";
  423. this.window.element.style.height = "500px";
  424. this.window.element.style.background = "none repeat scroll 0% 0% rgb(216, 216, 216)";
  425. this.Draw = function()
  426. {
  427. // Test whether the daily window should be drawn on this page
  428. if (data.TestHidePage(location.href))
  429. {
  430. this.Hide();
  431. return;
  432. }
  433. // Show the window if not already
  434. this.window.show();
  435. // Helper array to build the HTML
  436. var arr = new Array();
  437. arr.push('<table width="200"><tr><td align="left">Daily Helper</td>',
  438. '<td align="right"><p style="margin: 0pt; text-align: right;">',
  439. '<a href="javascript:void(0)" id="DailyHidePageButton">',
  440. '(Hide)</a></p></td></tr></table><br>');
  441. arr.push("Sequence: <b>" + data.sequenceName + "</b><br><br>");
  442. arr.push('<table width="200"><tr><td align="left">',
  443. '<a href="javascript:void(0)" id="DailyBackTaskButton">',
  444. '&lt;-----</a></td>');
  445. arr.push('<td align="center"><b>' + data.taskNum + '</b> / ' + (data.taskList.length-1) + '</td>');
  446. arr.push('<td align="right"><a href="javascript:void(0)" id="DailySkipTaskButton">',
  447. '-----&gt;</a></td></tr></table><br>');
  448. if (data.taskNum > 0 && data.taskNum < data.taskList.length)
  449. arr.push('Task: <b>' + data.taskList[data.taskNum].taskname + '</b>');
  450. else
  451. arr.push('Task: Undefined Task');
  452. arr.push('<br><br><div id="DailyMsgDiv"></div><br><br>');
  453. arr.push('Your sequences:');
  454. // Generate list of sequence options to choose from
  455. for (var i=0; i<data.sequenceList.length; i++)
  456. {
  457. var sequenceName = data.sequenceList[i];
  458. arr.push('<p style="margin: 0pt; text-align: right;">',
  459. '<a href="javascript:void(0)" val="' + sequenceName,
  460. '" id="ChooseSequenceButton_' + sequenceName + '">',
  461. sequenceName + ' &gt;</a></p>');
  462. }
  463. arr.push('<br><p style="margin: 0pt; text-align: left;">',
  464. '<a href="javascript:void(0)" id="DailySequenceEditorButton">',
  465. '&lt; Open Sequence Editor</a></p>');
  466. arr.push('<br><p style="margin: 0pt; text-align: left;">',
  467. '<a href="https://docs.google.com/leaf?id=0B10D12_4U2KiNzYxZjY0YTEtYzU1Mi00Y2YzLTg5NGYtYWZlNGQzMDQyNDE0&hl=en" id="MoreSequencesButton" target="_blank">',
  468. '&lt; Get More Sequences</a></p>');
  469. // arr.push("<b>Flags</b>:");
  470. // arr.push(data.flagStr.replace(/\|/g, "<br>"));
  471. // Concatenate everything in the array to form the html
  472. this.window.element.innerHTML = arr.join("");
  473. // Event handlers for sequenceList items
  474. for (var i=0; i<data.sequenceList.length; i++)
  475. {
  476. var sequenceName = data.sequenceList[i];
  477. var elem = document.getElementById("ChooseSequenceButton_" + sequenceName);
  478. elem.addEventListener("click", function() { data.LoadSequence(this.id.split("_")[1]); data.SaveState(); floatingDaily.Draw(); }, false);
  479. }
  480. document.getElementById("DailyHidePageButton").addEventListener("click", floatingDaily.HidePage, true);
  481. // document.getElementById("DailyResetDataButton").addEventListener("click", floatingDaily.ResetData, true);
  482. document.getElementById("DailySkipTaskButton").addEventListener("click", floatingDaily.SkipTask, true);
  483. document.getElementById("DailyBackTaskButton").addEventListener("click", floatingDaily.BackTask, true);
  484. document.getElementById("DailySequenceEditorButton").addEventListener("click", floatingDaily.OpenSequenceEditor, true);
  485. }
  486. // Hide the window (and remove the interior)
  487. this.Hide = function()
  488. {
  489. this.window.element.innerHTML = "";
  490. this.window.hide();
  491. }
  492. this.showErr = function(err)
  493. {
  494. document.getElementById("DailyMsgDiv").innerHTML += err.message;
  495. }
  496. this.HidePage = function()
  497. {
  498. data.AddHidePage(location.href);
  499. floatingDaily.Hide();
  500. }
  501. this.ResetData = function()
  502. {
  503. data.taskNum = 1;
  504. data.flagStr = "|";
  505. data.SaveState();
  506. floatingDaily.Draw();
  507. }
  508. this.SkipTask = function()
  509. {
  510. IncrementTask();
  511. }
  512. this.BackTask = function()
  513. {
  514. // Temporary for debugging
  515. if (data.taskNum > 1)
  516. data.taskNum--;
  517. data.SaveState();
  518. floatingDaily.Draw();
  519. }
  520. this.OpenSequenceEditor = function()
  521. {
  522. // Disable hotkeys
  523. hotkeyLock = true;
  524. // Initialize the Editor window if not already
  525. floatingEditor.Draw();
  526. // Load the current sequence if it exists
  527. if (data.TestSequence(data.sequenceName))
  528. floatingEditor.LoadSequence(data.sequenceName);
  529. // Show the editor window
  530. floatingEditor.window.show();
  531. }
  532. }
  533. function FloatingEditor()
  534. {
  535. this.window = new Window("floatingEditor", data.storage);
  536. // Add css style for report window
  537. this.window.element.style.border = "2px solid #000000";
  538. this.window.element.style.position = "fixed";
  539. this.window.element.style.zIndex = "100";
  540. this.window.element.style.color = "#000000";
  541. this.window.element.style.padding = "5";
  542. this.window.element.style.textAlign = "left";
  543. this.window.element.style.overflowX = "auto";
  544. this.window.element.style.overflowY = "auto";
  545. this.window.element.style.width = "600px";
  546. this.window.element.style.height = "620px";
  547. this.window.element.style.background = "none repeat scroll 0% 0% rgb(216, 216, 216)";
  548. this.Draw = function()
  549. {
  550. // Helper array to build the HTML
  551. var arr = new Array();
  552. arr.push("Sequence Editor<br><br>");
  553. // Drop down box for things in the sequence list
  554. arr.push('Choose an existing sequence to edit: ');
  555. arr.push('<select id="sequenceSelect">');
  556. for (var i=0; i < data.sequenceList.length; i++)
  557. arr.push('<option value="' + data.sequenceList[i] + '">' + data.sequenceList[i] + '</option>');
  558. arr.push('</select>&nbsp&nbsp');
  559. arr.push('<a href="javascript:void(0)" id="EditorLoadSequenceButton">',
  560. 'Load Sequence &gt;</a><br>');
  561. arr.push('<br><br>');
  562. // Textbox for sequence code
  563. arr.push('<textarea id="sequenceCode" rows="30" cols="76"></textarea><br>');
  564. // Remove button
  565. arr.push('<p style="margin: 0pt; text-align: left;">',
  566. '<a href="javascript:void(0)" id="EditorDeleteSequenceButton">',
  567. '&lt; Delete Sequence</a></p>');
  568. // Save button
  569. arr.push('<p style="margin: 0pt; text-align: right;">',
  570. '<a href="javascript:void(0)" id="EditorSaveSequenceButton">',
  571. 'Save Sequence &gt;</a></p><br>');
  572. // Concatenate everything in the array to form the html
  573. this.window.element.innerHTML = arr.join("");
  574. floatingEditor.LoadSequence(data.sequenceName);
  575. document.getElementById("EditorSaveSequenceButton").addEventListener("click", floatingEditor.SaveSequence, true);
  576. document.getElementById("EditorDeleteSequenceButton").addEventListener("click", floatingEditor.DeleteSequence, true);
  577. document.getElementById("EditorLoadSequenceButton").addEventListener("click", floatingEditor.LoadSelectedSequence, true);
  578. // Load the textarea with a sample sequence
  579. var sequenceStr =
  580. "//@SequenceName: Default\n\n\n" +
  581. "//------------------------------------------\n" +
  582. "//@NewTask\n" +
  583. "//@TaskName: Example Task 1\n\n" +
  584. "ShowMsg(\"Example task 1 only shows this message\");\n\n\n" +
  585. "//------------------------------------------\n" +
  586. "//@NewTask\n" +
  587. "//@TaskName: Example Task 2\n\n" +
  588. "ShowMsg(\"Example task 2 is almost the same\");";
  589. document.getElementById("sequenceCode").value = sequenceStr;
  590. }
  591. // Hide the window (and remove the interior)
  592. this.Hide = function()
  593. {
  594. this.window.element.innerHTML = "";
  595. this.window.hide();
  596. }
  597. this.SaveSequence = function()
  598. {
  599. // Extract the sequence string
  600. var sequenceCode = document.getElementById("sequenceCode").value;
  601. var sequenceName;
  602. // Get the sequence name and verify correct input formatting
  603. try
  604. {
  605. sequenceName = /@SequenceName: (.+)(?=\r|\n)/.exec(sequenceCode)[1];
  606. }
  607. catch(err)
  608. {
  609. alert("Please enter a sequence name on the first line with format:\n" +
  610. "//@SequenceName: Example Sequence Name");
  611. return;
  612. }
  613. // Clean the string for only alphanumeric characters and spaces
  614. if ( !(sequenceName === sequenceName.replace(/[^a-zA-Z 0-9]+/g,'')) )
  615. {
  616. alert("Alphanumeric characters and spaces only in sequence names");
  617. return;
  618. }
  619. data.SaveSequence(sequenceName, sequenceCode);
  620. data.LoadSequence(sequenceName);
  621. // floatingEditor.Draw();
  622. // document.getElementById("sequenceCode").value = sequenceCode;
  623. }
  624. this.LoadSelectedSequence = function()
  625. {
  626. var elem = document.getElementById("sequenceSelect");
  627. var sequenceName = elem.options[elem.selectedIndex].value;
  628. floatingEditor.LoadSequence(sequenceName);
  629. }
  630. this.DeleteSequence = function()
  631. {
  632. // Extract the sequence string
  633. var sequenceCode = document.getElementById("sequenceCode").value;
  634. var sequenceName;
  635. // Get the sequence name and verify correct input formatting
  636. try
  637. {
  638. sequenceName = /@SequenceName: (.+)(?=\r|\n)/.exec(sequenceCode)[1];
  639. }
  640. catch(err)
  641. {
  642. alert("Please enter a sequence name on the first line with format:\n" +
  643. "//@SequenceName: Example Sequence Name");
  644. return;
  645. }
  646. // Clean the string for only alphanumeric characters and spaces
  647. if ( !(sequenceName === sequenceName.replace(/[^a-zA-Z 0-9]+/g,'')) )
  648. {
  649. alert("Alphanumeric characters and spaces only in sequence names");
  650. return;
  651. }
  652. // Make sure the user really wants to do this
  653. if (!confirm("Are you sure you want to delete the sequence: \'" + sequenceName + "\'?"))
  654. return;
  655. // Remove the sequence and reload the editor
  656. data.RemoveSequence(sequenceName);
  657. data.LoadSequence("");
  658. floatingEditor.LoadSequence("");
  659. floatingEditor.Draw();
  660. floatingDaily.Draw();
  661. }
  662. this.LoadSequence = function(sequenceName)
  663. {
  664. // If sequenceName is null do nothing
  665. if (!sequenceName)
  666. return;
  667. // sequenceName is assumed to exist... error if not
  668. var sequenceStr = data.storage.getItem("Daily_Sequence_" + sequenceName, "");
  669. if (!sequenceStr)
  670. {
  671. alert("Sequence " + sequenceName + " does not exist\nThis is an error that should be reported.");
  672. return;
  673. }
  674. // Otherwise, load up the sequence text
  675. document.getElementById("sequenceCode").value = sequenceStr;
  676. // Also load up this sequence in browser cache
  677. data.LoadSequence(sequenceName);
  678. floatingDaily.Draw();
  679. }
  680. // hide the window by default
  681. this.window.hide();
  682. }
  683. ////////////////////////////////////////////////////////////////////////
  684. /////////// USER API FUNCTIONS ///////////////
  685. ////////////////////////////////////////////////////////////////////////
  686. //////////////// API Functions which halt task execution //////////////////
  687. // Put up a message in the floating daily window
  688. // This function halts script execution
  689. function ShowMsg(strMsg)
  690. {
  691. if (!strMsg)
  692. strMsg = "";
  693. else
  694. strMsg += '<br>';
  695. throw new Error(strMsg);
  696. }
  697. // Submit a form with name strName and display message strMsg on success
  698. // This function always halts task execution
  699. function FormSubmit(strName, strMsg)
  700. {
  701. if (!strMsg)
  702. strMsg = 'Submitting Form: ' + strName;
  703. if (FormTest(strName))
  704. {
  705. // Success, submit the form and display the desired message
  706. document.forms.namedItem(strName).submit();
  707. ShowMsg(strMsg);
  708. }
  709. else
  710. {
  711. // Display error message for user to see
  712. ShowMsg('Form ' + strName + ' does not exist');
  713. }
  714. }
  715. // Move to the next task if possible
  716. // This function always halts task execution
  717. function IncrementTask(strMsg)
  718. {
  719. if (data.taskNum < data.taskList.length-1)
  720. data.taskNum++;
  721. data.SaveState();
  722. floatingDaily.Draw();
  723. ShowMsg(strMsg);
  724. }
  725. // Move to the next task if possible
  726. // This function does NOT halt task execution
  727. function IncrementTaskNonBlock()
  728. {
  729. if (data.taskNum < data.taskList.length-1)
  730. data.taskNum++;
  731. data.SaveState();
  732. floatingDaily.Draw();
  733. }
  734. // Move to next task if condition is true
  735. // This function halts task execution if condition is true
  736. function IncrementTaskIf(cond, strMsg)
  737. {
  738. if (cond)
  739. IncrementTask(strMsg);
  740. }
  741. // Change to new sequence (useful for chaining together separate sequences)
  742. function ChangeSequence(strSequenceName, newTaskName)
  743. {
  744. // Search for strSequenceName in sequence list
  745. for (var i=0; i < data.sequenceList.length; i++)
  746. if (data.sequenceList[i] === strSequenceName)
  747. {
  748. // Load the sequence and set the task number if desired
  749. data.LoadSequence(strSequenceName);
  750. if (newTaskName)
  751. {
  752. for (var j=1; j < data.taskList.length; j++)
  753. if (data.taskList[j].taskname === newTaskName)
  754. data.taskNum = j;
  755. }
  756. // Save state
  757. data.SaveState();
  758. // Redraw the window
  759. floatingDaily.Draw();
  760. // Done
  761. ShowMsg('Loaded Sequence: ' + strSequenceName);
  762. }
  763. // If code reaches this point, sequence does not exist
  764. ShowMsg('Sequence ' + strSequenceName + ' does not exist');
  765. }
  766. //////////////// API Functions which test the page for information //////////////////
  767. // Test the document body HTML for the given text
  768. function DocTest(strText)
  769. {
  770. return (document.body.innerHTML.indexOf(strText) > -1);
  771. }
  772. // Test the href location for the given text
  773. function LocationTest(strText)
  774. {
  775. return (location.href.indexOf(strText) > -1);
  776. }
  777. // Test for the existence of a form with name = strName
  778. function FormTest(strName)
  779. {
  780. return (document.forms.namedItem(strName) ? true : false);
  781. }
  782. // Test whether a form input is already checked
  783. function FormCheckTest(strFormName, strInputName, strInputValue)
  784. {
  785. var strXPath = "";
  786. // Form name is optional, include it if necessary
  787. if (strFormName)
  788. strXPath += '//form[@name=\'' + strFormName + '\']';
  789. // Input name is mandatory (else we cannot find the input box...)
  790. strXPath += '//input[@name=\'' + strInputName + '\'';
  791. // Input value is also optional
  792. if (strInputValue)
  793. strXPath += ' and @value=\'' + strInputValue + '\'';
  794. strXPath += ']';
  795. var elem = document.evaluate(strXPath, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  796. // Element does not exist
  797. if (!elem)
  798. return false;
  799. // Otherwise return checked state
  800. return elem.checked;
  801. }
  802. /////////////// API Functions to manipulate forms on the page //////////////
  803. // Check a checkbox on a form
  804. // Returns false if element does not exist, or is disabled
  805. function FormCheck(strFormName, strInputName, strInputValue)
  806. {
  807. var strXPath = "";
  808. // Form name is optional, include it if necessary
  809. if (strFormName)
  810. strXPath += '//form[@name=\'' + strFormName + '\']';
  811. // Input name is mandatory (else we cannot find the input box...)
  812. strXPath += '//input[@name=\'' + strInputName + '\'';
  813. // Input value is also optional
  814. if (strInputValue)
  815. strXPath += ' and @value=\'' + strInputValue + '\'';
  816. strXPath += ']';
  817. var elem = document.evaluate(strXPath, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  818. // Return without action if element does not exist or is disabled
  819. if (!elem || elem.disabled)
  820. return false;
  821. // Otherwise check the box and return true
  822. elem.checked = "checked";
  823. return true;
  824. }
  825. // Select an option form a drop down box
  826. function FormSelect(strFormName, strSelectName, strOptionValue, strOptionText)
  827. {
  828. // First get the select object
  829. var strXPath = "";
  830. // Form name is optional, include it if necessary
  831. if (strFormName)
  832. strXPath += '//form[@name=\'' + strFormName + '\']';
  833. // Input name is mandatory (else we cannot find the input box...)
  834. strXPath += '//select[@name=\'' + strSelectName + '\']';
  835. var elem = document.evaluate(strXPath, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  836. // Element does not exist
  837. if (!elem || elem.disabled)
  838. return false;
  839. // loop through options and select any if found
  840. for (var i=0; i<elem.options.length; i++)
  841. {
  842. if ( (!strOptionValue || elem.options[i].value == strOptionValue) &&
  843. (!strOptionText || elem.options[i].text == strOptionText) )
  844. {
  845. elem.selectedIndex = i;
  846. return true;
  847. }
  848. }
  849. // If the code reaches this point, we did not find the option to select
  850. return false;
  851. }
  852. // Set .value field of an Input object
  853. function FormSetValue(strFormName, strInputName, newValue)
  854. {
  855. var strXPath = "";
  856. // Form name is optional, include it if necessary
  857. if (strFormName)
  858. strXPath += '//form[@name=\'' + strFormName + '\']';
  859. // Input name is mandatory (else we cannot find the input box...)
  860. strXPath += '//input[@name=\'' + strInputName + '\']';
  861. var elem = document.evaluate(strXPath, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  862. // Return without action if element does not exist or is disabled
  863. if (!elem || elem.disabled)
  864. return false;
  865. // Otherwise check the box and return true
  866. elem.value = newValue;
  867. return true;
  868. }
  869. // Get .value field of an Input object
  870. function FormGetValue(strFormName, strInputName)
  871. {
  872. var strXPath = "";
  873. // Form name is optional, include it if necessary
  874. if (strFormName)
  875. strXPath += '//form[@name=\'' + strFormName + '\']';
  876. // Input name is mandatory (else we cannot find the input box...)
  877. strXPath += '//input[@name=\'' + strInputName + '\']';
  878. var elem = document.evaluate(strXPath, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  879. // Return without action if element does not exist or is disabled
  880. if (!elem)
  881. return false;
  882. // Otherwise check the box and return true
  883. return elem.value;
  884. }
  885. ////////////// API Functions which navigate around the BvS world //////////////
  886. // Helper function to interact with BvS menus
  887. function GoMenuPage(strMenuItem)
  888. {
  889. var menucell = document.evaluate('//a[text()="' + strMenuItem + '"]', document, null,
  890. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  891. FormSubmit(menucell.href.split(":")[1].split(".")[1], 'Moving to page: ' + strMenuItem);
  892. };
  893. // General function to go to any (or at least most) bvs page
  894. function GoPage(strPageName)
  895. {
  896. // Class to define how to get to a specific page
  897. // funLoad is a function which loads the desired page (starting on the prereq page)
  898. // strPrereq indicates whether we should start from a simpler page
  899. // funTest is a function which determines whether we are already on the correct page
  900. function objPage(funLoad, strPrereq, funTest)
  901. {
  902. this.funLoad = funLoad;
  903. this.strPrereq = strPrereq;
  904. this.funTest = funTest;
  905. };
  906. // Create the list of page objects
  907. var pageList = {
  908. // Main menu items
  909. main: new objPage(function(){GoMenuPage('Main');}, null, function(){return LocationTest('/bvs/pages/main.html');} ),
  910. village: new objPage(function(){GoMenuPage('Village');}, null, function(){return LocationTest('/bvs/village.html');} ),
  911. partyhouse: new objPage(function(){GoMenuPage('Party House');}, null, function(){return LocationTest('/bvs/partyhouse.html');} ),
  912. shop: new objPage(function(){GoMenuPage('Shop');}, null, function(){return LocationTest('/bvs/shop.html');} ),
  913. consumables: new objPage(function(){GoMenuPage('Consumables');}, null, function(){return LocationTest('/bvs/oneuseitems.html');} ),
  914. worldkaiju: new objPage(function(){GoMenuPage('WorldKaiju');}, null, function(){return LocationTest('/bvs/worldkaiju.html');} ),
  915. missions: new objPage(function(){GoMenuPage('Missions');}, null, function(){return LocationTest('/bvs/missionstart.html') || LocationTest('/bvs/missions');} ),
  916. quests: new objPage(function(){GoMenuPage('Quests');}, null, function(){return LocationTest('/bvs/quests.html') || LocationTest('/bvs/questattempt.html') || LocationTest('/bvs/chuninexam.html');} ),
  917. spar: new objPage(function(){GoMenuPage('Spar');}, null, function(){return LocationTest('/bvs/spar.html');} ),
  918. arena: new objPage(function(){GoMenuPage('Arena');}, null, function(){return LocationTest('/bvs/arena.html');} ),
  919. team: new objPage(function(){GoMenuPage('Team');}, null, function(){return LocationTest('/bvs/team.html');} ),
  920. jutsu: new objPage(function(){GoMenuPage('Jutsu');}, null, function(){return LocationTest('/bvs/jutsu.html');} ),
  921. summons: new objPage(function(){GoMenuPage('Summons');}, null, function(){return LocationTest('/bvs/summon.html');} ),
  922. bucket: new objPage(function(){GoMenuPage('Bucket');}, null, function(){return LocationTest('/bvs/bucket.html');} ),
  923. // Party house menu items
  924. ph_tipline: new objPage(function(){GoMenuPage('Tip Line');}, 'partyhouse', function(){return FormTest('tipline');} ),
  925. ph_juicebar: new objPage(function(){GoMenuPage('\'Juice\' Bar');}, 'partyhouse', function(){return FormTest('br');} ),
  926. ph_firstloser: new objPage(function(){GoMenuPage('First Loser');}, 'partyhouse', function(){return DocTest('Four times a day a new First Loser contest begins (and the old one finishes).');} ),
  927. ph_wheel: new objPage(function(){GoMenuPage('Wheel');}, 'partyhouse', function(){return FormTest('raf');} ),
  928. ph_jackpot: new objPage(function(){GoMenuPage('Jackpot');}, 'partyhouse', function(){return FormTest('ninrou');} ),
  929. ph_lottery: new objPage(function(){GoMenuPage('Lottery');}, 'partyhouse', function(){return FormTest('el');} ),
  930. ph_tsukiball: new objPage(function(){GoMenuPage('Tsukiball');}, 'partyhouse', function(){return FormTest('skib');} ),
  931. ph_bigboard: new objPage(function(){GoMenuPage('Big Board');}, 'partyhouse', function(){return DocTest('<b>The Big Board</b>');} ),
  932. ph_scratchies: new objPage(function(){GoMenuPage('Scratchies');}, 'partyhouse', function(){return FormTest('scratch') || FormTest('mainform2');} ),
  933. ph_darts: new objPage(function(){GoMenuPage('Darts');}, 'partyhouse', function(){return FormTest('dgame');} ),
  934. ph_partyroom: new objPage(function(){GoMenuPage('Party Room');}, 'partyhouse', function(){return FormTest('pr');} ),
  935. ph_crane: new objPage(function(){GoMenuPage('Crane');}, 'partyhouse', function(){return FormTest('cgame');} ),
  936. ph_over11k: new objPage(function(){GoMenuPage('Over 11K');}, 'partyhouse', function(){return FormTest('over11');} ),
  937. ph_snakeman: new objPage(function(){GoMenuPage('SNAKEMAN');}, 'partyhouse', function(){return FormTest('newsnake');} ),
  938. ph_roulette: new objPage(function(){GoMenuPage('Roulette');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-roulette.html');} ),
  939. ph_mahjong: new objPage(function(){GoMenuPage('Mahjong');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-mahjong.html');} ),
  940. ph_superfail: new objPage(function(){GoMenuPage('SUPERFAIL');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-superfail.html');} ),
  941. ph_pigeons: new objPage(function(){GoMenuPage('Pigeons');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-keno.html');} ),
  942. ph_flowerwars: new objPage(function(){GoMenuPage('Flower Wars');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-hanafuda.html');} ),
  943. ph_pachinko: new objPage(function(){GoMenuPage('Pachinko');}, 'partyhouse', function(){return LocationTest('/bvs/partyhouse-pachinko.html');} ),
  944. // Linked from village
  945. marketplace: new objPage(function() {FormSubmit('market');}, 'village', function() {return LocationTest('/bvs/villagemarketplace.html');}),
  946. tattoo: new objPage(function() {FormSubmit('tatstime');}, 'village', function() {return LocationTest('/bvs/villagetattoo.html');}),
  947. fields: new objPage(function(){FormSubmit('fieldmenu');}, 'village', function(){return LocationTest('/bvs/villagefields.html');} ),
  948. phases: new objPage(function(){FormSubmit('phases');}, 'village', function(){return LocationTest('/bvs/villagephases.html') || LocationTest('/bvs/villager00t.html');} ),
  949. bingo: new objPage(function(){FormSubmit('bbook');}, 'village', function(){return LocationTest('/bvs/bingo');} ),
  950. jutsuenhance: new objPage(function(){FormSubmit('jenhance');}, 'village', function(){return LocationTest('/bvs/villagejenhance.html');} ),
  951. billycon: new objPage(function(){FormSubmit('concenter');}, 'village', function(){return LocationTest('/bvs/billycon-register.html');} ),
  952. robofighto: new objPage(function(){FormSubmit('robofighto');}, 'village', function(){return LocationTest('/bvs/villagerobofighto.html');} ),
  953. zrewards: new objPage(function(){FormSubmit('zrt');}, 'village', function(){return LocationTest('/bvs/zombjarewards.html');} ),
  954. kaiju: new objPage(function(){FormSubmit('kat');}, 'village', function(){return LocationTest('/bvs/villagemonsterfight');} ),
  955. pizzawitch: new objPage(function(){FormSubmit('pizzamenu');}, 'village', function(){return LocationTest('/bvs/pizzawitch.html') || LocationTest('/bvs/pizzawitchgarage.html');} ),
  956. // Linked from billycon
  957. glowslinging: new objPage(function(){FormSubmit('glowsling');}, 'billycon', function(){return LocationTest('/bvs/billycon-glowslinging.html') || LocationTest('/billycon-glowslingfight.html');} ),
  958. // Linked from main page
  959. breakfast: new objPage(function() {FormSubmit('dobreakfast');}, 'main', function(){return LocationTest('/bvs/breakfast.html');}),
  960. themes: new objPage(function(){FormSubmit('theme');}, 'main', function(){return LocationTest('/bvs/themesdifficulty.html');} ),
  961. tinybeevault: new objPage(function(){FormSubmit('tinybee');}, 'main', function(){return LocationTest('/bvs/tinybees.html');} ),
  962. sponsoritem: new objPage(function(){FormSubmit('sponsor');}, 'main', function(){return LocationTest('/bvs/sponsoritems.html');} ),
  963. favors: new objPage(function(){FormSubmit('sandstorm');}, 'main', function(){return LocationTest('/bvs/sandstorm.html');} ),
  964. reaperblood: new objPage(function(){FormSubmit('reaper');}, 'main', function(){return LocationTest('/bvs/reaper.html');} ),
  965. driftstyle: new objPage(function(){FormSubmit('drifter');}, 'main', function(){return LocationTest('/bvs/drifter.html');} ),
  966. avatar: new objPage(function(){FormSubmit('avatar');}, 'main', function(){return LocationTest('/bvs/avatar.html');} ),
  967. blank: new objPage(null,null,null)
  968. };
  969. // Extract the page from the pageList object
  970. var page = pageList[strPageName];
  971. if (!page)
  972. throw new Error('Page list object: ' + strPageName + ' does not exist');
  973. // Test whether we are already on the correct page
  974. if (page.funTest())
  975. return; // Early return, on a good page
  976. // If a prerequisite page is listed, go to it first
  977. if (page.strPrereq)
  978. GoPage(page.strPrereq);
  979. // Finally, move to the desired page
  980. page.funLoad();
  981. ShowMsg('Moving to page: ' + strPageName);
  982. }
  983. // Get a mission of a given rank
  984. function GetMission(rank)
  985. {
  986. GoPage('missions');
  987. if ( !LocationTest("/bvs/missionstart.html") )
  988. return;
  989. objMissionLookup = {
  990. D: "d",
  991. genD: "gd",
  992. ninD: "nd",
  993. taiD: "td",
  994. C: "c",
  995. genC: "gc",
  996. ninC: "nc",
  997. taiC: "tc",
  998. B: "b",
  999. genB: "gb",
  1000. ninB: "nb",
  1001. taiB: "tb",
  1002. A: "a",
  1003. genA: "ga",
  1004. ninA: "na",
  1005. taiA: "ta",
  1006. AA: "aa",
  1007. genAA: "gaa",
  1008. ninAA: "naa",
  1009. taiAA: "taa",
  1010. Reaper: "reaper",
  1011. genReaper: "greaper",
  1012. ninReaper: "nreaper",
  1013. taiReaper: "treaper",
  1014. Monochrome: "monochrome",
  1015. genMonochrome: "gmonochrome",
  1016. ninMonochrome: "nmonochrome",
  1017. taiMonochrome: "tmonochrome",
  1018. Outskirts: "outskirts",
  1019. Wasteland: "wasteland",
  1020. Burgerninja: "burger",
  1021. Pizzawitch: "pizza",
  1022. Witchinghour: "witch",
  1023. S: "s",
  1024. Blank: ""
  1025. };
  1026. FormSubmit("misform" + objMissionLookup[rank], 'Getting ' + rank + ' rank mission');
  1027. }
  1028. // Set the r00t field keys
  1029. function SetField(key1, key2, key3)
  1030. {
  1031. GoPage('fields');
  1032. // See whether we are on the right field
  1033. if ( key1 && key2 && key3 &&
  1034. (!DocTest("<b>"+key1+"</b></td>") ||
  1035. !DocTest("<b>"+key2+"</b></td>") ||
  1036. !DocTest("<b>"+key3+"</b></td>")) )
  1037. {
  1038. // Go to the right field if possible
  1039. if ( FormSelect(null, 'key_1', null, key1) &&
  1040. FormSelect(null, 'key_2', null, key2) &&
  1041. FormSelect(null, 'key_3', null, key3) )
  1042. {
  1043. FormSubmit('field', 'Changing to: ' + key1 + ' ' + key2 + ' ' + key3);
  1044. }
  1045. }
  1046. }
  1047. //////////////// API Functions for running missions //////////////////
  1048. // Enable megamissions -- this function might go away
  1049. function EnableMegamissions()
  1050. {
  1051. GoPage('missions');
  1052. IncrementTaskIf(DocTest("<i>MegaMissions Active!</i>"));
  1053. FormSubmit('megamis', 'Enabling megamissions');
  1054. }
  1055. // Simple attempt for current mission with given jutsu... does not return, always throws exception
  1056. function MissionAttempt(jutsu)
  1057. {
  1058. if (!jutsu)
  1059. {
  1060. jutsu = { code: -1, name: '' };
  1061. }
  1062. // Blindly attempt the mission using the given jutsu
  1063. if (FormTest('domission'))
  1064. FormSubmit('domission');
  1065. if (FormTest('attempt'))
  1066. {
  1067. if (jutsu.code > -1)
  1068. FormCheck(null, 'usejutsu', "" + jutsu.code);
  1069. FormSubmit('attempt', 'Attempting mission with jutsu: ' + jutsu.name);
  1070. }
  1071. // Show message
  1072. ShowMsg("Attempting mission with jutsu: " + jutsu.name);
  1073. }
  1074. // Complex attempt for current mission stack
  1075. // Script defaults to given jutsu if not found in the stack
  1076. function MissionStackAttempt(stack, defaultjutsu)
  1077. {
  1078. // Get the mission name cell
  1079. var missioncell = document.evaluate('//div[@class="miscontainer"]/div/div/div/center/font/b', document, null,
  1080. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  1081. var strMissionName = missioncell.innerHTML;
  1082. // stack is an array of Mission objects
  1083. for (var i in stack)
  1084. if (stack[i].name == strMissionName)
  1085. {
  1086. if (stack[i].allyget)
  1087. CheckAllyGet(stack[i].allyget);
  1088. MissionAttempt(stack[i].jutsu);
  1089. }
  1090. // This point is not reached unless mission is not in the stack
  1091. // Default jutsu
  1092. MissionAttempt(defaultjutsu);
  1093. }
  1094. // Function to attempt a mission based on difficulty and success (before crank) in addition to name and mission type
  1095. function MissionDetailedStackAttempt(stack, defaultjutsu)
  1096. {
  1097. /*
  1098. <div class="miscontainer"><div class="misshadow"><div class="miscontent_g"><div class="miscontent2" align="left">
  1099. <div class="misstat_g">Genjutsu</div><center>
  1100. <font style="font-size: 18px;"><b>Wander the Sands</b></font><br>The Wasteland is endless..<br><b><i><font style="font-size: 16px;">Crank Level: 27</font></i></b>
  1101. <i><font style="font-size: 12px;"><br>(+27 Diff, +27 Succ, +135% Ryo)</font></i><font style="font-size: 12px;"></font><br><br>
  1102. <div class="misonestat_g"><table class="misonetable"><tbody><tr><td align="right">Difficulty 40&nbsp;&nbsp;&nbsp;Successes 36&nbsp;</td></tr></tbody></table></div>
  1103. */
  1104. // Get the mission name
  1105. var missioncell = document.evaluate('//div[@class="miscontainer"]/div/div/div/center/font/b', document, null,
  1106. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  1107. var strMissionName = missioncell.innerHTML;
  1108. // Get mission type
  1109. missioncell = document.evaluate('//div[@class="miscontainer"]/div/div/div/div', document, null,
  1110. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  1111. var strMissionType = missioncell.innerHTML;
  1112. // Get crank
  1113. var numMissionCrank;
  1114. if (DocTest('Crank Level'))
  1115. {
  1116. missioncell = document.evaluate('//div[@class="miscontainer"]/div/div/div/center', document, null,
  1117. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  1118. numMissionCrank = parseInt(/Crank Level: (\d+)</.exec(missioncell.innerHTML)[1], 10);
  1119. }
  1120. else
  1121. numMissionCrank = 0;
  1122. // Get difficulty and successes
  1123. missioncell = document.evaluate('//div[@class="miscontainer"]/div/div/div/center/div/table/tbody/tr/td', document, null,
  1124. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
  1125. // Difficulty 40&nbsp;&nbsp;&nbsp;Successes 36&nbsp;
  1126. var numMissionDiff = parseInt(/Difficulty (\d+)&/.exec(missioncell.innerHTML)[1], 10) - numMissionCrank;
  1127. var numMissionSucc = parseInt(/Successes (\d+)&/.exec(missioncell.innerHTML)[1], 10) - numMissionCrank;
  1128. // stack is an array of Mission objects
  1129. for (var i in stack)
  1130. if (stack[i].name == strMissionName &&
  1131. stack[i].type == strMissionType &&
  1132. stack[i].diff == numMissionDiff &&
  1133. stack[i].succ == numMissionSucc)
  1134. {
  1135. if (stack[i].allyget)
  1136. CheckAllyGet(stack[i].allyget);
  1137. MissionAttempt(stack[i].jutsu);
  1138. }
  1139. // This point is not reached unless mission is not in the stack
  1140. // Default jutsu
  1141. MissionAttempt(defaultjutsu);
  1142. }
  1143. ///////////// API Functions for doing quests ///////////////////
  1144. // Generic function to perform quest steps -- jutsu selection is currently broken
  1145. function DoGenericQuest(quest, endstep, jutsu)
  1146. {
  1147. // Ensure that we are on the quest page or go there
  1148. // This function also continues a quest in progress
  1149. GoPage('quests');
  1150. if (FormTest('questcontinue'))
  1151. FormSubmit('questcontinue');
  1152. // safeguard against bad code for eval statement
  1153. if (typeof(quest.code) != "number")
  1154. ShowMsg("quest.code must be a number");
  1155. // Sanity check to make sure that we are on the correct page
  1156. if (!DocTest(quest.name))
  1157. ShowMsg("We are on the wrong quest?!?");
  1158. // Select the desired quest to start
  1159. if (FormTest('quest' + quest.code))
  1160. FormSubmit("quest" + quest.code);
  1161. // Check termination conditions
  1162. if ( (endstep == -1 && DocTest("--Epilogue--")) ||
  1163. DocTest("--Part " + endstep + " of " + quest.numsteps + "--") )
  1164. {
  1165. if (quest.flag)
  1166. {
  1167. data.SetFlag(quest.flag);
  1168. data.SaveState();
  1169. }
  1170. // Manually increment the task without halting execution
  1171. if (data.taskNum < data.taskList.length-1)
  1172. data.taskNum++;
  1173. data.SaveState();
  1174. floatingDaily.Draw();
  1175. GoMenuPage('Quests');
  1176. return;
  1177. }
  1178. // Set the requested jutsu
  1179. if (jutsu && FormTest('attack'))
  1180. FormCheck(null, 'usejutsu', '' + jutsu.code);
  1181. // document.getElementById(jutsu.code).checked = "checked";
  1182. // Blindly attempt the quest if we get this far
  1183. if (FormTest('attack'))
  1184. FormSubmit('attack');
  1185. if (FormTest('goquest'))
  1186. FormSubmit('goquest');
  1187. }
  1188. ////////////// API Functions primarily for convenience / miscellaneous /////////////
  1189. // Generic function to set flags based on an ally we might get on this page
  1190. // ally is an object of type Ally
  1191. function CheckAllyGet(strAllyName)
  1192. {
  1193. // Somewhat better version of CheckStuffGet()
  1194. if (DocTest("You got an Ally!<br><b>" + strAllyName + "!</b>") ||
  1195. DocTest("<b>" + strAllyName + " joins you!</b>") ||
  1196. DocTest("<b>" + strAllyName + " joins your party!</b>") ||
  1197. DocTest("<b>" + strAllyName + " joined your party!</b>") ||
  1198. DocTest("You got <b>" + strAllyName + "!</b>") )
  1199. {
  1200. data.SetFlag(strAllyName);
  1201. data.SaveState();
  1202. ShowMsg("Got ally:" + strAllyName);
  1203. }
  1204. // Ally Level 2
  1205. if (DocTest("Level Up!<br><b>" + strAllyName + "</b> is now <b>" + strAllyName + " Lvl. 2!</b>"))
  1206. {
  1207. data.SetFlag(strAllyName + " Lvl. 2");
  1208. data.SaveState();
  1209. ShowMsg("Got " + strAllyName + " Lvl. 2");
  1210. }
  1211. // Ally Level 3
  1212. if (DocTest("<b>" + strAllyName + " is now Lvl. 3!</b>")) // specific to stalker3 for now
  1213. {
  1214. data.SetFlag(strAllyName + " Lvl. 3");
  1215. data.SaveState();
  1216. ShowMsg("Got " + strAllyName + " Lvl. 3");
  1217. }
  1218. }
  1219. // Set themes
  1220. function SetThemes(theme1, theme2, theme3, theme4)
  1221. {
  1222. GoPage('themes');
  1223. if (theme1 && !FormCheckTest('themes1', 'theme_entry_1', theme1))
  1224. {
  1225. FormCheck('themes1', 'theme_entry_1', theme1);
  1226. FormSubmit('themes1');
  1227. ShowMsg("Setting Opening Theme");
  1228. }
  1229. if (theme2 && !FormCheckTest('themes2', 'theme_entry_2', theme2))
  1230. {
  1231. FormCheck('themes2', 'theme_entry_2', theme2);
  1232. FormSubmit('themes2');
  1233. ShowMsg("Setting Battle Theme");
  1234. }
  1235. if (theme3 && !FormCheckTest('themes3', 'theme_entry_3', theme3))
  1236. {
  1237. FormCheck('themes3', 'theme_entry_3', theme3);
  1238. FormSubmit('themes3');
  1239. ShowMsg("Setting Ending Theme");
  1240. }
  1241. if (theme4 && !FormCheckTest('themes4', 'theme_entry_4', theme4))
  1242. {
  1243. FormCheck('themes4', 'theme_entry_4', theme4);
  1244. FormSubmit('themes4');
  1245. ShowMsg("Setting Overworld Theme");
  1246. }
  1247. }
  1248. // Change teams -- exact text strings for ally names required
  1249. function TeamChange(strAllyName1, strAllyName2, strAllyName3)
  1250. {
  1251. GoPage('team');
  1252. // Confirm teams without thinking
  1253. if (FormTest('conteam'))
  1254. FormSubmit('conteam');
  1255. // Check whether the task is already complete
  1256. var indstart = document.body.innerHTML.indexOf("<b>-Current Team-</b>");
  1257. var ind1 = document.body.innerHTML.indexOf("<b>" + strAllyName1, indstart);
  1258. var ind2 = document.body.innerHTML.indexOf("<b>" + strAllyName2, indstart);
  1259. var ind3 = document.body.innerHTML.indexOf("<b>" + strAllyName3, indstart);
  1260. var indend = document.body.innerHTML.indexOf("Save current team as Quickteam:");
  1261. IncrementTaskIf(ind1 < indend && ind2 < indend && ind3 < indend);
  1262. // Helper function to test each element against the ally name
  1263. function AllyTest(strFor, strText)
  1264. {
  1265. return (strFor.indexOf('id_') > -1 &&
  1266. ( strText.indexOf('<b>' + strAllyName1) > -1 ||
  1267. strText.indexOf('<b>' + strAllyName2) > -1 ||
  1268. strText.indexOf('<b>' + strAllyName3) > -1 ) );
  1269. };
  1270. // Get a snapshot for each message in the village chat
  1271. var snapMessageList = document.evaluate("//label", document, null,
  1272. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1273. // Examine each snapshot
  1274. for (var i=0; i<snapMessageList.snapshotLength; i++)
  1275. {
  1276. var snap = snapMessageList.snapshotItem(i);
  1277. if (AllyTest(snap.htmlFor, snap.innerHTML))
  1278. document.getElementById(snap.htmlFor).checked = "checked";
  1279. }
  1280. // Submit the form
  1281. FormSubmit('maketeam');
  1282. }
  1283. ////////////////////////////////////////////////////////////////////////
  1284. /////////// DAILY CODE /////////////
  1285. ////////////////////////////////////////////////////////////////////////
  1286. function DailyStep()
  1287. {
  1288. // Perform a single step of daily
  1289. try
  1290. {
  1291. // Execute SequenceCode if it exists, stored in task 0
  1292. if (data.taskList[0])
  1293. eval(data.taskList[0].taskfun);
  1294. // Call the next function in the tasklist
  1295. eval(data.taskList[data.taskNum].taskfun);
  1296. }
  1297. catch(err)
  1298. {
  1299. // Report the error or message on the floating window
  1300. floatingDaily.showErr(err);
  1301. }
  1302. }
  1303. ////////////////////////////////////////////////////////////////////////
  1304. /////////// HOTKEY CODE /////////////
  1305. ////////////////////////////////////////////////////////////////////////
  1306. var hotkeyLock = false;
  1307. var keyDailyCheckRecentEscape = false;
  1308. function KeyCheck(event)
  1309. {
  1310. var KeyID = event.keyCode;
  1311. // Lock hotkeys if daily window is hidden
  1312. if (data.TestHidePage(location.href))
  1313. hotkeyLock = true;
  1314. if ( (KeyID == 192 || KeyID == 61 || KeyID == 187) && !hotkeyLock) // backquote key (` - code 192) or equals (= - code 61 in FireFox & code 187 in Chrome, etc)
  1315. {
  1316. // Lock hotkey usage to protect from button spamming
  1317. hotkeyLock = true;
  1318. // Perform one daily step
  1319. DailyStep();
  1320. // Unlock hotkey usage
  1321. hotkeyLock = false;
  1322. }
  1323. if (KeyID == 27) // escape key
  1324. {
  1325. // Close editor window if not already and unlock hotkeys
  1326. floatingEditor.Hide();
  1327. hotkeyLock = false;
  1328. // Unhide daily window if hidden
  1329. if (data.TestHidePage(location.href))
  1330. {
  1331. data.RemoveHidePage(location.href);
  1332. floatingDaily.Draw();
  1333. }
  1334. // If escape is pressed twice in succession, reset the window positions
  1335. if (keyDailyCheckRecentEscape)
  1336. {
  1337. floatingEditor.window.reset();
  1338. floatingDaily.window.reset();
  1339. }
  1340. else
  1341. {
  1342. keyDailyCheckRecentEscape = true;
  1343. setTimeout(function(){keyDailyCheckRecentEscape = false;}, 1000);
  1344. }
  1345. }
  1346. if (KeyID == 37 && !hotkeyLock) // left arrow
  1347. floatingDaily.BackTask();
  1348. if (KeyID == 39 && !hotkeyLock) // right arrow
  1349. floatingDaily.SkipTask();
  1350. }
  1351. document.documentElement.addEventListener("keyup", KeyCheck, true);
  1352. ////////////////////////////////////////////////////////////////////////
  1353. /////////// PAGE LOAD RUNTIME ///////////////
  1354. ////////////////////////////////////////////////////////////////////////
  1355. // Initialize the jutsus object
  1356. var jutsus = {
  1357. // Jutsu(name, code)
  1358. SRS: new Jutsu("Soul Reaper Style: Lunch, SandySword!", 499),
  1359. MBST: new Jutsu("Mind Body Switch Technique", 393),
  1360. PWK: new Jutsu("Projectile Weapons: Kunai", 373),
  1361. Redeye: new Jutsu("RedEye", 500),
  1362. Clone: new Jutsu("Clone Jutsu", 368),
  1363. Disguise: new Jutsu("Disguise Jutsu", 370),
  1364. ETA: new Jutsu("Exploding Tags: Activate", 371),
  1365. PWS: new Jutsu("Projectile Weapons: Shuriken", 372),
  1366. Escape: new Jutsu("Escape Jutsu", 374),
  1367. FSFJ: new Jutsu("Fire Style: Fireball Jutsu", 376),
  1368. OI: new Jutsu("Obsessive Insight", 466),
  1369. PSPDP: new Jutsu("Pinky Style: Pervert-Destroying Punch", 416),
  1370. AOTNS: new Jutsu("Attack on the Nervous System", 429),
  1371. FOS: new Jutsu("Flock of Seagulls", 419),
  1372. EDUT: new Jutsu("Epic Dog Urination Technique", 421),
  1373. KICHC: new Jutsu("Kido: I can has cheeseburger", 484),
  1374. INT: new Jutsu("I Need This", 497),
  1375. FGTT: new Jutsu("Flying Thunder God Technique", 448),
  1376. BSTIS: new Jutsu("Billy Style: This is Sparta", 444),
  1377. SSFLB: new Jutsu("Stalker Style: Freaking Laser Beams", 418),
  1378. SRSIN: new Jutsu("Soul Reaper Style: Imperishable Night", 480),
  1379. Diagnosis: new Jutsu("Diagnosis", 485),
  1380. Blank: new Jutsu("", -1)
  1381. };
  1382. // Initialize the quests object
  1383. var quests = {
  1384. // Quest(name, code, numsteps, flag)
  1385. ShowWatchin: new Quest("Watchin' Your Shows", 8, 1),
  1386. Blank: new Quest("", -1, -1, "")
  1387. }
  1388. // Create global instance of daily data object
  1389. var data = new dailyData();
  1390. // Create the floating window objects
  1391. var floatingDaily = new FloatingDaily();
  1392. var floatingEditor = new FloatingEditor();
  1393. floatingDaily.Draw();