Gota.io Features by Donut

Hold down S to freeze. Press K to show/hide skins, N to show/hide names, M to show/hide mass, F to show/hide food, H to show/hide chat. For Team Scrimmage players: auto respawn in Team Scrimmage, "Team 2v2" is selected by default, press Enter to queue a match or leave a match that has ended, L to leave a match at any time. You can change the keys if you wish. You can also set custom keys for triple split, show/hide minimap, score panel, party panel, leaderboard, and auto decline party invites.

目前為 2018-07-02 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Gota.io Features by Donut
  3. // @namespace https://www.youtube.com/channel/UCIpCflcKEN9YgaO9qDahpRg
  4. // @version 1.6.10
  5. // @description Hold down S to freeze. Press K to show/hide skins, N to show/hide names, M to show/hide mass, F to show/hide food, H to show/hide chat. For Team Scrimmage players: auto respawn in Team Scrimmage, "Team 2v2" is selected by default, press Enter to queue a match or leave a match that has ended, L to leave a match at any time. You can change the keys if you wish. You can also set custom keys for triple split, show/hide minimap, score panel, party panel, leaderboard, and auto decline party invites.
  6. // @match *://gota.io/web/*
  7. // @author Donut
  8. // @grant none
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. (function(){
  13. if (window.top != window.self) return;
  14.  
  15. if (!('code' in KeyboardEvent.prototype)) {
  16. return alert("Sorry, your browser is incompatible with Gota.io Features by Donut. You're recommended to install the newest version of Google Chrome or Mozilla Firefox browsers.");
  17. }
  18.  
  19. function getVersionParts(v, validate = false) {
  20. var parts = v.split('.');
  21. if (validate) for (var i = 0; i < parts.length; i++) if (!/^\d+$/.test(parts[i])) return false;
  22. return parts;
  23. }
  24.  
  25. function compareVersions(v1, v2) {
  26. var v1parts = getVersionParts(v1), v2parts = getVersionParts(v2);
  27.  
  28. v1parts = v1parts.map(Number);
  29. v2parts = v2parts.map(Number);
  30.  
  31. while (v1parts.length < v2parts.length) v1parts.push(0);
  32. while (v2parts.length < v1parts.length) v2parts.push(0);
  33.  
  34. for (var i = 0; i < v1parts.length; ++i) {
  35. if (v1parts[i] > v2parts[i]) return 1;
  36. else if (v1parts[i] < v2parts[i]) return -1;
  37. }
  38. return 0;
  39. }
  40.  
  41. var importantUpdates = ['1.5.3', '1.6', '1.6.3'];
  42. importantUpdates.sort(compareVersions);
  43.  
  44. var version = '1.6.10', storageVersion = localStorage['donut-version'], notify = false;
  45. if (!storageVersion || !getVersionParts(storageVersion, true) || compareVersions(version, storageVersion) == 1 && (importantUpdates.lastIndexOf(version) >= 0 || compareVersions(importantUpdates[importantUpdates.length - 1], storageVersion) == 1)) notify = true;
  46. else localStorage['donut-version'] = version;
  47.  
  48. var styles = {
  49. '.donut-features-table': {
  50. 'margin': 'auto',
  51. 'width': 'max-content',
  52. 'border-collapse': 'collapse'
  53. },
  54. '.donut-features-table td:nth-child(1)': {
  55. 'text-align': 'left'
  56. },
  57. '.donut-features-table th, .donut-features-table td': {
  58. 'padding': '2px 8px'
  59. },
  60. '.donut-features-table input[type="text"]': {
  61. 'width': '100px',
  62. 'text-align': 'center'
  63. },
  64. '.donut-features-div': {
  65. 'margin': 'auto',
  66. 'padding-top': '4px',
  67. 'width': 'max-content'
  68. },
  69. '.donut-checkbox': {
  70. 'position': 'relative',
  71. 'top': '1px',
  72. 'margin': '0 5px'
  73. },
  74. '#donut-scrimmageMode': {
  75. 'box-sizing': 'content-box',
  76. 'padding': '1px 0',
  77. 'width': '104px'
  78. },
  79. '.donut-channel-link': {
  80. 'box-sizing': 'border-box',
  81. 'display': 'block',
  82. 'margin': '3px auto 0',
  83. 'padding': '4px 8px 4px 5.5px',
  84. 'width': '85px',
  85. 'height': '24px',
  86. 'color': '#fefefe',
  87. 'font-family': 'Arial, Helvetica, sans-serif',
  88. 'font-size': '12px',
  89. 'line-height': 'normal',
  90. 'text-align': 'center',
  91. 'text-decoration': 'none',
  92. 'background-color': '#e62117',
  93. 'border': 'solid 1px transparent',
  94. 'border-radius': '2px',
  95. 'white-space': 'nowrap',
  96. 'vertical-align': 'middle',
  97. 'box-shadow': '0 1px 0 rgba(0,0,0,0.05)'
  98. },
  99. '.donut-channel-link::before': {
  100. 'content': '""',
  101. 'position': 'relative',
  102. 'top': '-1px',
  103. 'display': 'inline-block',
  104. 'margin-right': '6px',
  105. 'width': '16px',
  106. 'height': '12px',
  107. 'background': 'no-repeat url(//s.ytimg.com/yts/imgbin/www-hitchhiker-vfl-Nn88d.png) -721px -88px',
  108. 'background-size': 'auto',
  109. 'vertical-align': 'middle'
  110. },
  111. '.donut-channel-link>span': {
  112. 'display': 'inline-block',
  113. '-moz-box-sizing': 'border-box',
  114. 'box-sizing': 'border-box'
  115. },
  116. '.donut-channel-link:hover': {
  117. 'background-color': '#cc181e'
  118. },
  119. '.donut-channel-link:active': {
  120. 'background-color': '#b31217'
  121. }
  122. };
  123.  
  124. if (notify) {
  125. styles['.donut-features-btn::before'] = {
  126. 'content': '"!"',
  127. 'position': 'absolute',
  128. 'top': '-6px',
  129. 'right': '-6px'
  130. };
  131. styles['.donut-features-btn::before, .donut-updated'] = {
  132. 'width': '12px',
  133. 'height': '12px',
  134. 'color': 'white',
  135. 'font-size': '11px',
  136. 'font-weight': 'bold',
  137. 'text-align': 'center',
  138. 'line-height': '12px',
  139. 'background-color': 'red',
  140. 'border-radius': '50%',
  141. 'overflow': 'hidden',
  142. '-webkit-user-select': 'none',
  143. '-moz-user-select': 'none',
  144. '-ms-user-select': 'none',
  145. 'user-select': 'none',
  146. 'display': 'inline-flex',
  147. 'align-items': 'center',
  148. 'justify-content': 'center'
  149. };
  150. styles['.donut-updated'] = {
  151. 'position': 'relative',
  152. 'top': '-1px',
  153. 'vertical-align': 'middle'
  154. };
  155. }
  156.  
  157. function insertRule(selector) {
  158. var rule = selector + '{';
  159. for (var property in styles[selector]) rule += property + ':' + styles[selector][property] + ';';
  160. rule += '}';
  161. stylesheet.insertRule(rule, stylesheet.cssRules.length);
  162. }
  163.  
  164. var style = document.createElement('style');
  165. document.head.appendChild(style);
  166. var stylesheet = style.sheet;
  167. for (var selector in styles) insertRule(selector);
  168.  
  169. var left = document.getElementsByClassName('main-bottom-left')[0], right = document.getElementsByClassName('main-bottom-right')[0], stats = document.getElementsByClassName('main-bottom-stats')[0];
  170. left.style.position = 'relative';
  171. left.style.left = '-3px';
  172. left.style.marginRight = '6px';
  173. right.style.display = 'flex';
  174. right.style.flexFlow = 'column wrap';
  175. right.style.justifyContent = 'space-between';
  176. right.firstElementChild.style.margin = '0 auto';
  177. stats.style.width = '155px';
  178. stats.style.height = '148px';
  179.  
  180. var btnTemplate = document.createElement('button');
  181. btnTemplate.className = 'gota-btn bottom-btn';
  182. btnTemplate.style.color = 'white';
  183. btnTemplate.style.backgroundColor = 'rgba(23,22,23,.9)';
  184.  
  185. var btn = btnTemplate.cloneNode();
  186. btn.className += ' donut-features-btn';
  187. btn.style.position = 'relative';
  188. btn.style.boxSizing = 'border-box';
  189. btn.style.padding = '0px 3px';
  190. btn.style.width = '100%';
  191. btn.style.height = '32px';
  192. btn.style.fontSize = '16px';
  193. btn.style.lineHeight = '16px';
  194. btn.style.whiteSpace = 'nowrap';
  195. btn.style.overflow = 'visible';
  196. btn.innerText = 'Features by Donut';
  197. btn.addEventListener('click', function() {
  198. blackout.style.opacity = '0';
  199. blackout.style.display = 'block';
  200. resize();
  201. blackout.style.opacity = '1';
  202. if (notify) {
  203. localStorage['donut-version'] = version;
  204. stylesheet.insertRule('.donut-features-btn::before{content:none;}', stylesheet.cssRules.length);
  205. }
  206. });
  207. document.getElementsByClassName('main-bottom-right')[0].appendChild(btn);
  208.  
  209. var blackout = document.createElement('div');
  210. blackout.style.position = 'fixed';
  211. blackout.style.top = '0';
  212. blackout.style.right = '0';
  213. blackout.style.bottom = '0';
  214. blackout.style.left = '0';
  215. blackout.style.display = 'none';
  216. blackout.style.background = 'rgba(0,0,0,.5)';
  217. blackout.style.overflow = 'auto';
  218. blackout.style.zIndex = '100';
  219. document.body.appendChild(blackout);
  220.  
  221. var win = document.createElement('div');
  222. win.style.position = 'absolute';
  223. win.style.top = '50%';
  224. win.style.left = '50%';
  225. win.style.margin = '0';
  226. win.style.padding = '15px';
  227. win.style.color = 'white';
  228. win.style.fontFamily = 'Arial, Helvetica, sans-serif';
  229. win.style.fontSize = '16px';
  230. win.style.lineHeight = '22px';
  231. win.style.textAlign = 'center';
  232. win.style.backgroundColor = 'rgb(14,14,14)';
  233. win.style.border = 'solid 2px rgba(255,255,255,.2)';
  234. win.style.borderRadius = '5px';
  235. win.style.transform = 'translate(-50%, -50%)';
  236. win.innerHTML = `<table class='donut-features-table'><tbody><tr><th>Feature</th><th>Default</th><th>Custom key</th></tr>
  237. <tr><td>Freeze</td><td>S</td><td><input type="text" spellcheck="false" data-donut-feature="freeze"></td></tr>
  238. <tr><td>Show/hide skins</td><td>K</td><td><input type="text" spellcheck="false" data-donut-feature="skins"></td></tr>
  239. <tr><td>Show/hide names</td><td>N</td><td><input type="text" spellcheck="false" data-donut-feature="names"></td></tr>
  240. <tr><td>Show/hide mass</td><td>M</td><td><input type="text" spellcheck="false" data-donut-feature="mass"></td></tr>
  241. <tr><td>Show/hide food</td><td>F</td><td><input type="text" spellcheck="false" data-donut-feature="food"></td></tr>
  242. <tr><td>Show/hide chat</td><td>H</td><td><input type="text" spellcheck="false" data-donut-feature="chat"></td></tr>
  243. <tr><td colspan="2">Triple split</td><td><input type="text" spellcheck="false" data-donut-feature="tripleSplit"></td></tr>
  244. <tr><td colspan="2">Show/hide minimap</td><td><input type="text" spellcheck="false" data-donut-feature="minimap"></td></tr>
  245. <tr><td colspan="2">Show/hide score panel</td><td><input type="text" spellcheck="false" data-donut-feature="scorePanel"></td></tr>
  246. <tr><td colspan="2">Show/hide party panel</td><td><input type="text" spellcheck="false" data-donut-feature="partyPanel"></td></tr>
  247. <tr><td colspan="2">Show/hide leaderboard</td><td><input type="text" spellcheck="false" data-donut-feature="leaderboard"></td></tr>
  248. <tr><td colspan="2" style="padding-right:32px;">Toggle <em>Decline party invites</em></td><td><input type="text" spellcheck="false" data-donut-feature="autoDecline"></td></tr>
  249. <tr><td colspan="2">Toggle <em>Auto respawn</em></td><td><input type="text" spellcheck="false" data-donut-feature="autoRespawn"></td></tr>
  250. <tr><th colspan="3">Team Scrimmage</th>
  251. <tr><td>Queue</td><td>Enter</td><td><input type="text" spellcheck="false" data-donut-feature="queue"></td></tr>
  252. <tr><td>Leave a match</td><td>L</td><td><input type="text" spellcheck="false" data-donut-feature="leave"></td></tr></tbody></table>
  253. <div class="donut-features-div">You should only use the <em>Leave a match</em> hotkey<br>when playing with random teammates.<br>If you want to disable a hotkey, type Delete.</div>
  254. <div class="donut-features-div"><label><input type="checkbox" class="donut-checkbox" id="donut-hideScorePanel" data-donut-feature="hideScorePanel">Hide Score Panel</label><br>
  255. <label><input type="checkbox" class="donut-checkbox" id="donut-hidePartyPanel" data-donut-feature="hidePartyPanel">Hide Party Panel</label><br>
  256. <label><input type="checkbox" class="donut-checkbox" id="donut-hideLeaderboard" data-donut-feature="hideLeaderboard">Hide Leaderboard</label><br>
  257. <label><input type="checkbox" class="donut-checkbox" id="donut-scrimmageAutoRespawn" data-donut-feature="scrimmageAutoRespawn">Scrimmage Auto Respawn</label><br>
  258. <label><input type="checkbox" class="donut-checkbox" id="donut-startWithScrimmage" data-donut-feature="startWithScrimmage">Join Team Scrimmage as I open the game</label><br>
  259. <label><input type="checkbox" class="donut-checkbox" id="donut-leaveExperimental" data-donut-feature="leaveExperimental">Use my <em>Leave a match</em> hotkey to leave<br>my team in the other gamemodes</label></div>
  260. <div class="donut-features-div">Team Scrimmage Default: <select id="donut-scrimmageMode" data-donut-feature="scrimmageMode"><option value="0">Team 6v6</option><option value="1">Team 2v2</option><option value="2">Team 2v2 [MegaSplit]</option><option value="3">Duel 1v1</option></select></div>
  261. <div class="donut-features-div">You can support the developer by checking out<br>his YouTube channel:</div>
  262. <a href="https://www.youtube.com/channel/UCIpCflcKEN9YgaO9qDahpRg" target="_blank" class="donut-channel-link"><span>YouTube</span></a>`;
  263. if (notify && storageVersion) {
  264. if (compareVersions(storageVersion, '1.6') < 0) win.innerHTML = `<div class="donut-features-div" style="padding:0 0 4px 0;">Now you can use any key of your keyboard as<br>a hotkey, and select your <em>Leave a match</em> hotkey<br>to be used to leave a party in Experimental<br>(disabled by default, scroll down to enable).</div>` + win.innerHTML;
  265. if (compareVersions(storageVersion, '1.6.3') < 0) win.innerHTML = `<div class="donut-features-div" style="padding:0 0 4px 0;">Now you can select the default Scrimmage mode.</div>` + win.innerHTML;
  266. }
  267. blackout.appendChild(win);
  268.  
  269. function resize() {
  270. if (blackout.style.display == 'block') {
  271. if (window.innerHeight < win.offsetHeight + 20) {
  272. win.style.top = '0';
  273. win.style.margin = '10px';
  274. win.style.transform = 'translate(-50%, 0%)';
  275. } else {
  276. win.style.top = '50%';
  277. win.style.margin = '0';
  278. win.style.transform = 'translate(-50%, -50%)';
  279. }
  280. }
  281. }
  282. window.addEventListener('resize', resize);
  283.  
  284. document.addEventListener('click', function(e) {
  285. if (blackout.style.display == 'block' && e.target != win && !win.contains(e.target)) blackout.style.display = 'none';
  286. }, true);
  287.  
  288. var done = btnTemplate.cloneNode();
  289. done.style.display = 'block';
  290. done.style.margin = '12px auto 0';
  291. done.innerText = 'Done';
  292. done.addEventListener('click', function() {
  293. blackout.style.display = 'none';
  294. });
  295. win.appendChild(done);
  296.  
  297. var processedKeyCodes = {
  298. Escape: 'Esc',
  299. Minus: '-',
  300. Equal: '=',
  301. BracketLeft: '[',
  302. BracketRight: ']',
  303. Control: 'Ctrl',
  304. Semicolon: ';',
  305. Quote: "'",
  306. Backquote: '`',
  307. Backslash: '\\',
  308. Comma: ',',
  309. Period: '.',
  310. Slash: '/',
  311. NumpadMultiply: 'Numpad *',
  312. CapsLock: 'Caps Lock',
  313. ScrollLock: 'Scroll Lock',
  314. Numpad7: 'Numpad 7',
  315. Numpad8: 'Numpad 8',
  316. Numpad9: 'Numpad 9',
  317. NumpadSubtract: 'Numpad -',
  318. Numpad4: 'Numpad 4',
  319. Numpad5: 'Numpad 5',
  320. Numpad6: 'Numpad 6',
  321. NumpadAdd: 'Numpad +',
  322. Numpad1: 'Numpad 1',
  323. Numpad2: 'Numpad 2',
  324. Numpad3: 'Numpad 3',
  325. Numpad0: 'Numpad 0',
  326. NumpadDecimal: 'Numpad .',
  327. NumpadEqual: 'Numpad =',
  328. NumpadEnter: 'Enter',
  329. NumpadDivide: 'Numpad /',
  330. NumLock: 'Num Lock',
  331. ArrowUp: 'Arrow Up',
  332. PageUp: 'Page Up',
  333. ArrowLeft: 'Arrow Left',
  334. ArrowRight: 'Arrow Right',
  335. ArrowDown: 'Arrow Down',
  336. PageDown: 'Page Down',
  337. Meta: 'Win / \u2318',
  338. OS: 'Win / \u2318'
  339. };
  340.  
  341. function processKeyCode(code) {
  342. if (code.indexOf('Arrow') && code.indexOf('Bracket')) code = code.replace(/Key|Digit|Left|Right/, '');
  343. if (code in processedKeyCodes) return processedKeyCodes[code];
  344. return code;
  345. }
  346.  
  347. var keyCodes = {
  348. 8: 'Backspace',
  349. 9: 'Tab',
  350. 13: 'Enter',
  351. 33: 'Page Up',
  352. 34: 'Page Down',
  353. 35: 'End',
  354. 36: 'Home',
  355. 37: 'Arrow Left',
  356. 38: 'Arrow Up',
  357. 39: 'Arrow Right',
  358. 40: 'Arrow Down',
  359. 48: '0',
  360. 49: '1',
  361. 50: '2',
  362. 51: '3',
  363. 52: '4',
  364. 53: '5',
  365. 54: '6',
  366. 55: '7',
  367. 56: '8',
  368. 57: '9',
  369. 65: 'A',
  370. 66: 'B',
  371. 67: 'C',
  372. 68: 'D',
  373. 69: 'E',
  374. 70: 'F',
  375. 71: 'G',
  376. 72: 'H',
  377. 73: 'I',
  378. 74: 'J',
  379. 75: 'K',
  380. 76: 'L',
  381. 77: 'M',
  382. 78: 'N',
  383. 79: 'O',
  384. 80: 'P',
  385. 81: 'Q',
  386. 82: 'R',
  387. 83: 'S',
  388. 84: 'T',
  389. 85: 'U',
  390. 86: 'V',
  391. 87: 'W',
  392. 88: 'X',
  393. 89: 'Y',
  394. 90: 'Z',
  395. 96: 'Numpad 0',
  396. 97: 'Numpad 1',
  397. 98: 'Numpad 2',
  398. 99: 'Numpad 3',
  399. 100: 'Numpad 4',
  400. 101: 'Numpad 5',
  401. 102: 'Numpad 6',
  402. 103: 'Numpad 7',
  403. 104: 'Numpad 8',
  404. 105: 'Numpad 9'
  405. };
  406.  
  407. var defaultKeys = {
  408. freeze: 'S',
  409. skins: 'K',
  410. names: 'N',
  411. mass: 'M',
  412. food: 'F',
  413. chat: 'H',
  414. tripleSplit: null,
  415. minimap: null,
  416. scorePanel: null,
  417. partyPanel: null,
  418. leaderboard: null,
  419. autoDecline: null,
  420. autoRespawn: null,
  421. queue: 'Enter',
  422. leave: 'L'
  423. };
  424.  
  425. var inputs = document.querySelectorAll('.donut-features-table input[type="text"][data-donut-feature]'), errorKeys = 'Gota.io Features by Donut: An error occurred. We had to reset your custom keys.';
  426. function fillInputs(keys) {
  427. for (var i = 0; i < inputs.length; i++) {
  428. var feature = inputs[i].dataset.donutFeature, key = keys[feature];
  429. if (typeof key == 'undefined' && feature in defaultKeys) {
  430. key = keys[feature] = defaultKeys[feature];
  431. localStorage['donut-keys'] = JSON.stringify(keys);
  432. } else if (typeof(key) == 'number') {
  433. key = keys[feature] = key in keyCodes ? keyCodes[key] : defaultKeys[feature];
  434. localStorage['donut-keys'] = JSON.stringify(keys);
  435. }
  436. if (key === null) continue;
  437. inputs[i].value = key;
  438. }
  439. }
  440.  
  441. function tryLocalStorage(index, defaultObj, func, error) {
  442. var obj; index = 'donut-' + index;
  443. try {
  444. if (!localStorage[index]) throw null;
  445. obj = JSON.parse(localStorage[index]);
  446. if (func) func(obj);
  447. } catch (e) {
  448. obj = JSON.parse(JSON.stringify(defaultObj));
  449. if (e && error) console.error(error);
  450. localStorage[index] = JSON.stringify(obj);
  451. if (func) func(obj);
  452. }
  453. return obj;
  454. }
  455.  
  456. var keys = tryLocalStorage('keys', defaultKeys, fillInputs, errorKeys);
  457.  
  458. function handleInputKeydown(e) {
  459. e.preventDefault();
  460. var feature = this.dataset.donutFeature, code = processKeyCode(e.code);
  461. if (code) {
  462. if (code == 'Delete') {
  463. this.value = '';
  464. keys[feature] = null;
  465. localStorage['donut-keys'] = JSON.stringify(keys);
  466. } else if (code != keys[feature] && code != 'Unidentified') {
  467. for (var k in keys) {
  468. if (keys[k] == code) {
  469. keys[k] = null;
  470. for (var l = 0; l < inputs.length; l++) {
  471. if (inputs[l].dataset.donutFeature == k) {
  472. inputs[l].value = '';
  473. break;
  474. }
  475. }
  476. }
  477. }
  478. this.value = keys[feature] = code;
  479. localStorage['donut-keys'] = JSON.stringify(keys);
  480. }
  481. }
  482. }
  483.  
  484. for (var j = 0; j < inputs.length; j++) {
  485. inputs[j].addEventListener('keydown', handleInputKeydown);
  486. }
  487.  
  488. var cache = tryLocalStorage('cache', {});
  489.  
  490. function selectOption(id) {
  491. var select = document.getElementById(id), index = select.selectedIndex;
  492. select.selectedIndex = (index + (index == 1) + 1) % select.options.length;
  493. $(select).trigger('change');
  494. }
  495.  
  496. function triggerCheckbox(id) {
  497. $('#' + id).prop('checked', !$('#' + id).prop('checked')).trigger('change');
  498. }
  499.  
  500. function triggerDonutCheckbox(id) {
  501. var checkbox = document.getElementById(id);
  502. checkbox.checked = !checkbox.checked;
  503. checkbox.dispatchEvent(new Event('change'));
  504. }
  505.  
  506. function fadeOutMain() {
  507. if (document.getElementById('main').style.display == 'block') window.onkeydown({keyCode: 27, which: 27});
  508. }
  509.  
  510. var alertWin = win.cloneNode();
  511. alertWin.style.top = '10px';
  512. alertWin.style.display = 'none';
  513. alertWin.style.lineHeight = '19px';
  514. alertWin.style.backgroundColor = 'rgba(23,23,23,.9)';
  515. alertWin.style.boxShadow = '0 2px 3px rgba(0,0,0,.25)';
  516. alertWin.style.transform = 'translate(-50%, 0%)';
  517. alertWin.style.zIndex = '3';
  518. document.body.appendChild(alertWin);
  519.  
  520. var alertFadeOutTimer = 0;
  521. function Alert(html, timeout) {
  522. alertWin.innerHTML = html;
  523. $(alertWin).fadeIn(500);
  524. if (alertFadeOutTimer) clearTimeout(alertFadeOutTimer);
  525. alertFadeOutTimer = setTimeout(function() {
  526. $(alertWin).fadeOut(500);
  527. alertFadeOutTimer = 0;
  528. }, timeout);
  529. }
  530.  
  531. var frozen = false, x = 0, y = 0, originalMousemove;
  532. setTimeout(function delay() {
  533. if (window.onmousemove) {
  534. originalMousemove = window.onmousemove;
  535. window.onmousemove = function(e) {
  536. x = e.clientX; y = e.clientY;
  537. if (!frozen) originalMousemove(e);
  538. };
  539. } else {
  540. setTimeout(delay, 200);
  541. }
  542. }, 200);
  543.  
  544. window.addEventListener('keydown', function(e) {
  545. if (e.code == undefined) return;
  546. var code = processKeyCode(e.code), modifier = false;
  547. if ((code == 'Alt' && !e.ctrlKey && !e.metaKey && !e.shiftKey) || (code == 'Ctrl' && !e.altKey && !e.metaKey && !e.shiftKey) || (code == 'Win / \u2318' && !e.altKey && !e.ctrlKey && !e.shiftKey) || (code == 'Shift' && !e.altKey && !e.ctrlKey && !e.metaKey)) modifier = true;
  548. if (modifier || !e.altKey && !e.ctrlKey && !e.metaKey) {
  549. if (!modifier) {
  550. var key = e.which || e.keyCode || 0;
  551. if (key == 13 && document.activeElement === document.getElementById('name-box')) team2v2();
  552. else if (key == 27) {
  553. if (!firstEscape) firstEscape = true;
  554. if (alertWin.offsetHeight) $(alertWin).fadeOut(500);
  555. }
  556. }
  557. if ((modifier || !e.shiftKey) && document.activeElement.tagName != 'INPUT' && document.activeElement.tagName != 'TEXTAREA') {
  558. switch (code) {
  559. case keys.freeze:
  560. if (originalMousemove) {
  561. var X = window.innerWidth/2;
  562. var Y = window.innerHeight/2;
  563. originalMousemove({clientX: X, clientY: Y});
  564. frozen = true;
  565. }
  566. break;
  567. case keys.skins:
  568. selectOption('sShowSkins');
  569. break;
  570. case keys.names:
  571. selectOption('sShowNames');
  572. break;
  573. case keys.mass:
  574. triggerCheckbox('cShowMass');
  575. break;
  576. case keys.food:
  577. triggerCheckbox('cHideFood');
  578. break;
  579. case keys.chat:
  580. triggerCheckbox('cHideChat');
  581. break;
  582. case keys.tripleSplit:
  583. for (var i = 0; i < 3; i++) $(window).trigger($.Event('keydown', {keyCode: 32, which: 32}));
  584. break;
  585. case keys.minimap:
  586. triggerCheckbox('cHideMinimap');
  587. break;
  588. case keys.scorePanel:
  589. triggerDonutCheckbox('donut-hideScorePanel');
  590. break;
  591. case keys.partyPanel:
  592. triggerDonutCheckbox('donut-hidePartyPanel');
  593. break;
  594. case keys.leaderboard:
  595. triggerDonutCheckbox('donut-hideLeaderboard');
  596. break;
  597. case keys.autoDecline:
  598. triggerCheckbox('cAutoDecline');
  599. Alert('Auto Decline Party Invites: <strong>' + (document.getElementById('cAutoDecline').checked ? 'On' : 'Off') + '</strong>', 2500);
  600. break;
  601. case keys.autoRespawn:
  602. var id = done2v2 ? 'donut-scrimmageAutoRespawn' : 'cAutoRespawn';
  603. if (done2v2) triggerDonutCheckbox(id);
  604. else triggerCheckbox(id);
  605. Alert('Auto Respawn' + (done2v2 ? ' in Team Scrimmage' : '') + ': <strong>' + (document.getElementById(id).checked ? 'On' : 'Off') + '</strong>', 2500);
  606. break;
  607. case keys.queue:
  608. if (document.getElementById('scrimmage-btn-leave').style.display == 'block') $('#btn-leave-match').trigger('click');
  609. else if (document.getElementById('main-scrimmage').style.display == 'block') $('#btn-queue').trigger('click');
  610. fadeOutMain();
  611. break;
  612. case keys.leave:
  613. if (switches.leaveExperimental || scrimmage) {
  614. var cp = document.getElementById('chat-panel'), hidden = cp.style.display == 'none';
  615. if (hidden) {
  616. cp.style.opacity = '0';
  617. cp.style.display = 'block';
  618. }
  619. $('#chat-input').val('/leave').focus().trigger($.Event('keyup', {keyCode: 13, which: 13})).blur();
  620. scrimmage = false;
  621. if (hidden) {
  622. cp.style.display = 'none';
  623. cp.style.opacity = '1';
  624. }
  625. fadeOutMain();
  626. }
  627. }
  628. }
  629. }
  630. });
  631.  
  632. window.addEventListener('keyup', function(e) {
  633. if (originalMousemove && e.code && processKeyCode(e.code) == keys.freeze && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey && document.activeElement.tagName != 'INPUT' && document.activeElement.tagName != 'TEXTAREA') {
  634. frozen = false;
  635. originalMousemove({clientX: x, clientY: y});
  636. }
  637. });
  638.  
  639. var defaultSwitches = {
  640. hideScorePanel: false,
  641. hidePartyPanel: false,
  642. hideLeaderboard: false,
  643. scrimmageAutoRespawn: true,
  644. startWithScrimmage: false,
  645. leaveExperimental: false
  646. };
  647.  
  648. var checkboxes = document.getElementsByClassName('donut-checkbox'), errorSwitches = 'Gota.io Features by Donut: An error occurred. We had to reset your settings.';
  649. function fillCheckboxes(switches) {
  650. for (var i = 0; i < checkboxes.length; i++) {
  651. var feature = checkboxes[i].dataset.donutFeature, Switch = switches[feature];
  652. if (typeof Switch == 'undefined' && feature in defaultSwitches) {
  653. Switch = switches[feature] = defaultSwitches[feature];
  654. localStorage['donut-switches'] = JSON.stringify(switches);
  655. }
  656. if (typeof Switch == 'boolean') checkboxes[i].checked = Switch;
  657. else throw errorSwitches;
  658. }
  659. }
  660.  
  661. var switches = tryLocalStorage('switches', defaultSwitches, fillCheckboxes, errorSwitches);
  662.  
  663. var anchorObd = document.querySelector('.options-table>thead:nth-of-type(2)'), obd = anchorObd.cloneNode(true);
  664. obd.firstElementChild.firstElementChild.textContent = 'Options by Donut';
  665. anchorObd.parentNode.insertBefore(obd, anchorObd);
  666.  
  667. var tbody = document.createElement('tbody');
  668. anchorObd.parentNode.insertBefore(tbody, anchorObd);
  669.  
  670. function duplicatedCheckbox(feature, text) {
  671. var td = document.createElement('td');
  672. td.colSpan = '2';
  673. td.style.position = 'relative';
  674. td.style.paddingRight = '22px';
  675. td.textContent = text;
  676.  
  677. var checkbox = document.createElement('input');
  678. checkbox.type = 'checkbox';
  679. checkbox.className = 'checkbox-options';
  680. checkbox.dataset.donutFeature = feature;
  681. checkbox.style.position = 'absolute';
  682. checkbox.style.top = '1px';
  683. checkbox.style.right = '1px';
  684. td.appendChild(checkbox);
  685.  
  686. var tr = document.createElement('tr');
  687. tr.appendChild(td);
  688. tbody.appendChild(tr);
  689.  
  690. return checkbox;
  691. }
  692.  
  693. for (var feature in defaultSwitches) {
  694. var bro = document.querySelector('.donut-checkbox[data-donut-feature="' + feature + '"]'), text = (feature == 'startWithScrimmage' ? 'Join Scrimmage as I open the game' : bro.parentNode.innerText).replace('\n', ' ');
  695. duplicatedCheckbox(feature, text).checked = switches[feature];
  696. }
  697.  
  698. function handleCheckboxChange(e) {
  699. var feature = this.dataset.donutFeature;
  700. switches[feature] = this.checked;
  701. localStorage['donut-switches'] = JSON.stringify(switches);
  702. document.querySelector('input[type="checkbox"][data-donut-feature="' + feature + '"]' + (this.classList.contains('donut-checkbox') ? ':not(.donut-checkbox)' : '.donut-checkbox')).checked = this.checked;
  703. switch (feature) {
  704. case 'hideScorePanel':
  705. if (this.checked) hideScorePanel();
  706. else {
  707. document.getElementById('party-panel').style.top = document.getElementById('score-panel').offsetHeight + 20 + 'px';
  708. document.getElementById('score-panel').style.opacity = '1';
  709. }
  710. break;
  711. case 'hidePartyPanel':
  712. visibility('party-panel', !this.checked);
  713. break;
  714. case 'hideLeaderboard':
  715. visibility('leaderboard-panel', !this.checked);
  716. break;
  717. case 'scrimmageAutoRespawn':
  718. if (this.checked && scrimmage) scrimRespawn();
  719. }
  720. }
  721.  
  722. checkboxes = document.querySelectorAll('input[type="checkbox"][data-donut-feature]');
  723. for (var k = 0; k < checkboxes.length; k++) {
  724. checkboxes[k].addEventListener('change', handleCheckboxChange);
  725. }
  726.  
  727. function hideScorePanel() {
  728. document.getElementById('score-panel').style.opacity = '0';
  729. document.getElementById('party-panel').style.top = '10px';
  730. }
  731. if (switches.hideScorePanel) hideScorePanel();
  732.  
  733. document.getElementById('cHideId').addEventListener('change', function() {
  734. if (document.getElementById('score-panel').style.opacity == '1') document.getElementById('party-panel').style.top = document.getElementById('score-panel').offsetHeight + 20 + 'px';
  735. });
  736.  
  737. function visibility(id, visible) {
  738. document.getElementById(id).style.visibility = visible ? 'visible' : 'hidden';
  739. }
  740. if (switches.hideLeaderboard) visibility('leaderboard-panel', false);
  741. if (switches.hidePartyPanel) visibility('party-panel', false);
  742.  
  743. var defaultOptions = {
  744. scrimmageMode: '2'
  745. };
  746.  
  747. var selects = [document.getElementById('donut-scrimmageMode')];
  748. function fillSelects(options) {
  749. for (var i = 0; i < selects.length; i++) {
  750. var feature = selects[i].dataset.donutFeature, option = options[feature];
  751. if (typeof option == 'undefined' && feature in defaultOptions) {
  752. option = options[feature] = defaultOptions[feature];
  753. localStorage['donut-options'] = JSON.stringify(options);
  754. }
  755. var el = document.querySelector('[data-donut-feature="' + feature + '"] option[value="' + option + '"]');
  756. if (el) selects[i].selectedIndex = el.index;
  757. else throw null;
  758. }
  759. }
  760.  
  761. var options = tryLocalStorage('options', defaultOptions, fillSelects);
  762.  
  763. for (var l = 0; l < selects.length; l++) {
  764. selects[l].addEventListener('change', function(e) {
  765. var feature = this.dataset.donutFeature;
  766. options[feature] = this.options[this.selectedIndex].value;
  767. localStorage['donut-options'] = JSON.stringify(options);
  768. });
  769. }
  770.  
  771. var scrimmage = false, respawnCheckInterval = 0, respawnTimer = 0;
  772. document.getElementById('btn-queue').addEventListener('click', function() {
  773. scrimmage = true;
  774. if (switches.scrimmageAutoRespawn) scrimRespawn();
  775. });
  776.  
  777. function scrimmageFalse() {
  778. scrimmage = false;
  779. if (respawnTimer) {
  780. clearTimeout(respawnTimer);
  781. respawnTimer = respawnCheckInterval = 0;
  782. }
  783. }
  784. document.getElementById('btn-leave-match').addEventListener('click', scrimmageFalse);
  785.  
  786. function scrimRespawn() {
  787. var cells = document.getElementById('playerCells'), cellsNum = parseInt(cells.innerText, 10);
  788. if (respawnCheckInterval) clearInterval(respawnCheckInterval);
  789. respawnCheckInterval = setInterval(function() {
  790. if (switches.scrimmageAutoRespawn && scrimmage) {
  791. var temp = parseInt(cells.innerText, 10);
  792. if (temp != cellsNum) {
  793. cellsNum = temp;
  794. if (cellsNum === 0) {
  795. if (document.getElementById('main-scrimmage').style.display == 'none') {
  796. respawnTimer = setTimeout(function() {
  797. if (switches.scrimmageAutoRespawn && scrimmage) {
  798. $('#btn-play').trigger('click');
  799. respawnTimer = 0;
  800. scrimRespawn();
  801. }
  802. }, 10000);
  803. }
  804. clearInterval(respawnCheckInterval);
  805. respawnCheckInterval = 0;
  806. }
  807. }
  808. } else {
  809. clearInterval(respawnCheckInterval);
  810. respawnCheckInterval = 0;
  811. }
  812. }, 500);
  813. }
  814.  
  815. var firstEscape = false;
  816. function startScrimmage() {
  817. var region = document.getElementsByClassName('server-active')[0].getAttribute('region');
  818. var id = region == 'eu' ? 's_Beta' : region == 'na' ? 's_Jet' : 's_Citrus';
  819. var interval = setInterval(function() {
  820. if (document.getElementById(id) && document.getElementsByClassName('server-selected').length) {
  821. $('#' + id).trigger('click');
  822. $('#btn-play').trigger('click');
  823. setTimeout(function() {
  824. if (!firstEscape && !done2v2) Alert('It looks like the server is not responding.<br>You may want to press <strong>Esc</strong> to go back to the game menu.', 20000);
  825. }, 5000);
  826. clearInterval(interval);
  827. }
  828. }, 100);
  829. }
  830. if (switches.startWithScrimmage) startScrimmage();
  831.  
  832. var lastScrimmageServer = null;
  833. function isTeamScrimmage() {
  834. var servers = ['Beta', 'Jet', 'Citrus'];
  835. for (var i = 0; i < servers.length; i++) if (document.getElementById('s_' + servers[i]).classList.contains('server-selected')) return servers[i];
  836. return false;
  837. }
  838.  
  839. var done2v2 = false, checkigTean2v2 = false;
  840. function team2v2() {
  841. if (!checkigTean2v2) {
  842. var scrimmageServer = isTeamScrimmage();
  843. if (scrimmageServer) {
  844. if (!done2v2 || scrimmageServer != lastScrimmageServer) {
  845. lastScrimmageServer = scrimmageServer;
  846. checkigTean2v2 = true;
  847. var interval = setInterval(function() {
  848. if (document.getElementById('main-scrimmage').style.display == 'block' && document.getElementById('scrimmage-mode-select').selectedIndex === 0) {
  849. document.getElementById('scrimmage-mode-select').selectedIndex = options.scrimmageMode;
  850. $('#scrimmage-mode-select').trigger('change');
  851. clearTimeout(timeout);
  852. clearInterval(interval);
  853. done2v2 = true;
  854. checkigTean2v2 = false;
  855. if (switches.startWithScrimmage && alertWin.offsetHeight) alertWin.style.display = 'none';
  856. }
  857. }, 100), timeout = setTimeout(function() {
  858. clearInterval(interval);
  859. checkigTean2v2 = false;
  860. }, 25000);
  861. }
  862. } else {
  863. scrimmageFalse();
  864. done2v2 = false;
  865. }
  866. }
  867. }
  868.  
  869. document.getElementById('btn-play').addEventListener('click', team2v2);
  870. document.getElementById('btn-spec').addEventListener('click', team2v2);
  871.  
  872. var recaptcha = document.getElementById('recaptcha');
  873. if (recaptcha) recaptcha.style.display = 'none';
  874. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址