TagPro Timers With Previews

A timer script to be used with TagPro. All boosts, bombs, powerups, and player respawns will have a countdown.

  1. // ==UserScript==
  2. // @name TagPro Timers With Previews
  3. // @description A timer script to be used with TagPro. All boosts, bombs, powerups, and player respawns will have a countdown.
  4. // @locale
  5. // @version 0.4.1
  6. // @match *://*.koalabeast.com/*
  7. // @match *://*.jukejuice.com/*
  8. // @match *://*.newcompte.fr/*
  9. // @author Some Ball -1 modified by Niplepotamus
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @license MIT
  13. // @namespace https://greasyfork.org/users/840828
  14. // ==/UserScript==
  15.  
  16. tagpro.ready(function() {
  17. tr = tagpro.renderer;
  18. tr.layers.timers = new PIXI.DisplayObjectContainer();
  19. tr.layers.pupTimes = new PIXI.DisplayObjectContainer();
  20. var timers = [],
  21. redflag, blueflag, spawntime,
  22. pup = false,
  23. pups = [],
  24. powerups = [],
  25. lastTime = [],
  26. me;
  27.  
  28. var enable = GM_getValue('timers',true);
  29.  
  30. $('#optionsName').append('<label style="margin-left: 50px;"><input id="timers" type="checkbox"'+(enable ? ' checked' : '')+'/>Enable Timers</label>');
  31. function enableDisable()
  32. {
  33. if(enable)
  34. {
  35. tr.layers.timers.alpha = 1;
  36. if(!tagpro.spectator && tagpro.players[tagpro.playerId].sprites.timers)
  37. tagpro.players[tagpro.playerId].sprites.timers.alpha = 1;
  38. }
  39. else if(!enable)
  40. {
  41. tr.layers.timers.alpha = 0;
  42. if(!tagpro.spectator && tagpro.players[tagpro.playerId].sprites.timers)
  43. tagpro.players[tagpro.playerId].sprites.timers.alpha = 0;
  44. }
  45. }
  46. $('#timers').change(function() {
  47. enable = $(this).is(':checked');
  48. GM_setValue('timers',enable);
  49. enableDisable();
  50. });
  51.  
  52. tagpro.socket.on('end', function() {
  53. for(var x in timers)
  54. {
  55. for(var y in timers[x])
  56. {
  57. clearInterval(timers[x][y][4])
  58. }
  59. }
  60. for(var i = 0; i < 4; i++)
  61. {
  62. if (powerups[i] && powerups[i][3])
  63. {
  64. clearInterval(powerups[i][3])
  65. }
  66. }
  67. });
  68. tagpro.socket.on('mapupdate', function(data) {
  69. if(!(data instanceof Array)) data = [data];
  70. for(var i = 0; i < data.length; i++)
  71. {
  72. data[i].x = parseInt(data[i].x);
  73. data[i].y = parseInt(data[i].y);
  74. var which = parseFloat(data[i].v);
  75. if(which == 5 || which == 15 || which == 14 || which == 10 || which == 6.1 || which == 6.2 || which == 6.3 || which == 6.4 )
  76. {
  77. if(timers[data[i].x] && timers[data[i].x][data[i].y])
  78. {
  79. tr.layers.timers.removeChild(timers[data[i].x][data[i].y][0]);
  80. clearInterval(timers[data[i].x][data[i].y][4]);
  81. delete timers[data[i].x][data[i].y]
  82. }
  83. }
  84. else
  85. {
  86. switch(which)
  87. {
  88. case 5.1:
  89. createTimer(data[i].x, data[i].y, 10000, 0xFFFF00);
  90. break;
  91. case 14.1:
  92. createTimer(data[i].x, data[i].y, 10000, 0xFF0000);
  93. break;
  94. case 15.1:
  95. createTimer(data[i].x, data[i].y, 10000, 0x0000FF);
  96. break;
  97. case 10.1:
  98. createTimer(data[i].x, data[i].y, 30000, 0x696969);
  99. break;
  100. case 6.12:
  101. case 6.22:
  102. case 6.32:
  103. case 6.42:
  104. createTimer(data[i].x, data[i].y, 60000, 0xFFFFFF);
  105. updatePupTime(data[i].x, data[i].y)
  106. break;
  107. default:
  108. break;
  109. }
  110. }
  111. }
  112. });
  113. tagpro.socket.on('splat', function(data) {
  114. if(tagpro.playerId && !tagpro.spectator)
  115. {
  116. var me = tagpro.players[tagpro.playerId];
  117. if(data.t != me.team && !me.flag && (me.tagpro || me.bomb))
  118. {
  119. var theirflag = data.t == 1 ? redflag : blueflag;
  120. if (theirflag)
  121. {
  122. if(timers[theirflag.x] && timers[theirflag.x][theirflag.y])
  123. {
  124. tr.layers.timers.removeChild(timers[theirflag.x][theirflag.y][0]);
  125. clearInterval(timers[theirflag.x][theirflag.y][4]);
  126. delete timers[theirflag.x][theirflag.y];
  127. }
  128. createTimer(theirflag.x, theirflag.y, spawntime || 3000, 0x00FF00, 1)
  129. }
  130. }
  131. }
  132. });
  133. tagpro.socket.on('spawn', function(data) {
  134. spawntime = parseFloat(data.w);
  135. var locx = parseInt(data.x / 40);
  136. var locy = parseInt(data.y / 40);
  137. if(timers[locx] && timers[locx][locy])
  138. {
  139. tr.layers.timers.removeChild(timers[locx][locy][0]);
  140. clearInterval(timers[locx][locy][4]);
  141. delete timers[locx][locy];
  142. }
  143. createTimer(locx, locy, spawntime || 3000, 0x00FF00, 1);
  144. });
  145. var waitOne = false;
  146. tagpro.socket.on('spectator', function(data) {
  147. waitOne = true;
  148. });
  149.  
  150. tagpro.socket.on('time', function(data) {
  151. if(data.state && data.state == 5) //game going to overtime
  152. {
  153. updateOvertimePupTimes();
  154. }
  155.  
  156. });
  157.  
  158. function drawPups()
  159. {
  160. var me = tagpro.players[tagpro.playerId];
  161. if(!me || !me.sprites || !me.sprites.info)
  162. {
  163. setTimeout(drawPups, 50);
  164. return
  165. }
  166. me.sprites.timers = new PIXI.DisplayObjectContainer();
  167. var list = ['JJ', 'RB', 'TP', 'SP'];
  168. for(var i = 0; i < 4; i++)
  169. {
  170. if(powerups[i] && powerups[i][0])
  171. {
  172. powerups[i][0].alpha = 0;
  173. delete powerups[i][0]
  174. }
  175. powerups[i] = [tr.prettyText(''), list[i]];
  176. me.sprites.timers.addChild(powerups[i][0]);
  177. powerups[i][0].x = 40;
  178. powerups[i][0].y = 5 + i * 10;
  179. powerups[i][0].alpha = 0;
  180. }
  181. me.sprites.info.addChild(me.sprites.timers);
  182. tagpro.socket.on('p',function(data) {
  183. data = data.u || data;
  184. for(var i = 0;i < data.length;i++)
  185. {
  186. if(data[i].id===tagpro.playerId && data[i].bomb === false)
  187. {
  188. powerups[1][0].setStyle({
  189. font: "bold 8pt Arial",
  190. fill: '#ffffff',
  191. stroke: "#000000",
  192. strokeThickness: 3
  193. });
  194. powerups[1][0].alpha = 0;
  195. if (powerups[1][3])
  196. {
  197. clearInterval(powerups[1][3]);
  198. delete powerups[1][3]
  199. }
  200. }
  201. }
  202. });
  203. enableDisable();
  204. }
  205.  
  206. function ifSpec()
  207. {
  208. if (!tagpro.spectator)
  209. {
  210. if (!waitOne)
  211. {
  212. waitOne = true;
  213. setTimeout(ifSpec, 500);
  214. return
  215. }
  216. drawPups();
  217. tagpro.socket.on('sound', function(sound) {
  218. pup = sound.s === 'powerup' ? (new Date()) : false
  219. });
  220. tagpro.socket.on('mapupdate', function(data) {
  221. if(!(data instanceof Array)) data = [data];
  222. for(var i = 0; i < data.length; i++)
  223. {
  224. try
  225. {
  226. if(data[i].v == 6 && (new Date).getTime() - pup <= 10)
  227. {
  228. var me = tagpro.players[tagpro.playerId];
  229. if(!me) break;
  230. data[i].v = parseFloat(data[i].v);
  231. data[i].x = parseInt(data[i].x);
  232. data[i].y = parseInt(data[i].y);
  233. if(!me.sprites.timers)
  234. drawPups();
  235. if(!me.sprites.timers.parent)
  236. me.sprites.info.addChild(me.sprites.timers);
  237. pup = false;
  238. if(pups[data[i].x] && pups[data[i].x][data[i].y])
  239. {
  240. var was = pups[data[i].x][data[i].y],
  241. index = Math.round((was - 6.1) * 10);
  242. if(powerups[index][3])
  243. {
  244. clearInterval(powerups[index][3]);
  245. delete powerups[index][3]
  246. }
  247. powerups[index][0].setStyle({
  248. font: "bold 8pt Arial",
  249. fill: "#ffffff",
  250. stroke: "#000000",
  251. strokeThickness: 3
  252. });
  253. powerups[index][0].setText(powerups[index][1] + ': 20');
  254. powerups[index][0].alpha = 1;
  255. powerups[index][2] = new Date((new Date).getTime() + 20000);
  256. powerups[index][3] = setInterval(updateSelf, 500, index);
  257. }
  258. }
  259. else if(data[i].v > 6 && data[i].v <= 6.4)
  260. {
  261. if(!pups[data[i].x]) pups[data[i].x] = [];
  262. pups[data[i].x][data[i].y] = data[i].v;
  263. }
  264. }
  265. catch(e)
  266. {
  267. console.log("Error: "+e);
  268. }
  269. }
  270. });
  271.  
  272. function updateSelf(index)
  273. {
  274. var me = tagpro.players[tagpro.playerId];
  275. if(!me.sprites.timers)
  276. drawPups();
  277. if(!me.sprites.timers.parent)
  278. me.sprites.info.addChild(me.sprites.timers);
  279. var timeleft = powerups[index][2] - (new Date).getTime();
  280. if(timeleft <= 0)
  281. {
  282. powerups[index][0].setStyle({
  283. font: "bold 8pt Arial",
  284. fill: '#ffffff',
  285. stroke: "#000000",
  286. strokeThickness: 3
  287. });
  288. powerups[index][0].alpha = 0;
  289. clearInterval(powerups[index][3]);
  290. delete powerups[index][3];
  291. return;
  292. }
  293. var color = '#ffffff';
  294. if(timeleft <= 10000)
  295. {
  296. color = (255 * (timeleft / 10000) + 0x100).toString(16).substring(1, 3);
  297. color = '#ff' + color + '00'
  298. }
  299. else if(timeleft <= 15000)
  300. {
  301. color = '#ffff' + (255 * ((timeleft - 10000) / 10000) + 0x100).toString(16).substring(1, 3)
  302. }
  303. powerups[index][0].setStyle({
  304. font: "bold 8pt Arial",
  305. fill: color,
  306. stroke: "#000000",
  307. strokeThickness: 3
  308. });
  309. powerups[index][0].setText(powerups[index][1] + ': ' + (Math.ceil(timeleft / 1000)));
  310. }
  311. }
  312. }
  313. ifSpec();
  314.  
  315. function updateItems(x, y)
  316. {
  317. if(tr.gameContainer && !tr.layers.timers.parent)
  318. tr.gameContainer.addChildAt(tr.layers.timers, 2);
  319. if(tr.gameContainer && tr.gameContainer.getChildAt(2) != tr.layers.timers)
  320. tr.gameContainer.setChildIndex(tr.layers.timers, 2);
  321. if(!timers[x][y]) return //i don't know why this happens sometimes
  322. var curr = timers[x][y][0],
  323. end = timers[x][y][1],
  324. length = timers[x][y][2],
  325. color = timers[x][y][3],
  326. isSpawn = timers[x][y][5],
  327. time = curr.getChildAt(0),
  328. timeleft = end - (new Date).getTime(),
  329. radius = 15;
  330. if(timeleft <= 0)
  331. {
  332. tr.layers.timers.removeChild(timers[x][y][0]);
  333. clearInterval(timers[x][y][4]);
  334. delete timers[x][y];
  335. return;
  336. }
  337. time.setText(Math.ceil(timeleft / 1000))
  338. }
  339.  
  340. function onScreen(x, y)
  341. {
  342. var me = tagpro.players[tagpro.playerId];
  343. if(!me) return false;
  344. return tagpro.spectator ? true : (Math.abs(me.x / 40 - x) < 16.25 && Math.abs(me.y / 40 - y) < 10.25)
  345. }
  346.  
  347. function createTimer(x, y, timeout, color, force)
  348. {
  349. if (tr.gameContainer && !tr.layers.timers.parent)
  350. tr.gameContainer.addChildAt(tr.layers.timers, 2);
  351. if(tr.gameContainer && tr.gameContainer.getChildAt(2) != tr.layers.timers)
  352. tr.gameContainer.setChildIndex(tr.layers.timers, 2);
  353. if(!(force || onScreen(x,y)))
  354. return;
  355. var radius = 15,
  356. timer = new PIXI.DisplayObjectContainer(),
  357. time = new PIXI.Text((timeout / 1000).toString(), {
  358. font: '17.5pt Arial',
  359. fill: ((force || onScreen(x, y)) ? 'black' : 'brown'),
  360. stroke: 'white',
  361. strokeThickness: 3,
  362. });
  363. time.x = time.y = 20;
  364. time.anchor.x = time.anchor.y = .5;
  365. time.alpha = .9;
  366. timer.addChild(time);
  367. timer.x = Math.round(x * 40);
  368. timer.y = Math.round(y * 40);
  369. tr.layers.timers.addChild(timer);
  370. if(!timers[x]) timers[x] = [];
  371. timers[x][y] = [timer, new Date((new Date).getTime() + timeout), timeout, color, setInterval(updateItems, 500 - (force ? 250 : 0), x, y), force || 0];
  372. }
  373.  
  374. function getSecond()
  375. {
  376.  
  377. const date = new Date();
  378. var time = date.getTime();
  379. if(tagpro.state == 1) //game is in active state
  380. {
  381. var timeLeft = (tagpro.gameEndsAt - time)/1000;
  382. var second = 0;
  383. second = Math.floor(timeLeft % 60);
  384. return second;
  385. }
  386. else if(tagpro.state == 5)//game is in overtime state
  387. {
  388. var timeSinceOT = (time - tagpro.overtimeStartedAt )/1000;
  389. return Math.floor(timeSinceOT % 60);
  390. }
  391. return 0;
  392. }
  393.  
  394. function updatePupTime(x, y)
  395. {
  396. if(!onScreen(x,y))
  397. {
  398. return;
  399. }
  400. var second = getSecond();
  401. if (tr.gameContainer && !tr.layers.pupTimes.parent)
  402. tr.gameContainer.addChildAt(tr.layers.pupTimes, 3);
  403. if(tr.gameContainer && tr.gameContainer.getChildAt(3) != tr.layers.pupTimes)
  404. tr.gameContainer.setChildIndex(tr.layers.pupTimes, 3);
  405. if(lastTime[x] && lastTime[x][y])
  406. {
  407. tr.layers.pupTimes.removeChild(lastTime[x][y]);
  408. }
  409.  
  410. var timer = new PIXI.DisplayObjectContainer(),
  411. time = new PIXI.Text((second).toString(), {
  412. font: '11pt Arial',
  413. fill: 'black',
  414. stroke: 'blue',
  415. strokeThickness: 0.5,
  416. });
  417. time.x = time.y = 35;
  418. time.anchor.x = time.anchor.y = .5;
  419. time.alpha = .9;
  420. timer.addChild(time);
  421. timer.x = Math.round(x * 40);
  422. timer.y = Math.round(y * 40);
  423. tr.layers.pupTimes.addChild(timer);
  424. if(!lastTime[x]) lastTime[x] = [];
  425. lastTime[x][y] = timer;
  426. }
  427.  
  428. function updateOvertimePupTimes()
  429. {
  430. for(var x = 0; x < lastTime.length; x++)
  431. {
  432. if(!lastTime[x]) continue;
  433. for(var y = 0; y <lastTime[x].length; y++)
  434. {
  435. if(!lastTime[x][y]) continue;
  436. var time = lastTime[x][y].getChildAt(0);
  437. var newTime = (60 - parseInt(time.text)) % 60;
  438. time.setText(Math.floor(newTime))
  439. }
  440. }
  441. }
  442.  
  443. function findFlagsAndPups()
  444. {
  445. if(!tagpro.map)
  446. {
  447. setTimeout(findFlagsAndPups, 50);
  448. return
  449. }
  450. for(var i = 0; i < tagpro.map.length; i++)
  451. {
  452. var flags = [3, 19, 4, 20],
  453. powerups = [6.1, 6.2, 6.3, 6.4];
  454. for(var j = 0; j < flags.length; j++)
  455. {
  456. var found = tagpro.map[i].indexOf(flags[j]);
  457. if(found > -1)
  458. {
  459. if (flags[j] == 3 || flags[j] == 19) {
  460. redflag = {
  461. x: i,
  462. y: found
  463. }
  464. } else {
  465. blueflag = {
  466. x: i,
  467. y: found
  468. }
  469. }
  470. }
  471. found = tagpro.map[i].indexOf(powerups[j]);
  472. while(found > -1)
  473. {
  474. if (!pups[i]) pups[i] = [];
  475. pups[i][found] = powerups[j];
  476. found = tagpro.map[i].indexOf(powerups[j], found + 1)
  477. }
  478. }
  479. }
  480. }
  481. findFlagsAndPups();
  482. });