Guest User

Groups Stuff

a guest
Oct 7th, 2015
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.17 KB | None | 0 0
  1. // ==UserScript==
  2. // @name TagPro Group Enhancements
  3. // @namespace http://www.arfie.nl
  4. // @version 0.1
  5. // @description Better group layout
  6. // @author Ruud Verbeek
  7. // @include http://tagpro-*.koalabeast.com/groups*
  8. // @include http://tangent.jukejuice.com/groups*
  9. // @include http://*.newcompte.fr/groups*
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_deleteValue
  13. // @grant GM_addStyle
  14. // @grant GM_xmlhttpRequest
  15. // ==/UserScript==
  16.  
  17. var path = document.location.pathname.split('/');
  18.  
  19. servers = {
  20. Regular: {
  21. Chord: {name: 'Chord', url: 'tagpro-chord.koalabeast.com'},
  22. Orbit: {name: 'Orbit', url: 'tagpro-orbit.koalabeast.com'},
  23. Diameter: {name: 'Diameter', url: 'tagpro-diameter.koalabeast.com'},
  24. Pi: {name: 'Pi', url: 'tagpro-pi.koalabeast.com'},
  25. Radius: {name: 'Radius', url: 'tagpro-radius.koalabeast.com'},
  26. Segment: {name: 'Segment', url: 'tagpro-segment.koalabeast.com'},
  27. Origin: {name: 'Origin', url: 'tagpro-origin.koalabeast.com'},
  28. Sphere: {name: 'Sphere', url: 'tagpro-sphere.koalabeast.com'},
  29. Centra: {name: 'Centra', url: 'tagpro-centra.koalabeast.com'},
  30. Arc: {name: 'Arc', url: 'tagpro-arc.koalabeast.com'}
  31. },
  32. Testing: {
  33. Tangent: {name: 'Tangent', url: 'tangent.jukejuice.com'},
  34. Maptest: {name: 'Maptest', url: 'tagpro-maptest.koalabeast.com'},
  35. NC1: {name: 'NC Europe', url: 'maptest.newcompte.fr'},
  36. NC2: {name: 'NC US East', url: 'maptest2.newcompte.fr'},
  37. NC3: {name: 'NC US West', url: 'maptest3.newcompte.fr'},
  38. NC4: {name: 'NC Oceanic', url: 'oceanic.newcompte.fr'}
  39. }
  40. };
  41.  
  42. if(path.length < 3 || path[2] === '') {
  43. var currentServer = '';
  44. for(var type in servers) for(var server in servers[type]) {
  45. var d = servers[type][server];
  46. if(d.url === tagpro.serverHost)
  47. currentServer = d;
  48. else {
  49. GM_xmlhttpRequest({
  50. method: 'GET',
  51. url: 'http://' + d.url + '/groups/',
  52. onload: (function(d) {return function(response) {
  53. var tr = $('<div>').html(response.response).find('tr:not(:first-child)').clone().prepend($('<td>').append($('<a>').attr('href', 'http://' + d.url).text(d.name).css('color', 'white'))).appendTo('.board');
  54. tr.find('td:nth-child(2) a[href]').each(function() {$(this).attr('href', 'http://' + d.url + $(this).attr('href'));});
  55. };})(d)
  56. });
  57. }
  58. }
  59. $('.alt').removeClass('alt');
  60. GM_addStyle('.board tr:nth-child(odd) {background-color: #272727;} .board td:nth-child(1) {width: 25%;} .board td:nth-child(3) {width: 20%;}');
  61. $('.board tr:first-child').prepend('<th>Server</th>');
  62. $('.board tr:not(:first-child)').prepend($('<td>').append($('<a>').attr('href', 'http://' + currentServer.url).text(currentServer.name).css('color', 'white')));
  63. return;
  64. }
  65.  
  66. if(path[2] === 'create')
  67. return;
  68.  
  69. GM_addStyle(
  70. '.teams > div {width: 240px !important; float: none !important;}' +
  71. '#redTeam, #blueTeam {height: auto !important;}' +
  72. '#spectators, #waiting {position: absolute; right: -240px; height: 300px !important; overflow: visible;}' +
  73. '#spectators {top: 0;}' +
  74. '#waiting {bottom: -300px;}' +
  75. '.teams h2 {text-align: center;}' +
  76. '.teams li {display: block !important; width: 200px !important; color: inherit !important; height: 21px; margin: 1px 1px 2px 1px !important;}' +
  77. '#redTeam ul, #blueTeam ul {min-height: 0 !important; height: 96px !important; overflow-y: auto !important;}' +
  78. '#spectators ul {overflow-y: auto !important;}' +
  79. '.teams li div {display: inline-block; max-width: 150px; overflow-x: hidden; text-overflow: ellipsis; white-space: nowrap;}' +
  80. '.teams li span {float: right; margin-top: 4px !important;}' +
  81. '.teams li div::before, .playerName::before {width: 16px; height: 16px; content: ""; display: inline-block; margin-right: 4px;}' +
  82. '.teams li.leader div::before, .playerName._leader::before {background-image: url(../images/flair.png); background-position: -32px 0; background-repeat: no-repeat; position: relative; top: 2px;}' +
  83. '.teams li.you:not(.leader) div::before, .playerName._you:not(._leader)::before {background-image: url(../images/flair.png); background-position: -16px -16px; background-repeat: no-repeat; position: relative; top: 2px;}' +
  84. '#redTeam input, #blueTeam input {width: 50%;}' +
  85. '.score {margin-top: 12px !important; margin-left: 0 !important;}' +
  86. '.score select {margin-left: 4px;}' +
  87. 'body {position: absolute; width: 940px; left: calc(50% - 480px); height: 410px; top: calc(50% - 280px);}' +
  88. 'header {position: absolute; font-size: 200%; font-weight: bold;}' +
  89. 'header a {margin-right: 20px;}' +
  90. '.teams {position: absolute !important; left: auto !important;}' +
  91. '#chat {width: 600px; left: 40px !important; position: absolute !important; top: 70px !important; height: 300px; box-sizing: border-box; overflow-x: hidden !important;}' +
  92. '#chat a {text-decoration: underline; color: #49f;}' +
  93. '#chatSend {width: 592px !important; left: 40px !important; position: absolute !important; height: 16px; top: 390px;}' +
  94. '#actions {position: absolute !important; right: 50px !important; bottom: 0 !important; display: block !important; left: auto !important;}' +
  95. 'button, a.button {margin: 10px !important; display: block; min-width: 200px !important;}' +
  96. '#settings {display: none !important;}' +
  97. '#settingsOverview {position: absolute; top: 70px; left: -300px; bottom: auto; height: auto; border: 1px solid rgba(255,255,255,0.20); background-color: rgba(255,255,255,0.10); display: block; width: 300px;}' +
  98. '#settingsOverview ul {list-style: initial; max-height: 200px; overflow-y: auto;}' +
  99. '#settingsOverview hr {border: 1px solid rgba(255, 255, 255, 0.20); border-width: 1px 0 0 0;}' +
  100. '#settingsOverview > * {margin: 10px;}' +
  101. '#settingsOverview ul li {margin: 5px 0 5px 20px;}' +
  102. '.changeSettingButton {float: right; color: #0f0; margin-right: 10px; font-size: 75%;}' +
  103. '#status {position: absolute !important; right: -200px !important; top: 41px !important; left: auto !important;}' +
  104. '#playerOptions {display: none !important;}' +
  105. 'body.groupLeader .teams li:hover .playerStatus {display: none !important;}' +
  106. '.teams li .playerAction {display: none; background-image: url(../images/flair.png); width: 16px; height: 16px; float: right; opacity: 0.4; cursor: pointer; margin: 0 4px; position: relative; top: -2px;}' +
  107. 'body.groupLeader .teams li:hover .playerAction {display: inline-block;}' +
  108. '.teams li:hover .playerAction:hover {opacity: 1.0;}' +
  109. '.ban {background-position-x: -64px;}' +
  110. '.makeLeader {background-position-x: -32px;}' +
  111. '.leader .makeLeader {display: none !important;}' +
  112. '#mapSelector {position: absolute; left: -11px; border: 1px solid rgba(255,255,255,0.20); background-color: rgba(255,255,255,0.10); display: block; overflow-y: auto; width: 300px; padding: 10px; box-sizing: border-box;}' +
  113. '#mapSelectorCategory {width: 100%;}' +
  114. '.mapSelectorCategory {display: block; margin: 10px auto 0 auto; text-align: center;}' +
  115. 'input[type=number] {width: 96px;}' +
  116. 'input::-webkit-outer-spin-button, input::-webkit-inner-spin-button {-webkit-appearance: none; margin: 0;}' +
  117. '#mapPreview {width: 100%; margin-top: 10px;}' +
  118. '#mapSelector_group5 {width: 100%;}' +
  119. '#switchServer {padding: 0 20px;}' +
  120. '#switchServerSelect {width: 100%;}' +
  121. '#mapTitle {text-align: center; font-weight: bold; font-size: 120%;}' +
  122. 'body.groupLeader #mapTitle {display: none;}' +
  123. '#settingsOverview select:disabled {background: transparent; border: none; color: white; cursor: text; font: inherit; -webkit-appearance: initial;}' +
  124. '#settingsOverview input[type=number]:disabled {color: white; background: transparent; border: none; cursor: text;}' +
  125. '#settingsOverview input[type=checkbox]:not([gamemode=powerups]):disabled {-webkit-appearance: none; margin: 0; font: inherit;}' +
  126. '#settingsOverview input[type=checkbox]:not([gamemode=powerups]):disabled::after {display: inline; content: "no"; color: white; cursor: text;}' +
  127. '#settingsOverview input[type=checkbox]:not([gamemode=powerups]):disabled:checked::after {content: "yes";}' +
  128. '#settingsOverview label {cursor: text;}' +
  129. '#chat hr {border: 1px solid rgba(255,255,255,0.20); border-width: 1px 0 0 0;}' +
  130. '#rndTeamsButtons, #swapTeamsButtons {position: absolute; top: -163px; padding: 2px 4px; font-size: 70%; min-width: 25% !important; margin: 0 !important;}' +
  131. '#rndTeamsButtons {left: 10%;}' +
  132. '#swapTeamsButtons {right: 10%;}' +
  133. 'input[gamemode=powerups] {-webkit-appearance: none; width: 40px; height: 40px; background-image: url(../images/tiles.png); background-position-x: calc(-12 * 40px);}' +
  134. 'input[gamemode=powerups]:not(:checked) {opacity: 0.3;}' +
  135. 'input[gamemode=powerups]:focus {outline: 0;}' +
  136. 'input#GM_grip {background-position-y: calc(-4 * 40px);}' +
  137. 'input#GM_tagpro {background-position-y: calc(-5 * 40px);}' +
  138. 'input#GM_livingBomb {background-position-y: calc(-6 * 40px);}' +
  139. 'input#GM_speed {background-position-y: calc(-7 * 40px);}' +
  140. 'label[for=GM_grip], label[for=GM_tagpro], label[for=GM_livingBomb], label[for=GM_speed] {display: none;}' +
  141. 'li[gamemode=powerups] div:not(:first-child) {display: inline;}' +
  142. '#settingsOverview ul select:not(#newRule):not(#newRuleValue):not(:disabled) {background-color: transparent; color: white; border: none; -webkit-appearance: none; font: inherit; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAA+SURBVChTlYtBDgAwCML8/6fZyQWVYUbSA1UCwBdSOqR0SOngsmUM3Oj+8HPSU+6lEJlxG2JDSoeUDinfIA7S+cJM75pd5gAAAABJRU5ErkJggg==); background-repeat: no-repeat; background-position: right; padding-right: 15px;}' +
  143. '#settingsOverview ul select:not(#newRule):not(#newRuleValue):not(:disabled) option {color: black;}' +
  144. '#settingsOverview ul select:not(#newRule):not(#newRuleValue):not(:disabled):focus {outline: 0}'
  145. );
  146.  
  147. var format = {
  148. default: function(x) {return x;},
  149. minutes: function(x) {return x + ' minutes';},
  150. caps: function(x) {return x == 0 ? 'No Limit' : x;},
  151. percentage: function(x) {return x * 100 + '%';},
  152. milliseconds: function(x) {return x / 1000 + ' seconds';},
  153. potato: function(x) {return x == 0 ? 'Disabled' : x / 1000 + ' seconds';},
  154. boolean: function(x) {return x ? 'Yes' : 'No';}
  155. };
  156.  
  157. var defaults = {
  158. time: {
  159. label: 'Time Limit',
  160. default: '12',
  161. format: format.minutes,
  162. optgroup: 'Basic'
  163. },
  164. caps: {
  165. label: 'Cap Limit',
  166. default: '3',
  167. format: format.caps,
  168. optgroup: 'Basic'
  169. },
  170. accel: {
  171. label: 'Acceleration',
  172. default: '1',
  173. format: format.percentage,
  174. optgroup: 'Physics'
  175. },
  176. topspeed: {
  177. label: 'Top Speed',
  178. default: '1',
  179. format: format.percentage,
  180. optgroup: 'Physics'
  181. },
  182. bounce: {
  183. label: 'Bounciness',
  184. default: '1',
  185. format: format.percentage,
  186. optgroup: 'Physics'
  187. },
  188. playerRespawnTime: {
  189. label: 'Players',
  190. default: '3000',
  191. format: format.milliseconds,
  192. optgroup: 'Respawns'
  193. },
  194. speedPadRespawnTime: {
  195. label: 'Boosts',
  196. default: '10000',
  197. format: format.milliseconds,
  198. optgroup: 'Respawns'
  199. },
  200. dynamiteRespawnTime: {
  201. label: 'Bombs',
  202. default: '30000',
  203. format: format.milliseconds,
  204. optgroup: 'Respawns'
  205. },
  206. buffRespawnTime: {
  207. label: 'Powerups',
  208. default: '60000',
  209. format: format.milliseconds,
  210. optgroup: 'Respawns'
  211. },
  212. buffDelay: { // golden nub rule
  213. label: 'Delay Powerups',
  214. default: false,
  215. format: format.boolean,
  216. optgroup: 'Miscellaneous'
  217. },
  218. potatoTime: {
  219. label: 'Potato',
  220. default: '0',
  221. format: format.potato,
  222. optgroup: 'Miscellaneous'
  223. }
  224. };
  225.  
  226. var gameModes = (tagpro.serverHost.indexOf('newcompte') >= 0) ? {
  227. gravity: {
  228. label: 'Gravity',
  229. settings: {
  230. juggle: {
  231. label: 'Juggle',
  232. default: true,
  233. format: format.boolean
  234. },
  235. maxJumpCount: {
  236. label: 'Jump Amount',
  237. default: 2,
  238. format: format.default
  239. },
  240. jumpKey: {
  241. label: 'Jump Key',
  242. default: 'up',
  243. format: format.default
  244. },
  245. jumpY: {
  246. label: 'Jump Strength',
  247. default: -0.5,
  248. format: format.default
  249. },
  250. gravityY: {
  251. label: 'Gravity Force',
  252. default: 4.9,
  253. format: format.default
  254. }
  255. }
  256. },
  257. shapes: {
  258. label: 'Weird Shapes',
  259. settings: {
  260. shape: {
  261. label: 'Shape',
  262. default: 'square',
  263. format: format.default
  264. }
  265. }
  266. },
  267. ffa: {
  268. label: 'Free for All',
  269. settings: {
  270. singleTeam: {
  271. label: 'Single Team',
  272. default: true,
  273. format: format.boolean
  274. },
  275. deathMatchMode: {
  276. label: 'Deathmatch',
  277. default: true,
  278. format: format.boolean
  279. },
  280. neutralToggle: {
  281. label: 'Green Buttons',
  282. default: true,
  283. format: format.boolean
  284. }
  285. }
  286. },
  287. gameSettings: {
  288. label: 'Moar Game Settings', //nc pls
  289. settings: {
  290. speedpadModifier: {
  291. label: 'Boost Power',
  292. default: '1',
  293. format: format.percentage
  294. },
  295. powerupExpiration: {
  296. label: 'Pup Duration',
  297. default: '20000',
  298. format: format.milliseconds
  299. },
  300. afterPickupInvulnerability: {
  301. label: 'FC Invulnerability',
  302. default: '250',
  303. format: format.milliseconds
  304. }
  305. }
  306. },
  307. powerups: {
  308. label: 'Select Powerups',
  309. settings: {
  310. grip: {
  311. label: 'Juke Juice',
  312. default: true,
  313. format: format.boolean
  314. },
  315. tagpro: {
  316. label: 'TagPro',
  317. default: true,
  318. format: format.boolean
  319. },
  320. livingBomb: {
  321. label: 'Rolling Bomb',
  322. default: true,
  323. format: format.boolean
  324. },
  325. speed: {
  326. label: 'Top Speed',
  327. default: false,
  328. format: format.boolean
  329. }
  330. }
  331. },
  332. modifyExplosions: {
  333. label: 'Modify Explosions',
  334. settings: {
  335. redForce: {
  336. label: 'Red Pop Force',
  337. default: '1',
  338. format: format.default
  339. },
  340. redDistance: {
  341. label: 'Red Pop Range',
  342. default: '3.5',
  343. format: format.default
  344. },
  345. blueForce: {
  346. label: 'Blue Pop Force',
  347. default: '1',
  348. format: format.default
  349. },
  350. blueDistance: {
  351. label: 'Blue Pop Range',
  352. default: '3.5',
  353. format: format.default
  354. },
  355. rollingForce: {
  356. label: 'Rolling Bomb Force',
  357. default: 3,
  358. format: format.default
  359. },
  360. rollingDistance: {
  361. label: 'Rolling Bomb Range',
  362. default: 5,
  363. format: format.default
  364. },
  365. bombForce: {
  366. label: 'Bomb Force',
  367. default: 5,
  368. format: format.default
  369. },
  370. bombDistance: {
  371. label: 'Bomb Range',
  372. default: 7,
  373. format: format.default
  374. },
  375. portalForce: {
  376. label: 'Portal Boost Force',
  377. default: 1,
  378. format: format.default
  379. },
  380. portalDistance: {
  381. label: 'Portal Boost Range',
  382. default: 4,
  383. format: format.default
  384. }
  385. }
  386. }
  387. } : {};
  388.  
  389. $('#settings').after($('<section>').attr('id', 'settingsOverview'));
  390. $('#settingsOverview').addClass('privateGame').append($('<h2>').text('Game Settings')).append($('<ul>'));
  391. $('#settings h2 span').appendTo('#settingsOverview h2').addClass('leader');
  392. $('#rndTeamsButtons').text('Random');
  393. $('#swapTeamsButtons').text('Swap');
  394. $('#settings form div:last-child').css({position: 'absolute', right: '120px', top: '40px'}).addClass('privateGame').appendTo('body');
  395. updateSettings();
  396.  
  397. function updateSettings() {
  398. function getValue(el) {
  399. return $(el).prop('tagName') === 'INPUT' && $(el).attr('type') === 'checkbox' ? $(el).prop('checked') : $(el).attr('type') === 'number' || $(el).attr('jsType') === 'number' ? parseFloat($(el).val()) : $(el).val();
  400. }
  401.  
  402. $('#settingsOverview ul > *').remove();
  403.  
  404. var count = 0;
  405. var not = [];
  406.  
  407. // Add rule items
  408. for(var key in defaults) {
  409. var val = getValue($('#settings .setting[name=' + key + ']')),
  410. setting = defaults[key];
  411. if(val != setting.default) {
  412. $('<li>')
  413. .attr('setting', key)
  414. .text(setting.label + (key === 'buffDelay' ? '' : ': '))// + setting.format(val)))
  415. .append(key === 'buffDelay' ? '' :
  416. $('#settings .setting[name=' + key + ']').clone().change((function(key) {
  417. return function() {
  418. tagpro.group.socket.emit('setting', {name: key, value: $(this).val()});
  419. };
  420. })(key)).val(val)
  421. )
  422. .append(
  423. $('<a>') // remove button
  424. .attr('href', '#')
  425. .addClass('leader')
  426. .addClass('changeSettingButton')
  427. .text('remove')
  428. .click(
  429. function(key, val) {
  430. return function() {
  431. tagpro.group.socket.emit('setting', {
  432. name: key,
  433. value: val
  434. });
  435. };
  436. }(key, setting.default)
  437. )
  438. ).appendTo('#settingsOverview ul');
  439. ++count;
  440. not.push(key);
  441. }
  442. }
  443.  
  444. if(count === 0)
  445. $('<li>').text('Default Settings').appendTo('#settingsOverview ul');
  446.  
  447. // GameModes
  448.  
  449. var any = false;
  450.  
  451. for(var key in gameModes) {
  452. var gm = gameModes[key],
  453. enabled = $('.gameModeEnable[gamemode=' + key + ']').prop('checked');
  454.  
  455. if(enabled) {
  456. if(!any)
  457. $('#settingsOverview ul').append($('<hr>'));
  458. any = true;
  459. not.push(key);
  460. var remove = $('<a>').attr('href', '#').text('remove').addClass('changeSettingButton').addClass('leader'),
  461. div = $('<li>').attr('gamemode', key).append($('<div>').text(gm.label).append(remove));
  462. $('#settingsOverview ul').append(div);
  463. remove.click((function(key) {return function() {
  464. tagpro.group.socket.emit('setting', {
  465. gameMode: key,
  466. value: false,
  467. name: ''
  468. });
  469. };})(key));
  470. for(var child in gm.settings) {
  471. var setting = gm.settings[child],
  472. childDiv = $('<div>').css('margin-left', '10px');
  473. var input = $('[name=' + child + ']').clone().attr('name','').attr('id', 'GM_' + child).change((function(key, child){return function() {
  474. tagpro.group.socket.emit('setting', {
  475. gameMode: key,
  476. name: child,
  477. value: getValue($(this))
  478. });
  479. };})(key, child));
  480. childDiv.append($('<label>').attr('for', 'GM_' + child).text(setting.label + ': ')).append(input).appendTo(div);
  481. }
  482. }
  483. }
  484.  
  485. $('<hr>').addClass('leader').appendTo('#settingsOverview ul');
  486.  
  487. // New Rule
  488. var newRule = $('<select>')
  489. .attr('id', 'newRule')
  490. .append(
  491. $('<option>')
  492. .attr('value', '')
  493. .text('Add rule...')
  494. )
  495. .css('max-width', '120px');
  496.  
  497. for(key in defaults)
  498. if(not.indexOf(key) < 0) {
  499. var optgroup = defaults[key].optgroup;
  500. if(newRule.find('optgroup[label="' + optgroup + '"]').length === 0)
  501. newRule.append($('<optgroup>').attr('label', optgroup));
  502. newRule.find('optgroup[label="' + optgroup + '"]').append(
  503. $('<option>')
  504. .attr('value', key)
  505. .text(defaults[key].label)
  506. );
  507. }
  508.  
  509. if(tagpro.serverHost.indexOf('newcompte') >= 0)
  510. newRule.append($('<optgroup>').attr('label', 'Special Settings'));
  511.  
  512. for(var key in gameModes)
  513. if(not.indexOf(key) < 0)
  514. newRule.find('optgroup[label="Special Settings"]').append(
  515. $('<option>')
  516. .attr('value', 'GM_' + key)
  517. .text(gameModes[key].label)
  518. );
  519.  
  520. newRule.change(function() {
  521. $('#newRuleValue').remove();
  522.  
  523. var key = $(this).val();
  524. if(key.startsWith('GM_'))
  525. tagpro.group.socket.emit('setting', {
  526. gameMode: key.substring(3),
  527. name: '',
  528. value: true
  529. });
  530. else if(key !== "") {
  531. if(key === 'buffDelay')
  532. tagpro.group.socket.emit('setting', {name: key, value: true});
  533. else newRule.after(
  534. $('#settings .setting[name=' + key + ']').clone()
  535. .attr('id', 'newRuleValue')
  536. .removeClass('setting')
  537. .attr('name', '')
  538. .css('margin-left', '20px')
  539. .change(function() {
  540. tagpro.group.socket.emit('setting', {
  541. name: newRule.val(),
  542. value: getValue($('#newRuleValue'))
  543. });
  544. })
  545. );
  546. }
  547. });
  548. $('<li>').append(newRule).addClass('leader').appendTo('#settingsOverview ul');
  549.  
  550. if(!$('body').hasClass('groupLeader'))
  551. $('#settingsOverview .leader').addClass('hide');
  552. }
  553.  
  554. $('header').append('Play with Friends');
  555.  
  556. unread = 0;
  557. active = true;
  558.  
  559. $(window).focus(function() {active = true; document.title = 'TagPro Group'; unread = 0;});
  560. $(window).blur(function() {active = false;});
  561.  
  562. tagpro.group.socket._callbacks.chat[0] = function(e) {
  563. var msg = $('<div>');
  564.  
  565. // parse URLs
  566. e.message = e.message.replace(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, function(url) {
  567. return '<a target="_blank" href="' + url + '">' + url + '</a>';
  568. });
  569.  
  570. if(e.from) {
  571. var leader = false, you = false, color = "#AAAAAA";
  572. $('.teams li').each(function() {
  573. var p = $(this).clone();
  574. p.find('span').remove();
  575. if(p.text() == e.from) {
  576. leader = $(this).hasClass('leader');
  577. you = $(this).hasClass('you');
  578. switch($(this).parent().parent().attr('id')) {
  579. case 'redTeam':
  580. color = '#FF6666';
  581. break;
  582. case 'blueTeam':
  583. color = '#6666FF';
  584. }
  585. }
  586. });
  587. if(e.message.startsWith('[#] ') && leader)
  588. e.message = e.message.substring(3);
  589. else
  590. msg.append($('<span>').addClass('playerName').addClass(leader ? '_leader' : you ? '_you' : '').css('color', color).text(e.from + ': '));
  591. }
  592. msg.append(e.message).appendTo('#chat');
  593. $('#chat').scrollTop($('#chat').get(0).scrollHeight);
  594.  
  595. var history = GM_getValue('history_' + document.location.pathname.split('/')[2]) || [];
  596. history.push('<div>' + msg.html() + '</div>');
  597. GM_setValue('history_' + document.location.pathname.split('/')[2], history);
  598.  
  599. if(!active)
  600. document.title = '(' + (++unread) + ') TagPro Group';
  601. };
  602.  
  603. leader = '';
  604.  
  605. tagpro.group.socket.on('member', function(e) {
  606. if(e.leader) {
  607. if(leader !== e.id && leader !== "")
  608. $('<div>').text("'" + e.name + "' was set as group leader.").appendTo('#chat');
  609. leader = e.id;
  610. }
  611. });
  612.  
  613. tagpro.group.socket.on('setting', updateSettings);
  614.  
  615. if(!($('.teams li').length >= 4 || tagpro.serverHost.indexOf('maptest') >= 0))
  616. $('.privateGame').addClass('hide');
  617.  
  618. function playerButtons() {
  619. $('.teams li').each(function() {
  620. var c = $(this).children().clone().addClass('playerStatus');
  621. $(this).children().remove();
  622. $(this).html('<div>'+$(this).data('model').name+'</div>').prepend(c);
  623. }).append($('<span>').addClass('ban').addClass('playerAction').attr('title', 'Ban from Group').click(function() {
  624. tagpro.group.socket.emit('kick', $(this).parent().data('model').id);
  625. })).append($('<span>').addClass('makeLeader').addClass('playerAction').attr('title', 'Make Leader').click(function() {
  626. tagpro.group.socket.emit('leader', $(this).parent().data('model').id);
  627. }));
  628. }
  629.  
  630. ['port', 'you', 'member', 'private', 'removed'].forEach(function(x) {
  631. tagpro.group.socket.on(x, playerButtons);
  632. });
  633.  
  634. playerButtons();
  635.  
  636. // Maps
  637.  
  638. categories = [];
  639. maps = {};
  640. $('#settings .setting[name=map] > *').each(function(x) {
  641. if($(this).prop('tagName') === 'OPTGROUP') {
  642. categories.push(['group' + x, $(this).attr('label'), []]);
  643. $(this).find('option').each(function() {
  644. categories[categories.length - 1][2].push([$(this).attr('value'), $(this).text()]);
  645. maps[$(this).attr('value')] = {
  646. category: categories.length - 1
  647. };
  648. });
  649. } else {
  650. if($(this).attr('value') === '[object Object]') {
  651. categories.push(['jj1', 'maps.jukejuice.com']);
  652. categories.push(['jj2', 'unfortunate-maps.jukejuice.com']);
  653. } else
  654. categories.push(['random', 'Random Map']);
  655. }
  656. });
  657.  
  658. mapIds = { // positive is unfortunate-maps.jukejuice.com, negative is maps.jukejuice.com. always prefer unfortunate-maps because it has better previews. this was a lot of work so respect it pls
  659. '45': 28,
  660. '00101010': 5660,
  661. 'AngryPig': 5430,
  662. 'Backdoor': 5416,
  663. 'Basketball': -6503,
  664. 'Battledome2': -1879,
  665. 'BomberDOME': -1913,
  666. 'Boosts': -1594,
  667. 'BotBattle': 16050,
  668. 'Bounce': -3318,
  669. 'BuddySystem': 1184,
  670. 'Bulldog': 9201,
  671. 'CFB': 4931,
  672. 'ChaosBall': -3453,
  673. 'Classico': 4995,
  674. 'Cloud': 5433,
  675. 'CommandCenter': 3,
  676. 'Constriction': 4915,
  677. 'DZ4': 11158,
  678. 'DangerZone': 13358,
  679. 'Diamond': 6295,
  680. 'Dodgeball': 763,
  681. 'Draft': 13383,
  682. 'Duel': 4999,
  683. 'EMERALD': 5436,
  684. 'FindTheKey': -2320,
  685. 'Flame': 5057,
  686. 'Foozball': 4934,
  687. 'Frontdoor': 5439,
  688. 'GameMode': -3335,
  689. 'GateKeeper': 2620,
  690. 'GrailOfSpeed': 4916,
  691. 'Hockey': 12334,
  692. 'HolySee': 373,
  693. 'Hornswoggle': 584,
  694. 'Hourglass': 4906,
  695. 'Hub': 9200,
  696. 'Hurricane2': 2730,
  697. 'HyperReactor': 374,
  698. 'Hyperdrive': 4914,
  699. 'IRON': 170,
  700. 'IceRink': -1974,
  701. 'Jagged': 4935,
  702. 'Kite': 5327,
  703. 'Madness': -1789,
  704. 'Micro': 4929,
  705. 'Monarch': 9637,
  706. 'OFM': -3299,
  707. 'Penalties': -3300,
  708. 'Pilot': 690,
  709. 'Platypus': 7666,
  710. 'PushIt': -3302,
  711. 'RedRover': -1851,
  712. 'Renegade': 5481,
  713. 'Rink': 4926,
  714. 'RiskAndReward': 376, //glory hole
  715. 'RocketBalls': 4912,
  716. 'Rugby': 16051,
  717. 'Rush': 12192,
  718. 'SaM': 16052, //sharks and minnows
  719. 'Shine': 4917,
  720. 'Simplicity': 377,
  721. 'Smirk': 4913,
  722. 'SuperDuperStamp': 2731,
  723. 'TRArcTurnSpike': 6742,
  724. 'TRCalmSlopes': 6661,
  725. 'TRMagic8Lanes': 11803,
  726. 'TRPokeBomb': -3541,
  727. 'TRRainbowRoad': 6740,
  728. 'TRSerpentSwerve': 8995,
  729. 'TRSnooTrack': 3041,
  730. 'TRSpaceShuttle': 158,
  731. 'TRSpinoutRaceway': 6664,
  732. 'TRThreeCourseMeal': 702,
  733. 'TRTickTock': 157,
  734. 'TRWonky': 161,
  735. 'TRWormy': 8997,
  736. 'ThinkingWithPortals': 5937,
  737. 'ThunderDome': -1834, //mirrored version but only i could find
  738. 'Transilio': 9015,
  739. 'Ultradrive': 6008,
  740. 'Volt': 4918,
  741. 'WTFdome': -1984,
  742. 'War': -679,
  743. 'WelcomeToMars': -1636,
  744. 'Wombo_Combo': 10135,
  745. 'arena': -1588,
  746. 'battery': 362,
  747. 'bird': 365,
  748. 'blastoff': 366,
  749. 'bomber': 367,
  750. 'boombox': 368,
  751. 'caravan': 6291,
  752. 'centerflag': 4891,
  753. 'clutch': 4892,
  754. 'colors': 370,
  755. 'community1': 4902, //Pokeball
  756. 'elimination1v1multi': -1956,
  757. 'elimination4v4': -1954,
  758. 'evenhorizon2': 6632,
  759. 'fullspeed': 4893,
  760. 'gamepad': 372,
  761. 'lold': 4907,
  762. 'map2-2': 4895, //Figure 8
  763. 'marsballrace': -2303,
  764. 'nfm': -2758,
  765. 'oval': 375,
  766. 'reflex2': 4911,
  767. 'ricochet': 4920,
  768. 'shortcut': 4903,
  769. 'snes': 4938,
  770. 'snipers2': -2121,
  771. 'snipers3': -1623,
  772. 'speedway': 4904,
  773. 'spiders': 4930,
  774. 'star': 378,
  775. 'swoop': 379,
  776. 'teamwork': 4898, //GeoKoala
  777. 'thinking': -2276, //Thinking with neutral flags
  778. 'twister': 4996,
  779. 'vee2': 4921, //Big Vird
  780. 'velocity': 4923,
  781. 'whirlwind': 898,
  782. 'wormy': 1167,
  783. 'yiss 3.2': 4940,
  784. 'Fiend': 14696
  785. };
  786.  
  787. $('#settingsOverview').append($('<section>').addClass('privateGame').attr('id', 'mapSelector').append($('<div>').addClass('leader').append($('<select>').addClass('setting').attr('id', 'mapSelectorCategory'))));
  788.  
  789. categories.forEach(function(x) {
  790. $('#mapSelectorCategory').append($('<option>').attr('value', x[0]).text(x[1]));
  791. var $el;
  792. switch(x[0]) {
  793. case 'random': return;
  794. case 'jj1': case 'jj2': $el = $('<input>').attr('type', 'number').attr('placeholder', 'ID'); break;
  795. default: $el = $('<select>').append($('<option>').attr('value', '__none__').text('')); x[2].forEach(function(y) {
  796. $el.append($('<option>').attr('value', y[0]).text(y[1]));
  797. });
  798. }
  799. $el.attr('id', 'mapSelector_' + x[0]).addClass('setting').addClass('mapSelectorCategory').appendTo('#mapSelector > div').hide();
  800. });
  801.  
  802. $('#mapSelector').append($('<h3>').attr('id', 'mapTitle')).append($('<img>').attr('id', 'mapPreview').fadeOut().on('load', function() {$(this).fadeIn();}));
  803.  
  804. $('#mapSelectorCategory').change(function() {
  805. if($(this).val() === 'random')
  806. tagpro.group.socket.emit('setting', {name: 'map', value: ''});
  807. $('.mapSelectorCategory').hide();
  808. $('#mapSelector_' + $(this).val()).show();
  809. });
  810.  
  811. changeTimeout = 0;
  812.  
  813. function setPreview(url) {
  814. changeTimeout > 0 && clearTimeout(changeTimeout);
  815. changeTimeout = setTimeout(function() {
  816. $('#mapPreview').fadeOut();
  817. setTimeout(function() {
  818. $('#mapPreview').attr('src', url);
  819. }, 250);
  820. }, 750);
  821. }
  822.  
  823. $('select.mapSelectorCategory').change(function() {
  824. if($(this).val() !== '__none__') {
  825. tagpro.group.socket.emit('setting', {name: 'map', value: $(this).val()});
  826. setPreview('http://' + (mapIds[$(this).val()] > 0 ? 'unfortunate-maps' : 'maps') + '.jukejuice.com/static/thumbs/' + Math.abs(mapIds[$(this).val()]) + '.png');
  827. }
  828. });
  829.  
  830. jjSelectTimeout = 0;
  831.  
  832. function updateJJ(id, val) {
  833. tagpro.group.socket.emit('setting', {
  834. name: 'mapId',
  835. value: val
  836. });
  837. tagpro.group.socket.emit('setting', {
  838. name: 'mapSite',
  839. value: id === 'mapSelector_jj2' ? 1 : 0
  840. });
  841. }
  842.  
  843. $('#mapSelector_jj1, #mapSelector_jj2').keyup(function() {
  844. setPreview('http://' + ($(this).attr('id') === 'mapSelector_jj2' ? 'unfortunate-maps' : 'maps') + '.jukejuice.com/static/thumbs/' + $(this).val() + '.png');
  845. jjSelectTimeout > 0 && clearTimeout(jjSelectTimeout);
  846. jjSelectTimeout = setTimeout(updateJJ, 500, $(this).attr('id'), $(this).val());
  847. });
  848.  
  849. tagpro.group.socket.on('setting', function(s) {
  850. if(s.name === 'map') {
  851. var jj = typeof s.value === 'object', map = jj ? {category: 1 + s.value.site} : maps[s.value] || {category: 0}, category = categories[map.category];
  852. $('#mapSelectorCategory').val(category[0]);
  853. $('select.mapSelectorCategory').val('__none__');
  854. $('#mapSelector_jj1, #mapSelector_jj2').val('');
  855. $('.mapSelectorCategory').hide();
  856. $('#mapSelector_' + category[0]).val(jj ? s.value.id : s.value).show();
  857. if(jj || s.value != NaN)
  858. setPreview(jj ? 'http://' + ['maps', 'unfortunate-maps'][s.value.site] + '.jukejuice.com/static/thumbs/' + s.value.id + '.png'
  859. : 'http://' + (mapIds[s.value] > 0 ? 'unfortunate-maps' : 'maps') + '.jukejuice.com/static/thumbs/' + Math.abs(mapIds[s.value]) + '.png');
  860. $('#mapTitle').text(jj ? s.value.name : $('#mapSelector option[value=' + s.value + ']').text() || 'Random Map');
  861. }
  862. });
  863.  
  864. // Chat History
  865.  
  866. var history = GM_getValue('history_' + document.location.pathname.split('/')[2]) || [];
  867.  
  868. if(history.length > 0)
  869. $('#chat').prepend($('<hr>'));
  870.  
  871. $('#chat').prepend(history.join(''));
  872.  
  873. setTimeout(function(){$('#chat').scrollTop($('#chat').get(0).scrollHeight);},500);
  874.  
  875. // Server switcher
  876.  
  877. newGroupForm = $('<form>').attr('method', 'POST').attr('target', '_blank').append($('<input>').attr('name','name')).append($('<input>').attr('type','checkbox').attr('name','public'));
  878.  
  879. $('#actions').append($('<div>').attr('id', 'switchServer').addClass('leader').append($('<select>').attr('id', 'switchServerSelect').append($('<option>').attr('value', '').text('Switch Server...'))));
  880. for(var type in servers) {
  881. var optgroup = $('<optgroup>').attr('label', type);
  882. for(var server in servers[type])if(servers[type][server].url !== tagpro.serverHost) {
  883. var option = $('<option>').attr('value', servers[type][server].url).text(servers[type][server].name).appendTo(optgroup);
  884. ping(servers[type][server], function(x) {
  885. $('option[value="' + x.url + '"]').text(x.name + (x.error ? '' : ' (' + x.players + (x.players === 1 ? ' player' : ' players') + ')'));
  886. });
  887. }
  888. optgroup.appendTo('#switchServerSelect');
  889. }
  890.  
  891. $('#switchServerSelect').change(function() {
  892. var transferredSettings = {};
  893. $('.setting').each(function() {
  894. if(!($('.setting[name=map]').val() !== '[object Object]' && ($(this).attr('name') === 'mapId' || $(this).attr('name') === 'mapSite')))
  895. transferredSettings[$(this).attr('name')] = ($(this).attr('type') === 'checkbox' ? $(this).prop('checked') : $(this).val());
  896. });
  897. console.log('Switching to ' + $(this).val() + ' with settings ' + JSON.stringify(transferredSettings));
  898. GM_setValue('transferredSettings', transferredSettings);
  899. GM_deleteValue('newGroupURL');
  900. newGroupForm.attr('action', 'http://' + $(this).val() + '/groups/create').submit();
  901. tagpro.group.socket.emit('chat', '[#] Creating a new group on ' + $(this).val() + '...');
  902. $(this).val('').prop('disabled', true);
  903. interval = setInterval(function() {
  904. if(GM_getValue('newGroupURL')) {
  905. clearInterval(interval);
  906. $('#switchServerSelect').prop('disabled', false);
  907. tagpro.group.socket.emit('chat', '[#] New group: ' + GM_getValue('newGroupURL'));
  908. }
  909. }, 10);
  910. });
  911.  
  912. if(GM_getValue('transferredSettings')) {
  913. var transferredSettings = GM_getValue('transferredSettings');
  914. GM_deleteValue('transferredSettings');
  915. console.log('Restoring settings ' + JSON.stringify(transferredSettings));
  916. for(var key in transferredSettings)
  917. tagpro.group.socket.emit('setting', {name: key, value: transferredSettings[key]});
  918. GM_setValue('newGroupURL', document.location.href);
  919. }
  920.  
  921. function ping(server, callback) {
  922. $.ajax({
  923. url:'http://'+server.url+'/stats?callback=?',
  924. timeout:1000,
  925. success:function(response) {
  926. server.players = response.players;
  927. server.error = false;
  928. callback(server);
  929. },
  930. error:function() {
  931. server.error = true;
  932. callback(server);
  933. },
  934. dataType:'json'
  935. });
  936. }
Add Comment
Please, Sign In to add comment