DripStat DropOut

Calculates stats in DripStat, and provides a control panel for automation.

当前为 2014-11-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name DripStat DropOut
  3. // @namespace anonycat
  4. // @version 0.12.260
  5. // @description Calculates stats in DripStat, and provides a control panel for automation.
  6. // @match https://dripstat.com/game/
  7. // @grant none
  8. // ==/UserScript==
  9.  
  10. //Throttle auto purchases to one every 3 seconds, to minimize risk of desyncs with the server
  11. var lastBuy = 0;
  12.  
  13. //Track how many manual clicks have been made by second over the last 60 seconds
  14. var clickHistory = [];
  15. while (lastBuy < 60)
  16. {clickHistory[lastBuy++] = 0;}
  17.  
  18. //Convert upgrade indices to their order in the shop
  19. var upgIndex = [1,1,1,1,1,1,1,1,1,1,1];
  20.  
  21. var knownPrice = [0,0,0,0,0,0,0,0,0,0,0];
  22. var lastbytes = 0;
  23.  
  24. var cache=[0,0,0,0,0,0];
  25. var first = 1;
  26. var sec = 0;
  27.  
  28. //Keep track of how often the cup is being clicked (this doesn't clobber its existing onClick function)
  29. $('#btn-addMem').click(function (e) {
  30. if (e.preventDefault(), document.hasFocus() && gameInited)
  31. if (localStats.byteCount < localStats.memoryCapacity)
  32. if (clickHistory[0] <= 19)
  33. clickHistory[0]++;
  34. })
  35.  
  36. function byteConvert(val)
  37. {
  38. if(val < 1000)
  39. return +val.toFixed(2)+" B";
  40. else
  41. return NumUtils.byteConvert(val,2);
  42. }
  43.  
  44. function byteConvert2(val)
  45. {
  46. if(val < 1000)
  47. return val.toFixed(0)+" B";
  48. else
  49. return NumUtils.byteConvert(val,2);
  50. }
  51.  
  52. function loop()
  53. {
  54. if(typeof(localStats) == "undefined")
  55. return;
  56. var powerupCounter = 1;
  57. var newPurchase = 0;
  58. var mult = 0;
  59. var multm = 0;
  60. var bpc = CoffeeCup.calcBytesPerClick();
  61. var bpcBoosts = localStats.powerUps[0].purchasedUpgrades.length;
  62. if(first)
  63. {
  64. first=0;
  65. init();
  66. }
  67. else
  68. {
  69. //Check for any changes in the control panel and save the new values if found.
  70. if(localStats.dropout.autoBuy != cache[0])
  71. {
  72. cache[0]=localStats.dropout.autoBuy;
  73. GM_setValue("ab",cache[0]+1);
  74. }
  75. if(localStats.dropout.autoClick != cache[1])
  76. {
  77. cache[1]=localStats.dropout.autoClick;
  78. GM_setValue("ac",cache[1]+1);
  79. }
  80. if(localStats.dropout.autoDrip != cache[2])
  81. {
  82. cache[2]=localStats.dropout.autoDrip;
  83. GM_setValue("ad",cache[2]+1);
  84. }
  85. if(localStats.dropout.clickRate != cache[3])
  86. {
  87. cache[3]=localStats.dropout.clickRate;
  88. GM_setValue("cr",cache[3]+1);
  89. }
  90. if(localStats.dropout.cupmultl != cache[4])
  91. {
  92. cache[4]=localStats.dropout.cupmultl;
  93. GM_setValue("ml",cache[4]+1);
  94. }
  95. if(localStats.dropout.cupmultm != cache[5])
  96. {
  97. cache[5]=localStats.dropout.cupmultm;
  98. GM_setValue("mm",cache[5]+1);
  99. }
  100. if(localStats.dropout.clickToggle != cache[6])
  101. {
  102. cache[6]=localStats.dropout.clickToggle;
  103. GM_setValue("rt",cache[6]+1);
  104. }
  105. if(localStats.dropout.clickToggleOn != cache[7])
  106. {
  107. cache[7]=localStats.dropout.clickToggleOn;
  108. GM_setValue("rton",cache[7]+1);
  109. }
  110. if(localStats.dropout.clickToggleOff != cache[8])
  111. {
  112. cache[8]=localStats.dropout.clickToggleOff;
  113. GM_setValue("rtoff",cache[8]+1);
  114. }
  115. }
  116. var avg10 = 0;
  117. var avg60 = 0;
  118. for(var a = 0; a < 60; a++)
  119. {
  120. avg60 += clickHistory[a];
  121. if(a<10)
  122. avg10 += clickHistory[a];
  123. }
  124. clickHistory.pop();
  125. clickHistory.unshift(0);
  126. avg10 /= 10;
  127. avg60 /= 60;
  128. sec++;
  129. if (sec == 60)
  130. {
  131. //reload if we have a blank page
  132. if($("#powerupstore").length == 0)
  133. window.location.reload(false);
  134. else
  135. {
  136. sec = 0;
  137. if(localStats.dropout.autoClick)
  138. {
  139. if(localStats.dropout.clickToggle && Math.random()*100<localStats.dropout.clickToggleOff)
  140. {
  141. localStats.dropout.autoClick = 0;
  142. localStats.dropout.updatehud(2);
  143. }
  144. }
  145. else
  146. {
  147. if(localStats.dropout.clickToggle && Math.random()*100<localStats.dropout.clickToggleOn)
  148. {
  149. localStats.dropout.autoClick = 1;
  150. localStats.dropout.updatehud(2);
  151. }
  152. }
  153. }
  154. }
  155. lastbytes = localStats.byteCount;
  156. if (localStats.dropout.autoClick)
  157. {
  158. multm = localStats.dropout.cupmultm;
  159. mult = Math.min(20-clickHistory[1],Math.floor(Math.random()*(2 * multm - localStats.dropout.cupmultl)+localStats.dropout.cupmultl));
  160. if(mult)
  161. localStats.byteCount += bpc * mult;
  162. if(localStats.byteCount >= localStats.memoryCapacity)
  163. localStats.byteCount = localStats.memoryCapacity;
  164. }
  165. var bps = bpc * localStats.dropout.clickRate * (avg60 + multm) + localStats.bps;
  166. //Upgrades aren't necessarily in order, so untangle their order first
  167. $(".upgcontainer").each(function(upg) {
  168. if(this.children[0].className == "item")
  169. {
  170. var pos = Number(this.children[0].style.backgroundPosition.split(' ')[1].split('px')[0]) / -50;
  171. upgIndex[pos] = upg+1;
  172. if($(this).find('.upgROI').length==0)
  173. {
  174. $(this).append("<div class='upgROI'></div>");
  175. newPurchase = 1;
  176. }
  177. }
  178. })
  179. var data = Array();
  180. var upgdata = [1,1,1,1,1,1,1,1,1,1,1];
  181. var min = 1e+38;
  182. var bytesNeeded=0;
  183. var minObj = {};
  184. localStats.powerUps.slice(0).forEach(function(powerUp) {
  185. powerUp.position = "pu"+powerupCounter;
  186. var hasUpgrade = false;
  187. //Don't calculate ROI on upgrades that have zero powerups fueling them
  188. if(powerUp.count)
  189. powerUp.upgrades.forEach(function(upgrade) {
  190. if(hasUpgrade)
  191. return;
  192. hasUpgrade = true;
  193. upgrade.position = "upg"+upgIndex[powerupCounter-1];
  194. //Let's see which upgrade provides the biggest bang for the buck
  195. //(computed as "time taken before this upgrade will recoup its own cost").
  196. //If the price is so high that the current buffer can't possibly hold enough
  197. //(even if we cashed out for more space right now),
  198. //the "real" price includes what it takes to earn that extra buffer space.
  199. //If there's an object we can afford right now,
  200. //which will pay itself back in 2 hours,
  201. //and another object that would nominally pay itself back in 1h50m,
  202. //except that we can't afford it for 20 more minutes,
  203. //we should account for that in the time before recouping.
  204. //Add the time spent waiting to accrue sufficient funds.
  205. //Oh, and if we need 100MB for something, but can only hold 80MB
  206. //(with 70MB of it filled already), we can't just drip 20MB and keep the rest.
  207. //We have to drip everything at once, shooting all the way to 150MB.
  208. //Thus we can't make any progress on affording the item until a drip,
  209. //and then it costs a full additional 100MB after starting from scratch.
  210.  
  211. if(upgrade.price > localStats.byteCount + localStats.memoryCapacity)
  212. bytesNeeded = 2 * upgrade.price - (localStats.memoryCapacity + localStats.byteCount);
  213. else if(upgrade.price > localStats.memoryCapacity)
  214. bytesNeeded = upgrade.price;
  215. else if(upgrade.price > localStats.byteCount)
  216. bytesNeeded = upgrade.price - localStats.byteCount;
  217. else
  218. bytesNeeded = 0;
  219. //Cursor upgrades boost clicking too, so if autoclicks are on, take the rate
  220. //and overall BPS into account when determining its value.
  221. if(powerupCounter == 1)
  222. upgrade.value = upgrade.price/((powerUp.totalBps * (1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.1) + localStats.dropout.clickRate * (avg60 + multm) * bpc) / 10) + bytesNeeded / bps;
  223. else
  224. upgrade.value = upgrade.price/(powerUp.totalBps * (0.1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.01)) + bytesNeeded / bps;
  225. min = Math.min(min, upgrade.value);
  226. if(upgrade.value == min)
  227. minObj = upgrade;
  228. upgdata[upgIndex[powerupCounter-1]-1]=upgrade.value;
  229. });
  230. powerupCounter++;
  231. //Same procedure on the main power-ups themselves.
  232. if(powerUp.currentPrice > localStats.byteCount + localStats.memoryCapacity)
  233. bytesNeeded = 2 * powerUp.currentPrice - (localStats.memoryCapacity + localStats.byteCount);
  234. else if(powerUp.currentPrice > localStats.memoryCapacity)
  235. bytesNeeded = powerUp.currentPrice;
  236. else if(powerUp.currentPrice > localStats.byteCount)
  237. bytesNeeded = powerUp.currentPrice - localStats.byteCount;
  238. else
  239. bytesNeeded = 0;
  240. powerUp.value = powerUp.currentPrice/(powerUp.currentBps * (1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.1)) + bytesNeeded / Math.max(1,bps);
  241. data.push(powerUp.value);
  242. if(!(springPowerup.isLocked && powerUp.name == "Spring Framework"))
  243. {
  244. min = Math.min(min, powerUp.value);
  245. if(powerUp.value == min)
  246. minObj = powerUp;
  247. }
  248. });
  249. $('.storeItem, .upgcontainer').css('background-color', '');
  250. var selector = minObj.position;
  251. $("#"+selector).css('background-color', '#B2EDED');
  252. $('.storeItem').each(function(index){
  253. if($(this).find('.storeROI').length==0)
  254. {
  255. $(this).html("<div class='storeItemAmount'>"+localStats.powerUps[index].count+"</div>"
  256. +"<div class='storeItemName'>"+localStats.powerUps[index].name+"</div>"
  257. +"<div class='storePriceRow'>"
  258. +"<div class='storePrice'>"+byteConvert2(localStats.powerUps[index].currentPrice)+"</div>"
  259. +"<div class='storeROI'>("+String(data[index]).toHHMMSS()+")</div></div>"
  260. +"<div class='powerup-one'>"+byteConvert(localStats.powerUps[index].currentBps)+"ps each</div>"
  261. +"<div class='powerup-all'>"+byteConvert2(localStats.powerUps[index].totalBps)+"ps total</div>"
  262. +"<div class='powerup-pct'>"+(100 * localStats.powerUps[index].totalBps / localStats.bps).toFixed(3)+"%</div>");
  263. newPurchase = 1;
  264. }
  265. if(knownPrice[index] != localStats.powerUps[index].currentPrice)
  266. {
  267. knownPrice[index] = localStats.powerUps[index].currentPrice;
  268. newPurchase = 1;
  269. }
  270. });
  271. if(newPurchase)
  272. $('.storeItem').each(function(index){
  273. $(this).find('.powerup-one').html(byteConvert(localStats.powerUps[index].currentBps)+'ps each');
  274. $(this).find('.powerup-all').html(byteConvert2(localStats.powerUps[index].totalBps)+'ps total');
  275. $(this).find('.powerup-pct').html((100 * localStats.powerUps[index].totalBps / localStats.bps).toFixed(3)+'%');
  276. });
  277. $('.upgROI').each(function(index){
  278. $(this).html(String(upgdata[index]).toHHMMSS());
  279. });
  280. $('.storeROI').each(function(index){
  281. $(this).html("("+String(data[index]).toHHMMSS()+")");
  282. });
  283. var label = minObj.name;
  284. if(minObj.powerup) //Is our best deal an upgrade or a powerup? They use different syntax.
  285. {
  286. label = "<span style='color:#F00'>"+label+"</span>";
  287. var price = minObj.price;
  288. }
  289. else
  290. var price = minObj.currentPrice;
  291. var limitTime = Number((localStats.memoryCapacity - localStats.byteCount)/bps).toFixed(0);
  292. var limitstr = "";
  293. if ((localStats.dropout.autoDrip==1 || (localStats.dropout.autoDrip==2 && (localStats.dropout.autoBuy==0 || price >= localStats.memoryCapacity))) && localStats.byteCount == localStats.memoryCapacity)
  294. dripper.dripGlobal();
  295. if(price > localStats.byteCount + localStats.memoryCapacity)
  296. {
  297. var time = Number((2 * price - (localStats.memoryCapacity + localStats.byteCount))/bps).toFixed(0);
  298. if(localStats.memoryCapacity==localStats.byteCount)
  299. limitstr = " (Drip NOW!)";
  300. }
  301. else if(price > localStats.memoryCapacity)
  302. {
  303. var time = Number(price/bps).toFixed(0);
  304. limitstr = " (Drip NOW!)";
  305. if(localStats.dropout.autoDrip >= 2)
  306. dripper.dripGlobal();
  307. }
  308. else
  309. var time = Number((price - localStats.byteCount)/bps).toFixed(0);
  310. //Now to fill the control panel.
  311. $("#next-purchase-label").html("Next purchase: <strong>"+label+"</strong>");
  312. $("#next-purchase-payback").html("Pays for itself in "+String(minObj.value).toHHMMSS());
  313. if(time <= 0)
  314. $("#next-purchase-time").html("Affordable now");
  315. else
  316. $("#next-purchase-time").html("Affordable in "+String(time).toHHMMSS()+limitstr);
  317. if(limitTime <= 0)
  318. $("#max-space-label").html("Capacity is maxed out!");
  319. else
  320. $("#max-space-label").html("Capacity maxes out in "+String(limitTime).toHHMMSS());
  321. $("#click-rate-10").html(String(avg10.toFixed(1)));
  322. $("#click-rate-60").html(String(avg60.toFixed(1)));
  323. if(localStats.dropout.autoBuy && price<=lastbytes && lastBuy >= 3)
  324. {
  325. minObj.buy(localStats);
  326. lastBuy = 0;
  327. }
  328. else if (lastBuy < 3)
  329. lastBuy += 1;
  330. if(springPowerup.isLocked && mine.beanCount > 0 && gameInited && loggedIn && localStats.byteCount > 0)
  331. {
  332. if($('.vex').length)
  333. vex.closeAll();
  334. Mine.onGrab();
  335. }
  336. if($("#networkError")[0].style['cssText'] == "display: block;")
  337. window.location.reload(false);
  338. }
  339.  
  340. function init()
  341. {
  342. localStats.dropout = new Object;
  343. //Should powerups and upgrades be automatically purchased as they become affordable?
  344. //(As of level 5, also includes facilities for grabbing spring beans that appear)
  345. localStats.dropout.autoBuy = GM_getValue("ab",1)-1;
  346. //Should the BPS rate be increased to simulate automatic cup clicks?
  347. localStats.dropout.autoClick = GM_getValue("ac",1)-1;
  348. //Should memory automatically be dripped?
  349. //0 = no auto-drip, 1 = auto-drip when buffer is full, 2 = auto-drip as needed to create enough space to pay for upgrades
  350. localStats.dropout.autoDrip = GM_getValue("ad",1)-1;
  351.  
  352. //Should we take manual clicks into account when figuring out the payback rate of powerups?
  353. localStats.dropout.clickRate = GM_getValue("cr",2)-1;
  354. //Should auto-click randomly toggle itself on and off?
  355. localStats.dropout.clickToggle = GM_getValue("rt",1)-1;
  356. //Odds of randomly changing off->on
  357. localStats.dropout.clickToggleOn = GM_getValue("rton",2)-1;
  358. //Odds of randomly changing on->off
  359. localStats.dropout.clickToggleOff = GM_getValue("rtoff",51)-1;
  360.  
  361. //If autoclicking is enabled, each second will pick a random multiplier and count off that many cup clicks.
  362. //A multiplier of 0 means no clicking, only natural BPS intake.
  363. //Multipliers greater than 20 are rejected by the server, so we won't ever generate such a thing here.
  364. //Lowest possible multiplier to select
  365. localStats.dropout.cupmultl = GM_getValue("ml",1)-1;
  366. //Average multiplier
  367. localStats.dropout.cupmultm = GM_getValue("mm",6)-1;
  368. //There is no variable for the highest multiplier; it's automatically figured as 2*Middle - Low (but capped at 20).
  369. //zero-valued options don't always store correctly...solution, store X+1!
  370. cache=[localStats.dropout.autoBuy, localStats.dropout.autoClick, localStats.dropout.autoDrip, localStats.dropout.clickRate, localStats.dropout.cupmultl, localStats.dropout.cupmultm, localStats.dropout.clickToggle, localStats.dropout.clickToggleOn, localStats.dropout.clickToggleOff];
  371. GM_setValue("ab",cache[0]+1);
  372. GM_setValue("ac",cache[1]+1);
  373. GM_setValue("ad",cache[2]+1);
  374. GM_setValue("cr",cache[3]+1);
  375. GM_setValue("ml",cache[4]+1);
  376. GM_setValue("mm",cache[5]+1);
  377. GM_setValue("rt",cache[6]+1);
  378. GM_setValue("rton",cache[7]+1);
  379. GM_setValue("rtoff",cache[8]+1);
  380. //string (int) seconds to formatted time
  381. String.prototype.toHHMMSS = function () {
  382. var seconds = parseInt(this, 10); // don't forget the second param
  383. if(seconds <= 0)
  384. return "no time";
  385. var days = Math.floor(seconds / 86400);
  386. seconds -= days*86400;
  387. var hours = Math.floor(seconds / 3600);
  388. seconds -= hours*3600;
  389. var minutes = Math.floor(seconds / 60);
  390. seconds -= minutes*60;
  391. if (hours < 10 && days) {hours = "0"+hours;}
  392. if (minutes < 10 && hours) {minutes = "0"+minutes;}
  393. if (seconds < 10) {seconds = "0"+seconds;}
  394. //NOTE: this output contains zero-width spaces before each colon, mostly to fit in upgrade boxes
  395. if(days)
  396. return days+"d "+hours+"​:"+minutes+"​:"+seconds;
  397. else if(hours)
  398. return hours+"​:"+minutes+"​:"+seconds;
  399. else
  400. return minutes+"​:"+seconds;
  401. }
  402. //function to update the control panel
  403. localStats.dropout.updatehud = function(type) {
  404. if(type & 1)
  405. {
  406. if(this.autoBuy)
  407. {
  408. $(".apn").css('background-color', '');
  409. $(".apy").css('background-color', '#AFA');
  410. }
  411. else
  412. {
  413. $(".apy").css('background-color', '');
  414. $(".apn").css('background-color', '#FAA');
  415. }
  416. }
  417. if(type & 2)
  418. {
  419. if(this.autoClick)
  420. {
  421. $(".acn").css('background-color', '');
  422. $(".acy").css('background-color', '#AFA');
  423. }
  424. else
  425. {
  426. $(".acy").css('background-color', '');
  427. $(".acn").css('background-color', '#FAA');
  428. }
  429. }
  430. if(type & 4)
  431. {
  432. if(this.autoDrip==2)
  433. {
  434. $(".drip0").css('background-color', '');
  435. $(".drip1").css('background-color', '');
  436. $(".drip2").css('background-color', '#AFA');
  437. }
  438. else if(this.autoDrip)
  439. {
  440. $(".drip2").css('background-color', '');
  441. $(".drip0").css('background-color', '');
  442. $(".drip1").css('background-color', '#AAF');
  443. }
  444. else
  445. {
  446. $(".drip2").css('background-color', '');
  447. $(".drip1").css('background-color', '');
  448. $(".drip0").css('background-color', '#FAA');
  449. }
  450. }
  451. if(type & 8)
  452. {
  453. if(this.clickRate)
  454. {
  455. $(".crn").css('background-color', '');
  456. $(".cry").css('background-color', '#AFA');
  457. }
  458. else
  459. {
  460. $(".cry").css('background-color', '');
  461. $(".crn").css('background-color', '#FAA');
  462. }
  463. }
  464. if(type & 16)
  465. $("#multl").html("Min. Rate: "+String(this.cupmultl));
  466. if(type & 32)
  467. $("#multm").html("Avg. Rate: "+String(this.cupmultm));
  468. if(type & 64)
  469. {
  470. if(this.clickToggle)
  471. {
  472. $(".rtn").css('background-color', '');
  473. $(".rty").css('background-color', '#AFA');
  474. }
  475. else
  476. {
  477. $(".rty").css('background-color', '');
  478. $(".rtn").css('background-color', '#FAA');
  479. }
  480. }
  481. if(type & 128)
  482. $("#rton").html(String(this.clickToggleOn)+"%");
  483. if(type & 256)
  484. $("#rtoff").html(String(this.clickToggleOff)+"%");
  485. }
  486. //Create the control panel with divs
  487. $('#bpsChartContainer').parent().append("<table style='width:100%; height:105px; line-height:1.3; border-collapse: collapse'><tr>"
  488. +"<td rowspan=2 style='width:33%; border: 2px solid black'><div id='next-purchase-container'></div></td>"
  489. +"<td colspan=2 style='width:12%; height:35px; border: 2px solid black; border-bottom: none' class='apy apn' onclick='localStats.dropout.autoBuy = 1 - localStats.dropout.autoBuy; localStats.dropout.updatehud(1)'>Auto Buy</td>"
  490. +"<td colspan=3 style='width:18%; border: 2px solid black; border-bottom: none' class='drip0 drip1 drip2' onclick='localStats.dropout.autoDrip = (1 + localStats.dropout.autoDrip) % 3; localStats.dropout.updatehud(4)'>Auto Drip</td>"
  491. +"<td colspan=2 style='width:12%; border: 2px solid black; border-bottom: none' class='acy acn' onclick='localStats.dropout.autoClick = 1 - localStats.dropout.autoClick; localStats.dropout.updatehud(2)'>Auto Click</td>"
  492. +"<td style='width:15%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multl'></div></td>"
  493. +"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.cupmultl = Math.min(localStats.dropout.cupmultl + 1, localStats.dropout.cupmultm); localStats.dropout.updatehud(16)'> + </td>"
  494. +"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.cupmultl = Math.max(localStats.dropout.cupmultl - 1, 0); localStats.dropout.updatehud(16)'> - </td></tr>"
  495. +"<tr><td style='width:6%; height:35px; border: 2px solid black; border-top: 1px solid black' class='apn' onclick='localStats.dropout.autoBuy = 0; localStats.dropout.updatehud(1)'> Off </td>"
  496. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='apy' onclick='localStats.dropout.autoBuy = 1; localStats.dropout.updatehud(1)'> On </td>"
  497. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip0' onclick='localStats.dropout.autoDrip = 0; localStats.dropout.updatehud(4)'> Never </td>"
  498. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip1' onclick='localStats.dropout.autoDrip = 1; localStats.dropout.updatehud(4)'> At <br /> Limit </td>"
  499. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip2' onclick='localStats.dropout.autoDrip = 2; localStats.dropout.updatehud(4)'> For <br /> Costs </td>"
  500. +"<td style='width:5.5%; border: 2px solid black; border-top: 1px solid black' class='acn' onclick='localStats.dropout.autoClick = 0; localStats.dropout.updatehud(2)'> Off </td>"
  501. +"<td style='width:5.5%; border: 2px solid black; border-top: 1px solid black' class='acy' onclick='localStats.dropout.autoClick = 1; localStats.dropout.updatehud(2)'> On </td>"
  502. +"<td style='width:16%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multm'></div></td>"
  503. +"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.cupmultm = Math.min(localStats.dropout.cupmultm + 1, 20); localStats.dropout.updatehud(32)'> + </td>"
  504. +"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.cupmultm = Math.max(localStats.dropout.cupmultm - 1, localStats.dropout.cupmultl); localStats.dropout.updatehud(32)'> - </td></tr>"
  505. +"<tr><td colspan=2 style='height:35px; border: 2px solid black; border-right: none'> Average Click Rate per second - Last 10s: </td>"
  506. +"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-10'></div></strong></td>"
  507. +"<td colspan=2 style='border: 2px solid black; border-right: none'> Last 60s: </td>"
  508. +"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-60'></div></strong></td>"
  509. +"<td colspan=3 style='border: 2px solid black; border-right: none' class='rty rtn' onclick='localStats.dropout.clickToggle = 1 - localStats.dropout.clickToggle; localStats.dropout.updatehud(64)'> Randomly toggle Auto Click? </td>"
  510. +"<td style='border: 2px solid black; border-left: 1px solid black; border-right: 1px solid black' class='rty' onclick='localStats.dropout.clickToggle = 1; localStats.dropout.updatehud(64)'> Yes </td>"
  511. +"<td style='border: 2px solid black; border-left: none' class='rtn' onclick='localStats.dropout.clickToggle = 0; localStats.dropout.updatehud(64)'> No </td></tr>"
  512. +"<tr><td style='height:35px; border: 2px solid black; border-right: none' class='cry crn' onclick='localStats.dropout.clickRate = 1 - localStats.dropout.clickRate; localStats.dropout.updatehud(8)'> Take click rate into account? </td>"
  513. +"<td style='border: 2px solid black; border-left: 1px solid black; border-right: 1px solid black' class='cry' onclick='localStats.dropout.clickRate = 1; localStats.dropout.updatehud(8)'> Yes </td>"
  514. +"<td style='border: 2px solid black; border-left: none' class='crn' onclick='localStats.dropout.clickRate = 0; localStats.dropout.updatehud(8)'> No </td>"
  515. +"<td colspan=3 style='border: 2px solid black; border-right:1px solid black'> Odds to Enable: <strong><div id='rton'></div></strong></td>"
  516. +"<td style='border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.clickToggleOn = Math.min(localStats.dropout.clickToggleOn + 1, 100); localStats.dropout.updatehud(128)'> + </td>"
  517. +"<td style='border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.clickToggleOn = Math.max(localStats.dropout.clickToggleOn - 1, 0); localStats.dropout.updatehud(128)'> - </td>"
  518. +"<td style='border: 2px solid black; border-right:1px solid black'> Odds to Disable: <strong><div id='rtoff'></div></strong></td>"
  519. +"<td style='border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.clickToggleOff = Math.min(localStats.dropout.clickToggleOff + 1, 100); localStats.dropout.updatehud(256)'> + </td>"
  520. +"<td style='border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.clickToggleOff = Math.max(localStats.dropout.clickToggleOff - 1, 0); localStats.dropout.updatehud(256)'> - </td></tr></table>");
  521. $("#next-purchase-container").html("<div id='next-purchase-label'></div><div id='next-purchase-payback'></div><div id='next-purchase-time'></div><div id='max-space-label'></div>");
  522. $("head").append("<style id='tweaks'></style>");
  523. $("#tweaks").text('.navbar {max-height: 50px}'
  524. +'#upgrades .item {height: 50px}'
  525. +'#bpsChartContainer {padding-bottom: 2px}'
  526. +'#upgrades {height: 85px; line-height: 1.2}'
  527. +'#upgrades .upgcontainer {height: 85px; overflow-y: hidden}'
  528. +'#upgrades .upgROI {font-weight: bolder; text-align: center; color:#F00}'
  529. +'.storeItem {position: relative;}'
  530. +'.storeItemName {font-size: 130%}'
  531. +'.storeItemAmount {font-size: 200%; line-height: 1.25}'
  532. +'.storePriceRow {display: table}'
  533. +'.storeROI {display: table-cell; padding-left: 4px; font-size: 0.9em; font-weight: bolder; color: #F00}'
  534. +'.powerup-one {position: absolute; text-align: right; font-weight: bolder; font-size: 130%; top: 1px; right: 67px}'
  535. +'.powerup-all {position: absolute; text-align: right; font-weight: bolder; font-size: 130%; top: 26px; right: 70px; color: #BD511E}'
  536. +'.powerup-pct {position: absolute; text-align: right; font-weight: bolder; top: 30px; right: 4px; color: #F00; opacity: 0.6}');
  537. localStats.dropout.updatehud(511);
  538. }
  539.  
  540. //Reimplementing these functions at the script level, because otherwise we lose "@grant none" and its scoping.
  541. //Code snippets courtesy of Anthony Lieuallen.
  542. const __GM_STORAGE_PREFIX = [
  543. '', GM_info.script.namespace, GM_info.script.name, ''].join('***');
  544.  
  545. function GM_getValue(aKey, aDefault) {
  546. 'use strict';
  547. let val = localStorage.getItem(__GM_STORAGE_PREFIX + aKey)
  548. if (null === val && 'undefined' != typeof aDefault) return aDefault;
  549. return val;
  550. }
  551.  
  552. function GM_setValue(aKey, aVal) {
  553. 'use strict';
  554. localStorage.setItem(__GM_STORAGE_PREFIX + aKey, aVal);
  555. }
  556.  
  557. setInterval(function(){loop();}, 1000);