(Sandboxed) Lioden Improvements

Adds various improvements to the game Lioden. Sandboxed portion of the script.

  1. // Generated by CoffeeScript 1.9.3
  2.  
  3. /* UserScript options {{{1
  4. See http://wiki.greasespot.net/Metadata_Block for more info.
  5.  
  6. // ==UserScript==
  7. // @name (Sandboxed) Lioden Improvements
  8. // @description Adds various improvements to the game Lioden. Sandboxed portion of the script.
  9. // @namespace ahto
  10. // @version 9.1
  11. // @include http://*.lioden.com/*
  12. // @include http://lioden.com/*
  13. // @require https://greasyfork.org/scripts/10922-ahto-library/code/Ahto%20Library.js?version=75750
  14. // @grant GM_addStyle
  15. // @grant GM_setValue
  16. // @grant GM_getValue
  17. // ==/UserScript==
  18. */
  19.  
  20. /* Features and changes {{{1
  21. General:
  22. - Made the second-to-top bar a little slimmer.
  23. - Added significantly more quickly-accessible links, and made the site overall faster and easier to use.
  24.  
  25. Hunting:
  26. - Automatically reloads and flashes the tab when your hunt is finished.
  27.  
  28. Den:
  29. - Can automatically play with all lionesses.
  30. - Table order slightly tweaked.
  31.  
  32. Lion view:
  33. - Can see lion name and picture right next to the chase buttons.
  34. */
  35. var HUMAN_TIMEOUT_MAX, HUMAN_TIMEOUT_MIN, HUNT_BLINK_TIMEOUT, LionPlayer, aboutKing, aboutPlayer, blinker, chaseButtonTable, currentKingID, energyBar, energyBarBar, energyBarChangeBar, energyBarText, energyUpdate, etc, getResults, i, item, items, j, kingID, kingPortraitHref, len, lionImageClone, logout, minutesLeft, moveToToplinks, namePlateClone, navbar, newDropdown, newNavbarItem, pride, ref, ref1, setHumanTimeout, storedKingID, tables, toplinks, wait,
  36. slice = [].slice;
  37.  
  38. HUNT_BLINK_TIMEOUT = 500;
  39.  
  40. HUMAN_TIMEOUT_MIN = 200;
  41.  
  42. HUMAN_TIMEOUT_MAX = 1000;
  43.  
  44. GM_addStyle("/* Make the top bar slimmer. */\n.main { margin-top: 10px; }\n\n/*\n * Remove the Lioden logo since I can't figure out how to shrink it,\n * and it's taking up too much space on the page. It overlaps the veeery\n * top bar, with the link to the wiki and forums and stuff.\n *\n * TODO: Figure out how to just shrink it instead of flat-out removing it.\n */\n.navbar-brand > img { display: none; }");
  45.  
  46. setHumanTimeout = function(f) {
  47. return setTimeout_(randInt(HUMAN_TIMEOUT_MIN, HUMAN_TIMEOUT_MAX), f);
  48. };
  49.  
  50. energyBar = $('div.progress:first');
  51.  
  52. energyBarText = energyBar.find('div:last');
  53.  
  54. energyBarText.css('z-index', '2');
  55.  
  56. energyBarBar = energyBar.find('div:first');
  57.  
  58. energyBarBar.css('z-index', '1');
  59.  
  60. energyBarChangeBar = $("<div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 0%; background: #afc7c7;\" />");
  61.  
  62. energyBar.append(energyBarChangeBar);
  63.  
  64. energyUpdate = function() {
  65. var e, energyPercent, energyUpdateTime, minutes, now;
  66. try {
  67. energyPercent = /Energy: ([0-9]+)%/.exec(energyBarText.text())[1];
  68. } catch (_error) {
  69. e = _error;
  70. if (e instanceof TypeError) {
  71. console.log("Unable to read energy percent from " + energyBar);
  72. console.log('Disabling energyUpdate');
  73. return;
  74. } else {
  75. throw e;
  76. }
  77. }
  78. energyPercent = parseInt(energyPercent);
  79. now = new Date(Date.now());
  80. minutes = now.getMinutes() + now.getSeconds() / 60 + now.getMilliseconds() / (1000 * 60);
  81. energyUpdateTime = new Date(now);
  82. console.log("now: " + now);
  83. console.log("minutes: " + minutes);
  84. energyUpdateTime.setSeconds(0);
  85. energyUpdateTime.setMilliseconds(0);
  86. if ((0 <= minutes && minutes < 15)) {
  87. console.log("0 <= minutes < 15");
  88. energyUpdateTime.setMinutes(15);
  89. } else if ((15 <= minutes && minutes < 30)) {
  90. console.log("15 <= minutes < 30");
  91. energyUpdateTime.setMinutes(30);
  92. } else if ((30 <= minutes && minutes < 45)) {
  93. console.log("30 <= minutes < 45");
  94. energyUpdateTime.setMinutes(45);
  95. } else if (45 <= minutes) {
  96. console.log("45 <= minutes");
  97. energyUpdateTime.setMinutes(0);
  98. energyUpdateTime.setHours(now.getHours() + 1);
  99. }
  100. console.log("Target time for energy refresh is:", energyUpdateTime);
  101. console.log("That means we're waiting for " + ((energyUpdateTime - now) / (1000 * 60)) + " minutes.");
  102. return setTimeout_(energyUpdateTime - now, function() {
  103. if (energyPercent + 10 <= 100) {
  104. energyPercent += 10;
  105. } else if (energyPercent < 100) {
  106. console.log("Setting energyPercent to 100, from " + energyPercent);
  107. energyPercent = 100;
  108. }
  109. energyBarText.text("Energy: " + energyPercent + "%");
  110. energyBarChangeBar.css("width", energyPercent + "%");
  111. if (energyPercent <= 100) {
  112. return energyUpdate();
  113. } else {
  114. return console.log('energyPercent is > 100 so stopping energy update loop.');
  115. }
  116. });
  117. };
  118.  
  119. energyUpdate();
  120.  
  121. navbar = $('.nav.visible-lg');
  122.  
  123. toplinks = $('.toplinks');
  124.  
  125. logout = toplinks.find('a[href="/logout.php"]');
  126.  
  127. moveToToplinks = function(page, linkText) {
  128. var link;
  129. link = navbar.find("a[href='" + page + "']").parent();
  130. link.remove();
  131. link.find('a').text(linkText);
  132. return logout.before(link);
  133. };
  134.  
  135. moveToToplinks('/oasis.php', 'Oasis');
  136.  
  137. moveToToplinks('/boards.php', 'Chatter');
  138.  
  139. moveToToplinks('/news.php', 'News');
  140.  
  141. moveToToplinks('/event.php', 'Event');
  142.  
  143. moveToToplinks('/faq.php', 'FAQ');
  144.  
  145. GM_addStyle("ul li ul.dropdown {\n min-width: 125px;\n background: " + ($('.navbar.navbar-default').css('background')) + ";\n padding-left: 10px;\n padding-bottom: 5px;\n\n display: none;\n position: absolute;\n z-index: 999;\n left: 0;\n}\n\nul li ul.dropdown li {\n display: block;\n}\n\n/* Display the dropdown on hover. */\nul li:hover ul.dropdown {\n display: block;\n}");
  146.  
  147. newDropdown = function(menuItem, dropdownLinks) {
  148. var dropdown, j, len, link, linkText, ref, results;
  149. if (typeof menuItem === 'string') {
  150. menuItem = navbar.find("a[href='" + menuItem + "']").parent();
  151. }
  152. dropdown = $("<ul class=dropdown></ul>");
  153. menuItem.append(dropdown);
  154. results = [];
  155. for (j = 0, len = dropdownLinks.length; j < len; j++) {
  156. ref = dropdownLinks[j], link = ref[0], linkText = ref[1];
  157. results.push(dropdown.append("<li><a href='" + link + "'>" + linkText + "</a></li>"));
  158. }
  159. return results;
  160. };
  161.  
  162. newNavbarItem = function(page, linkText, dropdownLinks) {
  163. var navbarItem;
  164. navbarItem = $("<li><a href='" + page + "'>" + linkText + "</a></li>");
  165. navbar.append(navbarItem);
  166. if (dropdownLinks != null) {
  167. return newDropdown(navbarItem, dropdownLinks);
  168. }
  169. };
  170.  
  171. if ((kingID = GM_getValue('kingID')) != null) {
  172. newDropdown('/territory.php', [["/lion.php?mid=" + kingID, 'King Overview'], ["/lionoverview.php?id=" + kingID, 'Lion Overview'], ['/nesting.php', 'Nesting']]);
  173. }
  174.  
  175. newDropdown('/hoard.php', [['/hoard.php?type=Food', 'Food'], ['/hoard.php?type=Amusement', 'Amusement'], ['/hoard.php?type=Decoration', 'Decoration'], ['/hoard.php?type=Background', 'Background'], ['/hoard.php?type=Other', 'Other'], ['/hoard.php?type=Buried', 'Buried'], ['/hoard.php?type=Bundles', 'Bundles'], ['/hoard-organisation.php', 'Organisation']]);
  176.  
  177. newDropdown('/explore.php', [['/search.php', 'Search'], ['/trading_center.php', 'Trading Center'], ['/questing.php', 'Quests'], ['/monkeybusiness.php', 'Monkey Shop'], ['/sharpen_claws.php', 'Sharpen Claws'], ['/games.php', 'Games'], ['/patrol.php', 'Patrol'], ['/leaders.php', 'Leaderboards'], ['/special.php', 'Special Lioness']]);
  178.  
  179. newNavbarItem('/hunting.php', 'Hunting');
  180.  
  181. newNavbarItem('/exploring.php', 'Exploring', [['/explorearea.php?id=1', '(1) Temperate S'], ['/explorearea.php?id=2', '(2-5) Shrubland'], ['/explorearea.php?id=3', '(6-10) Trpcl Forest'], ['/explorearea.php?id=4', '(11-15) Dry S'], ['/explorearea.php?id=5', '(16-20) Rocky Hills'], ['/explorearea.php?id=6', '(26-30) Marshl.'], ['/explorearea.php?id=7', '(31+) Waterhole']]);
  182.  
  183. newNavbarItem('/branch.php', 'Branches', [['/branch.php', 'My Branch'], ['/search_branches.php', 'Search']]);
  184.  
  185. newNavbarItem('/territory_map.php', 'Territories');
  186.  
  187. newNavbarItem('/scryingstone.php', 'Scrying Stone', [['/wardrobe.php', 'Wardrobe'], ['/falcons-eye.php', "Falcon's Eye"]]);
  188.  
  189. if (urlMatches(new RegExp('/hunting\\.php', 'i'))) {
  190. minutesLeft = findMatches('div.center > p', 0, 1).text();
  191. getResults = findMatches('input[name=get_results', 0, 1);
  192. if (minutesLeft.length) {
  193. minutesLeft = (/([0-9]+) minutes/.exec(minutesLeft))[1];
  194. minutesLeft = safeParseInt(minutesLeft);
  195. console.log(minutesLeft, 'minutes remaining.');
  196. wait = (minutesLeft + 1) * 60 * 1000;
  197. console.log("Reloading in " + wait + " ms...");
  198. setTimeout_(wait, function() {
  199. return location.reload();
  200. });
  201. } else if (getResults.length) {
  202. blinker = setInterval((function() {
  203. if (document.title === 'Ready!') {
  204. return document.title = '!!!!!!!!!!!!!!!!';
  205. } else {
  206. return document.title = 'Ready!';
  207. }
  208. }), HUNT_BLINK_TIMEOUT);
  209. window.onfocus = function() {
  210. clearInterval(blinker);
  211. return document.title = 'Ready!';
  212. };
  213. }
  214. }
  215.  
  216. if (urlMatches(new RegExp('/lion\\.php', 'i'))) {
  217. namePlateClone = findMatches('h1', 1, 1).clone();
  218. lionImageClone = findMatches('center > div[style="width: 95%; overflow: auto;"]', 1, 1).clone();
  219. chaseButtonTable = findMatches('div.col-xs-12.col-md-4', 1, 1);
  220. chaseButtonTable.before(namePlateClone, lionImageClone, '<br>');
  221. }
  222.  
  223. if (urlMatches(new RegExp('/territory\\.php', 'i'))) {
  224. if (!(urlMatches(/[?&]id=/i))) {
  225. storedKingID = GM_getValue('kingID');
  226. console.log("storedKingID: " + storedKingID);
  227. kingPortraitHref = $('#lion_image').parent().attr('href');
  228. console.log("kingPortraitHref: " + kingPortraitHref);
  229. currentKingID = /\/lion\.php\?mid=([0-9]+)/.exec(kingPortraitHref)[1];
  230. if (currentKingID !== storedKingID) {
  231. console.log("Stored king ID '" + storedKingID + "' didn't match detected kingID '" + currentKingID + "' at URL '" + document.location.href + "'");
  232. GM_setValue('kingID', currentKingID);
  233. }
  234. GM_addStyle("/* Make the tables a little closer together. Website default 20px. */\n.table { margin-bottom: 10px; }");
  235. tables = $('div.container.main center table.table');
  236. ref = (function() {
  237. var j, len, results;
  238. results = [];
  239. for (j = 0, len = tables.length; j < len; j++) {
  240. i = tables[j];
  241. results.push($(i));
  242. }
  243. return results;
  244. })(), aboutKing = ref[0], aboutPlayer = ref[1], pride = ref[2], etc = 4 <= ref.length ? slice.call(ref, 3) : [];
  245. aboutKing.after(pride);
  246. LionPlayer = (function() {
  247. var lionPlayer;
  248.  
  249. LionPlayer.prototype.LION_URL_TO_ID = new RegExp('/lion\\.php.*[?&]id=([0-9]+)');
  250.  
  251. function LionPlayer(autoPlayLink) {
  252. this.autoPlayLink = autoPlayLink;
  253. this.lionIDs = [];
  254. this.safeToClick = true;
  255. this.autoPlayLink.click((function(_this) {
  256. return function() {
  257. return _this.clickListener();
  258. };
  259. })(this));
  260. }
  261.  
  262. LionPlayer.prototype.clickListener = function() {
  263. if (this.safeToClick) {
  264. this.safeToClick = false;
  265. this.updateLionIDs();
  266. return this.play();
  267. }
  268. };
  269.  
  270. LionPlayer.prototype.getLionID = function(lionLink) {
  271. var id, url;
  272. url = lionLink.attr('href');
  273. id = this.LION_URL_TO_ID.exec(url)[1];
  274. return id;
  275. };
  276.  
  277. LionPlayer.prototype.updateLionIDs = function() {
  278. var lionLinks;
  279. lionLinks = $('a[href^="/lion.php?id="]');
  280. return this.lionIDs = (function() {
  281. var j, len, results;
  282. results = [];
  283. for (j = 0, len = lionLinks.length; j < len; j++) {
  284. i = lionLinks[j];
  285. results.push(this.getLionID($(i)));
  286. }
  287. return results;
  288. }).call(this);
  289. };
  290.  
  291. LionPlayer.prototype.play = function(arg, playedWith, length) {
  292. var id, ids, recurse, ref1;
  293. ref1 = arg != null ? arg : this.lionIDs, id = ref1[0], ids = 2 <= ref1.length ? slice.call(ref1, 1) : [];
  294. if (playedWith == null) {
  295. playedWith = 0;
  296. }
  297. if (length == null) {
  298. length = ids.length + 1;
  299. }
  300. this.autoPlayLink.text("Loading... (" + playedWith + "/" + length + ")");
  301. recurse = (function(_this) {
  302. return function() {
  303. playedWith++;
  304. if (ids.length) {
  305. return setHumanTimeout(function() {
  306. return _this.play(ids, playedWith, length);
  307. });
  308. } else {
  309. return _this.autoPlayLink.text("Done! (" + playedWith + "/" + length + ")");
  310. }
  311. };
  312. })(this);
  313. return $.get("/lion.php?id=" + id).done((function(_this) {
  314. return function(response) {
  315. if ($(response).find('input[value=Interact]').length) {
  316. return $.post("/lion.php?id=" + id, {
  317. action: 'play',
  318. interact: 'Interact'
  319. }).done(function(response) {
  320. console.log("Played with " + id + " successfully.");
  321. return recurse();
  322. });
  323. } else {
  324. console.log("Couldn't play with " + id + "; probably on cooldown.");
  325. return recurse();
  326. }
  327. };
  328. })(this));
  329. };
  330.  
  331. $('th a[href^="/lionoverview.php"]').parent().after("<th style=\"text-align:center!important;\"><a href=\"javascript:void(0)\" id=autoPlay>Play with all.</a></th>");
  332.  
  333. lionPlayer = new LionPlayer($('#autoPlay'));
  334.  
  335. return LionPlayer;
  336.  
  337. })();
  338. }
  339. findMatches('h1 + br', 1, 1).remove();
  340. }
  341.  
  342. if (urlMatches(/\/branch\.php/i)) {
  343. items = $('div.item');
  344. ref1 = (function() {
  345. var k, len, ref1, results;
  346. ref1 = items.find('b');
  347. results = [];
  348. for (k = 0, len = ref1.length; k < len; k++) {
  349. i = ref1[k];
  350. results.push($(i));
  351. }
  352. return results;
  353. })();
  354. for (j = 0, len = ref1.length; j < len; j++) {
  355. item = ref1[j];
  356. if (!(/[SG]B:/.exec(item.text()))) {
  357. continue;
  358. }
  359. item.wrap("<a href=\"javascript:void(0)\"></a>");
  360. item.parent().click(function(event) {
  361. var a, itemName, k, len1, ref2, results, targetItem;
  362. console.log('Got click event:', event);
  363. a = $(event.currentTarget);
  364. targetItem = a.parents('div.item');
  365. console.log('targetItem:', targetItem);
  366. itemName = targetItem.find('div.item-header').text();
  367. console.log('itemName:', itemName);
  368. ref2 = (function() {
  369. var l, len1, results1;
  370. results1 = [];
  371. for (l = 0, len1 = items.length; l < len1; l++) {
  372. i = items[l];
  373. results1.push($(i));
  374. }
  375. return results1;
  376. })();
  377. results = [];
  378. for (k = 0, len1 = ref2.length; k < len1; k++) {
  379. i = ref2[k];
  380. if (!(i.find('div.item-header').text() === itemName)) {
  381. continue;
  382. }
  383. i.find('input[name="price[]"]').val(targetItem.find('input[name="price[]"]').val());
  384. results.push(i.find('input[name="cprice[]"]').val(targetItem.find('input[name="cprice[]"]').val()));
  385. }
  386. return results;
  387. });
  388. }
  389. }