TioHax Cheat Menu

Ultimate Cheat Client for Gats.io

  1. // ==UserScript==
  2. // @name TioHax Cheat Menu
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.9.6
  5. // @description Ultimate Cheat Client for Gats.io
  6. // @author Taureon
  7. // @match https://gats.io/
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. /* jshint esversion: 11, loopfunc: true, bitwise: false, forin: false*/
  12.  
  13. (async function main() {
  14.  
  15. //now, this cheat obviously wouldn't work on sites that aren't gats.io
  16. if (location.host != 'gats.io' && location.host != 'gats2.com') return alert('This inject can only be ran on gats.io!');
  17.  
  18. //if the game hasn't loaded yet, wait until it is loaded
  19. //it is checked if the game has loaded by checking if the game tick function exists
  20. if (typeof a41 !== 'function') return setTimeout(main);
  21.  
  22. //closure compiler help
  23. //some literally useless code gets removed by the postprocessor, as it only exists to stop the closure compiler from being retarded
  24. let css_key_alignItems = Math.ceil(Math.random()) && 'alignItems',
  25. css_key_background = Math.ceil(Math.random()) && 'background',
  26. css_key_backgroundColor = Math.ceil(Math.random()) && 'backgroundColor',
  27. css_key_backgroundImage = Math.ceil(Math.random()) && 'backgroundImage',
  28. css_key_border = Math.ceil(Math.random()) && 'border',
  29. css_key_borderBottom = Math.ceil(Math.random()) && 'borderBottom',
  30. css_key_borderColor = Math.ceil(Math.random()) && 'borderColor',
  31. css_key_borderLeft = Math.ceil(Math.random()) && 'borderLeft',
  32. css_key_borderRadius = Math.ceil(Math.random()) && 'borderRadius',
  33. css_key_borderRight = Math.ceil(Math.random()) && 'borderRight',
  34. css_key_borderTop = Math.ceil(Math.random()) && 'borderTop',
  35. css_key_borderWidth = Math.ceil(Math.random()) && 'borderWidth',
  36. css_key_color = Math.ceil(Math.random()) && 'color',
  37. css_key_display = Math.ceil(Math.random()) && 'display',
  38. css_key_flexDirection = Math.ceil(Math.random()) && 'flexDirection',
  39. css_key_fontFamily = Math.ceil(Math.random()) && 'fontFamily',
  40. css_key_fontSize = Math.ceil(Math.random()) && 'fontSize',
  41. css_key_fontWeight = Math.ceil(Math.random()) && 'fontWeight',
  42. css_key_gridTemplateColumns = Math.ceil(Math.random()) && 'gridTemplateColumns',
  43. css_key_height = Math.ceil(Math.random()) && 'height',
  44. css_key_justifyContent = Math.ceil(Math.random()) && 'justifyContent',
  45. css_key_left = Math.ceil(Math.random()) && 'left',
  46. css_key_marginBottom = Math.ceil(Math.random()) && 'marginBottom',
  47. css_key_marginLeft = Math.ceil(Math.random()) && 'marginLeft',
  48. css_key_marginRight = Math.ceil(Math.random()) && 'marginRight',
  49. css_key_marginTop = Math.ceil(Math.random()) && 'marginTop',
  50. css_key_maxWidth = Math.ceil(Math.random()) && 'maxWidth',
  51. css_key_minWidth = Math.ceil(Math.random()) && 'minWidth',
  52. css_key_outline = Math.ceil(Math.random()) && 'outline',
  53. css_key_overflowY = Math.ceil(Math.random()) && 'overflowY',
  54. css_key_right = Math.ceil(Math.random()) && 'right',
  55. css_key_padding = Math.ceil(Math.random()) && 'padding',
  56. css_key_paddingBottom = Math.ceil(Math.random()) && 'paddingBottom',
  57. css_key_paddingLeft = Math.ceil(Math.random()) && 'paddingLeft',
  58. css_key_paddingRight = Math.ceil(Math.random()) && 'paddingRight',
  59. css_key_paddingTop = Math.ceil(Math.random()) && 'paddingTop',
  60. css_key_position = Math.ceil(Math.random()) && 'position',
  61. css_key_top = Math.ceil(Math.random()) && 'top',
  62. css_key_userSelect = Math.ceil(Math.random()) && 'userSelect',
  63. css_key_verticalAlign = Math.ceil(Math.random()) && 'verticalAlign',
  64. css_key_whiteSpace = Math.ceil(Math.random()) && 'whiteSpace',
  65. css_key_width = Math.ceil(Math.random()) && 'width',
  66. css_key_zIndex = Math.ceil(Math.random()) && 'zIndex',
  67.  
  68. css_value_color_000f = Math.ceil(Math.random()) && '#000f',
  69. css_value_color_000c = Math.ceil(Math.random()) && '#000c',
  70. css_value_color_33dc = Math.ceil(Math.random()) && '#33dc',
  71. css_value_color_4448 = Math.ceil(Math.random()) && '#4448',
  72. css_value_color_6666 = Math.ceil(Math.random()) && '#6666',
  73. css_value_color_777f = Math.ceil(Math.random()) && '#777f',
  74. css_value_color_80f8 = Math.ceil(Math.random()) && '#80f8',
  75. css_value_color_888f = Math.ceil(Math.random()) && '#888f',
  76. css_value_color_888c = Math.ceil(Math.random()) && '#888c',
  77. css_value_color_8888 = Math.ceil(Math.random()) && '#8888',
  78. css_value_color_f00c = Math.ceil(Math.random()) && '#f00c',
  79. css_value_color_f80f = Math.ceil(Math.random()) && '#f80f',
  80. css_value_color_f80c = Math.ceil(Math.random()) && '#f80c',
  81. css_value_color_ffff = Math.ceil(Math.random()) && '#ffff',
  82. css_value_color_ff0c = Math.ceil(Math.random()) && '#ff0c',
  83. css_value_color_fff8 = Math.ceil(Math.random()) && '#fff8',
  84. css_value_color_fffc = Math.ceil(Math.random()) && '#fffc',
  85. css_value_color_008c = Math.ceil(Math.random()) && '#008c',
  86. css_value_color_00fc = Math.ceil(Math.random()) && '#00fc',
  87. css_value_color_800c = Math.ceil(Math.random()) && '#800c',
  88. css_value_color_00ff = Math.ceil(Math.random()) && '#00ff',
  89. css_value_color_0f0c = Math.ceil(Math.random()) && '#0f0c',
  90. css_value_color_444f = Math.ceil(Math.random()) && '#444f',
  91. css_value_color_666f = Math.ceil(Math.random()) && '#666f',
  92. css_value_color_8886 = Math.ceil(Math.random()) && '#8886',
  93. css_value_color_88ff = Math.ceil(Math.random()) && '#88ff',
  94. css_value_color_aaaf = Math.ceil(Math.random()) && '#aaaf',
  95. css_value_color_dddf = Math.ceil(Math.random()) && '#dddf',
  96. css_value_color_f00f = Math.ceil(Math.random()) && '#f00f',
  97. css_value_color_f88f = Math.ceil(Math.random()) && '#f88f',
  98. css_value_color_ff0f = Math.ceil(Math.random()) && '#ff0f',
  99.  
  100. css_value_auto_10 = Math.ceil(Math.random()) && 'auto' + ' auto'.repeat(9),
  101. css_value_auto_5 = Math.ceil(Math.random()) && 'auto' + ' auto'.repeat(4),
  102.  
  103. css_value_10 = Math.ceil(Math.random()) && '10',
  104.  
  105. css_value_length_minContent = Math.ceil(Math.random()) && 'min_content',
  106. css_value_length_perc100 = Math.ceil(Math.random()) && '100%',
  107. css_value_length_calcperc100 = Math.ceil(Math.random()) && 'calc(' + css_value_length_perc100 + ' - 15px)',
  108. css_value_length_calcperc102 = Math.ceil(Math.random()) && 'calc(' + css_value_length_perc100 + ' - 10px)',
  109. css_value_length_calcperc33 = Math.ceil(Math.random()) && 'calc(' + css_value_length_perc100 + ' / 3)',
  110. css_value_length_em2 = Math.ceil(Math.random()) && '2em',
  111. css_value_length_pxNeg5 = Math.ceil(Math.random()) && '-5px',
  112. css_value_length_px0 = Math.ceil(Math.random()) && '0px',
  113. css_value_length_px1 = Math.ceil(Math.random()) && '1px',
  114. css_value_length_px2 = Math.ceil(Math.random()) && '2px',
  115. css_value_length_px3 = Math.ceil(Math.random()) && '3px',
  116. css_value_length_px3p5 = Math.ceil(Math.random()) && '3.5px',
  117. css_value_length_px4 = Math.ceil(Math.random()) && '4px',
  118. css_value_length_px5 = Math.ceil(Math.random()) && '5px',
  119. css_value_length_px7 = Math.ceil(Math.random()) && '7px',
  120. css_value_length_px8 = Math.ceil(Math.random()) && '8px',
  121. css_value_length_px10 = Math.ceil(Math.random()) && '10px',
  122. css_value_length_px12 = Math.ceil(Math.random()) && '12px',
  123. css_value_length_px14 = Math.ceil(Math.random()) && '14px',
  124. css_value_length_px15 = Math.ceil(Math.random()) && '15px',
  125. css_value_length_px16 = Math.ceil(Math.random()) && '16px',
  126. css_value_length_px20 = Math.ceil(Math.random()) && '20px',
  127. css_value_length_px25 = Math.ceil(Math.random()) && '25px',
  128. css_value_length_px26 = Math.ceil(Math.random()) && '26px',
  129. css_value_length_px28 = Math.ceil(Math.random()) && '28px',
  130. css_value_length_px30 = Math.ceil(Math.random()) && '30px',
  131. css_value_length_px34 = Math.ceil(Math.random()) && '34px',
  132. css_value_length_px38 = Math.ceil(Math.random()) && '38px',
  133. css_value_length_px40 = Math.ceil(Math.random()) && '40px',
  134. css_value_length_px43 = Math.ceil(Math.random()) && '43px',
  135. css_value_length_px45 = Math.ceil(Math.random()) && '45px',
  136. css_value_length_px50 = Math.ceil(Math.random()) && '50px',
  137. css_value_length_px55 = Math.ceil(Math.random()) && '55px',
  138. css_value_length_px60 = Math.ceil(Math.random()) && '60px',
  139. css_value_length_px70 = Math.ceil(Math.random()) && '70px',
  140. css_value_length_px80 = Math.ceil(Math.random()) && '80px',
  141. css_value_length_px250 = Math.ceil(Math.random()) && '250px',
  142. css_value_length_px300 = Math.ceil(Math.random()) && '300px',
  143. css_value_length_px350 = Math.ceil(Math.random()) && '350px',
  144. css_value_length_px520 = Math.ceil(Math.random()) && '520px',
  145.  
  146. css_value_gradient_redblue = Math.ceil(Math.random()) && 'linear-gradient(to bottom, ' + css_value_color_800c + ' 0%, ' + css_value_color_f00c + ' 40%, ' + css_value_color_00fc + ' 60%, ' + css_value_color_008c + ' ' + css_value_length_perc100 + ')',
  147. css_value_gradient_gray = Math.ceil(Math.random()) && 'linear-gradient(to bottom, ' + css_value_color_888c + ' 0%, ' + css_value_color_fffc + ' 50%, ' + css_value_color_888c + ' ' + css_value_length_perc100 + ')',
  148.  
  149. css_value_random_solid = Math.ceil(Math.random()) && ' solid ',
  150.  
  151. css_value_border_3pxffff = Math.ceil(Math.random()) && css_value_length_px3 + css_value_random_solid + css_value_color_ffff,
  152. css_value_border_4pxffff = Math.ceil(Math.random()) && css_value_length_px4 + css_value_random_solid + css_value_color_ffff,
  153. css_value_border_35px000f = Math.ceil(Math.random()) && css_value_length_px3p5 + css_value_random_solid + css_value_color_000f,
  154. css_value_border_1px000f = Math.ceil(Math.random()) && css_value_length_px1 + css_value_random_solid + css_value_color_000f,
  155. css_value_border_2px000f = Math.ceil(Math.random()) && css_value_length_px2 + css_value_random_solid + css_value_color_000f,
  156. css_value_border_3px000f = Math.ceil(Math.random()) && css_value_length_px3 + css_value_random_solid + css_value_color_000f,
  157. css_value_border_4px000f = Math.ceil(Math.random()) && css_value_length_px4 + css_value_random_solid + css_value_color_000f,
  158.  
  159. css_value_misc_absolute = Math.ceil(Math.random()) && 'absolute',
  160. css_value_misc_bold = Math.ceil(Math.random()) && 'bold',
  161. css_value_misc_block = Math.ceil(Math.random()) && 'block',
  162. css_value_misc_center = Math.ceil(Math.random()) && 'center',
  163. css_value_misc_Consolas = Math.ceil(Math.random()) && 'Consolas',
  164. css_value_misc_flex = Math.ceil(Math.random()) && 'flex',
  165. css_value_misc_flexEnd = Math.ceil(Math.random()) && 'flex-end',
  166. css_value_misc_grid = Math.ceil(Math.random()) && 'grid',
  167. css_value_misc_none = Math.ceil(Math.random()) && 'none',
  168. css_value_misc_relative = Math.ceil(Math.random()) && 'relative',
  169. css_value_misc_row = Math.ceil(Math.random()) && 'row',
  170. css_value_misc_preWrap = Math.ceil(Math.random()) && 'pre-wrap',
  171. css_value_misc_scroll = Math.ceil(Math.random()) && 'scroll',
  172. css_value_misc_spaceBetween = Math.ceil(Math.random()) && 'space-between',
  173. css_value_misc_text = Math.ceil(Math.random()) && 'text',
  174. css_value_misc_inlineBlock = Math.ceil(Math.random()) && 'inline-block',
  175.  
  176. MOUSEEVENT_LEFT = 1,
  177. MOUSEEVENT_MIDDLE = 2,
  178. MOUSEEVENT_RIGHT = 3,
  179.  
  180. KEYPRESS_KEY_LEFT = 0,
  181. KEYPRESS_KEY_RIGHT = 1,
  182. KEYPRESS_KEY_UP = 2,
  183. KEYPRESS_KEY_DOWN = 3,
  184. KEYPRESS_KEY_RELOAD = 4,
  185.  
  186. KEYPRESS_STATE_OFF = 0,
  187. KEYPRESS_STATE_ON = 1,
  188.  
  189. SHIELD_RANGE = 45,
  190.  
  191. enumsCharDict = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$',
  192.  
  193. ATTRIBUTE_USERNAMEHASH = enumsCharDict[0],
  194. ATTRIBUTE_PREVACCX = enumsCharDict[1],
  195. ATTRIBUTE_PREVACCY = enumsCharDict[2],
  196. ATTRIBUTE_ACCX = enumsCharDict[3],
  197. ATTRIBUTE_ACCY = enumsCharDict[4],
  198. ATTRIBUTE_HITBOX = enumsCharDict[5],
  199. ATTRIBUTE_HITBOXOFFSET = enumsCharDict[6],
  200. ATTRIBUTE_HITBOXRADIUS = enumsCharDict[7],
  201. ATTRIBUTE_HITBOXFORWARDOFFSET = enumsCharDict[8],
  202. ATTRIBUTE_BULLETCOLLISIONS = enumsCharDict[9],
  203. ATTRIBUTE_WIDTH = enumsCharDict[10],
  204. ATTRIBUTE_HEIGHT = enumsCharDict[11],
  205. ATTRIBUTE_PINGS = enumsCharDict[12],
  206. ATTRIBUTE_AVERAGEPING = enumsCharDict[13],
  207. ATTRIBUTE_MINPING = enumsCharDict[14],
  208. ATTRIBUTE_MAXPING = enumsCharDict[15],
  209. ATTRIBUTE_TIMEALIVEEXTRA = enumsCharDict[16],
  210. ATTRIBUTE_ISFROMCHEAT = enumsCharDict[17],
  211. ATTRIBUTE_TAGGEDNAME = enumsCharDict[18],
  212. ATTRIBUTE_USERNAME = enumsCharDict[19],
  213. ATTRIBUTE_SANITIZEDNAME = enumsCharDict[20],
  214. ATTRIBUTE_USABLEACCX = enumsCharDict[21],
  215. ATTRIBUTE_USABLEACCY = enumsCharDict[22],
  216. ATTRIBUTE_ENEMYFRIENDS = enumsCharDict[23],
  217. ATTRIBUTE_ENEMIES = enumsCharDict[24],
  218. ATTRIBUTE_PREVSPDX = enumsCharDict[25],
  219. ATTRIBUTE_PREVSPDY = enumsCharDict[26],
  220. ATTRIBUTE_USABLESPDX = enumsCharDict[27],
  221. ATTRIBUTE_USABLESPDY = enumsCharDict[28],
  222. ATTRIBUTE_ENEMY = enumsCharDict[29],
  223. ATTRIBUTE_DISTANCE = enumsCharDict[30],
  224. ATTRIBUTE_RADIUS = enumsCharDict[31],
  225. ATTRIBUTE_UPDATE = enumsCharDict[32],
  226. ATTRIBUTE_HPRADIUS = enumsCharDict[33],
  227. ATTRIBUTE_FILLHITBOX = enumsCharDict[34],
  228. ATTRIBUTE_MAKEHITBOX = enumsCharDict[35],
  229. ATTRIBUTE_DRAW = enumsCharDict[36],
  230. ATTRIBUTE_DRAWBODY = enumsCharDict[37],
  231. ATTRIBUTE_DRAWGUN = enumsCharDict[38],
  232.  
  233. KEYCODE_ESC = enumsCharDict[0],
  234. KEYCODE_A = enumsCharDict[1],
  235. KEYCODE_E = enumsCharDict[2],
  236. KEYCODE_D = enumsCharDict[3],
  237. KEYCODE_R = enumsCharDict[4],
  238. KEYCODE_S = enumsCharDict[5],
  239. KEYCODE_T = enumsCharDict[6],
  240. KEYCODE_W = enumsCharDict[7],
  241. KEYCODE_Z = enumsCharDict[8],
  242. KEYCODE_ENTER = enumsCharDict[9],
  243. KEYCODE_SPACE = enumsCharDict[10],
  244. KEYCODE_ARROWLEFT = enumsCharDict[11],
  245. KEYCODE_ARROWRIGHT = enumsCharDict[12],
  246. KEYCODE_ARROWUP = enumsCharDict[13],
  247. KEYCODE_ARROWDOWN = enumsCharDict[14],
  248. KEYCODE_N = enumsCharDict[15],
  249. KEYCODE_SHIFT = enumsCharDict[16],
  250. KEYCODE_CTRL = enumsCharDict[17],
  251.  
  252. INSTANTCHAT_CHATBINDS = enumsCharDict[0],
  253. INSTANTCHAT_CHATBINDSTEXTS = enumsCharDict[1],
  254. INSTANTCHAT_ONKILL = enumsCharDict[2],
  255. INSTANTCHAT_ONKILLTEXT = enumsCharDict[3],
  256. INSTANTCHAT_ONDEATH = enumsCharDict[4],
  257. INSTANTCHAT_ONDEATHTEXT = enumsCharDict[5],
  258. INSTANTCHAT_AUTOTHANK = enumsCharDict[6],
  259. INSTANTCHAT_AUTOTHANKTEXT = enumsCharDict[7],
  260.  
  261. AIMBOT_ENABLE = enumsCharDict[0],
  262. AIMBOT_AIMSMOOTHING = enumsCharDict[1],
  263. AIMBOT_CURSORMODE = enumsCharDict[2],
  264. AIMBOT_USEACCELERATION = enumsCharDict[3],
  265. AIMBOT_IGNORECHATTING = enumsCharDict[4],
  266. AIMBOT_PINGCOMPENSATION = enumsCharDict[5],
  267. AIMBOT_TRIGGERBOT = enumsCharDict[6],
  268. AIMBOT_WALLCHECK = enumsCharDict[7],
  269. AIMBOT_USEAHEAD = enumsCharDict[8],
  270. AIMBOT_DISABLEWHENDASHING = enumsCharDict[9],
  271. AIMBOT_CURSORPROXCOSENESS = enumsCharDict[10],
  272. AIMBOT_TARGETMODE = enumsCharDict[11],
  273. AIMBOT_TRIGGERBOTWHENDOWN = enumsCharDict[12],
  274. AIMBOT_RIGHTCLICKFRIEND = enumsCharDict[13],
  275. AIMBOT_AUXCLICKTARGET = enumsCharDict[14],
  276. AIMBOT_DROPDOWN_GENERAL = enumsCharDict[15],
  277. AIMBOT_DROPDOWN_ENHANCED = enumsCharDict[16],
  278. AIMBOT_DROPDOWN_CURSORPROX = enumsCharDict[17],
  279. AIMBOT_DROPDOWN_SMART = enumsCharDict[18],
  280. AIMBOT_DROPDOWN_PRIORITY = enumsCharDict[19],
  281. AIMBOT_DROPDOWN_TRIGGERBOT = enumsCharDict[20],
  282. AIMBOT_TARGETSONLY = enumsCharDict[21],
  283. AIMBOT_AVOIDFRIENDS = enumsCharDict[22],
  284. AIMBOT_AHEADNESSDEPTH = enumsCharDict[23],
  285. AIMBOT_LEADERMODE = enumsCharDict[24],
  286. AIMBOT_ACCAPPLYMULTIPLIER = enumsCharDict[25],
  287. AIMBOT_ACCTIMEMULTIPLIER = enumsCharDict[26],
  288.  
  289. ESP_ZOOM = enumsCharDict[0],
  290. ESP_FIXCAMERA = enumsCharDict[1],
  291. ESP_TRACERSBODYENEMY = enumsCharDict[2],
  292. ESP_TRACERSCURSORENEMY = enumsCharDict[3],
  293. ESP_TRACERSWALLCHECK = enumsCharDict[4],
  294. ESP_TRACERSGUN = enumsCharDict[5],
  295. ESP_TRACERSGRENADES = enumsCharDict[6],
  296. ESP_SHOWINVIS = enumsCharDict[7],
  297. ESP_REVEALTEAMS = enumsCharDict[8],
  298. ESP_SHOWHEALTH = enumsCharDict[9],
  299. ESP_SHOWARMOR = enumsCharDict[10],
  300. ESP_SHOWMAGS = enumsCharDict[11],
  301. ESP_SHOWGUNRELOADSTATUS = enumsCharDict[12],
  302. ESP_CAMUSEREALPOSITION = enumsCharDict[13],
  303. ESP_INCLUDEYOU = enumsCharDict[14],
  304. ESP_DROPDOWN_CAMERA = enumsCharDict[15],
  305. ESP_DROPDOWN_TRACERS = enumsCharDict[16],
  306. ESP_DROPDOWN_PLAYERSTATS = enumsCharDict[17],
  307. ESP_DROPDOWN_OTHER = enumsCharDict[18],
  308. ESP_SHOWRANGE = enumsCharDict[19],
  309. ESP_SCROLLSENSITIVITY = enumsCharDict[20],
  310.  
  311. CHATSPAMMER_TEXT = enumsCharDict[0],
  312. CHATSPAMMER_WIDTH = enumsCharDict[1],
  313. CHATSPAMMER_INTERVAL = enumsCharDict[2],
  314. CHATSPAMMER_DIRECTION = enumsCharDict[3],
  315. CHATSPAMMER_SEPERATOR = enumsCharDict[4],
  316. CHATSPAMMER_INDEX = enumsCharDict[5],
  317. CHATSPAMMER_TIMEOUT = enumsCharDict[6],
  318. CHATSPAMMER_PAUSEPERIOD = enumsCharDict[7],
  319. CHATSPAMMER_VARIATION = enumsCharDict[8],
  320. CHATSPAMMER_PREFIX = enumsCharDict[9],
  321. CHATSPAMMER_SUFFIX = enumsCharDict[10],
  322.  
  323. ANTIAIM_RELOAD = enumsCharDict[0],
  324. ANTIAIM_SHOOT = enumsCharDict[1],
  325. ANTIAIM_IDLE = enumsCharDict[2],
  326. ANTIAIM_ANGLESTART = enumsCharDict[3],
  327. ANTIAIM_ANGLERANGE = enumsCharDict[4],
  328. ANTIAIM_SPINSPEED = enumsCharDict[5],
  329. ANTIAIM_DELAY = enumsCharDict[6],
  330. ANTIAIM_SAVEDX = enumsCharDict[7],
  331. ANTIAIM_SAVEDY = enumsCharDict[8],
  332. ANTIAIM_DRAWREALAIM = enumsCharDict[9],
  333.  
  334. RECORDER_ISRECORDING = enumsCharDict[0],
  335. RECORDER_CURRENT = enumsCharDict[1],
  336. RECORDER_SESSIONS = enumsCharDict[2],
  337. RECORDER_ISPLAYING = enumsCharDict[3],
  338. RECORDER_TIMEOUT = enumsCharDict[4],
  339. RECORDER_SESSIONTOPLAY = enumsCharDict[5],
  340.  
  341. MISC_AUTORELOAD = enumsCharDict[0],
  342. MISC_PINGDISPLAY = enumsCharDict[1],
  343. MISC_RENDERDISPLAY = enumsCharDict[2],
  344. MISC_STATICHUD = enumsCharDict[3],
  345. MISC_STATICHEALTH = enumsCharDict[4],
  346. MISC_DISABLECLOSEPOPUP = enumsCharDict[5],
  347. MISC_BETTERCRATEHP = enumsCharDict[6],
  348. MISC_HIDECHATTING = enumsCharDict[7],
  349. MISC_FFACLANDISPLAY = enumsCharDict[8],
  350. MISC_SHOWFEATURES = enumsCharDict[9],
  351. MISC_DROPDOWN_INGAME = enumsCharDict[10],
  352. MISC_DROPDOWN_DEBUG = enumsCharDict[11],
  353. MISC_DROPDOWN_HUD = enumsCharDict[12],
  354. MISC_DROPDOWN_OTHER = enumsCharDict[13],
  355. MISC_POSITION = enumsCharDict[14],
  356. MISC_LEADERBOARDBADGES = enumsCharDict[15],
  357.  
  358. THNET_SOCKET = enumsCharDict[0],
  359. THNET_ENABLE = enumsCharDict[1],
  360. THNET_DISCONNECT = enumsCharDict[2],
  361. THNET_MEMBERS = enumsCharDict[3],
  362. THNET_CHAT = enumsCharDict[4],
  363. THNET_DONATE = enumsCharDict[5],
  364. THNET_ENTEROPENCHAT = enumsCharDict[6],
  365. THNET_AUTH = enumsCharDict[7],
  366. THNET_CLOSEREASON = enumsCharDict[8],
  367. THNET_INFOSHARE = enumsCharDict[9],
  368. THNET_INFOSHARING = enumsCharDict[10],
  369. THNET_BROTHERS = enumsCharDict[11],
  370.  
  371. ADVANCED_PINGCOUNT = enumsCharDict[0],
  372. ADVANCED_AIMCONSTANT = enumsCharDict[1],
  373. ADVANCED_TPS = enumsCharDict[2],
  374. ADVANCED_OPTIMISEWALLCHECK = enumsCharDict[3],
  375. ADVANCED_PINGCOMP = enumsCharDict[4],
  376.  
  377. PERKHACKS_KNIFE = enumsCharDict[0],
  378. PERKHACKS_KNIFEMAXRANGE = enumsCharDict[1],
  379. PERKHACKS_TICK = enumsCharDict[2],
  380. PERKHACKS_SHIELD = enumsCharDict[3],
  381. PERKHACKS_SHIELDUPKEEP = enumsCharDict[4],
  382. PERKHACKS_STOREDANGLE = enumsCharDict[5],
  383. PERKHACKS_SHIELDMANUAL = enumsCharDict[6],
  384. PERKHACKS_CRATEPLACEVISION = enumsCharDict[7],
  385. PERKHACKS_SHIELDLOOKAHEAD = enumsCharDict[8],
  386. PERKHACKS_MEDKITSELFHEAL = enumsCharDict[9],
  387. PERKHACKS_MEDKITSELFHEALTHRESHOLD = enumsCharDict[10],
  388. PERKHACKS_SHIELDVISUALISER = enumsCharDict[11],
  389. PERKHACKS_SHIELDWALLCHECK = enumsCharDict[12],
  390.  
  391. WEIRD_CURSORMOVE = enumsCharDict[0],
  392.  
  393. DISCORDRPC_ENABLED = enumsCharDict[0],
  394. DISCORDRPC_STATE = enumsCharDict[1],
  395. DISCORDRPC_DETAILS = enumsCharDict[2],
  396. DISCORDRPC_UPDATEINTERVAL = enumsCharDict[3],
  397. DISCORDRPC_START = enumsCharDict[4],
  398. DISCORDRPC_TIMEOUT = enumsCharDict[5],
  399. DISCORDRPC_CONNECTION = enumsCharDict[6],
  400. DISCORDRPC_TRIES = enumsCharDict[7],
  401. DISCORDRPC_ACCESSTOKEN = enumsCharDict[8],
  402. DISCORDRPC_CLIENTID = enumsCharDict[9],
  403. DISCORDRPC_EXPECTING = enumsCharDict[10],
  404.  
  405. PAINT_GRID = enumsCharDict[0],
  406. PAINT_GRIDSPACEX = enumsCharDict[1],
  407. PAINT_GRIDSPACEY = enumsCharDict[2],
  408. PAINT_GRIDLINEWIDTHHORIZONTAL = enumsCharDict[3],
  409. PAINT_GRIDLINEWIDTHVERTICAL = enumsCharDict[4],
  410. PAINT_GRIDCOLOR = enumsCharDict[6],
  411. PAINT_CRATES = enumsCharDict[7],
  412. PAINT_CRATESQUARE = enumsCharDict[8],
  413. PAINT_CRATELONG = enumsCharDict[9],
  414. PAINT_CRATEUSER = enumsCharDict[10],
  415. PAINT_CRATEPREMIUM = enumsCharDict[11],
  416. PAINT_CRATESHOWHPMODE = enumsCharDict[12],
  417. PAINT_POINTS = enumsCharDict[13],
  418. PAINT_POINTSIDLE = enumsCharDict[14],
  419. PAINT_POINTSFFA = enumsCharDict[15],
  420. PAINT_POINTSBLU = enumsCharDict[16],
  421. PAINT_POINTSRED = enumsCharDict[17],
  422. PAINT_POINTEDGEWIDTH = enumsCharDict[18],
  423. PAINT_CRATECORPSE = enumsCharDict[19],
  424. PAINT_PRESETMANAGER = enumsCharDict[20],
  425. PAINT_PRESETS = enumsCharDict[21],
  426.  
  427. MULTIBOX_SELECTEDSOCKET = enumsCharDict[0],
  428. MULTIBOX_SPAWNCLONE = enumsCharDict[1],
  429. MULTIBOX_INSTANTRESPAWN = enumsCharDict[2],
  430.  
  431. //database of guide entries
  432. //very incomplete, missing a lot of information
  433. guide = [[
  434. 'Menu',
  435.  
  436. 'Navigation',
  437. 'You can select any menu from the main menu by clicking on the menu\'s name.',
  438.  
  439. 'Back Button',
  440. 'You can return to the menu selection screen by clicking the back button at the top left corner.',
  441.  
  442. 'Toggling',
  443. 'You can toggle the menu to make it vanish or reappear by pressing (T) on your keyboard at any particular time.',
  444.  
  445. 'Scrolling',
  446. 'You can scroll in some menus by either using your mouse wheel or moving the scroll bar at the right side of the menu.',
  447.  
  448. 'Moving',
  449. 'You can drag the menu around by holding the title element.'
  450. ],[
  451. 'Settings',
  452.  
  453. 'Toggles and Values',
  454. 'You can toggle On/Off settings by simply clicking on them. You can change Value settings by clicking the [+] or [-] buttons next to them or by using your scroll wheel on the value display. To know what a setting does, hover over the setting, since most controls have tooltips added.',
  455.  
  456. 'Special Controls',
  457. 'Some menus use custom controls like text inputs, perk selection and more. Though most of those special controls don\'t need an introduction (as I think it is self explanatory enough, correct me if i\'m wrong), but for Auto Upgrade, you can click a perk you have already selected to unselect it.',
  458.  
  459. 'Empty Menus',
  460. 'Some menus (Recorder) don\'t have menu contents, which means they will be eventually added, probably...',
  461.  
  462. 'Imperfect Features',
  463. 'Some features may decrease your effectiveness or may cause other issues, please report the issues if that is the case.',
  464.  
  465. 'Saving',
  466. 'When you change any setting, it gets saved, which means if you reload, the settings won\'t be lost!'
  467. ],[
  468. 'Contact',
  469.  
  470. 'Discord',
  471. 'We have a discord where you can talk with fellow TioHax users and even the Developer himself! https://discord.gg/CwWd5UKf6R'
  472. ]],
  473.  
  474. credits = [[
  475. 'Developing',
  476. 'Main Developer of this Cheat Software',
  477. 'Taureon',
  478. 'For helping with technical stuff',
  479. 'Vaakir & Nitrogem35',
  480. 'Providing an API for the FFA Clan Display feature',
  481. 'Nitrogem35'
  482. ],[
  483. 'Playtesting',
  484. 'Finding dumb bugs and general playtesting',
  485. 'Ravgo'
  486. ],[
  487. 'Inspiration',
  488. 'Making my own Cheat Client',
  489. 'Vaakir',
  490. 'Providing me with moral justifications',
  491. 'GodF4ther, cat421, CrimAnn, SHTURM, DeadForYears and pretty much the rest of the Gats.io Community, you toxic idiots'
  492. ],[
  493. 'Special Thanks',
  494. 'You!',
  495. 'For using this cheat! Thank you so much!'
  496. ]],
  497.  
  498. //if the current enviroment is tampermonkey
  499. //isUserscript = typeof GM === 'object' || typeof GM_info === 'object',
  500.  
  501. //make sure closure compiler deals with that aswell
  502. ctx = j58,
  503.  
  504. undefVar = Math.ceil(Math.random()) && undefined,
  505.  
  506. //used to make math easier to read
  507. {
  508. PI, abs, asin, atan2,
  509. ceil, cos, floor, max,
  510. min, random, round, sign,
  511. sin, sqrt, E
  512. } = Math,
  513. TAU = PI * 2,
  514. degToRad = TAU / 360,
  515. mathSin = sin(degToRad * 60),
  516. third = 1 / 3,
  517.  
  518. nullPos = {x: 0, y: 0},
  519.  
  520. idRefreshMenu = 0,
  521.  
  522. //hash of the developer's ign
  523. //this is 'TheS3xHaver' but hashed with hashString() function
  524. developerHash = -1599485949,
  525.  
  526. homeUrl = 's://cheats.gatsio.repl.co/',
  527.  
  528. //time it took to render a frame
  529. renderTime = 0,
  530.  
  531. //how many ticks the main function has ran for
  532. tickCount = 0,
  533.  
  534. chatBoxRandom,
  535.  
  536. //turning armor names into indexes
  537. armorMap = {
  538. noArmor: 0,
  539. lightArmor: 1,
  540. mediumArmor: 2,
  541. heavyArmor: 3
  542. },
  543.  
  544. //turning gun names to indexes
  545. gunMap = {
  546. pistol: 0,
  547. smg: 1,
  548. shotgun: 2,
  549. assault: 3,
  550. sniper: 4,
  551. lmg: 5,
  552. 'bolt-action-rifle': 4,
  553. 'machine-gun': 5
  554. },
  555.  
  556. //turning gun indexes into gun displaynames
  557. gunNames = ['Pistol', 'SMG', 'Shotgun', 'Assault', 'Sniper', 'LMG'],
  558.  
  559. //6 = knife
  560. //7 = shield
  561.  
  562. //bullet velocities of guns
  563. velocities = [24, 22, 24, 24, 30, 24, 7, Infinity],
  564.  
  565. //bullet spawn offsets based on gun lengths
  566. offsets = [44, 50, 55, 63, 75, 62, 0, 0],
  567.  
  568. //how far each bullet travels
  569. ranges = [18, 13, 10, 18, 22, 16, 32, Infinity],
  570.  
  571. //stupidness
  572. textBoxFocused = 0,
  573.  
  574. gunMinRange = 0,
  575.  
  576. //cursor position that is independent of the game
  577. cursor = {x: 0, y: 0, isPressed: 0, isShooting: 0},
  578.  
  579. highestZIndex = 3,
  580.  
  581. movableWindows = [],
  582.  
  583. clanTagCache = {},
  584.  
  585. menuNames = [
  586. '', 'Guide', 'Menu', 'Aimbot',
  587. 'ESP', 'Instant Chat', 'Misc', 'Player Manager',
  588. 'Auto Upgrades', 'Chat Spammer', 'Anti Aim', 'Perk Hacks',
  589. 'Paint', 'Recorder', 'Discord Rich Presence', 'THNet',
  590. 'Weird', 'Advanced', 'Credits'
  591. ],
  592.  
  593. aimbotLabel = {
  594. [AIMBOT_ENABLE]: [ 'Enable Aimbot', 'Automatically aims your weapon at enemies, toggleable with right click.'],
  595. [AIMBOT_AIMSMOOTHING]: [ 'Aim Smoothing', 'Makes aimbot\'s movement smoother.'],
  596. [AIMBOT_CURSORMODE]: [ 'Enable', 'Whichever is closest to your cursor.'],
  597. [AIMBOT_USEACCELERATION]: [ 'Use Acceleration', 'Tries to account for the enemy\'s velocity changes.'],
  598. [AIMBOT_IGNORECHATTING]: [ 'Ignore Chatting', 'Ignores players who are typing.'],
  599. [AIMBOT_PINGCOMPENSATION]: [ 'Ping Compensation', 'Tries to compensate for the internet connection.'],
  600. [AIMBOT_TRIGGERBOT]: [ 'Enable', 'Shoots automatically when possible, requires Wall Check to be enabled (not recommended with single fire weapons.)'],
  601. [AIMBOT_WALLCHECK]: [ 'Wall Check', 'Tries to not aim at enemies behind walls.'],
  602. [AIMBOT_USEAHEAD]: [ 'Use Ahead Check', 'Use the position of where the enemy will be for wall check instead of where they are right now.'],
  603. [AIMBOT_DISABLEWHENDASHING]: [ 'Dash Disable', 'Turns aimbot temporarily off when dashing.'],
  604. [AIMBOT_CURSORPROXCOSENESS]: [ 'Range', 'How close an enemy needs to be to be targetted by the aimbot when in Cursor Proximity mode.'],
  605. [AIMBOT_TARGETMODE]: [ 'Prioritise Targets', 'Prioritises targetted players over anything when applicable.'],
  606. [AIMBOT_TRIGGERBOTWHENDOWN]: [ 'When Mouse Down', 'Triggerbot fires only when you shoot, suppresses manual firing when this and Triggerbot is enabled.'],
  607. [AIMBOT_RIGHTCLICKFRIEND]: [ 'Rightclick Friend', 'When you Rightclick on someone, it adds them to the friends list.'],
  608. [AIMBOT_AUXCLICKTARGET]: [ 'Middleclick Target', 'When you Middleclick on someone (Mouse-wheel when you press on it), it adds them to the targets list.'],
  609. [AIMBOT_TARGETSONLY]: [ 'Targets Only', 'Ignores people you aren\'t targetting.'],
  610. [AIMBOT_AVOIDFRIENDS]: [ 'Avoid Friends (WIP)', 'Avoids shooting at an enemy if it would be too risky for a friend on the enemy team to get hit. THIS IS IN BETA, MAY RESULT IN UNINTENDED CONSEQUENCES.'],
  611. [AIMBOT_AHEADNESSDEPTH]: [ 'Ahead Calc Depth', 'The accuracy of the calculation that checks how far ahead the aimbot should aim.'],
  612. [AIMBOT_LEADERMODE]: [ 'Prioritise Leader', 'Prioritises the top scoring player if they are on the enemy team. This takes priority over the \'Prioritise Targets\' setting.'],
  613. [AIMBOT_DROPDOWN_GENERAL]: [ 'General', '' ],
  614. [AIMBOT_DROPDOWN_ENHANCED]: [ 'Enhancements', '' ],
  615. [AIMBOT_DROPDOWN_CURSORPROX]: [ 'Cursor Proximity', '' ],
  616. [AIMBOT_DROPDOWN_SMART]: [ 'Smarter Targeting', '' ],
  617. [AIMBOT_DROPDOWN_PRIORITY]: [ 'Priority', '' ],
  618. [AIMBOT_DROPDOWN_TRIGGERBOT]: [ 'Triggerbot', '' ]
  619. },
  620.  
  621. espLabel = {
  622. [ESP_ZOOM]: [ 'Extended View', 'Gives you maximum possible vision', ],
  623. [ESP_FIXCAMERA]: [ 'Fixed Camera', 'Stops the camera from moving', ],
  624. [ESP_TRACERSBODYENEMY]: [ 'Player Tracers', 'Draws a line from you to every player currently loaded in' ],
  625. [ESP_TRACERSCURSORENEMY]: [ 'CursorProx Tracers', 'When Cursor Proximity is enabled, draws lines from your cursor to your enemies' ],
  626. [ESP_TRACERSWALLCHECK]: [ 'Wall Check Tracers', 'Visualises the wall checking algorithm' ],
  627. [ESP_TRACERSGUN]: [ 'Gun Tracers', 'Draws the line a bullet would go if you shot your gun' ],
  628. [ESP_TRACERSGRENADES]: [ 'Grenade Tracers', 'Draws a line to where a grenade is to where the grenade will roughly land at' ],
  629. [ESP_SHOWINVIS]: [ 'Show Invisibles', 'Shows silencers, camo players and landmines', ],
  630. [ESP_REVEALTEAMS]: [ 'Reveal Teams', 'Reveals the team affiliations for grenades, landmines, gas and knifes', ],
  631. [ESP_SHOWHEALTH]: [ 'Healths', 'Shows every players\' current health', ],
  632. [ESP_SHOWARMOR]: [ 'Armors', 'Shows every players\' current armor', ],
  633. [ESP_SHOWMAGS]: [ 'Magazines', 'Shows every players\' current ammo counts', ],
  634. [ESP_SHOWGUNRELOADSTATUS]: [ 'Gun Reload', 'Shows every player\'s current gun reloading status with a percentage.', ],
  635. [ESP_SHOWRANGE]: [ 'Ranges', 'Shows how far players can shoot (may cause the game to look like a clusterfuck)' ],
  636. [ESP_CAMUSEREALPOSITION]: [ 'Camera Cursor Fix', 'When Aimbot is on, this makes the Camera follow your Cursor, and not where the Aimbot tells the game where the Cursor is' ],
  637. [ESP_INCLUDEYOU]: [ 'Self Attributes', 'Makes Player Healths, Player Armors, Player Magazines and Player Gun Status draw over you aswell' ],
  638. [ESP_SCROLLSENSITIVITY]: [ 'Zoom Sensitivity', 'When the \'Extended View\' mode is on \'Scroll\', this determines how much you zoom in and out when you use the scroll wheel' ],
  639. [ESP_DROPDOWN_CAMERA]: [ 'Camera', 'Various Camera Improvement Settings' ],
  640. [ESP_DROPDOWN_TRACERS]: [ 'Tracers', 'Some Lines and Circles' ],
  641. [ESP_DROPDOWN_PLAYERSTATS]: [ 'Player Attributes', 'Helpful Attributes of nearby Players' ],
  642. [ESP_DROPDOWN_OTHER]: [ 'Other', 'Other ESP Features' ]
  643. },
  644.  
  645. autoUpgradesLabel = [
  646. [ 'Auto Upgrade', 'Automatically upgrades specified perks for you' ],
  647. 'No Perk Selected'
  648. ],
  649.  
  650. scrollerLabel = {
  651. 0: [ 'Toggle Scroller', 'Turn the Chat Scroller either On or Off' ],
  652. [CHATSPAMMER_WIDTH]: [ 'Text Width', 'Maximum width of the scrolled text' ],
  653. [CHATSPAMMER_DIRECTION]: [ 'Direction', 'In which direction the text scrolls (- = left, + = right)' ],
  654. [CHATSPAMMER_INTERVAL]: [ 'Interval', 'The interval it takes for the text to shift' ],
  655. [CHATSPAMMER_PAUSEPERIOD]: [ 'Pause Period', 'When something besides the Scroller has said something in chat, for how long it should wait before it should scroll again' ],
  656. [CHATSPAMMER_TEXT]: [ 'Text', 'The Text to scroll in Chat' ],
  657. [CHATSPAMMER_SEPERATOR]: [ 'Seperator', 'The Seperator so it does not look like \'hello worldhello worldhello world\'' ],
  658. [CHATSPAMMER_PREFIX]: [ 'Prefix', 'Static text to add in front of your chat message' ],
  659. [CHATSPAMMER_SUFFIX]: [ 'Sufffix', 'Static text to add after your chat message' ]
  660. },
  661.  
  662. instantchatLabel = {
  663. 0: 'Change the text you say when you press a key',
  664. [INSTANTCHAT_CHATBINDS]: [ 'Chat Binds', 'Press buttons to make the cheat instantly say something in chat for you', ],
  665. [INSTANTCHAT_CHATBINDSTEXTS]: [ 'Edit Binds', 'Select a button on your keyboard to make the cheat say LITERALLY ANYTHING for you' ],
  666. [INSTANTCHAT_ONKILL]: [ 'On Kill Chat Msg', 'Say something when you kill someone', ],
  667. [INSTANTCHAT_ONKILLTEXT]: [ '', 'Change the text you say when you kill someone' ],
  668. [INSTANTCHAT_ONDEATH]: [ 'On Death Chat Msg', 'Say something when you die', ],
  669. [INSTANTCHAT_ONDEATHTEXT]: [ '', 'Change the text you say when you die' ],
  670. [INSTANTCHAT_AUTOTHANK]: [ 'Auto Medkit Thank', 'Instantly say thanks when you get healed', ],
  671. [INSTANTCHAT_AUTOTHANKTEXT]: [ '', 'Change the text you say when you get healed' ]
  672. },
  673.  
  674. antiAimLabel = {
  675. [ANTIAIM_RELOAD]: [ 'While Reloading', 'To hide aim while reloading your gun' ],
  676. [ANTIAIM_SHOOT]: [ 'While Shooting', 'To hide aim while shooting your gun' ],
  677. [ANTIAIM_IDLE]: [ 'While Idle', 'To hide wim while neither shooting or reloading your gun (not recommended with single fire weapons)' ],
  678. [ANTIAIM_ANGLESTART]: [ 'Min Angle', 'Minimum Angle where it starts off' ],
  679. [ANTIAIM_ANGLERANGE]: [ 'Angle Range', 'Random additional angle from 0 to the angle range which gets added on the Minimum Angle' ],
  680. [ANTIAIM_SPINSPEED]: [ 'Spin Speed', 'How fast it spins. Accepts negative numbers if you want it to spin the other direction' ],
  681. [ANTIAIM_DELAY]: [ 'Interval', 'The amount of time (in game ticks) at which it picks another position to aim at' ],
  682. [ANTIAIM_DRAWREALAIM]: [ 'Draw Real Aim', 'Draws the gun a second time as if Anti Aim wasn\'t enabled' ]
  683. },
  684.  
  685. miscLabel = {
  686. [MISC_AUTORELOAD]: [ 'Auto Reload', 'Automatically reloads when there are no enemies nearby', ],
  687. [MISC_PINGDISPLAY]: [ 'Ping Display', 'Displays the latency to the server', ],
  688. [MISC_RENDERDISPLAY]: [ 'FPS & Render Time', 'Displays your current FPS and how long it took to render the last frame', ],
  689. [MISC_STATICHUD]: [ 'Static Hud', 'Disables hud animations', ],
  690. [MISC_STATICHEALTH]: [ 'Static Health', 'Disables the hp moving animations on players when they take damage', ],
  691. [MISC_DISABLECLOSEPOPUP]: [ 'No Unload Popup', 'Disable the unload popup when you leave or reload the game' ],
  692. [MISC_BETTERCRATEHP]: [ 'Better Crate HP', 'Makes the health display pick colors better instead of just picking one of 5 colors' ],
  693. [MISC_HIDECHATTING]: [ 'Hide Chatbox', 'Others won\'t see that you\'re typing, they\'ll just see you not move' ],
  694. [MISC_FFACLANDISPLAY]: [ 'FFA Clan Tags', 'Shows clan tags next to names in FFA Mode' ],
  695. [MISC_SHOWFEATURES]: [ 'Feature Display', 'Shows what main features are enabled in the bottom right corner' ],
  696. [MISC_POSITION]: [ 'Coordinates', 'Shows your coordinates, velocity and acceleration' ],
  697. [MISC_LEADERBOARDBADGES]: [ 'Leaderboard Badges', 'Shows Friends, Targets, THNet members and the dev with badges next to their leaderboard' ],
  698. [MISC_DROPDOWN_INGAME]: [ 'In Game', 'Gameplay related settings' ],
  699. [MISC_DROPDOWN_DEBUG]: [ 'Debug', 'Special Technical Information' ],
  700. [MISC_DROPDOWN_HUD]: [ 'Heads Up Display', 'HUD-related settings' ],
  701. [MISC_DROPDOWN_OTHER]: [ 'Other', 'Settings that have no category of their own' ]
  702. },
  703.  
  704. playerManagerLabel = [[
  705. 'Friends',
  706. 'Switch to the list of ignored enemies'
  707. ],[
  708. 'Targets',
  709. 'Switch to the list of prioritised targets'
  710. ],[
  711. 'Muted',
  712. 'Switch to the list of muted players'
  713. ],[
  714. 'Add a friend',
  715. 'Add a target',
  716. 'Mute someone'
  717. ]],
  718.  
  719. advancedLabel = {
  720. 0: [ 'Disconnect', 'Disconnect from the current server' ],
  721. 1: [ 'Clear Bootloader', 'Clears the stored code and version of the bootloader' ],
  722. 2: [ 'Clear TioHax', 'Clears the settings and configutations, and resets them to factory defaults.' ],
  723. [ADVANCED_PINGCOUNT]: [ 'Ping Cache', 'How many recent ping times it stores' ],
  724. [ADVANCED_AIMCONSTANT]: [ 'Aim Constant', 'Lower = Aimbot aims further ahead' ],
  725. [ADVANCED_PINGCOMP]: [ 'Account for ping', 'How far the aimbot aims ahead depending on the ping. lower = further' ],
  726. [ADVANCED_TPS]: [ 'Sync TPS with Server', 'Makes the game run at 25 ticks per second instead of 62.5' ],
  727. [ADVANCED_OPTIMISEWALLCHECK]: [ 'Optimise Wallcheck', 'Optimises the checking for the wall checking algorithm' ]
  728. },
  729.  
  730. perkHacksLabel = {
  731. 0: [ 'KnifeBot (WIP)', 'Automatically shoots a knife at very near enemies' ],
  732. 1: [ 'ShieldBot (WIP)', 'Automatically blocks nearby bullets' ],
  733. 2: [ 'Medkit and Build (WIP)', 'Gives tools for using Medkit and Build perks' ],
  734.  
  735. [PERKHACKS_KNIFE]: [ 'Enable', 'Automatically shoots a knife at a close enemy' ],
  736. [PERKHACKS_KNIFEMAXRANGE]: [ 'Range', 'How close an enemy needs to be to be knifed' ],
  737.  
  738. [PERKHACKS_SHIELD]: [ 'Enable', 'Automatically block nearby bullets' ],
  739. [PERKHACKS_SHIELDUPKEEP]: [ 'Takedown delay', 'How long (in ticks) the shield should be up for even when the bullet is deflected' ],
  740. [PERKHACKS_SHIELDMANUAL]: [ 'Manual Ability', 'Does not take control over your ability to use the shield, but still aims torwards close bullets for you' ],
  741. [PERKHACKS_SHIELDLOOKAHEAD]: [ 'Lookahead', 'Tries to block incoming bullets earlier the higher this value is' ],
  742. [PERKHACKS_SHIELDVISUALISER]: [ 'Visualiser', 'For debugging purposes, visualises the check that the ShieldBot does.' ],
  743. [PERKHACKS_SHIELDWALLCHECK]: [ 'Wall Check', 'Only tries to block bullets that would have to go through crates.' ],
  744.  
  745. [PERKHACKS_CRATEPLACEVISION]: [ 'Placement Vision', 'Where exactly the build block or medkit will be placed when Build or Medkit is used' ],
  746. [PERKHACKS_MEDKITSELFHEAL]: [ 'Auto Self Heal', 'Automatically puts the Medkit in front of you if you\'re below a certain health threshold' ],
  747. [PERKHACKS_MEDKITSELFHEALTHRESHOLD]: [ 'Threshold', 'The health threshold that says when to heal yourself. If your health is lower, it heals' ]
  748. },
  749.  
  750. THNetLabel = {
  751. 0: [ 'THNet Rules', 'Rules you have to follow when using THNet' ],
  752. 1: [
  753. 'Don\'t kill other THNet members, the point is to make THNet work with each other.',
  754. 'Don\'t spam THNet Chat with garbage, else it drowns out good messages.',
  755. 'Don\'t be mean to others in THNet Chat, it does not make you a good person.'
  756. ],
  757. [THNET_ENABLE]: [ 'Connect', 'Connects to THNet when you join a server, bringing a variety of features' ],
  758. [THNET_DISCONNECT]: [ 'Disconnect', 'Disconnect from THNet, your Aimbot will shoot at them but their Aimbots will also shoot you' ],
  759. [THNET_MEMBERS]: [ 'THNet Members', 'The List of THNet Members in your current lobby' ],
  760. [THNET_CHAT]: [ 'Serverwide Chat', 'Chat with all other THNet members in your current server without needing to be close' ],
  761. [THNET_DONATE]: [ 'Donate Connection', 'Donate an unused Game Connection to Taureon for a Botnet which will assist you' ],
  762. [THNET_AUTH]: [ 'THNet Admin Authentication', 'Authentication Code Input Box for THNet Administrators' ],
  763. [THNET_INFOSHARE]: [ 'Share Gameplay Info', 'Shares health, position, ammo count and class with other members' ]
  764. },
  765.  
  766. weirdLabel = {
  767. [WEIRD_CURSORMOVE]: [ 'Move with Cursor', 'You will move to where your cursor is' ]
  768. },
  769.  
  770. discordRPCLabel = {
  771. [DISCORDRPC_ENABLED]: [ 'Enable', 'Makes the Rich Presence show up on your Discord Profile' ],
  772. [DISCORDRPC_STATE]: [ 'State', 'First line below the Presence Title' ],
  773. [DISCORDRPC_DETAILS]: [ 'Details', 'Line below the State Line' ],
  774. [DISCORDRPC_UPDATEINTERVAL]: [ 'Update Interval', 'In seconds, how often it updates' ]
  775. },
  776.  
  777. paintLabel = {
  778. 0: [ 'Reset Colors/Values', 'Resets every change back to default'],
  779. 1: [ 'ARE YOU SURE that you want to reset everything you have changed in Paint?', 'Type exactly \'yes\' if yes' ],
  780.  
  781. [PAINT_GRID]: [ 'Grid', 'Change the look of the floor' ],
  782. [PAINT_POINTS]: [ 'Capture Points', 'Change the look of capture points' ],
  783. [PAINT_CRATES]: [ 'Crates', 'Change the look of crates on the map' ],
  784.  
  785. [PAINT_GRIDSPACEX]: [ 'Horiz. Space', 'The horizontal space between the grid lines' ],
  786. [PAINT_GRIDSPACEY]: [ 'Vert. Space', 'The vertical space between the grid lines' ],
  787. [PAINT_GRIDLINEWIDTHHORIZONTAL]: [ 'Hori. Line Width', 'Width of the lines that go horizontally' ],
  788. [PAINT_GRIDLINEWIDTHVERTICAL]: [ 'Vert. Line Width', 'Width of the lines that go vertically' ],
  789. [PAINT_GRIDCOLOR]: [ 'Grid Color', 'The color of the Grid' ],
  790.  
  791. [PAINT_POINTSIDLE]: [ 'No One Capturing', 'The color if no one is capturing the point' ],
  792. [PAINT_POINTSFFA]: [ 'FFA You Capturing', 'The color if you are capturing the point' ],
  793. [PAINT_POINTSBLU]: [ 'Blue Capturing', 'The color if the blue team is capturing the point' ],
  794. [PAINT_POINTSRED]: [ 'Red Capturing', 'The color if the red team is capturing the point' ],
  795. [PAINT_POINTEDGEWIDTH]: [ 'Edge Width', 'How wide the edges of the capture points should be' ],
  796.  
  797. [PAINT_CRATESHOWHPMODE]: [ 'Health Display', 'Change which parts should turn white when build crates get damaged' ],
  798. [PAINT_CRATESQUARE]: [ 'Square Crates', 'The large square-shaped crates' ],
  799. [PAINT_CRATELONG]: [ 'Long Crates', 'The smaller rectangle-shaped crates' ],
  800. [PAINT_CRATEUSER]: [ 'Build Crates', 'The crates made with the Build perk' ],
  801. [PAINT_CRATEPREMIUM]: [ 'Premium Crates', 'Build crates but built by Premium Users' ],
  802. [PAINT_CRATECORPSE]: [ 'Crate Corpses', 'The colors the crate takes on as its Health decreases' ],
  803.  
  804. [PAINT_PRESETMANAGER]: [ 'Preset Manager', 'Manage Paint Presets. Save, Load, Export, Import and Name Presets' ]
  805. },
  806.  
  807. controlDropdownOptions = [
  808. [
  809. [ 'Normal', 'Normal Game View' ],
  810. [ 'Scroll', 'Use your scroll wheel to change how much you can see' ],
  811. [ 'Static', 'Automatically zooms out to the most possible you can see' ]
  812. ], [
  813. [ 'None', 'Crate colors do not change' ],
  814. [ 'Edges', 'Only the crate\'s edge changes' ],
  815. [ 'Inside', 'Only the inside of the crate changes' ],
  816. [ 'Both', 'Entire crate changes' ]
  817. ], [
  818. [ 'Disabled', 'No Display for what Main Features are enabled' ],
  819. [ 'Enabled', 'Main Features get displayed in the bottom right corner' ],
  820. [ 'Graytext', 'Subsettings are shown in Gray Colors instead of Rainbow' ]
  821. ], [
  822. [ 'None', 'No ShieldBot check visualisers' ],
  823. [ 'Closeness', 'The circle inside a bullet needs to be in' ],
  824. [ 'Bullets', 'Draws small arrows to see how far ahead it predicts the bullets to be' ],
  825. [ 'Both', 'Shows both Bullets and Closeness' ]
  826. ]
  827. ],
  828.  
  829. menuLabel = [
  830. 'Minimise the Menu, can be reopened by pressing T',
  831. 'Return back to the previous menu',
  832. 'Close THNet chat, can be reopened by pressing CTRL',
  833. 'TioHax Cheat Menu',
  834. 'THNet Serverwide Chat'
  835. ],
  836.  
  837. loadedLocalisation = {},
  838.  
  839. //for if the player has made friends on the enemy team
  840. friends = [],
  841.  
  842. //for if the player wants to really kill someone
  843. targets = [],
  844.  
  845. //muted players who you don't want to hear text from
  846. muted = [],
  847.  
  848. //0 = friends
  849. playermanagerSelectedMenu = 0,
  850.  
  851. //the divs that make up the cheat menu
  852. divs = {
  853. menu: 0,
  854. title: 0,
  855. chatbox: 0,
  856. content: 0,
  857. chatwrap: 0,
  858. chatinput: 0,
  859. backbutton: 0
  860. },
  861.  
  862. //selected perk slot for auto upgrade menu
  863. selectedPerkSlot = 1,
  864.  
  865. //alternate chat bind messages so we don't get kicked for spam
  866. lastMessageLength = 0,
  867.  
  868. //key code map
  869. // http://www.foreui.com/articles/Key_Code_Table.htm
  870. keyCodeMap = {
  871. [KEYCODE_ESC]: 27, [KEYCODE_A]: 65, [KEYCODE_E]: 69,
  872. [KEYCODE_D]: 68, [KEYCODE_R]: 82, [KEYCODE_S]: 83,
  873. [KEYCODE_T]: 84, [KEYCODE_W]: 87, [KEYCODE_Z]: 90,
  874. [KEYCODE_ENTER]: 13, [KEYCODE_SPACE]: 32, [KEYCODE_ARROWLEFT]: 37,
  875. [KEYCODE_ARROWRIGHT]: 39, [KEYCODE_ARROWUP]: 38, [KEYCODE_ARROWDOWN]: 40,
  876. [KEYCODE_N]: 78, [KEYCODE_SHIFT]: 16, [KEYCODE_CTRL]: 17,
  877. },
  878.  
  879. autoUpgrades = [0, '', '', ''],
  880.  
  881. perks = [
  882. 'bipod', 'optics', 'thermal',
  883. 'armorPiercing', 'extended', 'grip',
  884. 'silencer', 'lightweight', 'longRange',
  885. 'thickSkin'
  886. ],
  887. abilities = [
  888. 'shield', 'firstAid', 'grenade',
  889. 'knife', 'engineer', 'ghillie',
  890. 'dash', 'gasGrenade', 'landMine',
  891. 'fragGrenade'
  892. ],
  893.  
  894. perkNames = {
  895. 'bipod': 'No Recoil',
  896. 'optics': 'Binoculars',
  897. 'thermal': 'Thermal',
  898. 'armorPiercing': 'Damage',
  899. 'extended': 'Large Mags',
  900. 'grip': '+Accuracy',
  901. 'silencer': 'Silencer',
  902. 'lightweight': 'Speed',
  903. 'longRange': 'Range',
  904. 'thickSkin': 'Kevlar',
  905. 'shield': 'Shield',
  906. 'firstAid': 'Medkit',
  907. 'grenade': 'Grenade',
  908. 'knife': 'Knife',
  909. 'engineer': 'Build',
  910. 'ghillie': 'Camo',
  911. 'dash': 'Dash',
  912. 'gasGrenade': 'Gas',
  913. 'landMine': 'Landmine',
  914. 'fragGrenade': 'Frag'
  915. },
  916.  
  917. aimbot = {
  918. [AIMBOT_ENABLE]: 0,
  919. [AIMBOT_AIMSMOOTHING]: 0,
  920. [AIMBOT_CURSORMODE]: 0,
  921. [AIMBOT_CURSORPROXCOSENESS]: 200,
  922. [AIMBOT_USEACCELERATION]: 0,
  923. [AIMBOT_IGNORECHATTING]: 0,
  924. [AIMBOT_PINGCOMPENSATION]: 0,
  925. [AIMBOT_WALLCHECK]: 0,
  926. [AIMBOT_USEAHEAD]: 0,
  927. [AIMBOT_DISABLEWHENDASHING]: 0,
  928. [AIMBOT_TRIGGERBOT]: 0,
  929. [AIMBOT_TRIGGERBOTWHENDOWN]: 0,
  930. [AIMBOT_TARGETMODE]: 0,
  931. [AIMBOT_RIGHTCLICKFRIEND]: 1,
  932. [AIMBOT_AUXCLICKTARGET]: 1,
  933. [AIMBOT_AVOIDFRIENDS]: 0,
  934. [AIMBOT_AHEADNESSDEPTH]: 0,
  935. [AIMBOT_LEADERMODE]: 0
  936. },
  937.  
  938. esp = {
  939. [ESP_ZOOM]: 0,
  940. [ESP_FIXCAMERA]: 0,
  941. [ESP_CAMUSEREALPOSITION]: 0,
  942. [ESP_TRACERSBODYENEMY]: 0,
  943. [ESP_TRACERSCURSORENEMY]: 0,
  944. [ESP_TRACERSWALLCHECK]: 0,
  945. [ESP_TRACERSGUN]: 0,
  946. [ESP_TRACERSGRENADES]: 0,
  947. [ESP_SHOWINVIS]: 0,
  948. [ESP_REVEALTEAMS]: 0,
  949. [ESP_SHOWHEALTH]: 0,
  950. [ESP_SHOWARMOR]: 0,
  951. [ESP_SHOWMAGS]: 0,
  952. [ESP_SHOWGUNRELOADSTATUS]: 0,
  953. [ESP_SHOWRANGE]: 0,
  954. [ESP_INCLUDEYOU]: 0,
  955. [ESP_SCROLLSENSITIVITY]: 1.1
  956. },
  957.  
  958. chatSpam = {
  959. [CHATSPAMMER_TEXT]: 'TioHax on top! http' + homeUrl,
  960. [CHATSPAMMER_INDEX]: 0,
  961. [CHATSPAMMER_WIDTH]: 30,
  962. [CHATSPAMMER_TIMEOUT]: 0,
  963. [CHATSPAMMER_INTERVAL]: 100,
  964. [CHATSPAMMER_VARIATION]: 0,
  965. [CHATSPAMMER_DIRECTION]: 1,
  966. [CHATSPAMMER_SEPERATOR]: ' # ',
  967. [CHATSPAMMER_PAUSEPERIOD]: 3000,
  968. [CHATSPAMMER_PREFIX]: '',
  969. [CHATSPAMMER_SUFFIX]: ''
  970. },
  971.  
  972. instantchat = {
  973. [INSTANTCHAT_ONKILL]: 0,
  974. [INSTANTCHAT_ONKILLTEXT]: '[[ENEMY]] just died to TioHax!',
  975. [INSTANTCHAT_ONDEATH]: 0,
  976. [INSTANTCHAT_ONDEATHTEXT]: '[[ENEMY]] = god awful',
  977. [INSTANTCHAT_AUTOTHANK]: 0,
  978. [INSTANTCHAT_AUTOTHANKTEXT]: 'I have been healed! Thank you!',
  979. [INSTANTCHAT_CHATBINDS]: 0,
  980. [INSTANTCHAT_CHATBINDSTEXTS]: {
  981. [keyCodeMap[KEYCODE_E]]: 'I need a medic!' ,
  982. [keyCodeMap[KEYCODE_Z]]: 'Put Build Blocks here!'
  983. }
  984. },
  985.  
  986. antiAim = {
  987. [ANTIAIM_RELOAD]: 0,
  988. [ANTIAIM_SHOOT]: 0,
  989. [ANTIAIM_IDLE]: 0,
  990. [ANTIAIM_ANGLESTART]: 0,
  991. [ANTIAIM_ANGLERANGE]: 0,
  992. [ANTIAIM_SPINSPEED]: 0,
  993. [ANTIAIM_DELAY]: 1,
  994. [ANTIAIM_SAVEDX]: 0,
  995. [ANTIAIM_SAVEDY]: 0
  996. },
  997.  
  998. recorder = {
  999. [RECORDER_ISRECORDING]: 0,
  1000. [RECORDER_ISPLAYING]: 0,
  1001. [RECORDER_CURRENT]: [],
  1002. [RECORDER_SESSIONS]: [],
  1003. [RECORDER_TIMEOUT]: 0,
  1004. [RECORDER_SESSIONTOPLAY]: -1
  1005. },
  1006.  
  1007. misc = {
  1008. [MISC_AUTORELOAD]: 0,
  1009. [MISC_PINGDISPLAY]: 0,
  1010. [MISC_RENDERDISPLAY]: 0,
  1011. [MISC_STATICHUD]: 0,
  1012. [MISC_STATICHEALTH]: 0,
  1013. [MISC_DISABLECLOSEPOPUP]: 0,
  1014. [MISC_BETTERCRATEHP]: 0,
  1015. [MISC_HIDECHATTING]: 0,
  1016. [MISC_FFACLANDISPLAY]: 0,
  1017. [MISC_SHOWFEATURES]: 0,
  1018. [MISC_POSITION]: 0,
  1019. [MISC_LEADERBOARDBADGES]: 0
  1020. },
  1021.  
  1022. advanced = {
  1023. [ADVANCED_PINGCOUNT]: 10,
  1024. [ADVANCED_AIMCONSTANT]: 1,
  1025. [ADVANCED_TPS]: 2.5,
  1026. [ADVANCED_OPTIMISEWALLCHECK]: 1,
  1027. [ADVANCED_PINGCOMP]: 25 // originally 40 because the server updates once every 40 ms, though 25 is a better number
  1028. },
  1029.  
  1030. perkHacks = {
  1031. [PERKHACKS_TICK]: 0,
  1032. [PERKHACKS_KNIFE]: 0,
  1033. [PERKHACKS_KNIFEMAXRANGE]: 100,
  1034. [PERKHACKS_SHIELD]: 0,
  1035. [PERKHACKS_SHIELDUPKEEP]: 5,
  1036. [PERKHACKS_STOREDANGLE]: 0,
  1037. [PERKHACKS_SHIELDMANUAL]: 0,
  1038. [PERKHACKS_SHIELDLOOKAHEAD]: 0,
  1039. [PERKHACKS_CRATEPLACEVISION]: 0,
  1040. [PERKHACKS_MEDKITSELFHEAL]: 0,
  1041. [PERKHACKS_MEDKITSELFHEALTHRESHOLD]: 50,
  1042. [PERKHACKS_SHIELDVISUALISER]: 0,
  1043. [PERKHACKS_SHIELDWALLCHECK]: 0
  1044. },
  1045.  
  1046. thnet = {
  1047. [THNET_ENABLE]: 1,
  1048. [THNET_SOCKET]: 0,
  1049. [THNET_CHAT]: 0,
  1050. [THNET_DONATE]: 0,
  1051. [THNET_CLOSEREASON]: '',
  1052. [THNET_AUTH]: '',
  1053. [THNET_BROTHERS]: [],
  1054. [THNET_INFOSHARE]: 0,
  1055. [THNET_INFOSHARING]: {},
  1056. [THNET_ENTEROPENCHAT]: 0
  1057. },
  1058.  
  1059. weird = {
  1060. [WEIRD_CURSORMOVE]: 0
  1061. },
  1062.  
  1063. discordRPC = {
  1064. [DISCORDRPC_ENABLED]: 0,
  1065. [DISCORDRPC_STATE]: 'State',
  1066. [DISCORDRPC_DETAILS]: 'Details',
  1067. [DISCORDRPC_UPDATEINTERVAL]: 30,
  1068. // ^^ = configurable | vv = internal
  1069. [DISCORDRPC_START]: Date.now(),
  1070. [DISCORDRPC_TIMEOUT]: 0,
  1071. [DISCORDRPC_CONNECTION]: 0,
  1072. [DISCORDRPC_CLIENTID]: '1050361019609927690',
  1073. [DISCORDRPC_TRIES]: 0,
  1074. [DISCORDRPC_ACCESSTOKEN]: '',
  1075. [DISCORDRPC_EXPECTING]: []
  1076. },
  1077.  
  1078. paint = {
  1079. [PAINT_GRIDSPACEX]: 20,
  1080. [PAINT_GRIDSPACEY]: 20,
  1081. [PAINT_GRIDLINEWIDTHHORIZONTAL]: 1,
  1082. [PAINT_GRIDLINEWIDTHVERTICAL]: 1,
  1083. [PAINT_GRIDCOLOR]: ['#e3e3e8', '#efeff5'],
  1084.  
  1085. [PAINT_POINTSIDLE]: ['#aaaaaa', '#f9f9f9'],
  1086. [PAINT_POINTSFFA]: ['#00cc66', '#f9f9f9'],
  1087. [PAINT_POINTSBLU]: ['#8dd8f8', '#f9f9f9'],
  1088. [PAINT_POINTSRED]: ['#f26740', '#f9f9f9'],
  1089. [PAINT_POINTEDGEWIDTH]: 4,
  1090.  
  1091. [PAINT_CRATESHOWHPMODE]: 2,
  1092. [PAINT_CRATESQUARE]: ['#808080', '#dfbf9f'],
  1093. [PAINT_CRATELONG]: ['#808080', '#bec8dd'],
  1094. [PAINT_CRATEUSER]: ['#808080', '#53c68c'],
  1095. [PAINT_CRATEPREMIUM]: ['#2e2d2d', '#f0ba37'],
  1096. [PAINT_CRATECORPSE]: ['#ffffff', '#ffffff'],
  1097.  
  1098. [PAINT_PRESETS]: [
  1099. [ 'Default' , 'Dygn' , 20, 20, 1, 1, ['#e3e3e8', '#efeff5'], ['#aaaaaa', '#f9f9f9'], ['#00cc66', '#f9f9f9'], ['#8dd8f8', '#f9f9f9'], ['#f26740', '#f9f9f9'], 4 , 2, ['#808080', '#dfbf9f'], ['#808080', '#bec8dd'], ['#808080', '#53c68c'], ['#2e2d2d', '#f0ba37'], ['#ffffff', '#ffffff'] ],
  1100. [ 'Vaakir Style' , 'Vaakir' , 20, 20, 1, 1, ['#e3e3e8', '#efeff5'], ['#aaaaaa', '#f9f9f9'], ['#00cc66', '#f9f9f9'], ['#8dd8f8', '#f9f9f9'], ['#f26740', '#f9f9f9'], 4 , 2, ['#4dd8f0', '#b1e9f9'], ['#303030', '#646464'], ['#808080', '#53c68c'], ['#2e2d2d', '#f0ba37'], ['#ffffff', '#ffffff'] ],
  1101. [ 'Drawn on Paper', 'Taureon', 40, 40, 1, 0, ["#a0a0a0", "#ffffff"], ["#808080", "#c4c4c4"], ["#00cc66", "#8fff91"], ["#00b3ff", "#94d1ff"], ["#f26740", "#ffa680"], 10, 2, ["#ff0000", "#ff9494"], ["#2b00ff", "#94b6ff"], ["#00ff04", "#7cfebd"], ["#ff8800", "#ffd470"], ["#ffffff", "#ffffff"] ]
  1102. ]
  1103. },
  1104.  
  1105. multiBox = {
  1106. [MULTIBOX_SELECTEDSOCKET]: 0,
  1107. [MULTIBOX_SPAWNCLONE]: 0,
  1108. [MULTIBOX_INSTANTRESPAWN]: 0
  1109. },
  1110.  
  1111. renderFunctions = [],
  1112.  
  1113. //this really doesnt need to exist but idc
  1114. pInt = parseInt,
  1115.  
  1116. getElementById = x => x && document.getElementById(x),
  1117.  
  1118. keyPress = (socketId, inputId, state) => RF.list[socketId]?.send(a59('key-press', {inputId, state: state * 1})),
  1119.  
  1120. startGunfire = socketId => keyPress(socketId, 6, cursor.isShooting = 1),
  1121. stopGunfire = socketId => keyPress(socketId, 6, cursor.isShooting = 0),
  1122.  
  1123. startActivePerk = socketId => keyPress(socketId, 5, 1),
  1124. stopActivePerk = socketId => keyPress(socketId, 5, 0),
  1125.  
  1126. startReloading = socketId => keyPress(socketId, 4, 1),
  1127. stopReloading = socketId => keyPress(socketId, 4, 0),
  1128.  
  1129. getPlayerHoveringOverOnLeaderboard = mouseEvent => {
  1130. if (j3 < 1 && j3 > 2.6) return '';
  1131. let offset = 0.03,
  1132. x = 1.7 * j13;
  1133. for (let entry of j38.current) {
  1134. if (!entry.userId) continue;
  1135. let y = (0.05 + offset) * j14;
  1136. offset += 0.045;
  1137. if (mouseEvent.x > x && mouseEvent.y > y && mouseEvent.x < x + 0.295 * j13 && mouseEvent.y < y + 0.04 * j14) {
  1138. return sanitiseName(entry.userId);
  1139. }
  1140. }
  1141. },
  1142.  
  1143. getPlayerHoveringOverInGame = mouseEvent => {
  1144. let me = RD.pool[c3],
  1145. x = c2.x + mouseEvent.x / j6,
  1146. y = c2.y + mouseEvent.y / j5;
  1147. for (let player of getPool(RD)) {
  1148. if (player.activated && player.id != me.id && getDistanceSquared(player, {x, y}, nullPos) <= (player[ATTRIBUTE_RADIUS] + 2 ) ** 2) {
  1149. return player[ATTRIBUTE_SANITIZEDNAME];
  1150. }
  1151. }
  1152. },
  1153.  
  1154. nonLeftClickPressHandler = (player, primaryList, secondaryList, enumClickToggle, enumSettingToggle) => {
  1155. if (player && aimbot[enumClickToggle]) {
  1156. toggleUsernameInlist(primaryList, player);
  1157. if (includesInArray(secondaryList, player)) toggleUsernameInlist(secondaryList, player);
  1158. } else {
  1159. aimbot[enumSettingToggle] = 1 - aimbot[enumSettingToggle];
  1160. saveSettings();
  1161. }
  1162. },
  1163.  
  1164. gameMouseUp = mouseEvent => {
  1165. if (!j17 && c3 && mouseEvent.which == MOUSEEVENT_LEFT) {
  1166. cursor.isPressed = 0;
  1167. stopGunfire(multiBox[MULTIBOX_SELECTEDSOCKET]);
  1168. }
  1169. j18 = {x: 0, y: 0};
  1170. },
  1171.  
  1172. gameMouseDown = mouseEvent => {
  1173. if ($('#loginModal' ).is(':visible') ||
  1174. $('#registerModal' ).is(':visible') ||
  1175. $('#aboutModal' ).is(':visible') ||
  1176. $('#privacyModal' ).is(':visible')) return;
  1177.  
  1178. j18 = {x: mouseEvent.clientX, y: mouseEvent.clientY};
  1179.  
  1180. if (j17 || c3 == null) return;
  1181.  
  1182. let playerHover = '';
  1183. if (mouseEvent.which !== MOUSEEVENT_LEFT && (aimbot[AIMBOT_RIGHTCLICKFRIEND] || aimbot[AIMBOT_AUXCLICKTARGET])) {
  1184. playerHover = getPlayerHoveringOverOnLeaderboard(mouseEvent) || getPlayerHoveringOverInGame(mouseEvent);
  1185. }
  1186.  
  1187. switch (mouseEvent.which) {
  1188. case MOUSEEVENT_LEFT:
  1189. if (aimbot[AIMBOT_TRIGGERBOTWHENDOWN] || !aimbot[AIMBOT_ENABLE] || !aimbot[AIMBOT_TRIGGERBOT]) startGunfire(multiBox[MULTIBOX_SELECTEDSOCKET]);
  1190. cursor.isPressed = 1;
  1191. break;
  1192.  
  1193. case MOUSEEVENT_MIDDLE:
  1194. nonLeftClickPressHandler(playerHover, targets, friends, AIMBOT_RIGHTCLICKFRIEND, AIMBOT_TARGETSONLY);
  1195. break;
  1196.  
  1197. case MOUSEEVENT_RIGHT:
  1198. nonLeftClickPressHandler(playerHover, friends, targets, AIMBOT_AUXCLICKTARGET, AIMBOT_ENABLE);
  1199. break;
  1200. }
  1201.  
  1202. //reset aiming direction to the cursor
  1203. if (aimbot[AIMBOT_ENABLE]) return;
  1204. aimMeAt({ clientX: cursor.x, clientY: cursor.y });
  1205. sendMousePositionToServer(multiBox[MULTIBOX_SELECTEDSOCKET]);
  1206. },
  1207.  
  1208. hashString = str => {
  1209. let hash = 0, i;
  1210. for (i = 0; i < str.length; i++) hash = (((hash << 5) - hash) + str.charCodeAt(i)) | 0;
  1211. return hash;
  1212. },
  1213.  
  1214. fetchFromServer = path => new Promise(Resolve => fetch('http' + homeUrl + path).then(res => res.text()).then(Resolve)),
  1215.  
  1216. // https://stackoverflow.com/questions/3977792/how-to-convert-keycode-to-character-using-javascript
  1217. keyCodeToLetter = key => String.fromCharCode((96 <= key && key <= 105) ? key - 48 : key),
  1218.  
  1219. clamp = (minVal, val, maxVal) => isNaN(val) ? minVal : min(maxVal, max(minVal, val)),
  1220.  
  1221. lerp = (a, b, t) => a + t * (b - a),
  1222.  
  1223. lerpR = (a, b, t) => round(lerp(a, b, t)),
  1224.  
  1225. spacePadding = (val, minLength = 3) => {
  1226. val = val.toString();
  1227. while (val.length < minLength) val = ' ' + val;
  1228. return val;
  1229. },
  1230.  
  1231. percentify = a => round(a * 100) + '%',
  1232.  
  1233. pressKey = keyCode => document.onkeydown({keyCode, [ATTRIBUTE_ISFROMCHEAT]: 1, preventDefault: ()=>{}}),
  1234. releaseKey = keyCode => document.onkeyup({keyCode, [ATTRIBUTE_ISFROMCHEAT]: 1, preventDefault: ()=>{}}),
  1235.  
  1236. sendChatMessage = (socketId, message, dontpause) => {
  1237. if (!dontpause) pauseChatScrolling();
  1238. lastMessageLength = message.length;
  1239. RF.list[socketId].send(a59('message', {message: message.replace(/,/g, '~')}));
  1240. },
  1241.  
  1242. //remove clan tags in tdm and dom
  1243. sanitiseName = username => username.replace(/\[[\d\w]{1,4}\] /, ''),
  1244.  
  1245. indexOfInArray = (arr, target) => {
  1246. for (let i = 0; i < arr.length; i++) if (arr[i] == target) return i;
  1247. return -1;
  1248. },
  1249.  
  1250. includesInArray = (arr, target) => {
  1251. for (let i = 0; i < arr.length; i++) if (arr[i] == target) return 1;
  1252. return 0;
  1253. },
  1254.  
  1255. getPool = R => {
  1256. if (!R) return;
  1257. return Object.values(R.pool);
  1258. },
  1259.  
  1260. discordRPCConnect = onConnected => {
  1261. const port = 6463 + (discordRPC[DISCORDRPC_TRIES]++ % 10);
  1262. discordRPC[DISCORDRPC_CONNECTION] = applyAttrbutes(new WebSocket('ws://127.0.0.1:' + port + '/?v=1&client_id=' + discordRPC[DISCORDRPC_CLIENTID]), {
  1263. 'onopen': onConnected,
  1264. 'onmessage': event => {
  1265. let message = JSON.parse(event.data),
  1266. nonce = message.nonce;
  1267. if (message.cmd === 'DISPATCH' && message.evt === 'READY') {
  1268. onConnected();
  1269. } else if (nonce in discordRPC[DISCORDRPC_EXPECTING]) {
  1270. const { y, n } = discordRPC[DISCORDRPC_EXPECTING][nonce];
  1271. if (message.evt === 'ERROR') {
  1272. const e = new Error(message.data.message);
  1273. e.code = message.data.code;
  1274. e.data = message.data;
  1275. n(e);
  1276. } else {
  1277. y(message.data);
  1278. }
  1279. delete discordRPC[DISCORDRPC_EXPECTING][nonce];
  1280. }
  1281. },
  1282. 'onerror': event => {
  1283. try {
  1284. discordRPC[DISCORDRPC_CONNECTION].close();
  1285. } catch {}
  1286. if (discordRPC[DISCORDRPC_TRIES] > 20) {
  1287. //TODO: handle error of there being no discord client
  1288. } else {
  1289. setTimeout(discordRPCConnect, 250);
  1290. }
  1291. },
  1292. 'onclose': event => {
  1293. if (event.wasClean) for (let e of discordRPC[DISCORDRPC_EXPECTING]) e.n(new Error('connection closed'));
  1294. discordRPC[DISCORDRPC_CONNECTION] = 0;
  1295. }
  1296. });
  1297. },
  1298.  
  1299. discordRPCStart = () => {
  1300. let discordRPCUpdate = () => discordRPCActivitySet(discordRPC[DISCORDRPC_TIMEOUT] = setTimeout(discordRPCUpdate, discordRPC[DISCORDRPC_UPDATEINTERVAL] * 1e3));
  1301. discordRPCConnect(discordRPCUpdate);
  1302. },
  1303.  
  1304. discordRPCRequest = (cmd, args, evt) => {
  1305. return new Promise((y, n) => {
  1306. let nonce = random() + ''; //good enough
  1307. if (discordRPC[DISCORDRPC_CONNECTION].readyState == 'OPEN') discordRPC[DISCORDRPC_CONNECTION].send(JSON.stringify({ cmd, args, evt, nonce }));
  1308. discordRPC[DISCORDRPC_EXPECTING][nonce] = { y, n };
  1309. });
  1310. },
  1311.  
  1312. discordRPCActivitySet = () => {
  1313. discordRPCRequest('SET_ACTIVITY', {
  1314. pid: null,
  1315. activity: {
  1316. state: discordRPC[DISCORDRPC_STATE],
  1317. details: discordRPC[DISCORDRPC_DETAILS],
  1318. timestamps: { start: discordRPC[DISCORDRPC_START], end: undefVar },
  1319. assets: { large_image: 'tiohax_icon', large_text: 'TioHax Cheat Menu', small_image: 'gatsio_favicon', small_text: 'On Gats.io' },
  1320. buttons: undefVar,
  1321. instance: false,
  1322. },
  1323. });
  1324. },
  1325.  
  1326. discordRPCActivityClear = () => discordRPCRequest('SET_ACTIVITY', { pid: null }),
  1327.  
  1328. saveSettings = () => {
  1329. //TODO: multibox stop fire on everything
  1330. stopGunfire(multiBox[MULTIBOX_SELECTEDSOCKET]);
  1331. for (let func of renderFunctions) func();
  1332. localStorage.setItem('TioHax_settings', JSON.stringify([
  1333. friends.filter(x => !x.startsWith('Guest ')),
  1334. targets.filter(x => !x.startsWith('Guest ')),
  1335. autoUpgrades,
  1336. [
  1337. aimbot[AIMBOT_ENABLE],
  1338. aimbot[AIMBOT_AIMSMOOTHING],
  1339. aimbot[AIMBOT_CURSORMODE],
  1340. aimbot[AIMBOT_USEACCELERATION],
  1341. aimbot[AIMBOT_IGNORECHATTING],
  1342. aimbot[AIMBOT_PINGCOMPENSATION],
  1343. aimbot[AIMBOT_TRIGGERBOT],
  1344. aimbot[AIMBOT_WALLCHECK],
  1345. aimbot[AIMBOT_USEAHEAD],
  1346. aimbot[AIMBOT_DISABLEWHENDASHING],
  1347. aimbot[AIMBOT_CURSORPROXCOSENESS],
  1348. aimbot[AIMBOT_TARGETMODE],
  1349. aimbot[AIMBOT_TRIGGERBOTWHENDOWN],
  1350. aimbot[AIMBOT_RIGHTCLICKFRIEND],
  1351. aimbot[AIMBOT_AUXCLICKTARGET],
  1352. aimbot[AIMBOT_TARGETSONLY],
  1353. aimbot[AIMBOT_AVOIDFRIENDS],
  1354. aimbot[AIMBOT_AHEADNESSDEPTH],
  1355. aimbot[AIMBOT_LEADERMODE]
  1356. ],[
  1357. esp[ESP_ZOOM],
  1358. esp[ESP_FIXCAMERA],
  1359. esp[ESP_TRACERSBODYENEMY],
  1360. esp[ESP_TRACERSCURSORENEMY],
  1361. esp[ESP_TRACERSWALLCHECK],
  1362. esp[ESP_TRACERSGUN],
  1363. esp[ESP_TRACERSGRENADES],
  1364. esp[ESP_SHOWINVIS],
  1365. esp[ESP_REVEALTEAMS],
  1366. esp[ESP_SHOWHEALTH],
  1367. esp[ESP_SHOWARMOR],
  1368. esp[ESP_SHOWMAGS],
  1369. esp[ESP_SHOWGUNRELOADSTATUS],
  1370. esp[ESP_CAMUSEREALPOSITION],
  1371. esp[ESP_INCLUDEYOU],
  1372. esp[ESP_SHOWRANGE],
  1373. esp[ESP_SCROLLSENSITIVITY]
  1374. ],[
  1375. chatSpam[CHATSPAMMER_TEXT],
  1376. chatSpam[CHATSPAMMER_WIDTH],
  1377. chatSpam[CHATSPAMMER_INTERVAL],
  1378. chatSpam[CHATSPAMMER_DIRECTION],
  1379. chatSpam[CHATSPAMMER_SEPERATOR],
  1380. chatSpam[CHATSPAMMER_PREFIX],
  1381. chatSpam[CHATSPAMMER_SUFFIX]
  1382. ],[
  1383. antiAim[ANTIAIM_RELOAD],
  1384. antiAim[ANTIAIM_SHOOT],
  1385. antiAim[ANTIAIM_IDLE],
  1386. antiAim[ANTIAIM_ANGLESTART],
  1387. antiAim[ANTIAIM_ANGLERANGE],
  1388. antiAim[ANTIAIM_SPINSPEED],
  1389. antiAim[ANTIAIM_DELAY],
  1390. antiAim[ANTIAIM_DRAWREALAIM]
  1391. ],[
  1392. instantchat[INSTANTCHAT_CHATBINDS],
  1393. instantchat[INSTANTCHAT_CHATBINDSTEXTS],
  1394. instantchat[INSTANTCHAT_ONKILL],
  1395. instantchat[INSTANTCHAT_ONKILLTEXT],
  1396. instantchat[INSTANTCHAT_ONDEATH],
  1397. instantchat[INSTANTCHAT_ONDEATHTEXT],
  1398. instantchat[INSTANTCHAT_AUTOTHANK],
  1399. instantchat[INSTANTCHAT_AUTOTHANKTEXT]
  1400. ],[
  1401. misc[MISC_AUTORELOAD],
  1402. misc[MISC_PINGDISPLAY],
  1403. misc[MISC_RENDERDISPLAY],
  1404. misc[MISC_STATICHUD],
  1405. misc[MISC_STATICHEALTH],
  1406. misc[MISC_DISABLECLOSEPOPUP],
  1407. misc[MISC_BETTERCRATEHP],
  1408. misc[MISC_HIDECHATTING],
  1409. misc[MISC_FFACLANDISPLAY],
  1410. misc[MISC_SHOWFEATURES],
  1411. misc[MISC_POSITION],
  1412. misc[MISC_LEADERBOARDBADGES]
  1413. ],[
  1414. advanced[ADVANCED_PINGCOUNT],
  1415. advanced[ADVANCED_AIMCONSTANT],
  1416. advanced[ADVANCED_OPTIMISEWALLCHECK],
  1417. advanced[ADVANCED_TPS],
  1418. advanced[ADVANCED_PINGCOMP]
  1419. ],[
  1420. thnet[THNET_ENABLE],
  1421. thnet[THNET_CHAT],
  1422. thnet[THNET_DONATE],
  1423. thnet[THNET_INFOSHARE]
  1424. ],
  1425. muted.filter(x => !x.startsWith('Guest ')),
  1426. [
  1427. perkHacks[PERKHACKS_KNIFE],
  1428. perkHacks[PERKHACKS_KNIFEMAXRANGE],
  1429. perkHacks[PERKHACKS_SHIELD],
  1430. perkHacks[PERKHACKS_SHIELDUPKEEP],
  1431. perkHacks[PERKHACKS_SHIELDMANUAL],
  1432. perkHacks[PERKHACKS_CRATEPLACEVISION],
  1433. perkHacks[PERKHACKS_SHIELDLOOKAHEAD],
  1434. perkHacks[PERKHACKS_MEDKITSELFHEAL],
  1435. perkHacks[PERKHACKS_MEDKITSELFHEALTHRESHOLD],
  1436. perkHacks[PERKHACKS_SHIELDVISUALISER],
  1437. perkHacks[PERKHACKS_SHIELDWALLCHECK]
  1438. ],[
  1439. // discordRPC[DISCORDRPC_ENABLED],
  1440. // discordRPC[DISCORDRPC_STATE],
  1441. // discordRPC[DISCORDRPC_DETAILS],
  1442. // discordRPC[DISCORDRPC_UPDATEINTERVAL]
  1443. ],[
  1444. paint[PAINT_GRIDSPACEX],
  1445. paint[PAINT_GRIDSPACEY],
  1446. paint[PAINT_GRIDLINEWIDTHHORIZONTAL],
  1447. paint[PAINT_GRIDLINEWIDTHVERTICAL],
  1448. paint[PAINT_GRIDCOLOR],
  1449. paint[PAINT_POINTSIDLE],
  1450. paint[PAINT_POINTSFFA],
  1451. paint[PAINT_POINTSBLU],
  1452. paint[PAINT_POINTSRED],
  1453. paint[PAINT_POINTEDGEWIDTH],
  1454. paint[PAINT_CRATESHOWHPMODE],
  1455. paint[PAINT_CRATESQUARE],
  1456. paint[PAINT_CRATELONG],
  1457. paint[PAINT_CRATEUSER],
  1458. paint[PAINT_CRATEPREMIUM],
  1459. paint[PAINT_CRATECORPSE],
  1460. paint[PAINT_PRESETS]
  1461. ],[
  1462. multiBox[MULTIBOX_SELECTEDSOCKET],
  1463. multiBox[MULTIBOX_SPAWNCLONE],
  1464. multiBox[MULTIBOX_INSTANTRESPAWN]
  1465. ]
  1466. ]));
  1467. },
  1468.  
  1469. loadSettings = () => {
  1470. let data = JSON.parse(localStorage.getItem('TioHax_settings') || '{}'),
  1471. stuffToLoad = [
  1472. [friends
  1473. ],
  1474. [targets
  1475. ],
  1476. [autoUpgrades
  1477. ],
  1478. [aimbot,
  1479. AIMBOT_ENABLE + AIMBOT_AIMSMOOTHING + AIMBOT_CURSORMODE + AIMBOT_USEACCELERATION +
  1480. AIMBOT_IGNORECHATTING + AIMBOT_PINGCOMPENSATION + AIMBOT_TRIGGERBOT + AIMBOT_WALLCHECK +
  1481. AIMBOT_USEAHEAD + AIMBOT_DISABLEWHENDASHING + AIMBOT_CURSORPROXCOSENESS + AIMBOT_TARGETMODE +
  1482. AIMBOT_TRIGGERBOTWHENDOWN + AIMBOT_RIGHTCLICKFRIEND + AIMBOT_AUXCLICKTARGET + AIMBOT_TARGETSONLY +
  1483. AIMBOT_AVOIDFRIENDS + AIMBOT_AHEADNESSDEPTH + AIMBOT_LEADERMODE
  1484. ],
  1485. [esp,
  1486. ESP_ZOOM + ESP_FIXCAMERA + ESP_TRACERSBODYENEMY + ESP_TRACERSCURSORENEMY +
  1487. ESP_TRACERSWALLCHECK + ESP_TRACERSGUN + ESP_TRACERSGRENADES + ESP_SHOWINVIS +
  1488. ESP_REVEALTEAMS + ESP_SHOWHEALTH + ESP_SHOWARMOR + ESP_SHOWMAGS +
  1489. ESP_SHOWGUNRELOADSTATUS + ESP_CAMUSEREALPOSITION + ESP_INCLUDEYOU + ESP_SHOWRANGE +
  1490. ESP_SCROLLSENSITIVITY],
  1491. [chatSpam,
  1492. CHATSPAMMER_TEXT + CHATSPAMMER_WIDTH + CHATSPAMMER_INTERVAL + CHATSPAMMER_DIRECTION +
  1493. CHATSPAMMER_SEPERATOR + CHATSPAMMER_PREFIX + CHATSPAMMER_SUFFIX
  1494. ],
  1495. [antiAim,
  1496. ANTIAIM_RELOAD + ANTIAIM_SHOOT + ANTIAIM_IDLE + ANTIAIM_ANGLESTART +
  1497. ANTIAIM_ANGLERANGE + ANTIAIM_SPINSPEED + ANTIAIM_DELAY + ANTIAIM_DRAWREALAIM
  1498. ],
  1499. [instantchat,
  1500. INSTANTCHAT_CHATBINDS + INSTANTCHAT_CHATBINDSTEXTS + INSTANTCHAT_ONKILL + INSTANTCHAT_ONKILLTEXT +
  1501. INSTANTCHAT_ONDEATH + INSTANTCHAT_ONDEATHTEXT + INSTANTCHAT_AUTOTHANK + INSTANTCHAT_AUTOTHANKTEXT
  1502. ],
  1503. [misc,
  1504. MISC_AUTORELOAD + MISC_PINGDISPLAY + MISC_RENDERDISPLAY + MISC_STATICHUD +
  1505. MISC_STATICHEALTH + MISC_DISABLECLOSEPOPUP + MISC_BETTERCRATEHP + MISC_HIDECHATTING +
  1506. MISC_FFACLANDISPLAY + MISC_SHOWFEATURES + MISC_POSITION + MISC_LEADERBOARDBADGES
  1507. ],
  1508. [advanced,
  1509. ADVANCED_PINGCOUNT + ADVANCED_AIMCONSTANT + ADVANCED_OPTIMISEWALLCHECK + ADVANCED_TPS +
  1510. ADVANCED_PINGCOMP
  1511. ],
  1512. [thnet,
  1513. THNET_ENABLE + THNET_CHAT + THNET_DONATE + THNET_INFOSHARE
  1514. ],
  1515. [muted
  1516. ],
  1517. [perkHacks,
  1518. PERKHACKS_KNIFE + PERKHACKS_KNIFEMAXRANGE + PERKHACKS_SHIELD + PERKHACKS_SHIELDUPKEEP +
  1519. PERKHACKS_SHIELDMANUAL + PERKHACKS_CRATEPLACEVISION + PERKHACKS_SHIELDLOOKAHEAD + PERKHACKS_MEDKITSELFHEAL +
  1520. PERKHACKS_MEDKITSELFHEALTHRESHOLD + PERKHACKS_SHIELDVISUALISER + PERKHACKS_SHIELDWALLCHECK
  1521. ],
  1522. [discordRPC,
  1523. DISCORDRPC_ENABLED + DISCORDRPC_STATE + DISCORDRPC_DETAILS + DISCORDRPC_UPDATEINTERVAL
  1524. ],
  1525. [paint,
  1526. PAINT_GRIDSPACEX + PAINT_GRIDSPACEY + PAINT_GRIDLINEWIDTHHORIZONTAL + PAINT_GRIDLINEWIDTHVERTICAL +
  1527. PAINT_GRIDCOLOR + PAINT_POINTSIDLE + PAINT_POINTSFFA + PAINT_POINTSBLU +
  1528. PAINT_POINTSRED + PAINT_POINTEDGEWIDTH + PAINT_CRATESHOWHPMODE + PAINT_CRATESQUARE +
  1529. PAINT_CRATELONG + PAINT_CRATEUSER + PAINT_CRATEPREMIUM + PAINT_CRATECORPSE +
  1530. PAINT_PRESETS
  1531. ],
  1532. [multiBox,
  1533. MULTIBOX_SELECTEDSOCKET + MULTIBOX_SPAWNCLONE + MULTIBOX_INSTANTRESPAWN
  1534. ]
  1535. ];
  1536. for (let i = 0; i < stuffToLoad.length; i++) if (undefVar != data[i]) {
  1537. let renameThisLater = stuffToLoad[i],
  1538. [settingStorageObject, keystring] = renameThisLater;
  1539. if (keystring) {
  1540. for (let j = 0; j < keystring.length; j++) {
  1541. if (undefVar == data[i][j]) continue;
  1542. settingStorageObject[keystring[j]] = data[i][j];
  1543. }
  1544. } else {
  1545. settingStorageObject.length = 0; //this clears arrays because then the array class forgets that there were elements in it
  1546. settingStorageObject.push(...data[i]);
  1547. }
  1548. }
  1549. },
  1550.  
  1551. drawLineWrap = (x1, y1, x2, y2, w, c) => {
  1552. ctx.strokeStyle = c;
  1553. ctx.lineWidth = w;
  1554. ctx.beginPath();
  1555. ctx.moveTo(x1, y1);
  1556. ctx.lineTo(x2, y2);
  1557. ctx.stroke();
  1558. },
  1559.  
  1560. drawLine = (start, entity, offset, width, color) => drawLineWrap(
  1561. start.x, start.y,
  1562. entity.x + offset.x, entity.y + offset.y,
  1563. width,
  1564. color || getColor(entity)
  1565. ),
  1566.  
  1567. drawLine2 = (entity, end, offset, width, color) => drawLineWrap(
  1568. entity.x + offset.x,
  1569. entity.y + offset.y,
  1570. entity.x + offset.x + end.x,
  1571. entity.y + offset.y + end.y,
  1572. width,
  1573. color || getColor(entity)
  1574. ),
  1575.  
  1576. drawCircle = (entity, offset, radius, width, color) => {
  1577. ctx.strokeStyle = color || getColor(entity);
  1578. ctx.lineWidth = width;
  1579. ctx.beginPath();
  1580. ctx.moveTo(entity.x + offset.x + radius, entity.y + offset.y);
  1581. ctx.arc(entity.x + offset.x, entity.y + offset.y, radius, 0, TAU);
  1582. ctx.stroke();
  1583. },
  1584.  
  1585. drawCircle2 = (entity, offset, radius, width, color) => {
  1586. for (let i = 0; i < 3; i++) {
  1587. ctx.globalAlpha /= 2;
  1588. drawCircle(entity, offset, radius - width * i, width, color);
  1589. }
  1590. },
  1591.  
  1592. //text drawer wrapper
  1593. drawText = (x, y, text, color) => {
  1594. ctx.fillStyle = color;
  1595. ctx.lineWidth = 1;
  1596. ctx.strokeStyle = '#000';
  1597. ctx.fillText(text, x, y);
  1598. ctx.strokeText(text, x, y);
  1599. },
  1600.  
  1601. CLLonSegment = (p0, p1, q0, q1, r0, r1) => q0 <= max(p0, r0) && q0 >= min(p0, r0) && q1 <= max(p1, r1) && q1 >= min(p1, r1),
  1602.  
  1603. CLLorientation = (p0, p1, q0, q1, r0, r1) => {
  1604.  
  1605. // See https://www.geeksforgeeks.org/orientation-3-ordered-points/
  1606. // for details of below formula.
  1607. let v = (q1 - p1) * (r0 - q0) - (q0 - p0) * (r1 - q1);
  1608.  
  1609. return !v ? 0 : // collinear
  1610. v > 0 ? 1 : 2; // clock or counterclock wise
  1611. },
  1612.  
  1613. collisionLineLine = (p10, p11, q10, q11, p20, p21, q20, q21) => {
  1614.  
  1615. // Find the four orientations needed for general and
  1616. // special cases
  1617. let o1 = CLLorientation(p10, p11, q10, q11, p20, p21),
  1618. o2 = CLLorientation(p10, p11, q10, q11, q20, q21),
  1619. o3 = CLLorientation(p20, p21, q20, q21, p10, p11),
  1620. o4 = CLLorientation(p20, p21, q20, q21, q10, q11);
  1621. // General case
  1622. if (o1 != o2 && o3 != o4) return 1;
  1623. // Special Cases
  1624. return (
  1625. (o1 == 0 && CLLonSegment(p10, p11, p20, p21, q10, q11)) ||
  1626. (o2 == 0 && CLLonSegment(p10, p11, q20, q21, q10, q11)) ||
  1627. (o3 == 0 && CLLonSegment(p20, p21, p10, p11, q20, q21)) ||
  1628. (o4 == 0 && CLLonSegment(p20, p21, q10, q11, q20, q21))
  1629. );
  1630. },
  1631.  
  1632. // https://stackoverflow.com/a/1968345/10793061 but a comment by the god called cortijon
  1633. intersectionPointLineLine = (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) => {
  1634. let s1_x = p1_x - p0_x,
  1635. s1_y = p1_y - p0_y,
  1636. s2_x = p3_x - p2_x,
  1637. s2_y = p3_y - p2_y,
  1638. s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y),
  1639. t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
  1640. if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
  1641. return {
  1642. x: p0_x + t * s1_x,
  1643. y: p0_y + t * s1_y
  1644. };
  1645. }
  1646. },
  1647.  
  1648. distanceSquaredBetweenPoints = (Ax, Ay, Bx, By) => (Ax - Bx) ** 2 + (Ay - By) ** 2,
  1649.  
  1650. //https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
  1651. distanceSquaredLinePoint = (Ax, Ay, Bx, By, Cx, Cy) => {
  1652. if (Ax === Bx && Ay === By) return distanceSquaredBetweenPoints(Cx, Cy, Ax, Ay);
  1653. let t = max(0, min(1, ((Cx - Ax) * (Bx - Ax) + (Cy - Ay) * (By - Ay)) / distanceSquaredBetweenPoints(Cx, Cy, Ax, Ay)));
  1654. return distanceSquaredBetweenPoints(Cx, Cy, Ax + t * (Bx - Ax), Ay + t * (By - Ay));
  1655. },
  1656.  
  1657. upgradePerk = (socketId, upgrade, upgradeLevel) => {
  1658. o3[upgradeLevel] = upgrade;
  1659. RF.list[socketId].send(a59('upgrade', {upgrade, upgradeLevel}));
  1660. c8[upgradeLevel] = 0;
  1661. },
  1662.  
  1663. autoUpgrade = (socketId, me) => {
  1664. if ((me.score >= c33 || c10 >= 1) && !o3[1] && autoUpgrades[1]) upgradePerk(socketId, autoUpgrades[1], 1);
  1665. if ((me.score >= c34 || c10 >= 2) && !o3[2] && autoUpgrades[2]) upgradePerk(socketId, autoUpgrades[2], 2);
  1666. if ((me.score >= c35 || c10 >= 3) && !o3[3] && autoUpgrades[3]) upgradePerk(socketId, autoUpgrades[3], 3);
  1667. },
  1668.  
  1669. /*gets the color of an enemy by its team affiliation
  1670. -FFA player colors-
  1671. red: {a: '#f26740', b: '#fcd9cf'}
  1672. orange: {a: '#f6803c', b: '#fddfce'}
  1673. yellow: {a: '#fff133', b: '#fffccc'}
  1674. green: {a: '#92cd8b', b: '#ddf0db'}
  1675. blue: {a: '#8dd8f8', b: '#cfeefc'}
  1676. pink: {a: '#f7b0c2', b: '#fde8ed'}
  1677. */
  1678. getColor = entity => {
  1679. //fix for FFA
  1680. if (entity.ownerId && !entity.teamCode) return RD.pool[c3].id == entity.ownerId ? 'green' : 'red';
  1681.  
  1682. return entity.teamCode == 2 ? 'blue' : entity.teamCode == 1 ? 'red' : {
  1683. '#f26740': 'red',
  1684. '#f6803c': 'orange',
  1685. '#fff133': 'yellow',
  1686. '#92cd8b': 'green',
  1687. '#8dd8f8': 'blue',
  1688. '#f7b0c2': 'hotpink'
  1689. }[entity.color.a];
  1690. },
  1691.  
  1692. //either add them or remove them from the friends list depending on if they are already in it or not
  1693. toggleUsernameInlist = (list, username) => {
  1694. username = sanitiseName(username);
  1695. let index = indexOfInArray(list, username);
  1696.  
  1697. //if the player doesnt exist in the list, add them
  1698. if (index == -1) {
  1699. list.push(username);
  1700.  
  1701. //if the player does exist, delete them from the list
  1702. } else if (index == list.length - 1){
  1703. list.pop();
  1704. } else {
  1705. list[index] = list.pop();
  1706. }
  1707.  
  1708. saveSettings();
  1709. },
  1710.  
  1711. applyAttrbutes = (object, attributes) => {
  1712. for (let key in attributes) object[key] = attributes[key];
  1713. return object;
  1714. },
  1715.  
  1716. applyStyle = (element, style) => applyAttrbutes(element.style, style),
  1717.  
  1718. make = (type, style = {}, attributes = {}, babies = []) => {
  1719. let element = document.createElement(type);
  1720. applyStyle(element, style);
  1721. applyAttrbutes(element, attributes);
  1722. for (let baby of babies) element.append(baby);
  1723. return element;
  1724. },
  1725.  
  1726. //note: elements cannot be placed at two places at once
  1727. dupeImg = img => {
  1728. let element = make('canvas', {
  1729. [css_key_width]: css_value_length_perc100,
  1730. [css_key_height]: css_value_length_perc100
  1731. }, {
  1732. [css_key_width]: img.width,
  1733. [css_key_height]: img.height
  1734. });
  1735. element.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
  1736. return element;
  1737. },
  1738.  
  1739. //if a menu requires a canvas for whatever reason
  1740. //this function would later be re-defined in a menu
  1741. updateMenuCanvas = () => {},
  1742.  
  1743. stopChatScrolling = () => {
  1744. //surprisingly, clearTimeout doesn't throw an error if the argument is zero...
  1745. clearTimeout(chatSpam[CHATSPAMMER_TIMEOUT]);
  1746. chatSpam[CHATSPAMMER_TIMEOUT] = 0;
  1747. },
  1748.  
  1749. startChatScrolling = socketId => {
  1750. stopChatScrolling();
  1751. let chatSpamLoop = () => {
  1752. let text = chatSpam[CHATSPAMMER_TEXT] + chatSpam[CHATSPAMMER_SEPERATOR],
  1753. index = chatSpam[CHATSPAMMER_INDEX],
  1754. width = chatSpam[CHATSPAMMER_WIDTH] - (chatSpam[CHATSPAMMER_PREFIX].length + chatSpam[CHATSPAMMER_SUFFIX].length),
  1755. msg = text.length ? '' : ' ',
  1756. pad = ' '.repeat(chatSpam[CHATSPAMMER_VARIATION]);
  1757.  
  1758. if (!msg) for (let i = 0; i < width; i++) msg += text[(index + i) % text.length];
  1759. //the padding exists because the game kicks you for sending messages with the same length often
  1760. sendChatMessage(socketId, pad + chatSpam[CHATSPAMMER_PREFIX] + msg + chatSpam[CHATSPAMMER_SUFFIX] + pad, 1);
  1761.  
  1762. chatSpam[CHATSPAMMER_INDEX] = (index + chatSpam[CHATSPAMMER_DIRECTION] + text.length) % text.length;
  1763. chatSpam[CHATSPAMMER_VARIATION] = (chatSpam[CHATSPAMMER_VARIATION] + 1) % 3;
  1764. chatSpam[CHATSPAMMER_TIMEOUT] = setTimeout(chatSpamLoop, chatSpam[CHATSPAMMER_INTERVAL]);
  1765. };
  1766. chatSpamLoop();
  1767. },
  1768.  
  1769. pauseChatScrolling = socketId => {
  1770. if (!chatSpam[CHATSPAMMER_TIMEOUT]) return;
  1771. stopChatScrolling(socketId);
  1772. //to not conflict if this function was called another time
  1773. let localRandom = random();
  1774. chatBoxRandom = localRandom;
  1775. setTimeout(() => chatBoxRandom == localRandom && startChatScrolling(socketId), chatSpam[CHATSPAMMER_PAUSEPERIOD]);
  1776. },
  1777.  
  1778. removeChildren = element => {
  1779. while (element.hasChildNodes()) element.removeChild(element.lastChild);
  1780. },
  1781.  
  1782. checkScrollable = (bool, element, style) => {
  1783. bool = divs.content.scrollHeight > divs.content.clientHeight;
  1784. element = divs.content.lastChild;
  1785. style = element.style;
  1786. applyStyle(element, {
  1787. [css_key_borderBottom]: bool ? css_value_length_px0 : css_value_border_2px000f,
  1788. [css_key_height]: (pInt(style.height) - (4 - 2 * pInt(style.borderBottom || style.border))) + 'px'
  1789. });
  1790. },
  1791.  
  1792. loadLocalisationFile = fileStr => {
  1793. loadedLocalisation = {};
  1794. let entries = fileStr.split('\n');
  1795. for (let i = 0; i < entries.length; i++) {
  1796. let entry = entries[i],
  1797. index = indexOfInArray(entry, '=');
  1798. if (index == -1) continue;
  1799. let key = entry.slice(0, index),
  1800. value = entry.slice(index + 1, entry.length);
  1801. loadedLocalisation[key] = value;
  1802. }
  1803. },
  1804.  
  1805. getLocal = localisationEntry => loadedLocalisation[localisationEntry] ?? localisationEntry,
  1806.  
  1807. createControlBase = (label, controlSetting) => label && make('div', {
  1808. [css_key_width]: css_value_length_perc100,
  1809. [css_key_height]: css_value_length_px40,
  1810. [css_key_display]: css_value_misc_flex,
  1811. [css_key_alignItems]: css_value_misc_center,
  1812. [css_key_paddingLeft]: css_value_length_px5,
  1813. [css_key_paddingRight]: css_value_length_px5,
  1814. [css_key_borderBottom]: css_value_border_2px000f,
  1815. [css_key_paddingBottom]: css_value_length_px0,
  1816. [css_key_justifyContent]: css_value_misc_spaceBetween
  1817. }, {
  1818. title: getLocal(label[1])
  1819. }, [
  1820. make('div', {}, {
  1821. innerText: getLocal(label[0])
  1822. }),
  1823. controlSetting
  1824. ]),
  1825.  
  1826. createControlButton = (label, doThing) => {
  1827. return createControlBase(label, make('div', {
  1828. [css_key_width]: css_value_length_px45,
  1829. [css_key_height]: css_value_length_px30,
  1830. [css_key_border]: css_value_border_4pxffff,
  1831. [css_key_position]: css_value_misc_relative,
  1832. [css_key_borderRadius]: css_value_length_px7,
  1833. [css_key_backgroundColor]: css_value_color_33dc
  1834. }, {
  1835. onclick: () => {
  1836. saveSettings();
  1837. doThing();
  1838. }
  1839. }));
  1840. },
  1841.  
  1842. createControlToggle = (label, toggle, render) => {
  1843. let controlButtonDiv = make('div', {
  1844. [css_key_width]: css_value_length_px60,
  1845. [css_key_height]: css_value_length_px30,
  1846. [css_key_border]: css_value_border_4pxffff,
  1847. [css_key_display]: css_value_misc_flex,
  1848. [css_key_position]: css_value_misc_relative,
  1849. [css_key_alignItems]: css_value_misc_center,
  1850. [css_key_borderRadius]: css_value_length_px7,
  1851. [css_key_justifyContent]: css_value_misc_center
  1852. }, {
  1853. onclick: () => {
  1854. toggle();
  1855. controlButtonDiv[ATTRIBUTE_UPDATE]();
  1856. saveSettings();
  1857. },
  1858. [ATTRIBUTE_UPDATE]: () => {
  1859. let bool = render();
  1860. controlButtonDiv.innerText = bool ? 'On' : 'Off';
  1861. applyStyle(controlButtonDiv, {
  1862. [css_key_backgroundColor]: bool ? css_value_color_0f0c : css_value_color_f00c
  1863. });
  1864. }
  1865. });
  1866. controlButtonDiv[ATTRIBUTE_UPDATE]();
  1867. renderFunctions.push(controlButtonDiv[ATTRIBUTE_UPDATE]);
  1868. return createControlBase(label, controlButtonDiv);
  1869. },
  1870.  
  1871. createControlValue = (label, update, render) => {
  1872. let style = {
  1873. [css_key_width]: css_value_length_px30,
  1874. [css_key_height]: css_value_length_px30,
  1875. [css_key_border]: css_value_border_3pxffff,
  1876. [css_key_display]: css_value_misc_flex,
  1877. [css_key_position]: css_value_misc_relative,
  1878. [css_key_fontWeight]: css_value_misc_bold,
  1879. [css_key_alignItems]: css_value_misc_center,
  1880. [css_key_borderRadius]: css_value_length_px5,
  1881. [css_key_justifyContent]: css_value_misc_center,
  1882. [css_key_backgroundColor]: css_value_color_ff0c
  1883. },
  1884. controlIndicatorDiv = make('div', {
  1885. [css_key_color]: css_value_color_000f,
  1886. [css_key_width]: css_value_length_px60,
  1887. [css_key_height]: css_value_length_px34,
  1888. [css_key_border]: css_value_border_4pxffff,
  1889. [css_key_display]: css_value_misc_flex,
  1890. [css_key_position]: css_value_misc_relative,
  1891. [css_key_alignItems]: css_value_misc_center,
  1892. [css_key_marginLeft]: css_value_length_px5,
  1893. [css_key_marginRight]: css_value_length_px5,
  1894. [css_key_borderRadius]: css_value_length_px5,
  1895. [css_key_justifyContent]: css_value_misc_center,
  1896. [css_key_backgroundColor]: css_value_color_fffc
  1897. }, {
  1898. //type: css_value_misc_text,
  1899. //maxlength: 64,
  1900. //onfocus: () => textBoxFocused = 1,
  1901. //onblur: () => textBoxFocused = 0,
  1902. //value: render(),
  1903. //oninput: () => {
  1904. // update(editAutoTextInput.value);
  1905. // controlIndicatorDiv[ATTRIBUTE_UPDATE]();
  1906. // saveSettings();
  1907. //},
  1908. onwheel: E => {
  1909. E.preventDefault();
  1910. update(sign(-E.deltaY));
  1911. controlIndicatorDiv[ATTRIBUTE_UPDATE](1);
  1912. },
  1913. [ATTRIBUTE_UPDATE]: shouldSave => {
  1914. controlIndicatorDiv.innerText = render();
  1915. if (shouldSave) saveSettings();
  1916. }
  1917. }),
  1918. controlButtonLeftDiv = make('div', style, {
  1919. innerText: '-',
  1920. onclick: () => {
  1921. update(-1);
  1922. controlIndicatorDiv[ATTRIBUTE_UPDATE](1);
  1923. }
  1924. }),
  1925. controlButtonRightDiv = make('div', style, {
  1926. innerText: '+',
  1927. onclick: () => {
  1928. update(1);
  1929. controlIndicatorDiv[ATTRIBUTE_UPDATE](1);
  1930. }
  1931. });
  1932. controlIndicatorDiv[ATTRIBUTE_UPDATE]();
  1933. renderFunctions.push(controlIndicatorDiv[ATTRIBUTE_UPDATE]);
  1934. return createControlBase(label, make('div', {
  1935. [css_key_display]: css_value_misc_flex,
  1936. [css_key_alignItems]: css_value_misc_center,
  1937. [css_key_flexDirection]: css_value_misc_row
  1938. }, {}, [controlButtonLeftDiv, controlIndicatorDiv, controlButtonRightDiv]));
  1939. },
  1940.  
  1941. createControlText = (label, update, render) => {
  1942. let editAutoTextInput = make('input', {
  1943. [css_key_color]: css_value_color_000f,
  1944. [css_key_width]: css_value_length_perc100,
  1945. [css_key_height]: css_value_length_px34,
  1946. [css_key_border]: css_value_border_4pxffff,
  1947. [css_key_display]: css_value_misc_flex,
  1948. [css_key_position]: css_value_misc_relative,
  1949. [css_key_alignItems]: css_value_misc_center,
  1950. [css_key_borderRadius]: css_value_length_px5,
  1951. [css_key_justifyContent]: css_value_misc_center,
  1952. [css_key_backgroundColor]: css_value_color_fffc
  1953. }, {
  1954. type: css_value_misc_text,
  1955. maxlength: 64,
  1956. onfocus: () => textBoxFocused = 1,
  1957. onblur: () => textBoxFocused = 0,
  1958. oninput: () => {
  1959. update(editAutoTextInput.value);
  1960. editAutoTextInput.value = render();
  1961. saveSettings();
  1962. },
  1963. value: render()
  1964. });
  1965. renderFunctions.push(() => editAutoTextInput.value = render());
  1966. return make('div', {
  1967. [css_key_width]: css_value_length_perc100,
  1968. [css_key_padding]: css_value_length_px5,
  1969. [css_key_paddingTop]: css_value_length_px0,
  1970. [css_key_borderBottom]: css_value_border_2px000f,
  1971. [css_key_paddingBottom]: css_value_length_px0,
  1972. [css_key_justifyContent]: css_value_misc_spaceBetween,
  1973. [css_key_height]: css_value_length_px80
  1974. }, {
  1975. title: getLocal(label[1])
  1976. }, [
  1977. make('div', {
  1978. [css_key_width]: css_value_length_perc100,
  1979. [css_key_display]: css_value_misc_flex,
  1980. [css_key_padding]: css_value_length_px5,
  1981. [css_key_justifyContent]: css_value_misc_spaceBetween,
  1982. [css_key_height]: css_value_length_px40
  1983. }, {
  1984. innerText: getLocal(label[0])
  1985. }),
  1986. editAutoTextInput
  1987. ]);
  1988. },
  1989.  
  1990. createControlDropdown = (label, options, update, render) => {
  1991. let longest = 0;
  1992. for (let optionValue in options) if (options[optionValue][0].length > longest) longest = options[optionValue][0].length;
  1993. longest = (longest + 4.5) + 'ch';
  1994.  
  1995. let i = render(),
  1996. optionCount = Object.keys(options).length;
  1997. if (!options[i]) update(i = 0);
  1998. let controlOptionsDiv = make('div', {
  1999. [css_key_width]: longest,
  2000. [css_key_maxWidth]: longest,
  2001. [css_key_border]: css_value_border_4pxffff,
  2002. [css_key_display]: css_value_misc_flex,
  2003. [css_key_borderRadius]: css_value_length_px7,
  2004. [css_key_paddingRight]: css_value_length_px10,
  2005. [css_key_justifyContent]: css_value_misc_flexEnd,
  2006. [css_key_backgroundColor]: css_value_color_80f8,
  2007. [css_key_zIndex]: css_value_10
  2008. }, {
  2009. hidden: 1,
  2010. onclick: () => {
  2011. update(++i % optionCount);
  2012. controlOptionsDiv[ATTRIBUTE_UPDATE]();
  2013. },
  2014. [ATTRIBUTE_UPDATE]: () => applyAttrbutes(controlOptionsDiv, {
  2015. innerText: getLocal(options[render()][0]) + ' ▼',
  2016. title: getLocal(options[render()][1])
  2017. })
  2018. });
  2019.  
  2020. controlOptionsDiv[ATTRIBUTE_UPDATE]();
  2021. renderFunctions.push(controlOptionsDiv[ATTRIBUTE_UPDATE]);
  2022. return createControlBase(label, controlOptionsDiv);
  2023. },
  2024.  
  2025. createControlColor = (label, color) => {
  2026. let style = {
  2027. }, opts = [];
  2028. for (let i in color) {
  2029. let colorControl = make('input', applyAttrbutes(style, {
  2030. [css_key_width]: css_value_length_px26,
  2031. [css_key_height]: css_value_length_px26,
  2032. [css_key_borderRadius]: css_value_length_px7,
  2033. [css_key_border]: css_value_border_1px000f,
  2034. [css_key_padding]: css_value_length_px0,
  2035. [css_key_outline]: css_value_border_4pxffff,
  2036. [css_key_marginLeft]: css_value_length_px7,
  2037. [css_key_marginRight]: css_value_length_px5
  2038. }), {
  2039. type: 'color',
  2040. value: color[i],
  2041. oninput: () => {
  2042. color[i] = opts[i].value;
  2043. saveSettings();
  2044. opts[i][ATTRIBUTE_UPDATE]();
  2045. },
  2046. [ATTRIBUTE_UPDATE]: () => applyStyle(colorControl, { [css_key_backgroundColor]: colorControl.value = color[i] })
  2047. });
  2048. if (!color[i]) {
  2049. colorControl.value = '#ffffff';
  2050. colorControl.oninput();
  2051. }
  2052. colorControl[ATTRIBUTE_UPDATE]();
  2053. opts[i] = colorControl;
  2054. }
  2055. return createControlBase(label, make('div', {
  2056. [css_key_display]: css_value_misc_flex
  2057. }, {}, opts));
  2058. },
  2059.  
  2060. createMenuDropdown = (label, subcontrols) => {
  2061. let controlNameDiv = make('div', {
  2062. [css_key_display]: css_value_misc_flex
  2063. }, {
  2064. innerText: getLocal(label[0])
  2065. }),
  2066. controlButtonDiv = make('div', {
  2067. [css_key_width]: css_value_length_px45,
  2068. [css_key_height]: css_value_length_px30,
  2069. [css_key_border]: css_value_border_4pxffff,
  2070. [css_key_display]: css_value_misc_flex,
  2071. [css_key_position]: css_value_misc_relative,
  2072. [css_key_alignItems]: css_value_misc_center,
  2073. [css_key_borderRadius]: css_value_length_px7,
  2074. [css_key_justifyContent]: css_value_misc_center,
  2075. [css_key_backgroundColor]: css_value_color_888f
  2076. }, {
  2077. innerText: '▼',
  2078. onclick: () => checkScrollable(controlButtonDiv.innerText = (subcontrolsDiv.hidden = !subcontrolsDiv.hidden) ? '▼' : '▲')
  2079. }),
  2080. controlDiv = make('div', {
  2081. [css_key_width]: css_value_length_perc100,
  2082. [css_key_padding]: css_value_length_px5,
  2083. [css_key_display]: css_value_misc_flex,
  2084. [css_key_paddingBottom]: css_value_length_px0,
  2085. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2086. [css_key_backgroundColor]: css_value_color_6666,
  2087. [css_key_height]: css_value_length_px40
  2088. }, {
  2089. title: getLocal(label[1])
  2090. }, [controlNameDiv, controlButtonDiv]),
  2091. subcontrolsDiv = make('div', {
  2092. [css_key_borderTop]: css_value_border_2px000f,
  2093. [css_key_borderLeft]: css_value_border_4px000f,
  2094. [css_key_borderBottom]: css_value_border_4px000f
  2095. }, { hidden: 1 }, subcontrols);
  2096. return make('div', {
  2097. [css_key_borderBottom]: css_value_border_2px000f
  2098. }, {}, [controlDiv, subcontrolsDiv]);
  2099. },
  2100.  
  2101. refreshMenu = menuID => {
  2102. idRefreshMenu = 0;
  2103. updateMenuCanvas = () => {};
  2104. renderFunctions = [];
  2105. removeChildren(divs.content);
  2106. menus[menuID][1](x=>divs.content.append(x));
  2107. checkScrollable();
  2108. },
  2109.  
  2110. createWindow = (fullWidth, contentHeight, mainTitleLabel, minifyLabelTitle, backbuttonLabelTitle) => {
  2111. let movableWindow = {},
  2112. title, content, backbutton,
  2113. menu = make('div', {
  2114. [css_key_width]: "number" == typeof fullWidth ? fullWidth + 'px' : fullWidth,
  2115. [css_key_height]: css_value_length_minContent,
  2116. [css_key_color]: css_value_color_ffff,
  2117. [css_key_border]: css_value_border_2px000f,
  2118. [css_key_borderRadius]: css_value_length_px5,
  2119. [css_key_zIndex]: highestZIndex++,
  2120. [css_key_position]: css_value_misc_absolute,
  2121. [css_key_fontSize]: css_value_length_px20,
  2122. [css_key_fontFamily]: css_value_misc_Consolas,
  2123. [css_key_userSelect]: css_value_misc_none
  2124. }, {
  2125. hidden: 1
  2126. }, [
  2127. title = make('div', {
  2128. [css_key_width]: css_value_length_perc100,
  2129. [css_key_height]: css_value_length_px43,
  2130. [css_key_border]: css_value_border_2px000f,
  2131. [css_key_padding]: css_value_length_px5,
  2132. [css_key_display]: css_value_misc_flex,
  2133. [css_key_whiteSpace]: css_value_misc_preWrap,
  2134. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2135. [css_key_backgroundImage]: css_value_gradient_redblue
  2136. }, {
  2137. innerText: mainTitleLabel,
  2138. onmousedown: e => {
  2139. let style = menu.style;
  2140. style[css_key_zIndex] = highestZIndex++;
  2141. if (style[css_key_right]) {
  2142. style[css_key_left] = (window.innerWidth - (pInt(style[css_key_right]) + pInt(style[css_key_width]))) + 'px';
  2143. style[css_key_right] = '';
  2144. }
  2145. movableWindow.offsetX = e.clientX - pInt(style[css_key_left]);
  2146. movableWindow.offsetY = e.clientY - pInt(style[css_key_top]);
  2147. movableWindow.enable = 1;
  2148. },
  2149. onmouseup: () => movableWindow.enable = 0
  2150. }, [
  2151. make('div', {
  2152. [css_key_color]: css_value_color_000f,
  2153. [css_key_width]: css_value_length_px28,
  2154. [css_key_height]: css_value_length_px28,
  2155. [css_key_border]: css_value_border_35px000f,
  2156. [css_key_display]: css_value_misc_flex,
  2157. [css_key_fontWeight]: css_value_misc_bold,
  2158. [css_key_alignItems]: css_value_misc_center,
  2159. [css_key_paddingTop]: css_value_length_pxNeg5,
  2160. [css_key_borderRadius]: css_value_length_px10,
  2161. [css_key_justifyContent]: css_value_misc_center,
  2162. [css_key_backgroundColor]: css_value_color_fff8
  2163. }, {
  2164. title: getLocal(minifyLabelTitle),
  2165. innerText: '_',
  2166. onclick: () => divs.menu.hidden = 1
  2167. })
  2168. ]),
  2169. content = make('div', {
  2170. [css_key_width]: css_value_length_perc100,
  2171. [css_key_height]: "number" == typeof contentHeight ? contentHeight + 'px' : contentHeight,
  2172. [css_key_border]: css_value_border_2px000f,
  2173. [css_key_overflowY]: css_value_misc_scroll,
  2174. [css_key_borderTop]: css_value_border_2px000f,
  2175. [css_key_borderLeft]: css_value_border_2px000f,
  2176. [css_key_backgroundColor]: css_value_color_000c
  2177. })
  2178. ]);
  2179.  
  2180. if (backbuttonLabelTitle) {
  2181. backbutton = make('div', {
  2182. [css_key_color]: css_value_color_000f,
  2183. [css_key_width]: css_value_length_px28,
  2184. [css_key_height]: css_value_length_px28,
  2185. [css_key_border]: css_value_border_35px000f,
  2186. [css_key_display]: css_value_misc_flex,
  2187. [css_key_alignItems]: css_value_misc_center,
  2188. [css_key_justifyContent]: css_value_misc_center,
  2189. [css_key_backgroundColor]: css_value_color_fff8,
  2190. [css_key_borderRadius]: css_value_length_px10
  2191. }, {
  2192. title: getLocal(backbuttonLabelTitle),
  2193. innerText: '<',
  2194. onclick: () => refreshMenu(0)
  2195. });
  2196.  
  2197. title.prepend(backbutton);
  2198. }
  2199. movableWindow.element = menu;
  2200. movableWindows.push(movableWindow);
  2201.  
  2202. return [menu, title, content, backbutton];
  2203. },
  2204.  
  2205. createMenu = () => {
  2206. //custom scrollbar
  2207. //i wish there were a better way...
  2208. let windowElements = createWindow(350, 522, menuLabel[3], menuLabel[0], menuLabel[1]),
  2209. someText = '}::-webkit-scrollbar';
  2210. windowElements[0].hidden = 0;
  2211. document.head.append(make('style', {}, {
  2212. textContent:
  2213. 'img{'+
  2214. css_key_width + ':' + css_value_length_perc100 + ';' +
  2215. css_key_height + ':' + css_value_length_perc100 +
  2216. someText + '{'+
  2217. css_key_width + ':' + css_value_length_px16 +
  2218. someText + '-track{'+
  2219. css_key_background + ':' + css_value_color_000f + ';'+
  2220. 'border-left:' + css_value_border_4px000f +
  2221. someText + '-thumb{'+
  2222. css_key_background + ':' + css_value_color_666f + ';'+
  2223. 'border-left:' + css_value_border_4px000f +
  2224. someText + '-thumb:hover{'+
  2225. css_key_background + ':' + css_value_color_888f +
  2226. '}'
  2227. }));
  2228.  
  2229.  
  2230. divs.menu = windowElements[0];
  2231. divs.title = windowElements[1];
  2232. divs.content = windowElements[2];
  2233. divs.backbutton = windowElements[3];
  2234.  
  2235. // if (isUserscript) divs.menu.append(make('div', {
  2236. // [css_key_color]: css_value_color_000f,
  2237. // [css_key_width]: css_value_length_perc100,
  2238. // [css_key_border]: css_value_border_2px000f,
  2239. // [css_key_alignItems]: css_value_misc_center,
  2240. // [css_key_paddingLeft]: css_value_length_px5,
  2241. // [css_key_justifyContent]: css_value_misc_center,
  2242. // [css_key_backgroundImage]: css_value_gradient_gray
  2243. // }, {
  2244. // onclick: () => window.open('http' + homeUrl, '_blank').focus(),
  2245. // innerHTML: 'You are using:<br><b style="color:red">TioHax Userscript Edition</b><br><span style="color:blue">Click here to get the standalone version!<br></span><span style="fontSize: 14px">(It gets frequently updated)<span>'
  2246. // }));
  2247.  
  2248. document.body.append(divs.menu);
  2249. refreshMenu(0);
  2250. createChatbox();
  2251.  
  2252. applyStyle(divs.menu, { [css_key_left]: css_value_length_px5 });
  2253. setTimeout(applyStyle(divs.menu, { [css_key_top]: floor(window.innerHeight - pInt(divs.content.style[css_key_height])) / 2 + 'px' }));
  2254. },
  2255.  
  2256. createChatbox = () => {
  2257. let thnetChatWindow = createWindow(300, 294, menuLabel[4], menuLabel[2]);
  2258. divs.chatinput = make('input', {
  2259. [css_key_color]: css_value_color_000f,
  2260. [css_key_width]: css_value_length_perc100,
  2261. [css_key_height]: css_value_length_px34,
  2262. [css_key_border]: css_value_border_4pxffff,
  2263. [css_key_display]: css_value_misc_flex,
  2264. [css_key_position]: css_value_misc_relative,
  2265. [css_key_alignItems]: css_value_misc_center,
  2266. [css_key_borderRadius]: css_value_length_px5,
  2267. [css_key_justifyContent]: css_value_misc_center,
  2268. [css_key_backgroundColor]: css_value_color_fffc
  2269. }, {
  2270. type: css_value_misc_text,
  2271. maxlength: 128,
  2272. onfocus: () => textBoxFocused = 1,
  2273. onblur: () => textBoxFocused = 0,
  2274. onchange: () => {
  2275. thnet[THNET_SOCKET]?.send('0 ' + divs.chatinput.value);
  2276. divs.chatinput.value = '';
  2277. divs.chatinput.blur();
  2278. },
  2279. value: ''
  2280. });
  2281.  
  2282. thnetChatWindow[2].append(divs.chatbox = make('div', {
  2283. [css_key_width]: css_value_length_perc100,
  2284. [css_key_height]: css_value_length_px250,
  2285. [css_key_border]: css_value_border_2px000f,
  2286. [css_key_fontSize]: css_value_length_px14,
  2287. [css_key_overflowY]: css_value_misc_scroll,
  2288. [css_key_borderTop]: css_value_border_2px000f,
  2289. [css_key_userSelect]: css_value_misc_text,
  2290. [css_key_borderLeft]: css_value_border_2px000f,
  2291. }));
  2292. thnetChatWindow[2].append(make('div', {
  2293. [css_key_width]: css_value_length_perc100,
  2294. [css_key_display]: css_value_misc_flex,
  2295. [css_key_padding]: css_value_length_px5,
  2296. [css_key_paddingTop]: css_value_length_px2,
  2297. [css_key_paddingBottom]: css_value_length_px0,
  2298. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2299. [css_key_height]: css_value_length_px40
  2300. }, {}, [ divs.chatinput ]))
  2301. document.body.append(divs.chatwrap = thnetChatWindow[0]);
  2302.  
  2303. applyStyle(thnetChatWindow[2], { [css_key_overflowY]: '' });
  2304. applyStyle(divs.chatwrap, { [css_key_left]: '', [css_key_right]: css_value_length_px5 });
  2305. setTimeout(applyStyle(divs.chatwrap, { [css_key_top]: (window.innerHeight - pInt(divs.chatbox.style[css_key_height])) / 2 + 'px' }));
  2306. },
  2307.  
  2308. fixWindowPositions = () => {
  2309. for (let movableWindow of movableWindows) {
  2310. let element = movableWindow.element,
  2311. rect = element.getBoundingClientRect(),
  2312. style = element.style;
  2313. if (!style[css_key_right]) {
  2314. applyStyle(element, {
  2315. [css_key_left]: max(0, min(window.innerWidth - rect[css_key_width], pInt(style[css_key_left]))) + 'px',
  2316. [css_key_top]: max(0, min(window.innerHeight - rect[css_key_height], pInt(style[css_key_top]))) + 'px'
  2317. });
  2318. }
  2319. }
  2320. },
  2321.  
  2322. refreshMenuSelect = append => {
  2323. for (let i in menus) {
  2324. if (pInt(i)) {
  2325. let menuDiv = make('div', {
  2326. [css_key_width]: css_value_length_perc100,
  2327. [css_key_padding]: css_value_length_px5,
  2328. [css_key_alignItems]: css_value_misc_center,
  2329. [css_key_borderBottom]: css_value_border_2px000f,
  2330. [css_key_justifyContent]: css_value_misc_center,
  2331. [css_key_backgroundColor]: css_value_color_8888,
  2332. [css_key_height]: menus.length - 1 == i ? css_value_length_px38 : css_value_length_px40
  2333. }, {
  2334. innerText: getLocal(menus[i][0]),
  2335. onmouseover: () => menuDiv.style[css_key_backgroundColor] = css_value_color_888c,
  2336. onmouseout: () => menuDiv.style[css_key_backgroundColor] = css_value_color_8888,
  2337. onclick: () => refreshMenu(pInt(i)),
  2338. });
  2339.  
  2340. append(menuDiv);
  2341. }
  2342. }
  2343. },
  2344.  
  2345. //PEOPLE STILL DONT READ THIS FOR SOME REASON
  2346. refreshMenuGuide = append => {
  2347. //this was going to have submenus so it would be easier to navigate
  2348. //then the cheat controls menu would have submenus aswell so it isnt just one disorganized mess
  2349. for (let entry in guide) for (let i in guide[entry]) {
  2350. let bool = i == 0;
  2351. append(make('div', {
  2352. [css_key_fontSize]: bool ? css_value_length_px30 : i & 1 ? css_value_length_px25 : css_value_length_px20,
  2353. [css_key_borderTop]: (bool && entry * 1) ? css_value_border_4px000f : '',
  2354. [css_key_paddingTop]: bool ? css_value_length_px10 : '',
  2355. [css_key_paddingLeft]: css_value_length_px5,
  2356. [css_key_marginBottom]: bool ? css_value_length_px10 : i & 1 ? css_value_length_px15 : css_value_length_px5
  2357. }, {
  2358. innerText: guide[entry][i]
  2359. }));
  2360. }
  2361. },
  2362.  
  2363. refreshMenuMenu = append => {
  2364. append(make('div', {}, {innerText: 'Coming Soon'}));
  2365. },
  2366.  
  2367. refreshMenuAimbot = append => {
  2368. let dropdowns = {
  2369. [AIMBOT_DROPDOWN_GENERAL]: AIMBOT_ENABLE + AIMBOT_AIMSMOOTHING + AIMBOT_DISABLEWHENDASHING,
  2370. [AIMBOT_DROPDOWN_ENHANCED]: AIMBOT_USEACCELERATION + AIMBOT_PINGCOMPENSATION + AIMBOT_AHEADNESSDEPTH,
  2371. [AIMBOT_DROPDOWN_CURSORPROX]: AIMBOT_CURSORMODE + AIMBOT_CURSORPROXCOSENESS,
  2372. [AIMBOT_DROPDOWN_SMART]: AIMBOT_WALLCHECK + AIMBOT_USEAHEAD + AIMBOT_AVOIDFRIENDS,
  2373. [AIMBOT_DROPDOWN_PRIORITY]: AIMBOT_RIGHTCLICKFRIEND + AIMBOT_IGNORECHATTING + AIMBOT_TARGETMODE + AIMBOT_AUXCLICKTARGET + AIMBOT_TARGETSONLY + AIMBOT_LEADERMODE,
  2374. [AIMBOT_DROPDOWN_TRIGGERBOT]: AIMBOT_TRIGGERBOT + AIMBOT_TRIGGERBOTWHENDOWN
  2375. };
  2376.  
  2377. for (let dropdown in dropdowns) {
  2378. let controls = [];
  2379. for (let setting of dropdowns[dropdown]) {
  2380. controls.push(
  2381. setting == AIMBOT_CURSORPROXCOSENESS ?
  2382. createControlValue(aimbotLabel[setting], i => aimbot[setting] = clamp(0, aimbot[setting] + 50 * i, 500), () => aimbot[setting]) :
  2383. setting == AIMBOT_AHEADNESSDEPTH ?
  2384. createControlValue(aimbotLabel[setting], i => aimbot[setting] = clamp(0, aimbot[setting] + i, 4), () => aimbot[setting] + 1) :
  2385. createControlToggle(aimbotLabel[setting], () => aimbot[setting] = 1 - aimbot[setting], () => aimbot[setting])
  2386. );
  2387. }
  2388. append(createMenuDropdown(aimbotLabel[dropdown], controls));
  2389. }
  2390. },
  2391.  
  2392. refreshMenuESP = append => {
  2393. let dropdowns = {
  2394. [ESP_DROPDOWN_CAMERA]: ESP_ZOOM + ESP_FIXCAMERA + ESP_CAMUSEREALPOSITION + ESP_SCROLLSENSITIVITY,
  2395. [ESP_DROPDOWN_TRACERS]: ESP_TRACERSBODYENEMY + ESP_TRACERSCURSORENEMY + ESP_TRACERSWALLCHECK + ESP_TRACERSGUN + ESP_TRACERSGRENADES,
  2396. [ESP_DROPDOWN_PLAYERSTATS]: ESP_SHOWHEALTH + ESP_SHOWARMOR + ESP_SHOWMAGS + ESP_SHOWGUNRELOADSTATUS + ESP_SHOWRANGE + ESP_INCLUDEYOU,
  2397. [ESP_DROPDOWN_OTHER]: ESP_SHOWINVIS + ESP_REVEALTEAMS
  2398. };
  2399.  
  2400. for (let dropdown in dropdowns) {
  2401. let controls = [];
  2402. for (let setting of dropdowns[dropdown]) {
  2403. controls.push(
  2404. setting == ESP_ZOOM ?
  2405. createControlDropdown(espLabel[setting], controlDropdownOptions[0], i => esp[setting] = i, () => esp[setting] ) :
  2406. setting == ESP_SCROLLSENSITIVITY ?
  2407. createControlValue(espLabel[setting], i => esp[setting] = clamp(1, esp[setting] + i * 0.01, 2), () => round((esp[setting] - 1) * 100)) :
  2408. createControlToggle(espLabel[setting], () => esp[setting] = 1 - esp[setting], () => esp[setting])
  2409. );
  2410. }
  2411. append(createMenuDropdown(espLabel[dropdown], controls));
  2412. }
  2413. },
  2414.  
  2415. refreshMenuMisc = append => {
  2416. let dropdowns = {
  2417. [MISC_DROPDOWN_INGAME]: MISC_AUTORELOAD + MISC_STATICHEALTH + MISC_BETTERCRATEHP + MISC_HIDECHATTING + MISC_FFACLANDISPLAY,
  2418. [MISC_DROPDOWN_DEBUG]: MISC_PINGDISPLAY + MISC_RENDERDISPLAY + MISC_POSITION,
  2419. [MISC_DROPDOWN_HUD]: MISC_STATICHUD + MISC_SHOWFEATURES + MISC_LEADERBOARDBADGES,
  2420. [MISC_DROPDOWN_OTHER]: MISC_DISABLECLOSEPOPUP
  2421. };
  2422.  
  2423. for (let dropdown in dropdowns) {
  2424. let controls = [];
  2425. for (let setting of dropdowns[dropdown]) controls.push(
  2426. setting == MISC_SHOWFEATURES ?
  2427. createControlDropdown(miscLabel[setting], controlDropdownOptions[2], i => misc[setting] = i, () => misc[setting] ) :
  2428. createControlToggle(miscLabel[setting], () => misc[setting] = 1 - misc[setting], () => misc[setting])
  2429. );
  2430. append(createMenuDropdown(miscLabel[dropdown], controls));
  2431. }
  2432. },
  2433.  
  2434. refreshMenuInstantchat = append => {
  2435. for (let setting in instantchat) if (setting !== INSTANTCHAT_CHATBINDSTEXTS) {
  2436. if (includesInArray(INSTANTCHAT_ONKILLTEXT + INSTANTCHAT_ONDEATHTEXT + INSTANTCHAT_AUTOTHANKTEXT, setting)) {
  2437. let editAutoTextInput = make('input', {
  2438. [css_key_color]: css_value_color_000f,
  2439. [css_key_width]: css_value_length_perc100,
  2440. [css_key_height]: css_value_length_px34,
  2441. [css_key_border]: css_value_border_4pxffff,
  2442. [css_key_display]: css_value_misc_flex,
  2443. [css_key_position]: css_value_misc_relative,
  2444. [css_key_alignItems]: css_value_misc_center,
  2445. [css_key_borderRadius]: css_value_length_px5,
  2446. [css_key_justifyContent]: css_value_misc_center,
  2447. [css_key_backgroundColor]: css_value_color_fffc
  2448. }, {
  2449. type: css_value_misc_text,
  2450. maxlength: setting === INSTANTCHAT_AUTOTHANKTEXT ? 32 : 38,
  2451. onfocus: () => textBoxFocused = 1,
  2452. onblur: () => textBoxFocused = 0,
  2453. oninput: () => {
  2454. instantchat[setting] = editAutoTextInput.value;
  2455. saveSettings();
  2456. },
  2457. value: instantchat[setting]
  2458. });
  2459. append(make('div', {
  2460. [css_key_width]: css_value_length_perc100,
  2461. [css_key_display]: css_value_misc_flex,
  2462. [css_key_padding]: css_value_length_px5,
  2463. [css_key_paddingTop]: css_value_length_px0,
  2464. [css_key_borderBottom]: css_value_border_3px000f,
  2465. [css_key_paddingBottom]: css_value_length_px0,
  2466. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2467. [css_key_height]: css_value_length_px40
  2468. }, { title: instantchatLabel[setting][1] }, [editAutoTextInput]));
  2469. } else {
  2470. append(createControlToggle(instantchatLabel[setting], () => instantchat[setting] = 1 - instantchat[setting], () => instantchat[setting]));
  2471. }
  2472. }
  2473. let editBindInput = make('input', {
  2474. [css_key_color]: css_value_color_000f,
  2475. [css_key_width]: css_value_length_perc100,
  2476. [css_key_height]: css_value_length_px34,
  2477. [css_key_border]: css_value_border_4pxffff,
  2478. [css_key_display]: css_value_misc_flex,
  2479. [css_key_position]: css_value_misc_relative,
  2480. [css_key_alignItems]: css_value_misc_center,
  2481. [css_key_borderRadius]: css_value_length_px5,
  2482. [css_key_justifyContent]: css_value_misc_center,
  2483. [css_key_backgroundColor]: css_value_color_fffc
  2484. }, {
  2485. type: css_value_misc_text,
  2486. maxlength: 32,
  2487. onfocus: () => textBoxFocused = 1,
  2488. onblur: () => textBoxFocused = 0,
  2489. oninput: () => {
  2490. //memory leak prevention
  2491. if (selectedKey && !(instantchat[INSTANTCHAT_CHATBINDSTEXTS][selectedKey] = editBindInput.value)) delete instantchat[INSTANTCHAT_CHATBINDSTEXTS][selectedKey];
  2492. },
  2493. value: ''
  2494. }),
  2495. editBindDiv = make('div', {
  2496. [css_key_width]: css_value_length_perc100,
  2497. [css_key_display]: css_value_misc_flex,
  2498. [css_key_padding]: css_value_length_px5,
  2499. [css_key_paddingTop]: css_value_length_px2,
  2500. [css_key_borderBottom]: css_value_border_3px000f,
  2501. [css_key_paddingBottom]: css_value_length_px0,
  2502. [css_key_backgroundColor]: css_value_color_8888,
  2503. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2504. [css_key_height]: css_value_length_px40
  2505. }, { title: getLocal(instantchatLabel[0]) }, [editBindInput]),
  2506. bindSelectDiv = make('div', {
  2507. [css_key_width]: css_value_length_perc100,
  2508. [css_key_display]: css_value_misc_grid,
  2509. [css_key_gridTemplateColumns]: css_value_auto_10
  2510. }), selectedBindDiv, selectedKey = 0;
  2511. for (let validKey of [0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 85, 86, 88, 89, 90]) {
  2512. let bindKeyDiv = make('div', {
  2513. [css_key_display]: css_value_misc_flex,
  2514. [css_key_height]: bindSelectDiv.width / 9,
  2515. [css_key_alignItems]: css_value_misc_center,
  2516. [css_key_justifyContent]: css_value_misc_center,
  2517. [css_key_backgroundColor]: css_value_color_f80f
  2518. }, {
  2519. innerText: validKey ? ' ' + keyCodeToLetter(validKey) : ' ',
  2520. onclick: () => {
  2521. let oldDiv = selectedBindDiv;
  2522. selectedBindDiv = bindKeyDiv;
  2523. selectedKey = validKey;
  2524. oldDiv[ATTRIBUTE_UPDATE]();
  2525. bindKeyDiv[ATTRIBUTE_UPDATE]();
  2526. editBindInput.value = instantchat[INSTANTCHAT_CHATBINDSTEXTS][validKey] || '';
  2527. },
  2528. //update
  2529. [ATTRIBUTE_UPDATE]: () => applyStyle(bindKeyDiv, {
  2530. [css_key_border]: css_value_length_px2 + css_value_random_solid + (selectedBindDiv === bindKeyDiv ? css_value_color_ff0f : css_value_color_000f)
  2531. })
  2532. });
  2533. if (!validKey) selectedBindDiv = bindKeyDiv;
  2534. bindKeyDiv[ATTRIBUTE_UPDATE]();
  2535. bindSelectDiv.append(bindKeyDiv);
  2536. }
  2537. append(bindSelectDiv);
  2538. append(editBindDiv);
  2539. },
  2540.  
  2541. refreshMenuPlayermanager = append => {
  2542. let refreshPlayerManager = () => refreshMenu(7),
  2543. list = [friends, targets, muted][playermanagerSelectedMenu],
  2544. otherList = playermanagerSelectedMenu ? friends : targets,
  2545. controlAddButton = make('div', {
  2546. [css_key_width]: css_value_length_px50,
  2547. [css_key_height]: css_value_length_px34,
  2548. [css_key_color]: css_value_color_ffff,
  2549. [css_key_border]: css_value_border_4pxffff,
  2550. [css_key_display]: css_value_misc_flex,
  2551. [css_key_position]: css_value_misc_relative,
  2552. [css_key_alignItems]: css_value_misc_center,
  2553. [css_key_justifyContent]: css_value_misc_center,
  2554. [css_key_backgroundColor]: css_value_color_f80c
  2555. }, {
  2556. innerText: 'Add',
  2557. onclick: () => {
  2558. let name = sanitiseName(controlAddName.value);
  2559. if (includesInArray(list, name)) return;
  2560. if (playermanagerSelectedMenu !== 2 && includesInArray(otherList, name)) toggleUsernameInlist(otherList, name);
  2561. saveSettings(checkScrollable(refreshPlayerManager(toggleUsernameInlist(list, name))));
  2562. }
  2563. }),
  2564. controlAddName = make('input', {
  2565. [css_key_width]: css_value_length_calcperc100,
  2566. [css_key_height]: css_value_length_px34,
  2567. [css_key_color]: css_value_color_000f,
  2568. [css_key_border]: css_value_border_4pxffff,
  2569. [css_key_display]: css_value_misc_flex,
  2570. [css_key_marginLeft]: css_value_length_px5,
  2571. [css_key_position]: css_value_misc_relative,
  2572. [css_key_alignItems]: css_value_misc_center,
  2573. [css_key_justifyContent]: css_value_misc_center,
  2574. [css_key_backgroundColor]: css_value_color_fffc
  2575. }, {
  2576. type: css_value_misc_text,
  2577. onfocus: () => textBoxFocused = 1,
  2578. onblur: () => textBoxFocused = 0,
  2579. oninput: () => controlAddName.value = controlAddName.value.replace(/[^0-9a-zA-Z ]/g, '').slice(0, 12),
  2580. value: ''
  2581. }),
  2582. controlAdd = make('div', {
  2583. [css_key_width]: css_value_length_perc100,
  2584. [css_key_display]: css_value_misc_flex,
  2585. [css_key_padding]: css_value_length_px5,
  2586. [css_key_paddingTop]: css_value_length_px2,
  2587. [css_key_borderBottom]: css_value_border_3px000f,
  2588. [css_key_paddingBottom]: css_value_length_px0,
  2589. [css_key_backgroundColor]: css_value_color_8888,
  2590. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2591. [css_key_height]: css_value_length_px40
  2592. }, {
  2593. title: playerManagerLabel[3][playermanagerSelectedMenu]
  2594. }, [controlAddButton, controlAddName]),
  2595. submenus = [];
  2596. for (let i = 0; i < 3; i++) {
  2597. submenus[i] = make('div', {
  2598. [css_key_width]: css_value_length_calcperc33,
  2599. [css_key_padding]: css_value_length_px5,
  2600. [css_key_alignItems]: css_value_misc_center,
  2601. [css_key_borderBottom]: css_value_border_3px000f,
  2602. [css_key_borderRight]: (i == playerManagerLabel.length - 1) ? '' : css_value_border_3px000f,
  2603. [css_key_paddingBottom]: css_value_length_px0,
  2604. [css_key_paddingTop]: css_value_length_px0,
  2605. [css_key_justifyContent]: css_value_misc_center,
  2606. [css_key_backgroundColor]: css_value_color_8888,
  2607. [css_key_display]: css_value_misc_flex,
  2608. [css_key_position]: css_value_misc_relative,
  2609. [css_key_height]: css_value_length_px40
  2610. }, {
  2611. innerText: getLocal(playerManagerLabel[i][0]),
  2612. title: getLocal(playerManagerLabel[i][1]),
  2613. onclick: () => refreshPlayerManager(playermanagerSelectedMenu = i)
  2614. });
  2615. }
  2616. append(make('div', {}, {}, [make('div', {
  2617. [css_key_width]: css_value_length_perc100,
  2618. [css_key_display]: css_value_misc_flex
  2619. }, {}, submenus), controlAdd]));
  2620.  
  2621. for (let username of list) {
  2622. let entryNameDiv = make('div', {
  2623. [css_key_userSelect]: css_value_misc_text
  2624. }, {
  2625. innerText: username
  2626. }),
  2627. entryButtonDiv = make('div', {
  2628. [css_key_width]: css_value_length_px30,
  2629. [css_key_height]: css_value_length_px30,
  2630. [css_key_border]: css_value_border_4pxffff,
  2631. [css_key_display]: css_value_misc_flex,
  2632. [css_key_position]: css_value_misc_relative,
  2633. [css_key_alignItems]: css_value_misc_center,
  2634. [css_key_justifyContent]: css_value_misc_center,
  2635. [css_key_backgroundColor]: css_value_color_f00c
  2636. }, {
  2637. innerText: 'X',
  2638. onclick: () => refreshPlayerManager(toggleUsernameInlist(list, username))
  2639. }),
  2640. entryDiv = make('div', {
  2641. [css_key_width]: css_value_length_perc100,
  2642. [css_key_display]: css_value_misc_flex,
  2643. [css_key_padding]: css_value_length_px5,
  2644. [css_key_borderBottom]: css_value_border_2px000f,
  2645. [css_key_paddingBottom]: css_value_length_px0,
  2646. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2647. [css_key_height]: css_value_length_px40
  2648. }, {}, [entryNameDiv, entryButtonDiv]);
  2649.  
  2650. append(entryDiv);
  2651. }
  2652. },
  2653.  
  2654. //this menu was a serious pain in the ass
  2655. refreshMenuUpgrades = append => {
  2656. append(createControlToggle(autoUpgradesLabel[0], () => autoUpgrades[0] = 1 - autoUpgrades[0], () => autoUpgrades[0]));
  2657.  
  2658. let upgradeslotsDivs = [],
  2659. perkSelectDiv = make('div', {
  2660. [css_key_width]: ' 100%',
  2661. [css_key_display]: css_value_misc_grid,
  2662. [css_key_gridTemplateColumns]: css_value_auto_5
  2663. });
  2664.  
  2665. for (let i = 1; i < 4; i++) {
  2666. let upgradeNameDiv = make('div'),
  2667. perkSlotImageDiv = make('div', {
  2668. [css_key_width]: css_value_length_px30,
  2669. [css_key_height]: css_value_length_px30,
  2670. [css_key_border]: css_value_border_2px000f,
  2671. [css_key_padding]: css_value_length_px0,
  2672. [css_key_verticalAlign]: css_value_length_px0,
  2673. [css_key_backgroundColor]: css_value_color_4448
  2674. }),
  2675. upgradeSlotDiv = make('div', {
  2676. [css_key_width]: css_value_length_perc100,
  2677. [css_key_padding]: css_value_length_px5,
  2678. [css_key_display]: css_value_misc_flex,
  2679. [css_key_borderBottom]: css_value_border_2px000f,
  2680. [css_key_paddingBottom]: css_value_length_px0,
  2681. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2682. [css_key_height]: css_value_length_px40
  2683. }, {
  2684. onclick: () => {
  2685. perkSelectDiv.p(selectedPerkSlot = i);
  2686. for (let slot of upgradeslotsDivs) slot.f();
  2687. }
  2688. }, [upgradeNameDiv, perkSlotImageDiv]);
  2689.  
  2690. //b = update
  2691. //this is abstracted because closure compiler doesnt
  2692. upgradeSlotDiv.b = (perk, boolean) => {
  2693. upgradeNameDiv.innerText = perkNames[perk] || getLocal(autoUpgradesLabel[1]);
  2694. removeChildren(perkSlotImageDiv);
  2695. if (perk && j30[perk]) perkSlotImageDiv.append(dupeImg(j30[perk]));
  2696. };
  2697. upgradeSlotDiv.b(autoUpgrades[i], 1);
  2698.  
  2699. //f = update visually
  2700. //this is abstracted because closure compiler doesnt
  2701. upgradeSlotDiv.f = () => upgradeSlotDiv.style[css_key_backgroundColor] = i == selectedPerkSlot ? css_value_color_888c : css_value_color_8886;
  2702. upgradeSlotDiv.f();
  2703.  
  2704. upgradeslotsDivs.push(upgradeSlotDiv);
  2705. }
  2706.  
  2707. //p = update
  2708. //this is abstracted because closure compiler doesnt
  2709. perkSelectDiv.p = perkLevel => {
  2710. removeChildren(perkSelectDiv);
  2711. let perksToDisplay = perkLevel === 2 ? abilities : perks,
  2712. perkLevelOther = 4 - perkLevel;
  2713. for (let perk of perksToDisplay) {
  2714. let perkImageDiv = make('div', {
  2715. [css_key_border]: css_value_length_px2 + css_value_random_solid + (autoUpgrades[perkLevel] === perk ? css_value_color_ff0f : css_value_color_000f),
  2716. [css_key_height]: perkSelectDiv.width / 4
  2717. }, {
  2718. onclick: () => {
  2719. //if this perk is already set, clear it
  2720. upgradeslotsDivs[perkLevel - 1].b(autoUpgrades[perkLevel] = autoUpgrades[perkLevel] === perk ? '' : perk);
  2721.  
  2722. //if the other setting is equal, clear it
  2723. if (perkLevelOther !== 2 && autoUpgrades[perkLevel] && autoUpgrades[perkLevelOther] === autoUpgrades[perkLevel]) {
  2724. upgradeslotsDivs[perkLevelOther - 1].b(autoUpgrades[perkLevelOther] = '');
  2725. }
  2726.  
  2727. //alternatively you can update just the perk selects that actually change but this is easier to do soo...
  2728. perkSelectDiv.p(perkLevel);
  2729.  
  2730. saveSettings();
  2731. }
  2732. }, [j30[perk]]);
  2733. perkSelectDiv.append(perkImageDiv);
  2734. }
  2735. };
  2736. perkSelectDiv.p(selectedPerkSlot);
  2737. for (let div of upgradeslotsDivs) append(div);
  2738. append(perkSelectDiv);
  2739. },
  2740.  
  2741. refreshMenuSpammer = append => {
  2742. append(createControlToggle(scrollerLabel[0], () => {
  2743. if (!chatSpam[CHATSPAMMER_TIMEOUT]) {
  2744. startChatScrolling(multiBox[MULTIBOX_SELECTEDSOCKET]);
  2745. } else {
  2746. stopChatScrolling(multiBox[MULTIBOX_SELECTEDSOCKET]);
  2747. sendChatMessage(multiBox[MULTIBOX_SELECTEDSOCKET], ' ');
  2748. }
  2749. }, () => chatSpam[CHATSPAMMER_TIMEOUT]));
  2750.  
  2751. //makes sure the values don't go past a certain unsafe point
  2752. let maxLength = (str, max) => str.replace(/\n/g, '').slice(0, max),
  2753. clampValues = () => {
  2754. chatSpam[CHATSPAMMER_WIDTH] = clamp(5, chatSpam[CHATSPAMMER_WIDTH], 30);
  2755. chatSpam[CHATSPAMMER_DIRECTION] = clamp(-5, chatSpam[CHATSPAMMER_DIRECTION], 5);
  2756. chatSpam[CHATSPAMMER_INTERVAL] = clamp(25, chatSpam[CHATSPAMMER_INTERVAL], 1000);
  2757. chatSpam[CHATSPAMMER_SEPERATOR] = maxLength(chatSpam[CHATSPAMMER_SEPERATOR], 5);
  2758. chatSpam[CHATSPAMMER_TEXT] = maxLength(chatSpam[CHATSPAMMER_TEXT], 99999);
  2759. chatSpam[CHATSPAMMER_PAUSEPERIOD] = clamp(500, chatSpam[CHATSPAMMER_PAUSEPERIOD], 10000);
  2760. chatSpam[CHATSPAMMER_PREFIX] = maxLength(chatSpam[CHATSPAMMER_PREFIX], 25 - chatSpam[CHATSPAMMER_SUFFIX].length);
  2761. chatSpam[CHATSPAMMER_SUFFIX] = maxLength(chatSpam[CHATSPAMMER_SUFFIX], 25 - chatSpam[CHATSPAMMER_PREFIX].length);
  2762. saveSettings();
  2763. };
  2764. clampValues();
  2765.  
  2766. for (let attribute of CHATSPAMMER_WIDTH + CHATSPAMMER_DIRECTION + CHATSPAMMER_INTERVAL + CHATSPAMMER_PAUSEPERIOD) append(createControlValue(scrollerLabel[attribute],
  2767. i => clampValues(chatSpam[attribute] += (CHATSPAMMER_PAUSEPERIOD == attribute ? 500 : CHATSPAMMER_INTERVAL == attribute ? 25 : 1) * i),
  2768. () => chatSpam[attribute] / (attribute == CHATSPAMMER_PAUSEPERIOD ? 1000 : 1)
  2769. ));
  2770.  
  2771. for (let attribute of CHATSPAMMER_SEPERATOR + CHATSPAMMER_TEXT + CHATSPAMMER_PREFIX + CHATSPAMMER_SUFFIX) {
  2772. let controlTextNameDiv = make('div', {
  2773. [css_key_marginTop]: css_value_length_px3,
  2774. [css_key_marginRight]: css_value_length_px8,
  2775. [css_key_display]: css_value_misc_flex
  2776. }, { innerText: scrollerLabel[attribute][0]}),
  2777. controlTextInputDiv = make('input', {
  2778. [css_key_width]: attribute == CHATSPAMMER_TEXT ? css_value_length_calcperc102 : css_value_length_px70,
  2779. [css_key_height]: css_value_length_px34,
  2780. [css_key_color]: css_value_color_000f,
  2781. [css_key_border]: css_value_border_4pxffff,
  2782. [css_key_display]: css_value_misc_flex,
  2783. [css_key_position]: css_value_misc_relative,
  2784. [css_key_alignItems]: css_value_misc_center,
  2785. [css_key_justifyContent]: css_value_misc_center,
  2786. [css_key_backgroundColor]: css_value_color_fffc
  2787. }, {
  2788. type: css_value_misc_text,
  2789. oninput: () => {
  2790. chatSpam[attribute] = controlTextInputDiv.value;
  2791. clampValues();
  2792. controlTextInputDiv.value = chatSpam[attribute];
  2793. },
  2794. onfocus: () => textBoxFocused = 1,
  2795. onblur: () => textBoxFocused = 0,
  2796. value: chatSpam[attribute]
  2797. }),
  2798. controlTextDiv = make('div', {
  2799. [css_key_width]: css_value_length_perc100,
  2800. [css_key_display]: css_value_misc_flex,
  2801. [css_key_padding]: css_value_length_px5,
  2802. [css_key_paddingTop]: css_value_length_px2,
  2803. [css_key_borderBottom]: css_value_border_2px000f,
  2804. [css_key_paddingBottom]: css_value_length_px0,
  2805. [css_key_justifyContent]: css_value_misc_spaceBetween,
  2806. [css_key_height]: css_value_length_px40
  2807. }, { title: scrollerLabel[attribute][1] }, [controlTextNameDiv, controlTextInputDiv]);
  2808. append(controlTextDiv);
  2809. }
  2810. },
  2811.  
  2812. refreshMenuAntiAim = append => {
  2813. let clampValues = () => {
  2814. antiAim[ANTIAIM_ANGLESTART] = (360 + antiAim[ANTIAIM_ANGLESTART]) % 360;
  2815. antiAim[ANTIAIM_ANGLERANGE] = (365 + antiAim[ANTIAIM_ANGLERANGE]) % 365;
  2816. antiAim[ANTIAIM_SPINSPEED] = clamp(-180, antiAim[ANTIAIM_SPINSPEED], 180);
  2817. antiAim[ANTIAIM_DELAY] = clamp(1, antiAim[ANTIAIM_DELAY], 62);
  2818. };
  2819.  
  2820. //toggleable settings
  2821. for (let attribute of ANTIAIM_RELOAD + ANTIAIM_SHOOT + ANTIAIM_IDLE + ANTIAIM_DRAWREALAIM) append(createControlToggle(antiAimLabel[attribute], () => antiAim[attribute] = 1 - antiAim[attribute], () => antiAim[attribute]));
  2822.  
  2823. //number settings
  2824. for (let attribute of ANTIAIM_ANGLESTART + ANTIAIM_ANGLERANGE + ANTIAIM_SPINSPEED + ANTIAIM_DELAY) append(createControlValue(antiAimLabel[attribute], i => clampValues(antiAim[attribute] += (includesInArray(ANTIAIM_ANGLESTART + ANTIAIM_ANGLERANGE, attribute) ? 5 : 1) * i), () => antiAim[attribute]));
  2825.  
  2826. updateMenuCanvas = (me, offset, players, crates) => {
  2827. if (divs.menu.hidden) return;
  2828. let angle1 = (antiAim[ANTIAIM_ANGLESTART] + tickCount * antiAim[ANTIAIM_SPINSPEED]) * degToRad,
  2829. angle2 = angle1 + antiAim[ANTIAIM_ANGLERANGE] * degToRad,
  2830. length = me[ATTRIBUTE_RADIUS] * 1.5 + 20;
  2831. drawLine2(me, {
  2832. x: length * sin(angle1),
  2833. y: length * cos(angle1)
  2834. }, offset, 2, '#f00');
  2835. drawLine2(me, {
  2836. x: length * sin(angle2),
  2837. y: length * cos(angle2)
  2838. }, offset, 2, '#00f');
  2839. ctx.lineWidth = 1;
  2840. ctx.beginPath();
  2841. //fuck this shit
  2842. ctx.arc(me.x + offset.x, me.y + offset.y, length, -angle1 + TAU / 4, -angle2 + TAU / 4, true);
  2843. ctx.stroke();
  2844. };
  2845. },
  2846.  
  2847. refreshMenuPerkHacks = append => {
  2848. append(createMenuDropdown(perkHacksLabel[0], [
  2849. createControlToggle(perkHacksLabel[PERKHACKS_KNIFE], () => perkHacks[PERKHACKS_KNIFE] = 1 - perkHacks[PERKHACKS_KNIFE], () => perkHacks[PERKHACKS_KNIFE]),
  2850. createControlValue(perkHacksLabel[PERKHACKS_KNIFEMAXRANGE], i => perkHacks[PERKHACKS_KNIFEMAXRANGE] = clamp(20, perkHacks[PERKHACKS_KNIFEMAXRANGE] + 10 * i, 300), () => perkHacks[PERKHACKS_KNIFEMAXRANGE])
  2851. ]));
  2852. append(createMenuDropdown(perkHacksLabel[1], [
  2853. createControlToggle(perkHacksLabel[PERKHACKS_SHIELD], () => perkHacks[PERKHACKS_SHIELD] = 1 - perkHacks[PERKHACKS_SHIELD], () => perkHacks[PERKHACKS_SHIELD]),
  2854. createControlValue(perkHacksLabel[PERKHACKS_SHIELDUPKEEP], i => perkHacks[PERKHACKS_SHIELDUPKEEP] = clamp(0, perkHacks[PERKHACKS_SHIELDUPKEEP] + i, 50), () => perkHacks[PERKHACKS_SHIELDUPKEEP]),
  2855. createControlValue(perkHacksLabel[PERKHACKS_SHIELDLOOKAHEAD], i => perkHacks[PERKHACKS_SHIELDLOOKAHEAD] = clamp(0, perkHacks[PERKHACKS_SHIELDLOOKAHEAD] + i, 10), () => perkHacks[PERKHACKS_SHIELDLOOKAHEAD]),
  2856. createControlToggle(perkHacksLabel[PERKHACKS_SHIELDMANUAL], () => perkHacks[PERKHACKS_SHIELDMANUAL] = 1 - perkHacks[PERKHACKS_SHIELDMANUAL], () => perkHacks[PERKHACKS_SHIELDMANUAL]),
  2857. createControlDropdown(perkHacksLabel[PERKHACKS_SHIELDVISUALISER], controlDropdownOptions[3], i => perkHacks[PERKHACKS_SHIELDVISUALISER] = i, () => perkHacks[PERKHACKS_SHIELDVISUALISER]),
  2858. createControlToggle(perkHacksLabel[PERKHACKS_SHIELDWALLCHECK], () => perkHacks[PERKHACKS_SHIELDWALLCHECK] = 1 - perkHacks[PERKHACKS_SHIELDWALLCHECK], () => perkHacks[PERKHACKS_SHIELDWALLCHECK])
  2859. ]));
  2860. append(createMenuDropdown(perkHacksLabel[2], [
  2861. createControlToggle(perkHacksLabel[PERKHACKS_CRATEPLACEVISION], () => perkHacks[PERKHACKS_CRATEPLACEVISION] = 1 - perkHacks[PERKHACKS_CRATEPLACEVISION], () => perkHacks[PERKHACKS_CRATEPLACEVISION]),
  2862. //createControlToggle(perkHacksLabel[PERKHACKS_MEDKITSELFHEAL], () => perkHacks[PERKHACKS_MEDKITSELFHEAL] = 1 - perkHacks[PERKHACKS_MEDKITSELFHEAL], () => perkHacks[PERKHACKS_MEDKITSELFHEAL]),
  2863. //createControlValue(perkHacksLabel[PERKHACKS_MEDKITSELFHEALTHRESHOLD], i => perkHacks[PERKHACKS_MEDKITSELFHEALTHRESHOLD] = clamp(5, perkHacks[PERKHACKS_MEDKITSELFHEALTHRESHOLD] + i * 5, 100), () => perkHacks[PERKHACKS_MEDKITSELFHEALTHRESHOLD]),
  2864. ]));
  2865. },
  2866.  
  2867. refreshMenuPaint = append => {
  2868. let dropdowns = {
  2869. [PAINT_GRID]: PAINT_GRIDSPACEX + PAINT_GRIDSPACEY + PAINT_GRIDLINEWIDTHHORIZONTAL + PAINT_GRIDLINEWIDTHVERTICAL + PAINT_GRIDCOLOR,
  2870. [PAINT_POINTS]: PAINT_POINTSIDLE + PAINT_POINTSFFA + PAINT_POINTSBLU + PAINT_POINTSRED + PAINT_POINTEDGEWIDTH,
  2871. [PAINT_CRATES]: PAINT_CRATESHOWHPMODE + PAINT_CRATESQUARE + PAINT_CRATELONG + PAINT_CRATEUSER + PAINT_CRATEPREMIUM + PAINT_CRATECORPSE
  2872. };
  2873.  
  2874. for (let dropdown in dropdowns) {
  2875. let controls = [];
  2876. for (let setting of dropdowns[dropdown]) {
  2877. let control;
  2878. switch (setting) {
  2879. case PAINT_CRATESHOWHPMODE:
  2880. control = createControlDropdown(paintLabel[PAINT_CRATESHOWHPMODE],
  2881. controlDropdownOptions[1],
  2882. x => paint[PAINT_CRATESHOWHPMODE] = x,
  2883. () => paint[PAINT_CRATESHOWHPMODE]);
  2884. break;
  2885.  
  2886. case PAINT_POINTEDGEWIDTH:
  2887. control = createControlValue(paintLabel[PAINT_POINTEDGEWIDTH],
  2888. i => paint[PAINT_POINTEDGEWIDTH] = clamp(0, paint[PAINT_POINTEDGEWIDTH] + i, 20),
  2889. () => paint[PAINT_POINTEDGEWIDTH]
  2890. );
  2891. break;
  2892.  
  2893. case PAINT_GRIDLINEWIDTHHORIZONTAL:
  2894. control = createControlValue(paintLabel[PAINT_GRIDLINEWIDTHHORIZONTAL],
  2895. i => paint[PAINT_GRIDLINEWIDTHHORIZONTAL] = clamp(0, paint[PAINT_GRIDLINEWIDTHHORIZONTAL] + i, 10),
  2896. () => paint[PAINT_GRIDLINEWIDTHHORIZONTAL]
  2897. );
  2898. break;
  2899.  
  2900. case PAINT_GRIDLINEWIDTHVERTICAL:
  2901. control = createControlValue(paintLabel[PAINT_GRIDLINEWIDTHVERTICAL],
  2902. i => paint[PAINT_GRIDLINEWIDTHVERTICAL] = clamp(0, paint[PAINT_GRIDLINEWIDTHVERTICAL] + i, 10),
  2903. () => paint[PAINT_GRIDLINEWIDTHVERTICAL]
  2904. );
  2905. break;
  2906.  
  2907. case PAINT_GRIDSPACEX:
  2908. control = createControlValue(paintLabel[PAINT_GRIDSPACEX],
  2909. i => paint[PAINT_GRIDSPACEX] = clamp(2, paint[PAINT_GRIDSPACEX] + i, 500),
  2910. () => paint[PAINT_GRIDSPACEX]
  2911. );
  2912. break;
  2913.  
  2914. case PAINT_GRIDSPACEY:
  2915. control = createControlValue(paintLabel[PAINT_GRIDSPACEY],
  2916. i => paint[PAINT_GRIDSPACEY] = clamp(2, paint[PAINT_GRIDSPACEY] + i, 500),
  2917. () => paint[PAINT_GRIDSPACEY]
  2918. );
  2919. break;
  2920.  
  2921. default:
  2922. control = createControlColor(paintLabel[setting], paint[setting]);
  2923. }
  2924. controls.push(control);
  2925. }
  2926. append(createMenuDropdown(paintLabel[dropdown], controls));
  2927. }
  2928. append(createControlButton(paintLabel[0], () => {
  2929. if (prompt(paintLabel[0], paintLabel[1]) == 'yes') paint = {
  2930. [PAINT_GRIDSPACEX]: 20,
  2931. [PAINT_GRIDSPACEY]: 20,
  2932. [PAINT_GRIDLINEWIDTHHORIZONTAL]: 1,
  2933. [PAINT_GRIDLINEWIDTHVERTICAL]: 1,
  2934. [PAINT_GRIDCOLOR]: ['#e3e3e8', '#efeff5'],
  2935. [PAINT_POINTSIDLE]: ['#aaaaaa', '#f9f9f9'],
  2936. [PAINT_POINTSFFA]: ['#00cc66', '#f9f9f9'],
  2937. [PAINT_POINTSBLU]: ['#8dd8f8', '#f9f9f9'],
  2938. [PAINT_POINTSRED]: ['#f26740', '#f9f9f9'],
  2939. [PAINT_POINTEDGEWIDTH]: 4,
  2940. [PAINT_CRATESHOWHPMODE]: 2,
  2941. [PAINT_CRATESQUARE]: ['#808080', '#dfbf9f'],
  2942. [PAINT_CRATELONG]: ['#808080', '#bec8dd'],
  2943. [PAINT_CRATEUSER]: ['#808080', '#53c68c'],
  2944. [PAINT_CRATEPREMIUM]: ['#2e2d2d', '#f0ba37']
  2945. }
  2946. saveSettings();
  2947. }));
  2948. let presetElements = [];
  2949. for (let preset of paint[PAINT_PRESETS]) {
  2950.  
  2951. presetElements.push(createControlBase(preset, [make("div", {
  2952. [css_key_border]: css_value_border_3pxffff,
  2953. [css_key_backgroundColor]: css_value_color_00fc
  2954. //TODO: add css
  2955. }, {
  2956. innerText: '⇑', //TODO: find good character
  2957. onclick: () => {
  2958. if (paint[PAINT_CHANGEDSOMETHING] && prompt(paintLabel[0], paintLabel[1]) == 'yes') saveSettings(paint = {
  2959. [PAINT_GRIDSPACEX]: preset[ 2],
  2960. [PAINT_GRIDSPACEY]: preset[ 3],
  2961. [PAINT_GRIDLINEWIDTHHORIZONTAL]: preset[ 4],
  2962. [PAINT_GRIDLINEWIDTHVERTICAL]: preset[ 5],
  2963. [PAINT_GRIDCOLOR]: [ preset[ 6], preset[ 7] ],
  2964. [PAINT_POINTSIDLE]: [ preset[ 8], preset[ 9] ],
  2965. [PAINT_POINTSFFA]: [ preset[10], preset[11] ],
  2966. [PAINT_POINTSBLU]: [ preset[12], preset[13] ],
  2967. [PAINT_POINTSRED]: [ preset[14], preset[15] ],
  2968. [PAINT_POINTEDGEWIDTH]: preset[16],
  2969. [PAINT_CRATESHOWHPMODE]: preset[17],
  2970. [PAINT_CRATESQUARE]: [ preset[18], preset[19] ],
  2971. [PAINT_CRATELONG]: [ preset[20], preset[21] ],
  2972. [PAINT_CRATEUSER]: [ preset[22], preset[23] ],
  2973. [PAINT_CRATEPREMIUM]: [ preset[24], preset[25] ]
  2974. })
  2975. }
  2976. }, [])]));
  2977. }
  2978. append(createMenuDropdown(paintLabel[PAINT_PRESETMANAGER], [
  2979. createControlButton(paintLabel[PAINT_PRESETMANAGERSAVE]),
  2980. createControlButton(paintLabel[PAINT_PRESETMANAGERIMPORT]),
  2981. createControlButton(paintLabel[PAINT_PRESETMANAGEREXPORT]),
  2982. createMenuDropdown(paintLabel[PAINT_PRESETMANAGERPRESETS], presetElements)
  2983. ]));
  2984. },
  2985.  
  2986. refreshMenuRecorder = append => {
  2987. //a game recorder similar to nitrogem's recorder but it works offline and doesn't need an iframe to play
  2988. //it back since it just plays back server packets while making the game think it is connected to one
  2989. append(make('div', {}, {
  2990. innerText: 'Coming Soon'
  2991. }));
  2992. },
  2993.  
  2994. //L, find a solution that works
  2995. refreshMenuDiscordRPC = append => {
  2996. append(createControlToggle(discordRPCLabel[DISCORDRPC_ENABLED], () => {
  2997. discordRPC[DISCORDRPC_ENABLED] = !discordRPC[DISCORDRPC_ENABLED];
  2998. if (discordRPC[DISCORDRPC_ENABLED]) {
  2999. //TODO: login to discord rpc
  3000. discordRPCStart();
  3001. } else if (discordRPC[DISCORDRPC_CONNECTION]) {
  3002. discordRPCActivityClear();
  3003. discordRPC[DISCORDRPC_CONNECTION].close();
  3004. }
  3005. }, () => discordRPC[DISCORDRPC_ENABLED]));
  3006.  
  3007. append(createControlText(discordRPCLabel[DISCORDRPC_STATE], str => discordRPC[DISCORDRPC_STATE] = str, () => discordRPC[DISCORDRPC_STATE]));
  3008. append(createControlText(discordRPCLabel[DISCORDRPC_DETAILS], str => discordRPC[DISCORDRPC_DETAILS] = str, () => discordRPC[DISCORDRPC_DETAILS]));
  3009. append(createControlValue(discordRPCLabel[DISCORDRPC_UPDATEINTERVAL], i => discordRPC[DISCORDRPC_UPDATEINTERVAL] = clamp(15, discordRPC[DISCORDRPC_UPDATEINTERVAL] + i, 60), () => discordRPC[DISCORDRPC_UPDATEINTERVAL]));
  3010. },
  3011.  
  3012. refreshMenuTHNet = append => {
  3013. append(createControlToggle(THNetLabel[THNET_ENABLE], () => {
  3014. thnet[THNET_ENABLE] = !thnet[THNET_ENABLE];
  3015. if (c3 !== null) {
  3016. if (thnet[THNET_ENABLE]) {
  3017. connectToTHNet();
  3018. } else if (thnet[THNET_SOCKET]) {
  3019. thnet[THNET_CLOSEREASON] = 'Manual';
  3020. thnet[THNET_SOCKET].close();
  3021. }
  3022. }
  3023. }, () => thnet[THNET_ENABLE]));
  3024. append(createControlToggle(THNetLabel[THNET_INFOSHARE], () => (thnet[THNET_INFOSHARE] = 1 - thnet[THNET_INFOSHARE]) || thnet[THNET_SOCKET].send('1'), () => thnet[THNET_INFOSHARE]));
  3025. append(createControlToggle(THNetLabel[THNET_CHAT], () => thnet[THNET_CHAT] = 1 - (divs.chatwrap.hidden = 1 - divs.chatwrap.hidden), () => thnet[THNET_CHAT]));
  3026. let rules = [];
  3027. for (let i = 0; i < THNetLabel[1].length; i++) rules[i] = make('div', {
  3028. [css_key_paddingTop]: css_value_length_px5
  3029. }, {
  3030. innerText: THNetLabel[1][i]
  3031. });
  3032. append(createMenuDropdown(THNetLabel[0], rules));
  3033. },
  3034.  
  3035. refreshMenuWeird = append => {
  3036. for (let setting in weird) append(createControlToggle(weirdLabel[setting], () => weird[setting] = 1 - weird[setting], () => weird[setting]));
  3037. },
  3038.  
  3039. refreshMenuAdvanced = append => {
  3040. for (let setting in advanced) {
  3041. let control;
  3042. switch (setting) {
  3043. case ADVANCED_TPS:
  3044. control = createControlToggle(advancedLabel[setting], () => advanced[setting] = advanced[setting] === 2.5 ? 1 : 2.5, () => advanced[setting] === 1);
  3045. break;
  3046. case ADVANCED_OPTIMISEWALLCHECK:
  3047. control = createControlToggle(advancedLabel[setting], () => advanced[setting] = 1 - advanced[setting], () => advanced[setting]);
  3048. break;
  3049. case ADVANCED_PINGCOUNT:
  3050. control = createControlValue(advancedLabel[setting], i => advanced[setting] = clamp(1, advanced[setting] + i, 50), () => advanced[setting]);
  3051. break;
  3052. case ADVANCED_PINGCOMP:
  3053. control = createControlValue(advancedLabel[setting], i => advanced[setting] = clamp(1, advanced[setting] + i, 100), () => advanced[setting]);
  3054. break;
  3055. case ADVANCED_AIMCONSTANT:
  3056. control = createControlValue(advancedLabel[setting], i => advanced[setting] = parseFloat(clamp(0.5, advanced[setting] + 0.05 * i, 2.5).toFixed(2)), () => advanced[setting]);
  3057. }
  3058. append(control);
  3059. }
  3060. append(createControlButton(advancedLabel[0], () => {
  3061. for (let server of RF.list) server.socket.close();
  3062. }));
  3063. append(createControlButton(advancedLabel[1], () => localStorage.removeItem('TioHax_bootloader')));
  3064. append(createControlButton(advancedLabel[2], () => {
  3065. if (prompt("Are you sure that you want to clear all TioHax settings? This cannot be undone! Type 'yes' if you want to proceed:", "no") == 'yes' &&
  3066. prompt("ARE YOU ABSOLUTELY SURE that you want to clear ALL TioHax settings!? Your current settings will be lost forever if you do this!! Type 'yes' again if you absolutely want to proceed:", "no") == 'yes'
  3067. ) {
  3068. localStorage.removeItem('TioHax_settings');
  3069. location.reload();
  3070. }
  3071. }));
  3072. append(createControlText(THNetLabel[THNET_AUTH], str => thnet[THNET_AUTH] = str, () => thnet[THNET_AUTH]));
  3073. },
  3074.  
  3075. refreshMenuCredits = append => {
  3076. for (let entry of credits) for (let i in entry) {
  3077. let bool = i == 0;
  3078. append(make('div', {
  3079. [css_key_fontSize]: bool ? css_value_length_px30 : i & 1 ? css_value_length_px25 : css_value_length_px20,
  3080. [css_key_borderTop]: bool ? css_value_border_4px000f : '',
  3081. [css_key_marginTop]: bool ? css_value_length_px10 : i & 1 ? css_value_length_px15 : css_value_length_px5,
  3082. [css_key_paddingTop]: bool ? css_value_length_px10 : '',
  3083. [css_key_paddingLeft]: css_value_length_px5
  3084. }, { innerText: entry[i] }));
  3085. }
  3086. },
  3087.  
  3088. pingDisplay = () => {
  3089.  
  3090. //starts at 5 padding so it isn't directly on the screen's edge, looks nicer
  3091. let pingTextPadding = 5,
  3092. fallbackText = 'Not Connected',
  3093. pingSocket = RF.list[0] || {
  3094. currentPing: fallbackText,
  3095. [ATTRIBUTE_AVERAGEPING]: fallbackText,
  3096. [ATTRIBUTE_MAXPING]: fallbackText,
  3097. [ATTRIBUTE_MINPING]: fallbackText
  3098. },
  3099. pingTexts = [
  3100. 'Ping: ' + pingSocket.currentPing + ' ms',
  3101. 'Avg.: ' + round(pingSocket[ATTRIBUTE_AVERAGEPING]) + ' ms',
  3102. 'Max: ' + pingSocket[ATTRIBUTE_MAXPING] + ' ms',
  3103. 'Min: ' + pingSocket[ATTRIBUTE_MINPING] + ' ms'
  3104. ];
  3105.  
  3106. //if we're in a game or not
  3107. if (b21 || c28) {
  3108. pingTextPadding += 10;
  3109. //second padding for the VIP tag
  3110. if (selfPremiumMember) pingTextPadding += 35;
  3111.  
  3112. //second padding for the username text
  3113. if (b3 || b4) {
  3114. ctx.font = '14px Arial';
  3115. pingTextPadding += ceil(ctx.measureText((b3 ? 'Logged in' : 'Playing') + ' as ' + b4).width);
  3116. }
  3117. }
  3118. ctx.font = 'bold 16px consolas';
  3119.  
  3120. //draw the ping number
  3121. for (let i = 0; i < pingTexts.length; i++) drawText(pingTextPadding, 16 + (i * 17), pingTexts[i], '#fff');
  3122.  
  3123. //return the padding for the render time so we dont draw the render time text over server ping text
  3124. return pingTextPadding + ceil(ctx.measureText(pingTexts[2]).width);
  3125. },
  3126.  
  3127. renderDisplay = (renderDisplayPadding) => {
  3128. ctx.font = 'bold 16px consolas';
  3129. let texts = [
  3130. 'Render time: ' + renderTime + 'ms',
  3131. spacePadding('FPS: ', 13) + min(1000 / renderTime, 25 * advanced[ADVANCED_TPS]).toFixed(renderTime > 500 ? 2 : 1)
  3132.  
  3133. ];
  3134. drawText(renderDisplayPadding, 16, texts[0], '#fff');
  3135. drawText(renderDisplayPadding, 32, texts[1], '#fff');
  3136. return ceil(ctx.measureText(texts[0].length > texts[1].length ? texts[0] : texts[1]).width);
  3137. },
  3138.  
  3139. coordsDisplay = (renderDisplayPadding, me) => {
  3140. ctx.font = 'bold 16px consolas';
  3141. let texts = [
  3142. 'Pos: x:' + spacePadding(me.x, 7) + ' y: ' + spacePadding(me.y, 7),
  3143. 'Vel: x:' + spacePadding(me.spdX, 7) + ' y: ' + spacePadding(me.spdY, 7),
  3144. 'Acc: x:' + spacePadding(me[ATTRIBUTE_ACCX].toFixed(1), 7) + ' y: ' + spacePadding(me[ATTRIBUTE_ACCY].toFixed(1), 7)
  3145. ], y = 16, longest = '';
  3146. for (let text of texts) {
  3147. drawText(renderDisplayPadding, y, text, '#fff');
  3148. y += 17;
  3149. if (longest.length < text.length) longest = text;
  3150. }
  3151. return ceil(ctx.measureText(longest).width);
  3152. },
  3153.  
  3154. getEnemies = (me, players) => {
  3155.  
  3156. //enemies: enemy players which will be aimed at
  3157. //enemy friends: enemy players which are friended
  3158. let enemies = [], enemyFriends = [];
  3159.  
  3160. for (let player of players) {
  3161.  
  3162. //dont aimbot at invincible players or at team mates
  3163. if (player.invincible || (player.teamCode && player.teamCode == me.teamCode)) continue;
  3164.  
  3165. //dont aimbot at the developer of this cheat
  3166. if (player[ATTRIBUTE_USERNAMEHASH] === developerHash ||
  3167. //dont aimbot at chatting people if that setting is enabled
  3168. (aimbot[AIMBOT_IGNORECHATTING] && player.chatBoxOpen) ||
  3169. //dont aimbot at people the aimbot is not supposted to shoot at
  3170. includesInArray(friends, player[ATTRIBUTE_SANITIZEDNAME]) ||
  3171. //dont aimbot at other tiohax users
  3172. includesInArray(thnet[THNET_BROTHERS], player[ATTRIBUTE_USERNAMEHASH])
  3173. ) {
  3174. enemyFriends.push(player);
  3175. } else {
  3176. enemies.push(player);
  3177. }
  3178. }
  3179.  
  3180. return { [ATTRIBUTE_ENEMIES]: enemies, [ATTRIBUTE_ENEMYFRIENDS]: enemyFriends };
  3181. },
  3182.  
  3183. getDistanceSquared = (me, enemy, offset) => ((me.x - offset.x) - enemy.x) ** 2 + ((me.y - offset.y) - enemy.y) ** 2,
  3184.  
  3185. //calculate where someone will be with respect to how long it takes to get there
  3186. calcAheadness = (me, enemy, distance, gun, count = aimbot[AIMBOT_AHEADNESSDEPTH]) => {
  3187.  
  3188. if (count) distance = getDistanceSquared(me, calcAheadness(me, enemy, distance, gun, count - 1), nullPos);
  3189.  
  3190. let x = enemy.x,
  3191. y = enemy.y;
  3192.  
  3193. //mathematical
  3194. distance = (sqrt(distance) - offsets[gun]) / (velocities[gun] * advanced[ADVANCED_AIMCONSTANT]);
  3195.  
  3196. //aim a bit more ahead depending on the connection, since some server ticks may have happened during transport
  3197. if (aimbot[AIMBOT_PINGCOMPENSATION]) {
  3198. distance += ceil(RF.list[0][ATTRIBUTE_AVERAGEPING] / advanced[ADVANCED_PINGCOMP]);
  3199. }
  3200.  
  3201. //Formula for 'Pos + Vel + Acc + Time => New Pos': (np = new pos, p = pos, v = vel, t = time, a = acc) np = (p) + (v * t) + (0.5 * a * t²)
  3202. //https://math.stackexchange.com/questions/4538784/formula-for-predicting-next-position-does-not-include-maximum-velocity-is-there/4538831#4538831
  3203. //TODO: fix when a player just stops going in one direction that the bot thinks it is going in the opposite direction
  3204. if (aimbot[AIMBOT_USEACCELERATION]) {
  3205. let maxXvel = me[ATTRIBUTE_USABLEACCX] ? me[ATTRIBUTE_USABLEACCX] * 8 : me[ATTRIBUTE_USABLESPDX],
  3206. maxYvel = me[ATTRIBUTE_USABLEACCY] ? me[ATTRIBUTE_USABLEACCY] * 8 : me[ATTRIBUTE_USABLESPDY];
  3207. if (distance > (maxXvel - me[ATTRIBUTE_USABLESPDX]) / me[ATTRIBUTE_USABLEACCX]) {
  3208. x += maxXvel * distance - ((maxXvel - me[ATTRIBUTE_USABLESPDX]) ** 2) / (me[ATTRIBUTE_USABLEACCX] ? 2 * me[ATTRIBUTE_USABLEACCX] : Infinity);
  3209. x += maxYvel * distance - ((maxYvel - me[ATTRIBUTE_USABLESPDY]) ** 2) / (me[ATTRIBUTE_USABLEACCY] ? 2 * me[ATTRIBUTE_USABLEACCY] : Infinity);
  3210. } else {
  3211. x += enemy[ATTRIBUTE_USABLESPDX] * distance + 0.5 * me[ATTRIBUTE_USABLEACCX] * (distance ** 2);
  3212. x += enemy[ATTRIBUTE_USABLESPDY] * distance + 0.5 * me[ATTRIBUTE_USABLEACCY] * (distance ** 2);
  3213. }
  3214. } else {
  3215. x += enemy[ATTRIBUTE_USABLESPDX] * distance;
  3216. y += enemy[ATTRIBUTE_USABLESPDY] * distance;
  3217. }
  3218.  
  3219. return {x, y};
  3220. },
  3221.  
  3222. wouldHitWall = (me, enemy, crates, gun) => {
  3223.  
  3224. //TODO: move the MAAAAAAAAAAAAAATH to a function
  3225. let enemyPos = aimbot[AIMBOT_USEAHEAD] ? calcAheadness(me, enemy, getDistanceSquared(me, enemy, nullPos), gun) : enemy,
  3226. relPos = {
  3227. x: enemyPos.x - me.x,
  3228. y: enemyPos.y - me.y
  3229. },
  3230. possibleAngle = atan2(relPos.y, relPos.x) + asin(18 / sqrt(relPos.x ** 2 + relPos.y ** 2)),
  3231. handAngle = 0 - (TAU * 0.6 + possibleAngle),
  3232. gunOffset = offsets[gun] + velocities[gun] - 14,
  3233. gunAngle = 0 - (TAU * 0.75 + possibleAngle),
  3234. gunEnd = {
  3235. x: me.x + sin(handAngle) * me[ATTRIBUTE_RADIUS] + sin(gunAngle) * gunOffset,
  3236. y: me.y + cos(handAngle) * me[ATTRIBUTE_RADIUS] + cos(gunAngle) * gunOffset
  3237. },
  3238. inclusionBox = {
  3239. x: (gunEnd.x + enemyPos.x) / 2,
  3240. y: (gunEnd.y + enemyPos.y) / 2,
  3241. z: sqrt(getDistanceSquared(gunEnd.x, enemyPos.x, nullPos)) / 2
  3242. },
  3243. hitCrates = [[gunEnd, enemyPos]];
  3244.  
  3245. wallcheckoptimise: {
  3246. for (let i = 0; i < crates.length; i++) {
  3247. let crate = crates[i];
  3248.  
  3249. //avoid calculating collisions if it would just be a waste
  3250. if (!crate[ATTRIBUTE_BULLETCOLLISIONS] || getDistanceSquared(inclusionBox, crate, nullPos) > (inclusionBox.z + crate[ATTRIBUTE_HITBOXRADIUS]) ** 2) continue;
  3251.  
  3252. //if the crate intersects with the line, add them to the list of crates that have been hit
  3253. //works by checking if the line from the gun end to the enemy position collides with any line from the crate hitbox
  3254. for (let j = 0; j < crate[ATTRIBUTE_HITBOX].length; j++) {
  3255. if (collisionLineLine(
  3256. gunEnd.x, gunEnd.y,
  3257. enemyPos.x, enemyPos.y,
  3258. crate.x + crate[ATTRIBUTE_HITBOX][j][0], crate.y + crate[ATTRIBUTE_HITBOX][j][1],
  3259. crate.x + crate[ATTRIBUTE_HITBOX][j][2], crate.y + crate[ATTRIBUTE_HITBOX][j][3]
  3260. ) || collisionLineLine(
  3261. enemy.x, enemy.y,
  3262. enemyPos.x, enemyPos.y,
  3263. crate.x + crate[ATTRIBUTE_HITBOX][j][0], crate.y + crate[ATTRIBUTE_HITBOX][j][1],
  3264. crate.x + crate[ATTRIBUTE_HITBOX][j][2], crate.y + crate[ATTRIBUTE_HITBOX][j][3]
  3265. )) {
  3266. hitCrates.push(crate);
  3267. if (advanced[ADVANCED_OPTIMISEWALLCHECK]) break wallcheckoptimise;
  3268. break;
  3269. }
  3270. }
  3271. }
  3272. }
  3273. return hitCrates;
  3274. },
  3275.  
  3276. couldHitFriend = (me, enemy, enemyFriends, gun) => {
  3277.  
  3278. //TODO: move the MAAAAAAAAAAAAAATH to a function
  3279. let enemyPos = aimbot[AIMBOT_USEAHEAD] ? calcAheadness(me, enemy, getDistanceSquared(me, enemy, nullPos), gun) : enemy.getAttr(), //the onlytime this method is ever needed...
  3280. relPos = {
  3281. x: enemyPos.x - me.x,
  3282. y: enemyPos.y - me.y
  3283. },
  3284. possibleAngle = atan2(relPos.y, relPos.x) + asin(18 / sqrt(relPos.x ** 2 + relPos.y ** 2)),
  3285. handAngle = 0 - (TAU * 0.6 + possibleAngle),
  3286. gunOffset = offsets[gun] + velocities[gun] - 14,
  3287. gunAngle = 0 - (TAU * 0.75 + possibleAngle),
  3288. gunEnd = {
  3289. x: me.x + sin(handAngle) * me[ATTRIBUTE_RADIUS] + sin(gunAngle) * gunOffset,
  3290. y: me.y + cos(handAngle) * me[ATTRIBUTE_RADIUS] + cos(gunAngle) * gunOffset
  3291. },
  3292. factor = (gunOffset + ranges[gun] * velocities[gun]) / sqrt(getDistanceSquared(me, enemyPos, nullPos));
  3293. enemyPos.x *= factor;
  3294. enemyPos.y *= factor;
  3295.  
  3296. for (let i = 0; i < enemyFriends.length; i++) {
  3297. let friend = enemyFriends[i],
  3298. offset = {x: -c2.x, y: -c2.y},
  3299. //scale radius based on distance
  3300. //TODO: this is goofy af, add stuff for speed and acceleration, make sure it also knows how far bullets can even go with ranges[gun] * velocities[gun]
  3301. radius = friend[ATTRIBUTE_RADIUS] * sqrt(max(1, (getDistanceSquared(me, friend, nullPos) - getDistanceSquared(me, gunEnd, nullPos)) / (velocities[gun] * 2.5))),
  3302. canHit = distanceSquaredLinePoint(
  3303. gunEnd.x, gunEnd.y,
  3304. enemyPos.x, enemyPos.y,
  3305. friend.x, friend.y,
  3306. ) < radius ** 2;
  3307. drawCircle(friend, offset, radius, 2, canHit ? '#888' : '#aaa');
  3308. if (canHit) return 1;
  3309. }
  3310. },
  3311.  
  3312. //NOTE: all distances calculated here are left squared because it is not required for them to be square-rooted until later on
  3313. getTarget = (me, offset, enemies, enemyFriends, crates, minRange, maxRange, gun) => {
  3314.  
  3315. //two of those will be returned and one of those will be used in the distance check
  3316. let includeOnlyTargets = aimbot[AIMBOT_TARGETSONLY],
  3317. smallestDistanceToPoint = aimbot[AIMBOT_CURSORMODE] && aimbot[AIMBOT_CURSORPROXCOSENESS] ? aimbot[AIMBOT_CURSORPROXCOSENESS] ** 2 : Infinity,
  3318. distanceToMe, distanceToPoint, enemy, distance,
  3319. c = {x: j9[0], y: j9[1]};
  3320. for (let currentEnemy of enemies) {
  3321. //compare distances and check if the current enemy to check is closer
  3322. distanceToMe = getDistanceSquared(me, currentEnemy, nullPos);
  3323.  
  3324. //or closer to the mouse if that setting is enabled
  3325. if (aimbot[AIMBOT_CURSORMODE]) {
  3326. distanceToPoint = getDistanceSquared(c, currentEnemy, offset);
  3327.  
  3328. //draws lines from cursor to enemies
  3329. if (esp[ESP_TRACERSCURSORENEMY]) drawLine(c, currentEnemy, offset, 1, '#888');
  3330. } else {
  3331. distanceToPoint = distanceToMe;
  3332. }
  3333.  
  3334. if (aimbot[AIMBOT_WALLCHECK]) {
  3335. let hitCrates = wouldHitWall(me, currentEnemy, crates, gun);
  3336.  
  3337. if (esp[ESP_TRACERSWALLCHECK]) {
  3338. let pos = hitCrates[0];
  3339. ctx.globalAlpha = hitCrates.length > 1 ? 1 : 0.5;
  3340. drawLineWrap(
  3341. pos[0].x + offset.x, pos[0].y + offset.y,
  3342. pos[1].x + offset.x, pos[1].y + offset.y,
  3343. 2,
  3344. '#888'
  3345. );
  3346. ctx.globalAlpha = 0.5;
  3347. for (let i = 1; i < hitCrates.length; i++) hitCrates[i][ATTRIBUTE_FILLHITBOX]();
  3348. ctx.globalAlpha = 1;
  3349. }
  3350.  
  3351. //NOTE: first hitCrates element is not a crate, it is the raycast line
  3352. if (hitCrates.length > 1) continue;
  3353. }
  3354.  
  3355. //if the enemy is too close or far for the gun to hit, completely disregard them
  3356. if (distanceToMe < minRange || distanceToPoint > maxRange) continue;
  3357.  
  3358. let isATarget = includesInArray(targets, currentEnemy[ATTRIBUTE_SANITIZEDNAME]);
  3359.  
  3360. //if (aimbot[AIMBOT_LEADERMODE] && currentEnemy.isLeader) return {[ATTRIBUTE_ENEMY]: currentEnemy, [ATTRIBUTE_DISTANCE]: distanceToMe};
  3361. //if (aimbot[AIMBOT_LEADERMODE] && currentEnemy.isLeader) break;
  3362.  
  3363. if (includeOnlyTargets && !isATarget) continue;
  3364. if (aimbot[AIMBOT_TARGETMODE] && isATarget && !includeOnlyTargets) {
  3365. includeOnlyTargets = 1;
  3366. smallestDistanceToPoint = aimbot[AIMBOT_CURSORMODE] ? aimbot[AIMBOT_CURSORPROXCOSENESS] ** 2 : Infinity;
  3367. }
  3368.  
  3369. if (distanceToPoint > smallestDistanceToPoint) continue;
  3370. if (aimbot[AIMBOT_AVOIDFRIENDS] && couldHitFriend(me, currentEnemy, enemyFriends, gun)) continue;
  3371.  
  3372. smallestDistanceToPoint = distanceToPoint;
  3373. distance = distanceToMe;
  3374. enemy = currentEnemy;
  3375. }
  3376.  
  3377. //a visualiser so you know whats close to your cursor
  3378. if (aimbot[AIMBOT_CURSORMODE]) {
  3379. if (enemy) drawLine(c, enemy, offset, 2, '#888');
  3380. let radius = sqrt(smallestDistanceToPoint);
  3381. ctx.beginPath();
  3382. ctx.moveTo(c.x + radius, c.y);
  3383. ctx.arc(c.x, c.y, radius, 0, TAU);
  3384. ctx.stroke();
  3385. }
  3386.  
  3387. return {[ATTRIBUTE_ENEMY]: enemy, [ATTRIBUTE_DISTANCE]: distance};
  3388. },
  3389.  
  3390. aimTorwards = (me, enemy, offset, distance, gun) => {
  3391.  
  3392. //not accounting for velocity when the enemy is dashing is mostly a better idea
  3393. if (!enemy.dashing) enemy = calcAheadness(me, enemy, distance, gun);
  3394.  
  3395. //if too close to player move the position to aim at somewhat away so it doesnt break
  3396. distance = sqrt(getDistanceSquared(me, enemy, nullPos));
  3397. if (distance < 50) {
  3398. distance = 50 / distance;
  3399. enemy.x -= me.x;
  3400. enemy.y -= me.y;
  3401. enemy.x *= distance;
  3402. enemy.y *= distance;
  3403. enemy.x += me.x;
  3404. enemy.y += me.y;
  3405. }
  3406.  
  3407. //immitate mouse cursor movement
  3408. return {
  3409. clientX: enemy.x + offset.x,
  3410. clientY: enemy.y + offset.y
  3411. };
  3412. },
  3413.  
  3414. setNameVariations = (player, username) => {
  3415. player[ATTRIBUTE_USERNAMEHASH] = hashString(player[ATTRIBUTE_SANITIZEDNAME] = sanitiseName(player[ATTRIBUTE_TAGGEDNAME] = player[ATTRIBUTE_USERNAME] = username));
  3416. if (c22 == 'FFA' && !player[ATTRIBUTE_TAGGEDNAME].startsWith('Guest ')) {
  3417. if (player[ATTRIBUTE_USERNAME] in clanTagCache) {
  3418. if (clanTagCache[player[ATTRIBUTE_USERNAME]]) {
  3419. player[ATTRIBUTE_TAGGEDNAME] = '[' + clanTagCache[player[ATTRIBUTE_USERNAME]] + '] ' + player[ATTRIBUTE_TAGGEDNAME];
  3420. }
  3421. } else {
  3422. fetchFromServer('clanof/' + player[ATTRIBUTE_TAGGEDNAME])
  3423. .then(clanTag => {
  3424. clanTagCache[player[ATTRIBUTE_USERNAME]] = clanTag;
  3425. if (clanTag) player[ATTRIBUTE_TAGGEDNAME] = '[' + clanTag + '] ' + player[ATTRIBUTE_TAGGEDNAME];
  3426. });
  3427. }
  3428. }
  3429. },
  3430.  
  3431. doAimbotThings = (me, offset, enemies, enemyFriends, crates, gunMinRange, playerScreenPos, gun) => {
  3432. let target = {[ATTRIBUTE_ENEMY]: undefVar, [ATTRIBUTE_DISTANCE]: undefVar};
  3433. if (!aimbot[AIMBOT_ENABLE]) return target;
  3434.  
  3435. drawCircle(me, offset, 10, 2, '#000');
  3436. if (aimbot[AIMBOT_TARGETSONLY]) drawCircle(me, offset, 15, 2, 'gray');
  3437.  
  3438. if (me.dashing && aimbot[AIMBOT_DISABLEWHENDASHING]) return target;
  3439.  
  3440. target = getTarget(me, offset, enemies, enemyFriends, crates, gunMinRange, Infinity, gun);
  3441. if (target[ATTRIBUTE_ENEMY]) {
  3442. if (!perkHacks[PERKHACKS_TICK]) aimMeAt(aimTorwards(me, target[ATTRIBUTE_ENEMY], offset, target[ATTRIBUTE_DISTANCE], gun), 1);
  3443. if (esp[ESP_TRACERSBODYENEMY]) drawLine(playerScreenPos, target[ATTRIBUTE_ENEMY], offset, 3);
  3444. }
  3445.  
  3446. return target;
  3447. },
  3448.  
  3449. hideAim = (me, offset, animationSubtraction) => {
  3450. if (me.dashing) return;
  3451. if (!(
  3452. (antiAim[ANTIAIM_IDLE] && !(me.reloading || me.shooting || cursor.isShooting)) ||
  3453. (antiAim[ANTIAIM_RELOAD] && me.reloading && me.reloadingAnimation && (me.reloadingFrame < me.reloadingAnimation.length - animationSubtraction)) ||
  3454. (antiAim[ANTIAIM_SHOOT] && me.shooting && me.shootingAnimation && (me.shootingFrame < me.shootingAnimation.length - animationSubtraction))
  3455. )) return;
  3456. if (0 === tickCount % antiAim[ANTIAIM_DELAY]) {
  3457. let angle = (antiAim[ANTIAIM_ANGLESTART] + antiAim[ANTIAIM_ANGLERANGE] * random() + tickCount * antiAim[ANTIAIM_SPINSPEED]) * degToRad,
  3458. ahead = me[ATTRIBUTE_RADIUS] * 2;
  3459. antiAim[ANTIAIM_SAVEDX] = me.x + offset.x + ahead * sin(angle);
  3460. antiAim[ANTIAIM_SAVEDY] = me.y + offset.y + ahead * cos(angle);
  3461. }
  3462. aimMeAt({
  3463. clientX: antiAim[ANTIAIM_SAVEDX],
  3464. clientY: antiAim[ANTIAIM_SAVEDY]
  3465. }, 1, 1);
  3466. },
  3467.  
  3468. showFeatures = () => {
  3469. ctx.font = 'bold 20px consolas';
  3470. let maxX = j1 * 2 - 5,
  3471. maxY = c2 ? floor(1.725 * j2) : (j2 * 2 - 30),
  3472. tracers = esp[ESP_TRACERSBODYENEMY] || esp[ESP_TRACERSCURSORENEMY] || esp[ESP_TRACERSWALLCHECK] || esp[ESP_TRACERSGUN] || esp[ESP_TRACERSGRENADES],
  3473. playerAttribs = esp[ESP_SHOWHEALTH] || esp[ESP_SHOWARMOR] || esp[ESP_SHOWMAGS] || esp[ESP_SHOWGUNRELOADSTATUS] || esp[ESP_SHOWRANGE],
  3474. things = [
  3475. [
  3476. chatSpam[CHATSPAMMER_TIMEOUT],
  3477. 'Chat Spammer',
  3478. ],[
  3479. misc[MISC_FFACLANDISPLAY],
  3480. 'FFA Clan Display',
  3481. ],[
  3482. chatSpam[CHATSPAMMER_TIMEOUT],
  3483. 'Chat Scroller',
  3484. ],[
  3485. esp[ESP_SHOWINVIS] || esp[ESP_REVEALTEAMS],
  3486. 'Invis Reveal',
  3487. ],[
  3488. misc[MISC_AUTORELOAD],
  3489. 'Auto Reload',
  3490. ],[
  3491. perkHacks[PERKHACKS_KNIFE] || perkHacks[PERKHACKS_SHIELD] || perkHacks[PERKHACKS_CRATEPLACEVISION],
  3492. 'Perk Hacks',
  3493. perkHacks[PERKHACKS_KNIFE] ? 'KnifeBot' : '',
  3494. perkHacks[PERKHACKS_SHIELD] ? 'ShieldBot' : '',
  3495. perkHacks[PERKHACKS_CRATEPLACEVISION] ? 'Build & Medkit' : ''
  3496. ],[
  3497. antiAim[ANTIAIM_RELOAD] || antiAim[ANTIAIM_SHOOT] || antiAim[ANTIAIM_IDLE],
  3498. 'Anti Aim',
  3499. ],[
  3500. aimbot[AIMBOT_ENABLE],
  3501. 'Aimbot',
  3502. aimbot[AIMBOT_WALLCHECK] ? 'Wall Check' : '',
  3503. aimbot[AIMBOT_TARGETSONLY] ? 'Targets Only' : '',
  3504. aimbot[AIMBOT_CURSORMODE] ? 'Cursor Prox' : '',
  3505. aimbot[AIMBOT_TRIGGERBOT] ? 'Triggerbot' + (aimbot[AIMBOT_TRIGGERBOTWHENDOWN] ? ', Mouse Down' : '') : ''
  3506. ],[
  3507. esp[ESP_ZOOM] || esp[ESP_FIXCAMERA],
  3508. 'Camera',
  3509. esp[ESP_ZOOM] ? 'Zoom' : '',
  3510. esp[ESP_FIXCAMERA] ? 'Fix' : ''
  3511. ],[
  3512. tracers || playerAttribs,
  3513. 'ESP',
  3514. tracers ? 'Tracers' : '',
  3515. playerAttribs ? 'Player Attributes' : ''
  3516. ],[
  3517. thnet[THNET_ENABLE],
  3518. 'THNet',
  3519. thnet[THNET_SOCKET].readyState != WebSocket.OPEN ? 'Not Connected' : '',
  3520. thnet[THNET_INFOSHARE] ? 'Info Share' : ''
  3521. ]
  3522. ];
  3523. for (let [should, head, ...ext] of things) if (should) {
  3524. let rainbowText = head,
  3525. grayText = '',
  3526. pad = 0;
  3527. for (let e of ext) if (e) grayText += ' (' + e + ')';
  3528. if (misc[MISC_SHOWFEATURES] == 1) {
  3529. rainbowText += grayText;
  3530. grayText = '';
  3531. }
  3532. pad = ctx.measureText(grayText).width;
  3533. drawText(maxX - ctx.measureText(rainbowText).width - pad, maxY - 10, rainbowText, 'hsl(' + round(tickCount * third + (maxY - j7) / E) % 360 + ', 100%, 50%)');
  3534. drawText(maxX - ctx.measureText(grayText).width, maxY - 10, grayText, '#888');
  3535. maxY -= 20;
  3536. }
  3537. },
  3538.  
  3539. drawTracers = (players, playerScreenPos, offset, animationSubtraction) => {
  3540. for (let player of players) {
  3541.  
  3542. //if they have no bullets and they arent reloading, assume they have max bullets
  3543. //because the server doesnt send accurate currentbullets info unless the other players update their bullet count in any way
  3544. if (!player.reloading && player.currentBullets == 0) player.currentBullets = player.maxBullets;
  3545.  
  3546. //the tracer
  3547. if (esp[ESP_TRACERSBODYENEMY]) drawLine(playerScreenPos, player, offset, 1);
  3548.  
  3549. let ringColor;
  3550. //congrats, you're playing with the dev of this cheat
  3551. if (player[ATTRIBUTE_USERNAMEHASH] == developerHash) {
  3552. ctx.globalAlpha = third * 2;
  3553. ringColor = 'blue';
  3554.  
  3555. //make a light blue circle to signify fellow tiohax users
  3556. } else if (includesInArray(thnet[THNET_BROTHERS], player[ATTRIBUTE_USERNAMEHASH])) {
  3557. ctx.globalAlpha = third;
  3558. ringColor = 'blue';
  3559.  
  3560. //make a red circle to tell targets apart
  3561. } else if (includesInArray(targets, player[ATTRIBUTE_SANITIZEDNAME])) {
  3562. ctx.globalAlpha = third;
  3563. ringColor = 'red';
  3564.  
  3565. //make a dark circle to tell friends apart
  3566. } else if (includesInArray(friends, player[ATTRIBUTE_SANITIZEDNAME])) {
  3567. ctx.globalAlpha = third * 2;
  3568. ringColor = '#000';
  3569.  
  3570. //show that they wont be shot at because they are chatting and the ignorechatting option is enabled
  3571. } else if (aimbot[AIMBOT_IGNORECHATTING] && player.chatBoxOpen) {
  3572. ctx.globalAlpha = third;
  3573. ringColor = '#000';
  3574. }
  3575.  
  3576. if (ringColor) drawCircle(player, offset, player[ATTRIBUTE_RADIUS] * 1.4, 5, ringColor);
  3577.  
  3578. //dont make the health value text transparent
  3579. ctx.globalAlpha = 1;
  3580.  
  3581. //draw the health values (hp and armor) either above or below the player
  3582. //could be more elegant, but ehh
  3583. let x = player.x + offset.x - player[ATTRIBUTE_RADIUS],
  3584. y = player.y + offset.y - (player[ATTRIBUTE_RADIUS] + 6);
  3585.  
  3586. //move health text further down if the player is chatting and above the upper half of the screen
  3587. //figuring out the exact offset values took 2 whole days of trial and error for some reason.
  3588. if (esp[ESP_SHOWHEALTH]) {
  3589. drawText(x, y, player.hp, getColor(player)); //drawText(x, y, spacePadding(player.hp), getColor(player));
  3590. y -= 20;
  3591. }
  3592. if (esp[ESP_SHOWARMOR]) {
  3593. drawText(x, y, player.armorAmount, '#666'); //drawText(x, y, spacePadding(player.armorAmount), '#666');
  3594. y -= 20;
  3595. }
  3596. if (esp[ESP_SHOWMAGS]) {
  3597. drawText(x, y, player.currentBullets + '/' + player.maxBullets, '#000'); //drawText(x, y, spacePadding(player.currentBullets) + '/' + player.maxBullets, '#000');
  3598. y -= 20;
  3599. }
  3600. if (esp[ESP_SHOWGUNRELOADSTATUS] && player.reloading) drawText(x, y, 'RELOADING ' + spacePadding(percentify(player.reloadingAnimation ? player.reloadingFrame / (player.reloadingAnimation.length - animationSubtraction) : 0)), '#888');
  3601. if (esp[ESP_SHOWRANGE]) {
  3602. let gun = gunMap[player.class], range = ranges[gun] * velocities[gun];
  3603. ctx.globalAlpha = 1;
  3604. drawCircle2(player, offset, sqrt((range * mathSin) ** 2 + (range * 0.5 + player[ATTRIBUTE_RADIUS]) ** 2), 3);
  3605. ctx.globalAlpha = 1;
  3606. drawCircle2(player, offset, sqrt((range * 1.5 * mathSin) ** 2 + (range * 0.75 + player[ATTRIBUTE_RADIUS]) ** 2), 3);
  3607. ctx.globalAlpha = 1;
  3608. }
  3609. }
  3610. },
  3611.  
  3612. drawTeamAffiliations = offset => {
  3613. //draw team affiliations of various stuff
  3614. if (!esp[ESP_REVEALTEAMS]) return;
  3615. for (let item of getPool(RA)) {
  3616. if (!item.activated) continue;
  3617.  
  3618. //landmines
  3619. if (item.type == 'landMine') {
  3620. drawCircle(item, offset, 20, 2);
  3621. continue;
  3622. }
  3623. //gas
  3624. if (item.emitting) {
  3625. drawCircle(item, offset, item.emissionRadius, 2);
  3626. continue;
  3627. }
  3628. //grenades
  3629. drawCircle(item, offset, 10, 2);
  3630.  
  3631. if (!esp[ESP_TRACERSGRENADES] || item.timeAlive > item.travelTime) continue;
  3632.  
  3633. //a line from where they are to roughly where they will be
  3634. let factor = (item.travelTime - (item.timeAlive + item[ATTRIBUTE_TIMEALIVEEXTRA])) * advanced[ADVANCED_TPS];
  3635. item[ATTRIBUTE_TIMEALIVEEXTRA] += third;
  3636. drawLine2(item, {x: item.spdX * factor, y: item.spdY * factor}, offset, 1);
  3637. }
  3638.  
  3639. //reveal team affiliations of knifes
  3640. for (let knife of getPool(RC)) if (knife.activated && knife.isKnife) drawCircle(knife, offset, 5, 2);
  3641. },
  3642.  
  3643. perkHacksActionKnife = (me, socketId, offset, enemies, enemyFriends, crates) => {
  3644. if (!perkHacks[PERKHACKS_KNIFE]) return;
  3645.  
  3646. let range = me[ATTRIBUTE_RADIUS] + perkHacks[PERKHACKS_KNIFEMAXRANGE],
  3647. gun = 6, // 6 is knife
  3648. target = getTarget(me, offset, enemies, enemyFriends, crates, me[ATTRIBUTE_RADIUS] ** 2, range ** 2, gun);
  3649. drawCircle(me, offset, range, 3, '#f88');
  3650.  
  3651. if (target[ATTRIBUTE_ENEMY] && target[ATTRIBUTE_DISTANCE] < range ** 2) {
  3652. aimMeAt(aimTorwards(me, target[ATTRIBUTE_ENEMY], offset, target[ATTRIBUTE_DISTANCE], gun), 1, 1);
  3653. if (perkHacks[PERKHACKS_TICK]) {
  3654. startActivePerk(socketId);
  3655. } else {
  3656. stopActivePerk(socketId);
  3657. }
  3658. perkHacks[PERKHACKS_TICK] = 1;
  3659.  
  3660. } else {
  3661. perkHacks[PERKHACKS_TICK] = 0;
  3662. }
  3663. },
  3664.  
  3665. perkHacksActionShield = (me, socketId, playerScreenPos, offset, crates, animationSubtraction) => {
  3666. if (!perkHacks[PERKHACKS_SHIELD]) return;
  3667.  
  3668. let closestBullet = 0,
  3669. shortestDistance = SHIELD_RANGE ** 2,
  3670. chosenAngle = 0.,
  3671. factor = animationSubtraction + perkHacks[PERKHACKS_SHIELDLOOKAHEAD],
  3672. futurePos = calcAheadness(me, me, 0, 0);
  3673.  
  3674. futurePos.x = me.x + (me.x - futurePos.x);
  3675. futurePos.y = me.y + (me.y - futurePos.y);
  3676.  
  3677. if (perkHacks[PERKHACKS_SHIELDVISUALISER] & 1) {
  3678. drawCircle(futurePos, offset, SHIELD_RANGE, 2, '#000');
  3679. drawCircle(futurePos, offset, 30, 2, '#000');
  3680. }
  3681.  
  3682. //look for the best bullet to block
  3683. for (let bullet of getPool(RC)) {
  3684. if (bullet.ownerId === me.id || (bullet.teamCode && bullet.teamCode == me.teamCode) ||
  3685. getDistanceSquared(bullet, me, nullPos) < 30 ** 2
  3686. ) continue;
  3687. let lineEnd = {
  3688. x: bullet.spdX * factor + bullet.length * cos(bullet.angle * degToRad),
  3689. y: bullet.spdY * factor + bullet.length * sin(bullet.angle * degToRad)
  3690. },
  3691. distance = distanceSquaredLinePoint(
  3692. bullet.x, bullet.y,
  3693. bullet.x + lineEnd.x, bullet.y + lineEnd.y,
  3694. futurePos.x, futurePos.y
  3695. );
  3696.  
  3697. if (perkHacks[PERKHACKS_SHIELDVISUALISER] > 1) drawLine2(bullet, lineEnd, offset, 1, '#ddd');
  3698.  
  3699. //if closer than the current closest bullet
  3700. if (distance > shortestDistance) continue;
  3701.  
  3702. //ignore bullets that would have to go through a wall
  3703. if (perkHacks[PERKHACKS_SHIELDWALLCHECK]) {
  3704. let hasToHit = 0;
  3705. for (let i = 0; i < crates.length; i++) {
  3706. let crate = crates[i];
  3707.  
  3708. //avoid calculating collisions if it would just be a waste
  3709. if (!crate[ATTRIBUTE_BULLETCOLLISIONS] || getDistanceSquared(inclusionBox, crate, nullPos) > (inclusionBox.z + crate[ATTRIBUTE_HITBOXRADIUS]) ** 2) continue;
  3710.  
  3711. //if the crate intersects with the line, add them to the list of crates that have been hit
  3712. //works by checking if the line from the gun end to the enemy position collides with any line from the crate hitbox
  3713. let wallIntersect = 0;
  3714. for (let j = 0; j < crate[ATTRIBUTE_HITBOX].length; j++) {
  3715.  
  3716. //find out where the wall is currently intersecting
  3717. let currentIntersect = intersectionPointLineLine(
  3718. bullet.x, bullet.y,
  3719. bullet.x + lineEnd.x, bullet.y + lineEnd.y,
  3720. crate.x + crate[ATTRIBUTE_HITBOX][j][0], crate.y + crate[ATTRIBUTE_HITBOX][j][1],
  3721. crate.x + crate[ATTRIBUTE_HITBOX][j][2], crate.y + crate[ATTRIBUTE_HITBOX][j][3]
  3722. );
  3723.  
  3724. //if we are intersecting, we have hit something
  3725. if (currentIntersect) {
  3726. hasToHit = 1;
  3727.  
  3728. //get the intersection point that is closer to the bullet
  3729. if (wallIntersect) {
  3730. if (getDistanceSquared(currentIntersect, bullet, nullPos) > getDistanceSquared(wallIntersect, bullet, nullPos)) {
  3731. wallIntersect = currentIntersect;
  3732. }
  3733. } else {
  3734. wallIntersect = currentIntersect;
  3735. }
  3736. }
  3737. }
  3738. }
  3739.  
  3740. //
  3741.  
  3742. if (hasToHit) continue;
  3743. }
  3744.  
  3745. closestBullet = bullet;
  3746. shortestDistance = distance;
  3747. }
  3748.  
  3749. if (closestBullet) {
  3750. if (!perkHacks[PERKHACKS_SHIELDMANUAL]) startActivePerk(socketId);
  3751. perkHacks[PERKHACKS_TICK] = perkHacks[PERKHACKS_SHIELDUPKEEP] * 2.5;
  3752. chosenAngle = perkHacks[PERKHACKS_STOREDANGLE] = atan2(-closestBullet.spdY, -closestBullet.spdX);
  3753.  
  3754. } else if (perkHacks[PERKHACKS_TICK] > 0 && (perkHacks[PERKHACKS_TICK] -= 2.5 / advanced[ADVANCED_TPS])) {
  3755. chosenAngle = perkHacks[PERKHACKS_STOREDANGLE];
  3756. if (!perkHacks[PERKHACKS_SHIELDMANUAL]) startActivePerk(socketId);
  3757.  
  3758. } else {
  3759. if (!perkHacks[PERKHACKS_SHIELDMANUAL]) stopActivePerk(socketId);
  3760. perkHacks[PERKHACKS_TICK] = perkHacks[PERKHACKS_STOREDANGLE] = 0;
  3761. return;
  3762. }
  3763. aimMeAt({
  3764. clientX: playerScreenPos.x + 50 * cos(perkHacks[PERKHACKS_STOREDANGLE]),
  3765. clientY: playerScreenPos.y + 50 * sin(perkHacks[PERKHACKS_STOREDANGLE])
  3766. }, 1, 1);
  3767. },
  3768.  
  3769. perkHacksActionBuildMedkit = (me, socketId, offset) => {
  3770. if (perkHacks[PERKHACKS_CRATEPLACEVISION]) {
  3771. let box = {
  3772. x: 50 * cos(me.playerAngle * degToRad),
  3773. y: 50 * sin(me.playerAngle * degToRad)
  3774. };
  3775. ctx.strokeStyle = '#000';
  3776. ctx.lineWidth = 1;
  3777. ctx.strokeRect(me.x + offset.x + box.x - 20, me.y + offset.y + box.y - 20, 40, 40);
  3778. drawLine2(me, box, offset, 1, '#000');
  3779. }
  3780.  
  3781. // if medkit
  3782. if (false && o3[2] == abilities[1]) {
  3783. if (perkHacks[PERKHACKS_MEDKITSELFHEAL] && me.hp < perkHacks[PERKHACKS_MEDKITSELFHEALTHRESHOLD]) {
  3784. let futurePos
  3785. aimMeAt({
  3786. clientX: me.x + offset.x + me[ATTRIBUTE_USABLESPDX],
  3787. clientY: me.y + offset.y + me[ATTRIBUTE_USABLESPDY]
  3788. }, 1, 1);
  3789. if (perkHacks[PERKHACKS_TICK]) startActivePerk(socketId);
  3790. perkHacks[PERKHACKS_TICK] = 1;
  3791. } else {
  3792. stopActivePerk(socketId);
  3793. perkHacks[PERKHACKS_TICK] = 0;
  3794. }
  3795. return;
  3796. }
  3797. // if build
  3798. },
  3799.  
  3800. perkHacksAction = (me, socketId, playerScreenPos, offset, enemies, enemyFriends, crates, animationSubtraction) => {
  3801. if (c9.current - animationSubtraction > 0 || !o3[2]) {
  3802. perkHacks[PERKHACKS_TICK] = 0;
  3803. if ((perkHacks[PERKHACKS_KNIFE] || perkHacks[PERKHACKS_SHIELD]) &&
  3804. !(perkHacks[PERKHACKS_SHIELD] && abilities[0] == o3[2] && perkHacks[PERKHACKS_SHIELDMANUAL])
  3805. ) stopActivePerk(socketId);
  3806. return;
  3807. }
  3808.  
  3809. switch (o3[2]) {
  3810. case abilities[3]: //Knife
  3811. perkHacksActionKnife(me, socketId, offset, enemies, enemyFriends, crates);
  3812. break;
  3813.  
  3814. case abilities[0]: //Shield
  3815. perkHacksActionShield(me, socketId, playerScreenPos, offset, crates, animationSubtraction);
  3816. break;
  3817.  
  3818. case abilities[1]: //Medkit
  3819. case abilities[4]: //Build
  3820. perkHacksActionBuildMedkit(me, socketId, offset);
  3821. break;
  3822. }
  3823. },
  3824.  
  3825. thnetInfoShare = leaderboardLeft => {
  3826. ctx.font = 'bold 14px consolas';
  3827. for (let entryName in thnet[THNET_INFOSHARING]) {
  3828. let entry = thnet[THNET_INFOSHARING][entryName],
  3829. spacing = 5,
  3830. width = 160,
  3831. height = 160;
  3832. if (entry.length < 10) continue;
  3833. leaderboardLeft -= spacing + width;
  3834. ctx.strokeStyle = ctx.fillStyle = '#888';
  3835. ctx.globalAlpha = 0.5;
  3836. ctx.fillRect(leaderboardLeft, 5, width, height);
  3837. ctx.lineWidth = 3;
  3838. ctx.globalAlpha = 1;
  3839. ctx.strokeRect(leaderboardLeft, 5, width, height);
  3840. leaderboardLeft += 5;
  3841. let text = [
  3842. ' Name: ' + entry[0],
  3843. ' HP: ' + spacePadding(entry[1]) + '/' + entry[2],
  3844. 'Armor: ' + spacePadding(entry[3]) + '/' + entry[4],
  3845. ' Ammo: ' + spacePadding(entry[5]) + '/' + entry[6],
  3846. 'Class: ' + gunNames[entry[7]],
  3847. ' X: ' + spacePadding(round(entry[8]), 4) + ' Y: ' + spacePadding(round(entry[9]), 4)
  3848. ];
  3849. for (let i = 0; i < text.length; i++) {
  3850. drawText(leaderboardLeft, 20 + i * 17, text[i], '#000');
  3851. }
  3852. ctx.lineWidth = 2;
  3853. for (let i = 0; i < 3; i++) {
  3854. ctx.strokeRect(leaderboardLeft + 5 + i * 50, 115, 40, 40);
  3855. if (j30[entry[11 + i]]) {
  3856. ctx.drawImage(j30[entry[11 + i]], leaderboardLeft + 5 + i * 50, 115, 40, 40);
  3857. if (i == 1 && entry[14] > 0) {
  3858. j58.globalAlpha = 0.75;
  3859. j58.fillStyle = "#7a7a7a";
  3860. j58.fillRect(leaderboardLeft + 5 + i * 50, 115, 40 * entry[14], 40);
  3861. ctx.globalAlpha = 1;
  3862. }
  3863. }
  3864. }
  3865. //0: sanitisedname
  3866. //1: hp
  3867. //2: hpMax
  3868. //3: armorAmount
  3869. //4: armorMax
  3870. //5: currentBullets
  3871. //6: maxBullets
  3872. //7: gun
  3873. //8: x
  3874. //9: y
  3875. //a: color
  3876. //b: o3[1]
  3877. //c: o3[2]
  3878. //d: o3[3]
  3879. //e: c9.current / c9.total
  3880.  
  3881.  
  3882. //RD.prototype[ATTRIBUTE_DRAWBODY].call({});
  3883. //RD.prototype[ATTRIBUTE_DRAWGUN].call({});
  3884. leaderboardLeft -= 10;
  3885. }
  3886. },
  3887.  
  3888. goToSpotWithPackets = (socketId, me, goal) => {
  3889. //resets movement
  3890. for (let inputId of [KEYPRESS_KEY_LEFT, KEYPRESS_KEY_RIGHT, KEYPRESS_KEY_UP, KEYPRESS_KEY_DOWN]) keyPress(socketId, inputId, 0);
  3891.  
  3892. //sends the correct movement
  3893. for (let inputId of [
  3894. [KEYPRESS_KEY_RIGHT],
  3895. [KEYPRESS_KEY_RIGHT, KEYPRESS_KEY_DOWN],
  3896. [KEYPRESS_KEY_DOWN],
  3897. [KEYPRESS_KEY_DOWN, KEYPRESS_KEY_LEFT],
  3898. [KEYPRESS_KEY_LEFT],
  3899. [KEYPRESS_KEY_UP, KEYPRESS_KEY_LEFT],
  3900. [KEYPRESS_KEY_UP],
  3901. [KEYPRESS_KEY_UP, KEYPRESS_KEY_RIGHT]
  3902. ][ round(( atan2(me.y - goal.y, me.x - goal.x) / TAU ) * 8 + 4) % 8 ]) keyPress(socketId, inputId, 1);
  3903. },
  3904.  
  3905. //will i ever use this?
  3906. sanitizeMessage = message => make('p', {}, { innerText: message }).innerHTML,
  3907.  
  3908. makeChatMessage = args => {
  3909. let scrollback = divs.chatbox.scrollTop === divs.chatbox.scrollHeight - divs.chatbox.clientHeight, msgs = [];
  3910. for (let msg of args) {
  3911. msgs.push(make('div', {
  3912. color: msg[0],
  3913. whiteSpace: msg[2] ? 'pre' : 'normal'
  3914. }, { innerText: msg[1] }));
  3915. }
  3916. divs.chatbox.append(make('div', {
  3917. [css_key_paddingLeft]: css_value_length_px3,
  3918. [css_key_display]: css_value_misc_flex,
  3919. [css_key_minWidth]: css_value_length_em2
  3920. }, {}, msgs));
  3921. if (scrollback) divs.chatbox.scroll({ top: divs.chatbox.scrollHeight, behavior: 'instant' });
  3922. },
  3923.  
  3924. thnetOnMessage = event => {
  3925. let data = event.data.split(' ');
  3926. switch (pInt(data.shift())) {
  3927. case 0: //load new people into dict without dublicates
  3928. for (let user of data) {
  3929. user = pInt(user);
  3930. if (!includesInArray(thnet[THNET_BROTHERS], user)) thnet[THNET_BROTHERS].push(user);
  3931. }
  3932. break;
  3933.  
  3934. case 1: //remove a person from the dict
  3935. let i = indexOfInArray(thnet[THNET_BROTHERS], pInt(data[0]));
  3936. if (thnet[THNET_BROTHERS].length - 1 > i) {
  3937. thnet[THNET_BROTHERS][i] = thnet[THNET_BROTHERS].pop();
  3938. } else {
  3939. thnet[THNET_BROTHERS].pop();
  3940. }
  3941. break;
  3942.  
  3943. case 2: //serverwide chat
  3944. makeChatMessage([['#88f', data.shift().replace('_', ' ')], ['#fff', ': ', 1], ['#fff', data.join(' ')]]);
  3945. break;
  3946.  
  3947. case 3: //keepalive
  3948. thnet[THNET_SOCKET].send('');
  3949. if (thnet[THNET_INFOSHARE] && c3 !== null && thnet[THNET_SOCKET].readyState == WebSocket.OPEN) {
  3950. let me = RD.pool[c3];
  3951. thnet[THNET_SOCKET].send('1 ' + [
  3952. me.hp, me.hpMax,
  3953. me.armorAmount, armorMap[c1.armor] * 30,
  3954. me.currentBullets, me.maxBullets,
  3955. gunMap[me.class],
  3956. me.x, me.y, me.color.a,
  3957. o3[1], o3[2], o3[3], c9.current / c9.total
  3958. ].join(' '));
  3959. }
  3960. break;
  3961.  
  3962. case 4: //received close reason
  3963. thnet[THNET_CLOSEREASON] = data.join(' ');
  3964. break;
  3965.  
  3966. case 5:
  3967. makeChatMessage([['#f88', data.join(' ')]]);
  3968. break;
  3969.  
  3970. case 6:
  3971. let name = data[0].replace('_', ' ');
  3972. if (data.length < 2) {
  3973. delete thnet[THNET_INFOSHARING][name];
  3974. return;
  3975. }
  3976. data[0] = name;
  3977. thnet[THNET_INFOSHARING][name] = data;
  3978. }
  3979. },
  3980.  
  3981. connectToTHNet = () => thnet[THNET_SOCKET] = applyAttrbutes(new WebSocket('ws' + homeUrl + sanitiseName(b4) + '/' + encodeURIComponent(o4.server + '/' + c22) + '/' + thnet[THNET_AUTH]), {
  3982. onopen: event => {
  3983. divs.chatwrap.hidden = !thnet[THNET_CHAT];
  3984. makeChatMessage([['#ff0', 'Connected']]);
  3985. },
  3986. onmessage: thnetOnMessage,
  3987. onerror: event => thnet[THNET_CLOSEREASON] = 'Error',
  3988. onclose: event => {
  3989. thnet[THNET_BROTHERS] = [];
  3990. thnet[THNET_SOCKET] = 0;
  3991. makeChatMessage([['#ff0', 'Disconnected' + (thnet[THNET_CLOSEREASON] ? ' (' + thnet[THNET_CLOSEREASON] + ')' : '')]]);
  3992.  
  3993. }
  3994. }),
  3995.  
  3996. handleUncomplicatedKeypress = (keyEvent, msg) => {
  3997. switch (keyEvent.keyCode) {
  3998. case keyCodeMap[KEYCODE_A]:
  3999. case keyCodeMap[KEYCODE_ARROWLEFT]:
  4000. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_LEFT, KEYPRESS_STATE_ON);
  4001. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_RIGHT, KEYPRESS_STATE_OFF);
  4002. break;
  4003. case keyCodeMap[KEYCODE_D]:
  4004. case keyCodeMap[KEYCODE_ARROWRIGHT]:
  4005. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_RIGHT, KEYPRESS_STATE_ON);
  4006. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_LEFT, KEYPRESS_STATE_OFF);
  4007. break;
  4008. case keyCodeMap[KEYCODE_W]:
  4009. case keyCodeMap[KEYCODE_ARROWUP]:
  4010. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_UP, KEYPRESS_STATE_ON);
  4011. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_DOWN, KEYPRESS_STATE_OFF);
  4012. break;
  4013. case keyCodeMap[KEYCODE_S]:
  4014. case keyCodeMap[KEYCODE_ARROWDOWN]:
  4015. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_DOWN, KEYPRESS_STATE_ON);
  4016. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_UP, KEYPRESS_STATE_OFF);
  4017. break;
  4018. case keyCodeMap[KEYCODE_R]:
  4019. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_RELOAD, KEYPRESS_STATE_ON);
  4020. break;
  4021. case keyCodeMap[KEYCODE_SPACE]:
  4022. startActivePerk(multiBox[MULTIBOX_SELECTEDSOCKET]);
  4023. break;
  4024. case keyCodeMap[KEYCODE_N]:
  4025. o10.push({type: 8, content: c37 = !c37, initTime: Date.now()});
  4026. break;
  4027. case keyCodeMap[KEYCODE_T]:
  4028. divs.menu.hidden = !divs.menu.hidden;
  4029. break;
  4030. case keyCodeMap[KEYCODE_CTRL]:
  4031. divs.chatwrap.hidden = !divs.chatwrap.hidden;
  4032. break;
  4033. default:
  4034. if (!instantchat[INSTANTCHAT_CHATBINDS] || !msg) break;
  4035. let padding = ' '.repeat(lastMessageLength = (lastMessageLength + 1) & 1);
  4036. sendChatMessage(multiBox[MULTIBOX_SELECTEDSOCKET], padding + msg + padding);
  4037. }
  4038. },
  4039.  
  4040. handleEnterPress = (socket, { style: chatboxContainerStyle }, chatbox, shiftPressed) => {
  4041. if (shiftPressed) return divs.chatinput.focus();
  4042.  
  4043. //get chat input value
  4044. j47 = chatbox.value;
  4045.  
  4046. //if there is a chat input value, send it as a chat message
  4047. if (j46 && j47 != '') {
  4048. sendChatMessage(multiBox[MULTIBOX_SELECTEDSOCKET], j47.replace(/,/g, '~').substring(0, 30));
  4049. chatboxContainerStyle[css_key_display] = css_value_misc_none;
  4050. chatbox.value = j47 = '';
  4051.  
  4052. //if no chat input value, close the chat input
  4053. } else if (j46 && j47 == '') {
  4054. chatboxContainerStyle[css_key_display] = css_value_misc_none;
  4055. } else if (!j46) {
  4056. chatboxContainerStyle[css_key_display] = css_value_misc_inlineBlock;
  4057. chatbox.focus();
  4058. }
  4059. j46 = !j46;
  4060. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], 7, j46 * !misc[MISC_HIDECHATTING]);
  4061. socket.send(a59('focus'));
  4062. },
  4063.  
  4064. colorLerp = (color1, color2, percent) => {
  4065. color1 = [
  4066. pInt(color1.slice(1, 3), 16),
  4067. pInt(color1.slice(3, 5), 16),
  4068. pInt(color1.slice(5, 7), 16)
  4069. ];
  4070. color2 = [
  4071. pInt(color2.slice(1, 3), 16),
  4072. pInt(color2.slice(3, 5), 16),
  4073. pInt(color2.slice(5, 7), 16)
  4074. ];
  4075. let result = '#';
  4076. for (let i = 0; i < 3; i++) {
  4077. let chunk = lerpR(color2[i], color1[i], percent).toString(16);
  4078. result += chunk.length == 1 ? '0' + chunk : chunk;
  4079. }
  4080.  
  4081. return result;
  4082. },
  4083.  
  4084. onAFK = (me, socketId) => {
  4085. let horizontal = j11 / 2 - me.x,
  4086. vertical = j12 / 2 - me.y,
  4087. key = [[ KEYPRESS_KEY_LEFT, KEYPRESS_KEY_RIGHT ][ horizontal > 1 ], [ KEYPRESS_KEY_DOWN, KEYPRESS_KEY_UP ][ vertical > 1 ]][ abs(horizontal) > abs(vertical) ];
  4088. keyPress(socketId, key, KEYPRESS_STATE_OFF);
  4089. keyPress(socketId, key, KEYPRESS_STATE_ON);
  4090. },
  4091.  
  4092. replaceENEMYInText = (str, enemy) => str.replace('[[ENEMY]]', sanitiseName(enemy.replace('Guest ', ''))),
  4093.  
  4094. onKill = (socketId, victim) => instantchat[INSTANTCHAT_ONKILL] && sendChatMessage(socketId, replaceENEMYInText(instantchat[INSTANTCHAT_ONKILLTEXT], victim)),
  4095.  
  4096. onDeath = (socketId, killer) => instantchat[INSTANTCHAT_ONDEATH] && sendChatMessage(socketId, replaceENEMYInText(instantchat[INSTANTCHAT_ONDEATHTEXT], killer)),
  4097.  
  4098. onHeal = (socketId, geduldig) => instantchat[INSTANTCHAT_AUTOTHANK] && geduldig == c3 && sendChatMessage(socketId, instantchat[INSTANTCHAT_AUTOTHANKTEXT]),
  4099.  
  4100. drawMinimap = player => {
  4101. if (j43) return;
  4102. let baseWidth = 144,
  4103. baseHeight = 144,
  4104. scaledWidth = (100 / j11 - j31) * 0.01,
  4105. scaledHeight = (100 / j12 - j41) * 0.01,
  4106. widthOffset = baseWidth / 2 - scaledWidth,
  4107. heightOffset = baseHeight / 2 - scaledWidth,
  4108. width = baseWidth * (c24 / j11),
  4109. height = baseHeight * (c24 / j12),
  4110. baseX = (baseWidth - width) * 0.5,
  4111. baseY = (baseHeight - height) * 0.5;
  4112. ctx.globalAlpha = 0.5;
  4113. ctx.fillStyle = "#808080";
  4114. ctx.fillRect(5, 20, 150, 150);
  4115. ctx.fillStyle = "#7a7a7a";
  4116. ctx.fillRect(8, 23, baseWidth, baseHeight);
  4117. ctx.fillStyle = "#b5b5b5";
  4118. ctx.strokeStyle = "#d9d9d9";
  4119. ctx.lineWidth = 1;
  4120. ctx.fillRect(widthOffset + 8, heightOffset + 23, scaledWidth * 2, scaledHeight * 2);
  4121. if (c22 == "FFA" || c22 == "TDM") {
  4122. ctx.strokeStyle = "#d9d9d9";
  4123. j25(ctx, baseX + 8, baseY + 23, width, height);
  4124. } else if (c22 == "2TEAM" || c22 == "DOM") {
  4125. for (let i = 0; i < 4; i++) {
  4126. ctx.strokeStyle = [
  4127. "#d9d9d9", //light gray, neutral
  4128. "#f26740", //reddish orange, red capped
  4129. "#8dd8f8" //light blue, blue capped
  4130. ][j52[i + 1]];
  4131.  
  4132. let baseX = baseWidth * 0.5 - 20,
  4133. baseY = baseHeight * 0.5 - 20;
  4134. if (i & 1) baseX += 40 - width;
  4135. if (i > 1) baseY += 40 - height;
  4136.  
  4137. j25(ctx, baseX + 8, baseY + 23, width, height);
  4138. }
  4139. }
  4140. ctx.strokeStyle = "#666";
  4141. ctx.lineWidth = 0;
  4142. if (thnet[THNET_INFOSHARE]) for (let entryName in thnet[THNET_INFOSHARING]) if (entryName != player[ATTRIBUTE_SANITIZEDNAME]) {
  4143. let entry = thnet[THNET_INFOSHARING][entryName];
  4144. ctx.fillStyle = entry[10];
  4145. j22(ctx, baseWidth * (entry[8] / j11) + 8, baseHeight * (entry[9] / j12) + 23, 2);
  4146. ctx.fill();
  4147. }
  4148. if (player == null || player === undefVar) return;
  4149. ctx.fillStyle = player.color.a;
  4150. j22(ctx, baseWidth * (player.x / j11) + 8, baseHeight * (player.y / j12) + 23, 2);
  4151. ctx.fill();
  4152. ctx.globalAlpha = 1;
  4153. },
  4154.  
  4155. //send mouse position to server
  4156. sendMousePositionToServer = socketId => {
  4157. //thank you dygn for coding packet sending in such a weird way
  4158. let str = a60('mouse-move', {mouseX: j16[0], mouseY: j16[1], mouseAngle: j16[2]});
  4159.  
  4160. //convert string to bytes then send
  4161. //j15 isnt used anywhere so we can reuse it for whatever purpose
  4162. if (RF.list[socketId] !== undefVar && str !== j15) RF.list[socketId].send(a66(j15 = str));
  4163. },
  4164.  
  4165. //draw floor
  4166. drawFloor = (ctx, camera) => {
  4167. let relPos1 = {x: -camera.x , y: -camera.y},
  4168. relPos2 = {x: j11 - camera.x, y: j12 - camera.y},
  4169. playerPos = RD.pool[c3],
  4170. position = {x: relPos1.x + j11 / 2 - c24 / 2, y: relPos1.y + j12 / 2 - c24 / 2},
  4171. positionMap = [
  4172. {x: relPos1.x + j11 / 2 - 1000 , y: relPos1.y + j12 / 2 - 1000 },
  4173. {x: relPos1.x + j11 / 2 + 1000 - c24 , y: relPos1.y + j12 / 2 - 1000 },
  4174. {x: relPos1.x + j11 / 2 - 1000 , y: relPos1.y + j12 / 2 + 1000 - c24},
  4175. {x: relPos1.x + j11 / 2 + 1000 - c24 , y: relPos1.y + j12 / 2 + 1000 - c24}
  4176. ],
  4177. capturepointPos = { x: (j11 - c24) / 2, y: (j12 - c24) / 2 },
  4178. midPointColor = playerPos.x > capturepointPos.x && playerPos.x < capturepointPos.x + c24 && playerPos.y > capturepointPos.y && playerPos.y < capturepointPos.y + c24 ? paint[PAINT_POINTSFFA] : paint[PAINT_POINTSIDLE],
  4179. i = 0;
  4180.  
  4181. for (i = 0; i < 4; i++) positionMap[i].z = [paint[PAINT_POINTSIDLE], paint[PAINT_POINTSRED], paint[PAINT_POINTSBLU]][j52[i + 1]];
  4182.  
  4183. //background
  4184. ctx.fillStyle = paint[PAINT_GRIDCOLOR][1];
  4185. ctx.fillRect(0, 0, j7, j8);
  4186.  
  4187. //mid point
  4188. if (c22 == 'FFA' || c22 == 'TDM') {
  4189. ctx.fillStyle = midPointColor[1];
  4190. ctx.fillRect(position.x, position.y, c24, c24);
  4191. }
  4192. if (c22 == '2TEAM' || c22 == 'DOM') for (let i = 0; i < positionMap.length; i++) {
  4193. ctx.fillStyle = positionMap[i].z[1];
  4194. ctx.fillRect(positionMap[i].x, positionMap[i].y, c24, c24);
  4195. }
  4196.  
  4197. //hey whats up guys its gr1dical here today we are changing how the grid looks
  4198. ctx.strokeStyle = paint[PAINT_GRIDCOLOR][0];
  4199. for (i = 0; i <= j12; i += paint[PAINT_GRIDSPACEY]) if (relPos1.y + i > 0 && relPos1.y + i <= relPos2.y) j21(ctx, relPos1.x, relPos1.y + i, relPos2.x, relPos1.y + i, paint[PAINT_GRIDLINEWIDTHHORIZONTAL]);
  4200. for (i = 0; i <= j11; i += paint[PAINT_GRIDSPACEX]) if (relPos1.x + i > 0 && relPos1.x + i <= relPos2.x) j21(ctx, relPos1.x + i, relPos1.y, relPos1.x + i, relPos2.y, paint[PAINT_GRIDLINEWIDTHVERTICAL]);
  4201.  
  4202. //map border
  4203. ctx.strokeStyle = '#aaa';
  4204. ctx.lineWidth = 10;
  4205. ctx.strokeRect(relPos1.x, relPos1.y, j11, j12);
  4206.  
  4207. //if mid capture point is being capped
  4208. ctx.lineWidth = paint[PAINT_POINTEDGEWIDTH];
  4209. if (c22 == 'FFA' || c22 == 'TDM') {
  4210. ctx.strokeStyle = midPointColor[0];
  4211. ctx.strokeRect(position.x, position.y, c24, c24);
  4212.  
  4213. }
  4214. //if dom capture points are being capped
  4215. if (c22 == '2TEAM' || c22 == 'DOM') for (let i = 0; i < positionMap.length; i++) {
  4216. ctx.strokeStyle = positionMap[i].z[0];
  4217. ctx.strokeRect(positionMap[i].x, positionMap[i].y, c24, c24);
  4218. }
  4219. },
  4220.  
  4221. //draw leaderboard
  4222. drawLeaderBoard = (ctx, leaderboard) => {
  4223. leaderboard.current = leaderboard.new;
  4224. if (j3 < 1 || j3 > 2.6) return;
  4225. let offset = 0.03,
  4226. leftiest = 1.695 * j1;
  4227. ctx.fillStyle = '#609b68';
  4228. ctx.textAlign = css_value_misc_center;
  4229. ctx.font = 'bold 11px Arial';
  4230. ctx.fillText('Total Players Online: ' + c29, 1.845 * j1, 0.032 * j2);
  4231. ctx.fillStyle = '#4C4C4C';
  4232. if (leaderboard.current.length > 0) ctx.fillText('Leaderboard', 1.845 * j1, 0.07 * j2);
  4233. ctx.textAlign = 'start';
  4234. for (let entry of leaderboard.current) {
  4235. if (!entry.userId) continue;
  4236. let horizontalOffset = 1.695 * j1,
  4237. name = entry.userId,
  4238. nameHash = hashString(sanitiseName(name)),
  4239. selectedStyle = nameHash == developerHash ? '#00f' :
  4240. includesInArray(thnet[THNET_BROTHERS], nameHash) ? '#88f' :
  4241. includesInArray(targets, name) ? '#f00' :
  4242. includesInArray(friends, name) ? '#000' : 0,
  4243. label = {
  4244. '#00f': 'DEV',
  4245. '#88f': 'THnet',
  4246. '#f00': 'Target',
  4247. '#000': 'Friend'
  4248. }[selectedStyle];
  4249. ctx.globalAlpha = 0.5;
  4250. ctx.fillStyle = ['#808080', '#f26740', '#40b2e5'][pInt(entry.teamCode)];
  4251. ctx.fillRect(1.7 * j1, (0.05 + offset) * j2, 0.295 * j1, 0.04 * j2);
  4252. if (entry.isMember) {
  4253. ctx.globalAlpha = 0.65;
  4254. drawImage(j30.vip, 1.703 * j1, (0.055 + offset) * j2, 18, 10);
  4255. }
  4256. ctx.globalAlpha = 1;
  4257. ctx.fillStyle = 'white';
  4258. ctx.font = '10px Arial';
  4259. ctx.fillText(name + ': ' + entry.score, (entry.isMember ? 1.735 : 1.705) * j1, (0.0787 + offset) * j2);
  4260. ctx.textAlign = 'right';
  4261. ctx.fillText('Kills: ' + entry.kills, 1.99 * j1, (0.0795 + offset) * j2);
  4262. ctx.textAlign = 'start';
  4263. if (misc[MISC_LEADERBOARDBADGES] && selectedStyle) {
  4264. ctx.strokeStyle = ctx.fillStyle = selectedStyle;
  4265. ctx.font = 'bold 13px consolas';
  4266. let width = ctx.measureText(label).width + 8;
  4267. ctx.globalAlpha = 0.5;
  4268. ctx.fillRect(horizontalOffset - width, (0.05 + offset) * j2, width, 0.04 * j2);
  4269. ctx.globalAlpha = ctx.lineWidth = 1;
  4270. ctx.strokeRect(horizontalOffset - width, (0.05 + offset) * j2, width, 0.04 * j2);
  4271. ctx.fillStyle = '#ffffff';
  4272. ctx.fillText(label, horizontalOffset - width + 4, (0.0795 + offset) * j2);
  4273. horizontalOffset -= width;
  4274. }
  4275. leftiest = min(leftiest, horizontalOffset);
  4276. offset += 0.045;
  4277. }
  4278. ctx.textAlign = 'right';
  4279. ctx.fillStyle = '#4C4C4C';
  4280. ctx.font = 'bold 11px Arial';
  4281. ctx.fillText('Players in arena: ' + o4.currentPlayers, 1.99 * j1, (offset + 0.075) * j2);
  4282. ctx.textAlign = 'start';
  4283. return leftiest;
  4284. },
  4285.  
  4286. aimMeAt = (event, isBot, isAbility) => {
  4287. let me = RD.pool[c3],
  4288. relPos = {
  4289. x: (me.x - c2.x) * (isBot ? 1 : j6) - event.clientX,
  4290. y: (me.y - c2.y) * (isBot ? 1 : j5) - event.clientY
  4291. },
  4292. mouseAngle = atan2(relPos.y, relPos.x) / degToRad + 180,
  4293. playerAngle = mouseAngle + (isAbility ? 0 : asin(18 / sqrt(relPos.x ** 2 + relPos.y ** 2)) / degToRad);
  4294. j16 = [round(relPos.x), round(relPos.y), round(mouseAngle)];
  4295. if (!playerAngle && playerAngle !== 0) playerAngle = mouseAngle;
  4296. me.playerAngle = round(playerAngle);
  4297. j9 = [event.clientX, event.clientY];
  4298. if (esp[ESP_CAMUSEREALPOSITION]) {
  4299. relPos.x += event.clientX - cursor.x;
  4300. relPos.y += event.clientY - cursor.y;
  4301. mouseAngle = atan2(relPos.y, relPos.x) / degToRad + 180;
  4302. }
  4303. me.mouseAngle = round(mouseAngle);
  4304. j39 = sqrt(relPos.x ** 2 + relPos.y ** 2);
  4305. },
  4306.  
  4307. handleMessage = (socketId, wsMsgEvent) => {
  4308. if (wsMsgEvent.data === undefVar || RF.list[0] === undefVar) return;
  4309. var messageString = a67(wsMsgEvent.data);
  4310. if (messageString == ".") {
  4311. RF.list[socketId].a74();
  4312. RF.list[socketId].a76();
  4313. }
  4314. var messageStringFragments = messageString.split("|");
  4315. for (var i = 0; i < messageStringFragments.length; i++) {
  4316. var wsMessage = a61(messageStringFragments[i]);
  4317. if (wsMessage) switch (wsMessage.code) {
  4318. case "a":
  4319. a78();
  4320. a90();
  4321. c3 = wsMessage.id;
  4322. c2 = new RE(wsMessage.c2);
  4323. c2.trackingId = wsMessage.id;
  4324. a1(c2);
  4325. RD.pool[wsMessage.id].activate(wsMessage, 0);
  4326. c10 = 0;
  4327. c5 = wsMessage.hp;
  4328. c6 = wsMessage.armorAmount;
  4329. c4 = 1;
  4330. var me = RD.pool[c3];
  4331. if (me) {
  4332. c2.x = me.x - window.innerWidth / j6 / 2;
  4333. c2.y = me.y - window.innerHeight / j5 / 2;
  4334. }
  4335. b4 = wsMessage.username;
  4336. b38 = wsMessage.b38;
  4337. selfPremiumMember = wsMessage.isPremiumMember;
  4338. b11 = 0;
  4339. j43 = 0;
  4340. if (thnet[THNET_ENABLE] && !thnet[THNET_SOCKET]) connectToTHNet();
  4341. break;
  4342. case "b":
  4343. RD.pool[wsMessage.id].applyPrimaryUpdate(wsMessage);
  4344. break;
  4345. case "c":
  4346. RD.pool[wsMessage.id].applyAuxUpdate(wsMessage);
  4347. break;
  4348. case "d":
  4349. RD.pool[wsMessage.id].activate(wsMessage, 1);
  4350. break;
  4351. case "e":
  4352. RD.pool[wsMessage.id].deactivate();
  4353. break;
  4354. case "f":
  4355. if (c3) RD.pool[c3].applyFirstPersonUpdateData(wsMessage);
  4356. break;
  4357. case "g":
  4358. RC.pool[wsMessage.id].activate(wsMessage);
  4359. break;
  4360. case "h":
  4361. var bullet = RC.pool[wsMessage.id];
  4362. if (bullet) bullet.applyUpdate(wsMessage);
  4363. break;
  4364. case "i":
  4365. RC.pool[wsMessage.id].deactivate();
  4366. break;
  4367. case "j":
  4368. RB.pool[wsMessage.id].activate(wsMessage);
  4369. break;
  4370. case "k":
  4371. RB.pool[wsMessage.id].applyUpdate(wsMessage);
  4372. break;
  4373. case "l":
  4374. RB.pool[wsMessage.id].deactivate();
  4375. break;
  4376. case "m":
  4377. RA.pool[wsMessage.id].activate(wsMessage);
  4378. break;
  4379. case "n":
  4380. var thrown = RA.pool[wsMessage.id];
  4381. if (thrown) thrown.applyUpdate(wsMessage);
  4382. break;
  4383. case "o":
  4384. RA.pool[wsMessage.id].deactivate();
  4385. break;
  4386. case "p":
  4387. c10 = wsMessage.level;
  4388. break;
  4389. case "q":
  4390. j27.push({
  4391. x: wsMessage.x / 10,
  4392. y: wsMessage.y / 10,
  4393. c42: 0
  4394. });
  4395. break;
  4396. case "r":
  4397. let type = pInt(wsMessage.type),
  4398. content = wsMessage.content;
  4399. if (type == 1) onKill(socketId, content);
  4400. if (type == 2 || type == 9) onDeath(socketId, content);
  4401. if (type == 5) onAFK(socketId, RD.pool[c3]);
  4402. if (pInt(wsMessage.type) == 3) {
  4403. //hit damage notification
  4404. let notif = _.find(o10, {type: 3});
  4405. content = pInt(content);
  4406. if (!notif) {
  4407. o10.push({
  4408. type: type,
  4409. content: content,
  4410. initTime: Date.now()
  4411. });
  4412. break;
  4413. }
  4414. notif.content += content;
  4415. notif.initTime = Date.now();
  4416. break;
  4417. }
  4418. o10.push({
  4419. type: type,
  4420. content: content,
  4421. initTime: Date.now()
  4422. });
  4423. break;
  4424. case "s":
  4425. a4();
  4426. break;
  4427. case "t":
  4428. b11 = 1;
  4429. a45();
  4430. break;
  4431. case "v":
  4432. j38.new = wsMessage.j38;
  4433. o4.currentPlayers = wsMessage.currentPlayers;
  4434. break;
  4435. case "w":
  4436. b4 = wsMessage.username;
  4437. b38 = wsMessage.b38;
  4438. selfPremiumMember = wsMessage.isPremiumMember;
  4439. b3 = 1;
  4440. a111("registerModal");
  4441. a111("loginModal");
  4442. if (wsMessage.rememberCookie.length > 0) a2("remember_cookie", wsMessage.rememberCookie, 365);
  4443. if (selfPremiumMember) $("#hostServerTabLi").show();
  4444. b2 = 0;
  4445. a104();
  4446. a99();
  4447. b24();
  4448. break;
  4449. case "x":
  4450. a18(wsMessage);
  4451. b2 = 0;
  4452. a99();
  4453. break;
  4454. case "y":
  4455. a20(wsMessage);
  4456. break;
  4457. case "z":
  4458. if (wsMessage.status) {
  4459. b4 = "Mystery Creature";
  4460. b38 = "";
  4461. selfPremiumMember = 0;
  4462. b3 = 0;
  4463. $("#hostServerTabLi").hide();
  4464. }
  4465. a99();
  4466. a104();
  4467. break;
  4468. case "sq":
  4469. j52[1] = pInt(wsMessage.squareOneTeam);
  4470. j52[2] = pInt(wsMessage.squareTwoTeam);
  4471. j52[3] = pInt(wsMessage.squareThreeTeam);
  4472. j52[4] = pInt(wsMessage.squareFourTeam);
  4473. break;
  4474. case "sz":
  4475. j31 = pInt(wsMessage.newSize);
  4476. j41 = pInt(wsMessage.newSize);
  4477. break;
  4478. case "sta":
  4479. c27 = wsMessage;
  4480. break;
  4481. case "re":
  4482. j43 = 1;
  4483. a80("respawn");
  4484. break;
  4485. case "fr":
  4486. j43 = 1;
  4487. a80("respawn");
  4488. grecaptcha.execute("6LenZt4ZAAAAAF-2nPKzH9111gkjBlaJCEp8UsQV", {action: "connect"})
  4489. .then(function (grecaptchatoken) {
  4490. grecaptcha.LoToken = grecaptchatoken;
  4491. grecaptcha.LoTime = (new Date).getTime();
  4492. RF.list[socketId].send(new Uint8Array(a68("q," + grecaptcha.LoToken + "," + grecaptcha.LoTime + "")));
  4493. });
  4494. break;
  4495. case "reco":
  4496. b1 = 0;
  4497. b2 = 0;
  4498. servers = [];
  4499. b11 = 0;
  4500. c4 = 0;
  4501. a47();
  4502. break;
  4503. }
  4504. }
  4505. if (messageString == "+") {
  4506. RF.list[socketId].b12 = 1;
  4507. RF.list[socketId].send(new Uint8Array(a68("q," + grecaptcha.LoToken + "," + grecaptcha.LoTime + "")));
  4508. b17();
  4509. a91();
  4510. b15 = 0;
  4511. if (!b1) {
  4512. loginViaCookie();
  4513. b1 = 1;
  4514. }
  4515. } else if (messageString.substring(0, 7) == "version") {
  4516. var receivedVersion = b35(messageString.substr(8)),
  4517. clientVersion = b35(window.clientVersion),
  4518. latestVersion = b35(window.latestVersion);
  4519. if (receivedVersion.pat > clientVersion.pat
  4520. || receivedVersion.min != clientVersion.min
  4521. || receivedVersion.maj != clientVersion.maj
  4522. ) return b36(receivedVersion);
  4523. a2("clv", clientVersion.maj + "." + clientVersion.min + "." + clientVersion.pat);
  4524. b37();
  4525. } else if (messageString.substring(0, 10) == "highScores" && messageString.substr(11).length > 20) {
  4526. var highScorePackage = JSON.parse(messageString.substr(11));
  4527. getElementById("hscrs").style[css_key_display] = "block";
  4528. getElementById("highScoresHeading").innerHTML = "Top Scores Today";
  4529. var todayHighScores = getElementById("hsd");
  4530. todayHighScores.innerHTML = "";
  4531. for (var highScoreEntry in highScorePackage) {
  4532. if (!highScorePackage[highScoreEntry].score) continue;
  4533. var highScoreEntryMainContainer = document.createElement("div");
  4534. highScoreEntryMainContainer.className = "high-score-row";
  4535. var highScoreEntryVIPContainer = document.createElement("div");
  4536. highScoreEntryVIPContainer.className = "vip-image-div";
  4537. if (highScorePackage[highScoreEntry].is_member) {
  4538. var vipImg = document.createElement("img");
  4539. vipImg.src = "/img/vip.png";
  4540. vipImg.className = "vip-score-image";
  4541. highScoreEntryVIPContainer.appendChild(vipImg);
  4542. }
  4543. highScoreEntryMainContainer.appendChild(highScoreEntryVIPContainer);
  4544. var nameContainer = document.createElement("div");
  4545. nameContainer.className = "high-scores-text";
  4546. nameContainer.innerHTML = highScorePackage[highScoreEntry].username + ": " + highScorePackage[highScoreEntry].score.toLocaleString();
  4547. highScoreEntryMainContainer.appendChild(nameContainer);
  4548. todayHighScores.appendChild(highScoreEntryMainContainer);
  4549. }
  4550. } else if (messageString.substring(0, 8) == "c22") {
  4551. a103(a61(messageString).j50);
  4552. }
  4553. },
  4554.  
  4555. menus = [
  4556. [menuNames[ 0], refreshMenuSelect],
  4557. [menuNames[ 1], refreshMenuGuide],
  4558. [menuNames[ 2], refreshMenuMenu],
  4559. [menuNames[ 3], refreshMenuAimbot],
  4560. [menuNames[ 4], refreshMenuESP],
  4561. [menuNames[ 5], refreshMenuInstantchat],
  4562. [menuNames[ 6], refreshMenuMisc],
  4563. [menuNames[ 7], refreshMenuPlayermanager],
  4564. [menuNames[ 8], refreshMenuUpgrades],
  4565. [menuNames[ 9], refreshMenuSpammer],
  4566. [menuNames[10], refreshMenuAntiAim],
  4567. [menuNames[11], refreshMenuPerkHacks],
  4568. [menuNames[12], refreshMenuPaint],
  4569. [menuNames[13], refreshMenuRecorder],
  4570. //[menuNames[14], refreshMenuDiscordRPC],
  4571. [menuNames[15], refreshMenuTHNet],
  4572. [menuNames[16], refreshMenuWeird],
  4573. [menuNames[17], refreshMenuAdvanced],
  4574. [menuNames[18], refreshMenuCredits],
  4575. ];
  4576.  
  4577. /*
  4578. //handle stuff when other cheats are loaded aswell, since they can cause issues
  4579. if (//getElementById('box2') || //vaakir
  4580. //getElementById('m2') || //dewey's spammer
  4581. //getElementById('scrollerGUI') //nitro's spammer
  4582. false) {
  4583. if (await new Promise(Resolve => {
  4584. let def = localStorage.getItem('TioHax_abortWhenRanWithOtherMods');
  4585. if (def) return Resolve(pInt(def));
  4586. document.body.append(make('div', {}))
  4587. Resolve();
  4588. })) return;
  4589. }*/
  4590.  
  4591. //this is the DRM!
  4592. setInterval(console.dir, 30000, 'GATS.io TioHax Menu\nMade by Taureon.\nhttp' + homeUrl + '\nhttps://discord.gg/CwWd5UKf6R');
  4593.  
  4594.  
  4595. /*
  4596. this is planned shit for an uktrakill-like style meter which would use the chat for the style level and the duration of the style
  4597. concept:
  4598. -------SSShitstorm-------
  4599. ------SSShitstorm------
  4600. -----SSShitstorm-----
  4601. ----SSShitstorm----
  4602. ---SSShitstorm---
  4603. -SSShitstorm-
  4604. SSShitstorm
  4605. when it ends it downgrades to the level before
  4606. if the user kills someone it levels up and resets the timer
  4607.  
  4608. (11) Destructive
  4609. ( 7) Chaotic
  4610. ( 6) Brutal
  4611. ( 8) Anarchic
  4612. ( 7) Supreme
  4613. ( 9) SSadistic
  4614. (11) SSShitstorm
  4615. ( 9) ULTRAKILL
  4616. 30 - 11 = 19 => 18
  4617. (30) jgihrehgioerhgiorehiogheriohge
  4618. */
  4619.  
  4620.  
  4621. RE = function(data) {
  4622. let that = this;
  4623. for (let prop of ['x', 'y', 'spdX', 'spdY', 'width', 'height']) {
  4624. that[prop] = pInt(data[prop]);
  4625. if (isNaN(that[prop])) that[prop] = 0;
  4626. }
  4627. that.update = that[ATTRIBUTE_UPDATE] = function(bool) {
  4628. let player = RD.pool[that.trackingId];
  4629. if (!player) return;
  4630. if (player.mouseAngle === undefVar) player.mouseAngle = 0;
  4631. if (esp[ESP_FIXCAMERA]) {
  4632. that.x = player.x + round(player.spdX / advanced[ADVANCED_TPS]) - j40.x;
  4633. that.y = player.y + round(player.spdY / advanced[ADVANCED_TPS]) - j40.y;
  4634. return;
  4635. }
  4636. if (!bool) {
  4637. that.spdX += sign(player.spdX - that.spdX) / 10;
  4638. that.spdY += sign(player.spdY - that.spdY) / 10;
  4639. if (that.spdX > -0.1 && that.spdX < 0.1) that.spdX = 0;
  4640. if (that.spdY > -0.1 && that.spdY < 0.1) that.spdY = 0;
  4641. that.spdX = round(that.spdX * 10) / 10;
  4642. that.spdY = round(that.spdY * 10) / 10;
  4643. }
  4644. let angleRad = player.mouseAngle * degToRad;
  4645. if (that.spdX > -22 && that.spdX < 22) that.x = j39 / 15 * cos(angleRad) + (player.x - j40.x) - that.spdX * 12;
  4646. if (that.spdY > -22 && that.spdY < 22) that.y = j39 / 15 * sin(angleRad) + (player.y - j40.y) - that.spdY * 12;
  4647. };
  4648. that.getRelPos = obj => ({ x: obj.x - that.x, y: obj.y - that.y });
  4649. that.getPos = () => ({ x: that.x, y: that.y });
  4650. that.getSize = () => ({ width: that.width, height: that.height });
  4651. };
  4652.  
  4653.  
  4654. //crates
  4655. RB.prototype[ATTRIBUTE_FILLHITBOX] = function () {
  4656. let relPos = { x: this.x - c2.x, y: this.y - c2.y };
  4657. ctx.beginPath();
  4658. ctx.moveTo(this[ATTRIBUTE_HITBOX][0][0] + relPos.x, this[ATTRIBUTE_HITBOX][0][1] + relPos.y);
  4659. for (let i = 1; i < 4; i++) ctx.lineTo(this[ATTRIBUTE_HITBOX][i][0] + relPos.x, this[ATTRIBUTE_HITBOX][i][1] + relPos.y);
  4660. ctx.closePath();
  4661. ctx.fill();
  4662. };
  4663.  
  4664. RB.prototype[ATTRIBUTE_MAKEHITBOX] = function () {
  4665.  
  4666. //`this.angle` is weird
  4667. let angle = 0 - (this.angle * degToRad - PI / 2),
  4668.  
  4669. hitboxOffset = {
  4670. x: this[ATTRIBUTE_HITBOXFORWARDOFFSET] * sin(angle),
  4671. y: this[ATTRIBUTE_HITBOXFORWARDOFFSET] * cos(angle)
  4672. },
  4673.  
  4674. //generate the relative corners
  4675. relativeCorners = [
  4676. atan2( this[ATTRIBUTE_WIDTH], this[ATTRIBUTE_HEIGHT]) + angle,
  4677. atan2(0 - this[ATTRIBUTE_WIDTH], this[ATTRIBUTE_HEIGHT]) + angle,
  4678. atan2(0 - this[ATTRIBUTE_WIDTH], 0 - this[ATTRIBUTE_HEIGHT]) + angle,
  4679. atan2( this[ATTRIBUTE_WIDTH], 0 - this[ATTRIBUTE_HEIGHT]) + angle
  4680. ],
  4681.  
  4682. distance = sqrt(this[ATTRIBUTE_WIDTH] ** 2 + this[ATTRIBUTE_HEIGHT] ** 2);
  4683.  
  4684. //ceonver 4 corners into 4 lines
  4685. for (let i = 0; i < 4; i++) relativeCorners[i] = {
  4686. x: hitboxOffset.x + distance * sin(relativeCorners[i]),
  4687. y: hitboxOffset.y + distance * cos(relativeCorners[i])
  4688. };
  4689. this[ATTRIBUTE_HITBOX] = [
  4690. [relativeCorners[0].x, relativeCorners[0].y, relativeCorners[1].x, relativeCorners[1].y],
  4691. [relativeCorners[1].x, relativeCorners[1].y, relativeCorners[2].x, relativeCorners[2].y],
  4692. [relativeCorners[2].x, relativeCorners[2].y, relativeCorners[3].x, relativeCorners[3].y],
  4693. [relativeCorners[3].x, relativeCorners[3].y, relativeCorners[0].x, relativeCorners[0].y]
  4694. ];
  4695.  
  4696. this[ATTRIBUTE_HITBOXOFFSET] = hitboxOffset;
  4697. this[ATTRIBUTE_HITBOXRADIUS] = distance;
  4698. };
  4699.  
  4700. RB.prototype.activate = function (data) {
  4701. this.parent = data.parentId;
  4702. this.type = data.type;
  4703. this.x = data.x / 10;
  4704. this.y = data.y / 10;
  4705. this.angle = data.angle;
  4706. this.maxHp = data.maxHp;
  4707. this.hp = data.hp;
  4708. this.isPremium = data.isPremium;
  4709. this.model = a11(this.type, this.isPremium);
  4710. this[ATTRIBUTE_WIDTH] = 0;
  4711. this[ATTRIBUTE_HEIGHT] = 0;
  4712. this[ATTRIBUTE_HITBOXFORWARDOFFSET] = 0;
  4713. this[ATTRIBUTE_BULLETCOLLISIONS] = 0;
  4714. switch (this.type) {
  4715. case 'crate':
  4716. this[ATTRIBUTE_WIDTH] = 45;
  4717. this[ATTRIBUTE_HEIGHT] = 45;
  4718. this[ATTRIBUTE_BULLETCOLLISIONS] = 1;
  4719. break;
  4720. case 'longCrate':
  4721. this[ATTRIBUTE_WIDTH] = 45;
  4722. this[ATTRIBUTE_HEIGHT] = 20;
  4723. this[ATTRIBUTE_BULLETCOLLISIONS] = 1;
  4724. break;
  4725. case 'userCrate':
  4726. case 'premiumCrate':
  4727. this[ATTRIBUTE_WIDTH] = 15;
  4728. this[ATTRIBUTE_HEIGHT] = 15;
  4729. this[ATTRIBUTE_BULLETCOLLISIONS] = 1;
  4730. break;
  4731. case 'shield':
  4732. this[ATTRIBUTE_WIDTH] = 30;
  4733. this[ATTRIBUTE_HEIGHT] = 10;
  4734. this[ATTRIBUTE_HITBOXFORWARDOFFSET] = 33;
  4735. this[ATTRIBUTE_BULLETCOLLISIONS] = 1;
  4736. break;
  4737. }
  4738. this.activated = 1;
  4739. this[ATTRIBUTE_MAKEHITBOX]();
  4740. };
  4741.  
  4742. RB.prototype[ATTRIBUTE_UPDATE] = function () {
  4743. if (this.model) this.animationFrame = (this.animationFrame + 1) % this.model.length;
  4744. if (this.type != 'shield') return;
  4745. let parent = RD.pool[this.parent];
  4746. if (!parent) return;
  4747. let angle = parent.playerAngle * degToRad;
  4748. this.x = parent.x + parent.spdX / advanced[ADVANCED_TPS] + cos(angle);
  4749. this.y = parent.y + parent.spdY / advanced[ADVANCED_TPS] + sin(angle);
  4750. this.angle = parent.playerAngle;
  4751. };
  4752.  
  4753. RB.prototype.applyUpdate = function (data) {
  4754. let bool = this.angle != data.angle;
  4755. this.x = data.x / 10;
  4756. this.y = data.y / 10;
  4757. this.angle = data.angle;
  4758. if (data.hp !== undefVar && data.hp != '') this.hp = pInt(data.hp);
  4759. if (bool) this[ATTRIBUTE_MAKEHITBOX]();
  4760. };
  4761.  
  4762. RB.prototype[ATTRIBUTE_DRAW] = function() {
  4763. if (!this.model) return;
  4764.  
  4765. let hpPercent = this.maxHp ? this.hp / this.maxHp : 1,
  4766. model = this.model[this.animationFrame],
  4767. color = {
  4768. 'crate': paint[PAINT_CRATESQUARE],
  4769. 'longCrate': paint[PAINT_CRATELONG],
  4770. 'userCrate': this.isPremium ? paint[PAINT_CRATEPREMIUM] : paint[PAINT_CRATEUSER]
  4771. }[this.type];
  4772.  
  4773. if (color) {
  4774. model[0][1][3] = color[0];
  4775. model[1][1][3] = color[1];
  4776. if (hpPercent < 0 || hpPercent > 1) hpPercent = 0;
  4777. if (!misc[MISC_BETTERCRATEHP]) hpPercent = ceil(hpPercent * 5) / 5;
  4778. if (paint[PAINT_CRATESHOWHPMODE] & 1) model[0][1][3] = colorLerp(color[0], paint[PAINT_CRATECORPSE][0], hpPercent);
  4779. if (paint[PAINT_CRATESHOWHPMODE] >> 1) model[1][1][3] = colorLerp(color[1], paint[PAINT_CRATECORPSE][1], hpPercent);
  4780. }
  4781. a38(ctx, c2, this, this.angle, model);
  4782. };
  4783.  
  4784.  
  4785. //bullets
  4786. RC.prototype[ATTRIBUTE_UPDATE] = function () {
  4787. if (this.model) this.animationFrame = (this.animationFrame + 1) % this.model.length;
  4788. this.x += this.spdX;
  4789. this.y += this.spdY;
  4790. };
  4791.  
  4792. RC.prototype[ATTRIBUTE_DRAW] = function() {
  4793. if (this.isKnife) return a38(ctx, c2, this, this.angle, this.model[this.animationFrame]);
  4794.  
  4795. ctx.strokeStyle = '#000';
  4796. if (this.silenced && !esp[ESP_SHOWINVIS]) {
  4797. ctx.strokeStyle = '#D3D3DA';
  4798. } else if (this.ownerId == c3 || (this.teamCode > 0 && this.teamCode == RD.pool[c3].teamCode)) {
  4799. ctx.strokeStyle = '#107a24';
  4800. } else if (RD.pool[c3].thermal) {
  4801. ctx.strokeStyle = '#f00';
  4802. }
  4803. let relPosX = this.x - c2.x,
  4804. relPosY = this.y - c2.y;
  4805. j21(ctx, relPosX, relPosY, relPosX + this.length * cos(this.angle * degToRad), relPosY + this.length * sin(this.angle * degToRad), this.width);
  4806. };
  4807.  
  4808.  
  4809. //players
  4810. RD.prototype.activate = async function(data, isMe) {
  4811. this.color = data.color;
  4812. this.x = parseFloat(data.x / 10);
  4813. this.y = parseFloat(data.y / 10);
  4814. this[ATTRIBUTE_PREVSPDX] = this[ATTRIBUTE_PREVSPDY] = this.spdY = this.spdX = this[ATTRIBUTE_PREVACCX] = this[ATTRIBUTE_PREVACCY] = this[ATTRIBUTE_ACCX] = this[ATTRIBUTE_ACCY] = 0;
  4815. this[ATTRIBUTE_RADIUS] = pInt(data.radius / 10);
  4816. this.playerAngle = pInt(data.playerAngle);
  4817. this.hp = pInt(data.hp);
  4818. this[ATTRIBUTE_HPRADIUS] = this.hp * this[ATTRIBUTE_RADIUS] / 100;
  4819. this.armorAmount = pInt(data.armorAmount);
  4820. this.shootingAnimation = a6('shooting', this.class = data.class);
  4821. this.ghillie = data.ghillie;
  4822. this.maxBullets = data.maxBullets;
  4823. this.invincible = data.invincible;
  4824. this.isLeader = pInt(data.isLeader);
  4825. this.isPremiumMember = pInt(data.isPremiumMember);
  4826. this.teamCode = pInt(data.teamCode);
  4827. this.chatBoxOpen = pInt(data.chatBoxOpen);
  4828. this.activated = 1;
  4829. if (!isMe) {
  4830. this.currentBullets = pInt(data.currentBullets);
  4831. this.maxBullets = pInt(data.maxBullets);
  4832. this.armor = data.armor;
  4833. this.c2 = data.c2;
  4834. this.hpMax = data.hpMax;
  4835. this.numExplosivesLeft = 3;
  4836. j31 = pInt(data.mapWidth) / 10;
  4837. j41 = pInt(data.mapHeight) / 10;
  4838. }
  4839. setNameVariations(this, formatUserName(data.username));
  4840. };
  4841.  
  4842. RD.prototype.applyFirstPersonUpdateData = function (data) {
  4843. if (data.currentBullets !== undefVar && data.currentBullets != '') this.currentBullets = pInt(data.currentBullets);
  4844. if (data.score !== undefVar && data.score != '') this.score = pInt(data.score);
  4845. if (data.kills !== undefVar && data.kills != '') this.kills = pInt(data.kills);
  4846. if (data.rechargeTimer !== undefVar) c9 = {current: pInt(data.rechargeTimer) * advanced[ADVANCED_TPS], total: pInt(data.rechargeTimer) * advanced[ADVANCED_TPS]};
  4847. if (data.maxBullets !== undefVar && data.maxBullets != '') this.maxBullets = pInt(data.maxBullets);
  4848. if (data.c2 !== undefVar && data.c2 != '') {
  4849. let c = data.c2.split('x');
  4850. c2.width = pInt(c[0]);
  4851. c2.height = pInt(c[1]);
  4852. }
  4853. if (data.thermal !== undefVar && data.thermal != '') this.thermal = pInt(data.thermal);
  4854. if (data.numExplosivesLeft !== undefVar && data.numExplosivesLeft != '') this.numExplosivesLeft = pInt(data.numExplosivesLeft);
  4855. };
  4856.  
  4857. RD.prototype[ATTRIBUTE_UPDATE] = function () {
  4858. let hpRadius = round((this.hp / 100) * (this[ATTRIBUTE_RADIUS] - this.armorAmount / 10 - 1));
  4859. if (misc[MISC_STATICHEALTH]) {
  4860. this[ATTRIBUTE_HPRADIUS] = hpRadius;
  4861.  
  4862. //if end user wants to keep health animations
  4863. } else {
  4864. if (this[ATTRIBUTE_HPRADIUS] > hpRadius - 0.5 && this[ATTRIBUTE_HPRADIUS] < hpRadius + 0.5) {
  4865. this[ATTRIBUTE_HPRADIUS] = hpRadius;
  4866. } else if (this[ATTRIBUTE_HPRADIUS] > hpRadius) {
  4867. this[ATTRIBUTE_HPRADIUS] = this[ATTRIBUTE_HPRADIUS] - 0.5;
  4868. } else if (this[ATTRIBUTE_HPRADIUS] < hpRadius) {
  4869. this[ATTRIBUTE_HPRADIUS] = this[ATTRIBUTE_HPRADIUS] + 0.5;
  4870. }
  4871. if (this[ATTRIBUTE_HPRADIUS] < 0) this[ATTRIBUTE_HPRADIUS] = 0;
  4872. }
  4873.  
  4874. if (this.hp > 0) {
  4875. this.x += round(this.spdX / advanced[ADVANCED_TPS]);
  4876. this.y += round(this.spdY / advanced[ADVANCED_TPS]);
  4877. }
  4878.  
  4879. //chat timer
  4880. if (this.j47Timer > 0) {
  4881. this.j47Timer -= 2.5 / advanced[ADVANCED_TPS];
  4882. if (this.j47Timer <= 0) this.j47 = "";
  4883. }
  4884.  
  4885. //animation handler
  4886. this.shootingAnimation = a6("shooting", this.class);
  4887. if (this.shooting) {
  4888. this.shootingFrame = (this.shootingFrame + 1) % this.shootingAnimation.length;
  4889. } else if (this.reloading && this.reloadingAnimation) {
  4890. this.reloadingFrame = (this.reloadingFrame + 1) % this.reloadingAnimation.length;
  4891. }
  4892. if (!this.shooting) this.shootingFrame = 0;
  4893. if (!this.reloading) this.reloadingFrame = 0;
  4894. };
  4895.  
  4896. RD.prototype.applyPrimaryUpdate = function(data) {
  4897. this.x = parseFloat(data.x / 10);
  4898. this.y = parseFloat(data.y / 10);
  4899. let spdX = parseFloat(data.spdX / 10);
  4900. let spdY = parseFloat(data.spdY / 10);
  4901. this[ATTRIBUTE_PREVACCX] = this[ATTRIBUTE_ACCX];
  4902. this[ATTRIBUTE_PREVACCY] = this[ATTRIBUTE_ACCY];
  4903. this[ATTRIBUTE_ACCX] = spdX - this.spdX;
  4904. this[ATTRIBUTE_ACCY] = spdY - this.spdY;
  4905. this[ATTRIBUTE_PREVSPDX] = this.spdX;
  4906. this[ATTRIBUTE_PREVSPDY] = this.spdY;
  4907. this.spdX = spdX;
  4908. this.spdY = spdY;
  4909. if (aimbot[AIMBOT_AIMSMOOTHING]) {
  4910. this[ATTRIBUTE_USABLESPDX] = (spdX + this[ATTRIBUTE_PREVSPDX]) / 2;
  4911. this[ATTRIBUTE_USABLESPDY] = (spdY + this[ATTRIBUTE_PREVSPDY]) / 2;
  4912. this[ATTRIBUTE_USABLEACCX] = (this[ATTRIBUTE_ACCX] + this[ATTRIBUTE_PREVACCX]) / 2;
  4913. this[ATTRIBUTE_USABLEACCY] = (this[ATTRIBUTE_ACCY] + this[ATTRIBUTE_PREVACCY]) / 2;
  4914. } else {
  4915. this[ATTRIBUTE_USABLESPDX] = spdX;
  4916. this[ATTRIBUTE_USABLESPDY] = spdY;
  4917. this[ATTRIBUTE_USABLEACCX] = this[ATTRIBUTE_ACCX];
  4918. this[ATTRIBUTE_USABLEACCY] = this[ATTRIBUTE_ACCY];
  4919. }
  4920. if (data.id != c3) this.playerAngle = pInt(data.playerAngle);
  4921. };
  4922.  
  4923. RD.prototype.applyAuxUpdate = function (data) {
  4924. if (!this.activated) return;
  4925. if (data.color !== undefVar && data.color != '') this.color = data.color;
  4926. if (data.radius !== undefVar && data.radius != '') this[ATTRIBUTE_RADIUS] = pInt(data.radius / 10);
  4927. if (data.dashing !== undefVar && data.dashing != '') this.dashing = pInt(data.dashing);
  4928. if (data.ghillie !== undefVar && data.ghillie != '') this.ghillie = pInt(data.ghillie);
  4929. if (data.shooting !== undefVar && data.shooting != '') this.shooting = pInt(data.shooting);
  4930. if (data.isLeader !== undefVar && data.isLeader != '') this.isLeader = pInt(data.isLeader);
  4931. if (data.reloading !== undefVar && data.reloading != '') this.reloading = pInt(data.reloading);
  4932. if (data.maxBullets !== undefVar && data.maxBullets != '') this.maxBullets = pInt(data.maxBullets);
  4933. if (data.invincible !== undefVar && data.invincible != '') this.invincible = pInt(data.invincible);
  4934. if (data.armorAmount !== undefVar && data.armorAmount != '') this.armorAmount = pInt(data.armorAmount);
  4935. if (data.chatBoxOpen !== undefVar && data.chatBoxOpen != '') this.chatBoxOpen = pInt(data.chatBoxOpen);
  4936. if (data.currentBullets !== undefVar && data.currentBullets != '') this.currentBullets = pInt(data.currentBullets);
  4937. if (data.hp !== undefVar && data.hp != '') {
  4938. let newHp = pInt(data.hp);
  4939. if (this.hp + 1 < newHp) onHeal(this.id);
  4940. this.hp = newHp;
  4941. }
  4942. if (data.beingHit !== undefVar && data.beingHit != '') {
  4943. if (data.id == c3) j37 = 6;
  4944. this.beingHit = pInt(data.beingHit);
  4945. }
  4946. if (data.j47 !== undefVar && data.j47 != '') {
  4947. this.j47 = data.j47.replace(/~/g, ',');
  4948. this.j47Timer = 200;
  4949. //if (!thnet[THNET_ENABLE] && this[ATTRIBUTE_USERNAMEHASH] == developerHash && this.j47 == ',revealRogues') sendChatMessage('I am rogue');
  4950. }
  4951. };
  4952.  
  4953. RD.prototype[ATTRIBUTE_DRAWBODY] = function() {
  4954. let relPos = {
  4955. x: this.x - c2.x,
  4956. y: this.y - c2.y
  4957. };
  4958. if (!(this.ghillie && !esp[ESP_SHOWINVIS]) || this.spdX != 0 || this.spdY != 0 || this.beingHit || this.shooting) {
  4959. if (this.isLeader) {
  4960. ctx.globalAlpha = 0.3;
  4961. ctx.strokeStyle = this.color.a;
  4962. ctx.lineWidth = 10;
  4963. j22(ctx, relPos.x, relPos.y, this[ATTRIBUTE_RADIUS] * 1.65);
  4964. }
  4965. ctx.globalAlpha = this.invincible ? 0.3 : 1;
  4966. ctx.lineWidth = 2;
  4967. ctx.strokeStyle = ctx.fillStyle = this.isPremiumMember ? '#000' : '#666';
  4968. j22(ctx, relPos.x, relPos.y, this[ATTRIBUTE_RADIUS] + 1);
  4969. ctx.fill();
  4970. ctx.lineWidth = 1;
  4971. ctx.strokeStyle = ctx.fillStyle = this.color.b;
  4972. j22(ctx, relPos.x, relPos.y, this[ATTRIBUTE_RADIUS] - this.armorAmount / 10);
  4973. ctx.fill();
  4974. if (this.dashing) {
  4975. ctx.strokeStyle = '#bababa';
  4976. j21(ctx, relPos.x , relPos.y , relPos.x - this.spdX * 5, relPos.y - this.spdY * 5, 1);
  4977. j21(ctx, relPos.x , relPos.y + 20, relPos.x - this.spdX * 5, relPos.y + 20 - this.spdY * 5, 1);
  4978. j21(ctx, relPos.x , relPos.y - 20, relPos.x - this.spdX * 5, relPos.y - 20 - this.spdY * 5, 1);
  4979. j21(ctx, relPos.x + 20, relPos.y , relPos.x + 20 - this.spdX * 5, relPos.y - this.spdY * 5, 1);
  4980. j21(ctx, relPos.x - 20, relPos.y , relPos.x - 20 - this.spdX * 5, relPos.y - this.spdY * 5, 1);
  4981. }
  4982. ctx.lineWidth = 1;
  4983. ctx.strokeStyle = ctx.fillStyle = this.color.a;
  4984. j22(ctx, relPos.x, relPos.y, this[ATTRIBUTE_HPRADIUS] + 1);
  4985. ctx.fill();
  4986. if (c37 && this.id != c3) {
  4987. ctx.fillStyle = this.isPremiumMember ? '#000' : '#666';
  4988. ctx.font = 'bold 12px Arial';
  4989. ctx.textAlign = 'center';
  4990. let usedName = misc[MISC_FFACLANDISPLAY] ? this[ATTRIBUTE_TAGGEDNAME] : this[ATTRIBUTE_USERNAME],
  4991. textWidth = ctx.measureText(usedName).width;
  4992. if (this.isPremiumMember) {
  4993. ctx.globalAlpha = 0.75;
  4994. ctx.fillText(usedName, relPos.x - 9, relPos.y + this[ATTRIBUTE_RADIUS] * 1.75);
  4995. drawImage(j30.vip, relPos.x + textWidth / 2 - 6, relPos.y + this[ATTRIBUTE_RADIUS] * 1.75 - 9, 18, 10);
  4996. ctx.globalAlpha = 1;
  4997. } else {
  4998. ctx.fillText(usedName, relPos.x, relPos.y + this[ATTRIBUTE_RADIUS] * 1.75);
  4999. }
  5000. ctx.textAlign = 'start';
  5001. }
  5002. ctx.globalAlpha = 1;
  5003. } else if (this.id != c3 && RD.pool[c3].thermal == 1) {
  5004. if (this.teamCode > 0 && this.teamCode == RD.pool[c3].teamCode) {
  5005. ctx.strokeStyle = '#107a24';
  5006. ctx.font = 'bold 12px Arial';
  5007. ctx.textAlign = 'center';
  5008. ctx.fillStyle = '#107a24';
  5009. ctx.fillText(this[ATTRIBUTE_USERNAME], relPos.x, relPos.y + this[ATTRIBUTE_RADIUS] * 1.75);
  5010. ctx.textAlign = 'start';
  5011. } else {
  5012. ctx.strokeStyle = '#f00';
  5013. }
  5014. } else {
  5015. ctx.strokeStyle = '#efeff5';
  5016. ctx.lineWidth = 2;
  5017. j22(ctx, relPos.x, relPos.y, this[ATTRIBUTE_RADIUS]);
  5018. ctx.fillStyle = '#efeff5';
  5019. ctx.fill();
  5020. }
  5021. if (!c37 || includesInArray(muted, this[ATTRIBUTE_SANITIZEDNAME])) return;
  5022. let chatMessage = this.j47;
  5023. if (chatMessage == '' && this.chatBoxOpen) chatMessage = '...';
  5024. if (chatMessage[chatMessage.length - 1] == ' ') chatMessage = chatMessage.substring(0, chatMessage.length - 1);
  5025. if (!chatMessage.length) return;
  5026. ctx.font = 'bold 12px Arial';
  5027. ctx.textAlign = 'center';
  5028. let textWidth = ctx.measureText(chatMessage).width;
  5029. ctx.globalAlpha = 0.7;
  5030. ctx.fillStyle = this.isPremiumMember ? '#000' : '#7a7a7a';
  5031. ctx.fillRect(relPos.x - textWidth / 2 - 3, relPos.y + this[ATTRIBUTE_RADIUS] * 2.7 - 13, textWidth + 6, 18);
  5032. ctx.globalAlpha = 1;
  5033. ctx.fillStyle = this.isPremiumMember ? '#deb34c' : '#fff';
  5034. ctx.fillText(chatMessage, relPos.x, relPos.y + this[ATTRIBUTE_RADIUS] * 2.7);
  5035. ctx.textAlign = 'start';
  5036. };
  5037.  
  5038. RD.prototype[ATTRIBUTE_DRAWGUN] = function () {
  5039. if (this.ghillie && !this.spdX && !this.spdY && !this.beingHit && !this.shooting) {
  5040. if (!RD.pool[c3].thermal || c3 == this.id) return;
  5041. let relPos = {
  5042. x: this.x - c2.x,
  5043. y: this.y - c2.y
  5044. };
  5045. ctx.strokeStyle = (this.teamCode > 0 && this.teamCode == RD.pool[c3].teamCode) ? "#107a24" : "#ff0000";
  5046. j21(ctx, relPos.x, relPos.y, relPos.x + cos(this.playerAngle * degToRad) * 20, relPos.y + sin(this.playerAngle * degToRad) * 20, 4);
  5047. return;
  5048. }
  5049.  
  5050. this.shootingAnimation = a6("shooting", this.class);
  5051. let animationFrameToDraw = this.shootingAnimation[this.shootingFrame],
  5052. what = 0;
  5053. if (this.beingHit) {
  5054. what = -1;
  5055. this.beingHit = 0;
  5056. }
  5057. if (this.reloading) {
  5058. this.reloadingAnimation = a6("reloading", this.class, this.maxBullets - this.currentBullets, !this.currentBullets);
  5059. animationFrameToDraw = this.reloadingAnimation[this.reloadingFrame];
  5060. }
  5061. if (this.invincible) ctx.globalAlpha = 0.3;
  5062. a38(ctx, c2, this.getAttr(), this.playerAngle, animationFrameToDraw, 4, null, what);
  5063. ctx.globalAlpha = 1;
  5064. };
  5065.  
  5066. //connections
  5067. RF.prototype.a74 = function () {
  5068. this.pingReceivedTime = Date.now();
  5069. this.currentPing = (this.pingReceivedTime - this.pingSentTime) >> 1; //divides by 2 and also rounds in the same operation!
  5070. ++this.numSuccessfulPings;
  5071.  
  5072. if (!this[ATTRIBUTE_PINGS]) this[ATTRIBUTE_PINGS] = [];
  5073. this[ATTRIBUTE_PINGS].push(this.currentPing);
  5074. if (this[ATTRIBUTE_PINGS].length > advanced[ADVANCED_PINGCOUNT]) this[ATTRIBUTE_PINGS].shift();
  5075.  
  5076. this[ATTRIBUTE_AVERAGEPING] = 0;
  5077. for (let ping of this[ATTRIBUTE_PINGS]) this[ATTRIBUTE_AVERAGEPING] += ping;
  5078. this[ATTRIBUTE_AVERAGEPING] /= this[ATTRIBUTE_PINGS].length;
  5079.  
  5080. this[ATTRIBUTE_MINPING] = min(...this[ATTRIBUTE_PINGS]);
  5081. this[ATTRIBUTE_MAXPING] = max(...this[ATTRIBUTE_PINGS]); //lag spikes? L
  5082. };
  5083.  
  5084. RF.prototype.createGameSocket = function () {
  5085. this.socket = new WebSocket(this.connectHostname);
  5086. this.socket.binaryType = 'arraybuffer';
  5087. this.pingSentTime = Date.now();
  5088. this.socket.onopen = () => {
  5089. if (this.socket == null) return;
  5090. let indexInList = indexOfInArray(RF.list, this);
  5091. this.socket.onmessage = wsMsgEvent => {
  5092. if (recorder[RECORDER_ISRECORDING]) recorder[RECORDER_CURRENT].push([Date.now(), wsMsgEvent.data]);
  5093. handleMessage(indexInList, wsMsgEvent);
  5094. };
  5095. };
  5096. this.socket.onclose = () => {
  5097. if (thnet[THNET_SOCKET]) thnet[THNET_SOCKET].close();
  5098. this.close();
  5099. a45();
  5100. };
  5101. };
  5102.  
  5103.  
  5104. //non-bullet projectiles
  5105. RA.prototype.applyUpdate = function(data) {
  5106. this.x = pInt(data.x / 10);
  5107. this.y = pInt(data.y / 10);
  5108. this.exploding = pInt(data.exploding);
  5109. this.emitting = pInt(data.emitting);
  5110. this.emissionRadius = pInt(data.emissionRadius / 10);
  5111. this[ATTRIBUTE_TIMEALIVEEXTRA] = 0;
  5112. this.timeAlive++;
  5113. };
  5114.  
  5115. RA.prototype[ATTRIBUTE_UPDATE] = function () {
  5116. if (this.type == "landMine" || this.emitting) return;
  5117. if (this.exploding) {
  5118. this.animationFrame++;
  5119. if (this.animationFrame < this.model.length) this.deactivate();
  5120. }
  5121. if (this.timeAlive < this.travelTime) {
  5122. this.x += this.spdX;
  5123. this.y += this.spdY;
  5124. }
  5125. this.angle = (this.angle + 7) % 360;
  5126. };
  5127.  
  5128. RA.prototype[ATTRIBUTE_DRAW] = function () {
  5129. if (!this.activated) return;
  5130. if (this.exploding) return a38(ctx, c2, this.getAttr(), this.angle, this.model[this.animationFrame]);
  5131. a38(ctx, c2, this.getAttr(), this.angle, this.model[0]);
  5132. if (this.type == "landMine" && RD.pool[c3].thermal == 1) {
  5133. let relPos = {
  5134. x: this.x - c2.x,
  5135. y: this.y - c2.y
  5136. };
  5137. ctx.strokeStyle = (this.ownerId == c3 || this.teamCode > 0 && this.teamCode == RD.pool[c3].teamCode) ? "#107a24" : "#ff0000";
  5138. j22(ctx, relPos.x, relPos.y, 20);
  5139. j22(ctx, relPos.x, relPos.y, 4);
  5140. }
  5141. };
  5142.  
  5143.  
  5144. //yes i could use addEventListener but I felt like doing it this way anyway
  5145. document.onkeydown = keyEvent => {
  5146.  
  5147. //prevents stupidness
  5148. if (textBoxFocused && !keyEvent[ATTRIBUTE_ISFROMCHEAT]) return;
  5149.  
  5150. let msg = instantchat[INSTANTCHAT_CHATBINDSTEXTS][keyEvent.keyCode],
  5151. socket = RF.list[multiBox[MULTIBOX_SELECTEDSOCKET]],
  5152. chatboxContainer = getElementById('chatboxContainer'),
  5153. chatbox = getElementById('chatbox');
  5154.  
  5155. //if the key code is the key code used to toggle the menu
  5156. if ((!(j46 || c4) && includesInArray([keyCodeMap[KEYCODE_T], keyCodeMap[KEYCODE_SHIFT]], keyEvent.keyCode)) ||
  5157. //if the chatbox is closed and if we are in a game
  5158. (c4 && !j46 && (msg || includesInArray(Object.values(keyCodeMap), keyEvent.keyCode)))
  5159. ) {
  5160. keyEvent.preventDefault();
  5161. handleUncomplicatedKeypress(keyEvent, msg);
  5162. }
  5163.  
  5164. //handle enter press
  5165. if (keyEvent.keyCode == keyCodeMap[KEYCODE_ENTER] && c4 && !c28) handleEnterPress(socket, chatboxContainer, chatbox, keyEvent.shiftKey);
  5166.  
  5167. //if ESC key pressed, simply close the chat input
  5168. if (keyEvent.keyCode == keyCodeMap[KEYCODE_ESC] && j46) {
  5169. divs.chatinput.blur();
  5170. chatboxContainer.style[css_key_display] = css_value_misc_none;
  5171. j46 = 0;
  5172. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], 7, 0);
  5173. }
  5174. };
  5175.  
  5176. document.onkeyup = function (keyEvent) {
  5177. if (!c4 || j46 || !includesInArray([68, 83, 65, 87, 82, 32, 45, 37, 38, 39, 40], keyEvent.keyCode)) return;
  5178. keyEvent.preventDefault();
  5179. switch (keyEvent.keyCode) {
  5180. case keyCodeMap[KEYCODE_A]:
  5181. case keyCodeMap[KEYCODE_ARROWLEFT]:
  5182. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_LEFT, KEYPRESS_STATE_OFF);
  5183. break;
  5184. case keyCodeMap[KEYCODE_D]:
  5185. case keyCodeMap[KEYCODE_ARROWRIGHT]:
  5186. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_RIGHT, KEYPRESS_STATE_OFF);
  5187. break;
  5188. case keyCodeMap[KEYCODE_W]:
  5189. case keyCodeMap[KEYCODE_ARROWUP]:
  5190. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_UP, KEYPRESS_STATE_OFF);
  5191. break;
  5192. case keyCodeMap[KEYCODE_S]:
  5193. case keyCodeMap[KEYCODE_ARROWDOWN]:
  5194. keyPress(multiBox[MULTIBOX_SELECTEDSOCKET], KEYPRESS_KEY_DOWN, KEYPRESS_STATE_OFF);
  5195. break;
  5196. case keyCodeMap[KEYCODE_R]:
  5197. stopReloading(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5198. break;
  5199. case keyCodeMap[KEYCODE_SPACE]:
  5200. stopActivePerk(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5201. break;
  5202. }
  5203. };
  5204.  
  5205. //game tick
  5206. a41 = () => {
  5207. let start = Date.now(),
  5208. renderDisplayPadding = 5,
  5209. leaderboardLeft;
  5210.  
  5211. //modified game loop tick
  5212. if (!c4 && !b21 && window.location.pathname != '/model') a29();
  5213.  
  5214. if (c3 != null) {
  5215.  
  5216. if (1 !== esp[ESP_ZOOM]) {
  5217. j7 = esp[ESP_ZOOM] ? 2000 : c2.width;
  5218. j8 = esp[ESP_ZOOM] ? 1125 : c2.height;
  5219. a1();
  5220. }
  5221.  
  5222. //shows landmines
  5223. for (let i in landMine[0]) landMine[0][i][1][3] = esp[ESP_SHOWINVIS] ? '#000' : '#e8e8ed';
  5224.  
  5225. j17 = 0;
  5226. ctx.clearRect(0, 0, canvas.width, canvas.height);
  5227. c2[ATTRIBUTE_UPDATE]();
  5228. drawFloor(ctx, c2);
  5229. for (let entity of getPool(RA)) {
  5230. if (!entity.activated || entity.type != 'landMine') continue;
  5231. entity[ATTRIBUTE_UPDATE]();
  5232. entity[ATTRIBUTE_DRAW]();
  5233. }
  5234. for (let bullet of getPool(RC)) {
  5235. if (!bullet.activated) continue;
  5236. bullet[ATTRIBUTE_UPDATE]();
  5237. bullet[ATTRIBUTE_DRAW]();
  5238. }
  5239. for (let crate of getPool(RB)) {
  5240. if (!crate.activated) continue;
  5241. crate[ATTRIBUTE_UPDATE]();
  5242. crate[ATTRIBUTE_DRAW]();
  5243. if (!crate[ATTRIBUTE_HITBOX]) crate[ATTRIBUTE_MAKEHITBOX]();
  5244. }
  5245. for (let entity of getPool(RA)) {
  5246. if (!entity.activated || entity.type == 'landMine') continue;
  5247. if (!entity[ATTRIBUTE_TIMEALIVEEXTRA]) entity[ATTRIBUTE_TIMEALIVEEXTRA] = 0;
  5248. entity[ATTRIBUTE_UPDATE]();
  5249. entity[ATTRIBUTE_DRAW]();
  5250. }
  5251. for (let player of getPool(RD)) {
  5252. if (!player.activated || (c28 && player.id == c3)) continue;
  5253. player[ATTRIBUTE_UPDATE]();
  5254. player[ATTRIBUTE_DRAWBODY]();
  5255. player[ATTRIBUTE_DRAWGUN]();
  5256. }
  5257. for (let gas of getPool(RA)) if (gas.activated) gas.drawEmission(ctx, c2);
  5258. for (let i in j27) {
  5259. let hitParticle = j27[i];
  5260. if (hitParticle.c42++ < 5) {
  5261. j26(c2, hitParticle.x, hitParticle.y);
  5262. } else {
  5263. delete hitParticle[i];
  5264. }
  5265. }
  5266. a55(ctx, c2);
  5267. let me = RD.pool[c3];
  5268. if (misc[MISC_STATICHUD]) {
  5269. c5 = me.hp;
  5270. c6 = me.armorAmount;
  5271. c7 = me.score;
  5272. }
  5273. if (autoUpgrades[0]) autoUpgrade(multiBox[MULTIBOX_SELECTEDSOCKET], me);
  5274.  
  5275. //fixes hud visual glitches
  5276. //for some reason this works without major errors?
  5277. j9 = [cursor.x, cursor.y];
  5278.  
  5279. a9(me);
  5280. drawMinimap(me);
  5281. a13(ctx, c8);
  5282. leaderboardLeft = drawLeaderBoard(ctx, j38);
  5283. }
  5284. a113();
  5285. a56();
  5286.  
  5287. if (misc[MISC_SHOWFEATURES]) showFeatures();
  5288.  
  5289. //:trolleybus:
  5290. j9[0] /= j6;
  5291. j9[1] /= j5;
  5292.  
  5293. //server latency display
  5294. if (misc[MISC_PINGDISPLAY]) renderDisplayPadding += pingDisplay() + 10;
  5295.  
  5296. //draw the time taken to draw everything in the last frame
  5297. if (misc[MISC_RENDERDISPLAY]) renderDisplayPadding += renderDisplay(renderDisplayPadding) + 10;
  5298.  
  5299. //only do shit when in a game, else the cheat breaks
  5300. if (c2) {
  5301. //important variable declarations
  5302. let players = [], crates = [],
  5303. me = RD.pool[c3],
  5304. playerScreenPos = {
  5305. x: me.x - c2.x,
  5306. y: me.y - c2.y
  5307. },
  5308. offset = {
  5309. x: nullPos.x - c2.x,
  5310. y: nullPos.y - c2.y
  5311. },
  5312. animationSubtraction = ceil(RF.list[0][ATTRIBUTE_AVERAGEPING] / 2.5);
  5313.  
  5314. //get all RELEVANT players and crates
  5315. for (let player of getPool(RD)) if (player.activated && (esp[ESP_INCLUDEYOU] || player.id != me.id) && player.hp != 0) players.push(player);
  5316. for (let crate of getPool(RB)) if (crate.activated) crates.push(crate);
  5317. let {[ATTRIBUTE_ENEMIES]: enemies, [ATTRIBUTE_ENEMYFRIENDS]: enemyFriends} = getEnemies(me, players);
  5318.  
  5319. if (misc[MISC_POSITION]) renderDisplayPadding += coordsDisplay(renderDisplayPadding, me) + 10;
  5320.  
  5321. if (thnet[THNET_INFOSHARE]) thnetInfoShare(leaderboardLeft);
  5322. ctx.font = 'bold 20px consolas';
  5323.  
  5324. //cursor can control movement
  5325. if (weird[WEIRD_CURSORMOVE]) {
  5326. goToSpotWithPackets(multiBox[MULTIBOX_SELECTEDSOCKET], playerScreenPos, cursor);
  5327. drawCircle(playerScreenPos, nullPos, 50, 2, '#444');
  5328. for (let i = TAU / 16; i < TAU; i += TAU / 8) drawLine2(me, {x: sin(i) * 50, y: cos(i) * 50}, offset, 1, '#000');
  5329. drawLine(playerScreenPos, cursor, nullPos, 2, '#000');
  5330. }
  5331.  
  5332. drawTracers(players, playerScreenPos, offset, animationSubtraction);
  5333.  
  5334. drawTeamAffiliations(offset);
  5335.  
  5336. if (!perkHacks[PERKHACKS_TICK]) aimMeAt({
  5337. clientX: cursor.x / j6,
  5338. clientY: cursor.y / j5
  5339. }, 1);
  5340.  
  5341. //no need to get a target if the setting isnt even activated
  5342. let gun = gunMap[c1.weapon],
  5343. target = doAimbotThings(me, offset, enemies, enemyFriends, crates, gunMinRange, playerScreenPos, gun);
  5344.  
  5345. perkHacksAction(me, multiBox[MULTIBOX_SELECTEDSOCKET], playerScreenPos, offset, enemies, enemyFriends, crates, animationSubtraction);
  5346.  
  5347. if (aimbot[AIMBOT_ENABLE] && aimbot[AIMBOT_WALLCHECK] && aimbot[AIMBOT_TRIGGERBOT]) {
  5348. let bulletPathLength = ranges[gun] * velocities[gun] * ((o3[1] === perks[8] || o3[3] === perks[8]) ? 1.5 : 1),
  5349. rangeSquared = (bulletPathLength * mathSin) ** 2 + (bulletPathLength * 0.5 + me[ATTRIBUTE_RADIUS]) ** 2;
  5350.  
  5351. drawCircle(me, offset, sqrt(rangeSquared), 2, '#000');
  5352.  
  5353. if (target[ATTRIBUTE_ENEMY] && !perkHacks[PERKHACKS_TICK] && target[ATTRIBUTE_DISTANCE] < rangeSquared && !(aimbot[AIMBOT_TRIGGERBOTWHENDOWN] && !cursor.isPressed)) {
  5354. startGunfire(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5355. } else {
  5356. stopGunfire(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5357. }
  5358. }
  5359.  
  5360. if (antiAim[ANTIAIM_DRAWREALAIM]) me[ATTRIBUTE_DRAWGUN](ctx, c2);
  5361.  
  5362. hideAim(me, offset, animationSubtraction);
  5363.  
  5364. //the H A N D of P O W E R R R R R
  5365. gun = gunMap[c1.weapon];
  5366. let newAngle = (me.playerAngle + 210) * -degToRad,
  5367. gunOffset = offsets[gun] + velocities[gun] - 14,
  5368. gunAngle = (me.playerAngle + 270) * -degToRad,
  5369. hand = { x: playerScreenPos.x + sin(newAngle) * me[ATTRIBUTE_RADIUS], y: playerScreenPos.y + cos(newAngle) * me[ATTRIBUTE_RADIUS] },
  5370. gunEnd = { x: hand.x + sin(gunAngle) * gunOffset, y: hand.y + cos(gunAngle) * gunOffset };
  5371.  
  5372. //draw a laser from the gun to the mouse cursor
  5373. if (esp[ESP_TRACERSGUN]) {
  5374. //scuffed
  5375. drawLine2(hand, {x: j9[0] - hand.x, y: j9[1] - hand.y}, nullPos, 1, '#000');
  5376. drawCircle(gunEnd, nullPos, 1, 2, 'red');
  5377. }
  5378.  
  5379. gunMinRange = (me.x + offset.x - gunEnd.x) ** 2 + (me.y + offset.y - gunEnd.y) ** 2;
  5380.  
  5381. //update the server with our new aiming direction
  5382. sendMousePositionToServer(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5383.  
  5384. //auto reload the gun if: not fully reloaded, not currently reloading, there are no enemies nearby, the player isnt shooting for no reason
  5385. //reloads by pressing R to tell game to reload the gun
  5386. if (misc[MISC_AUTORELOAD] && !(enemies.length || cursor.isPressed || me.shooting || me.reloading || me.maxBullets == me.currentBullets)) {
  5387. startReloading(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5388. } else {
  5389. stopReloading(multiBox[MULTIBOX_SELECTEDSOCKET]);
  5390. }
  5391.  
  5392. //if any menu is needing a canvas right now
  5393. updateMenuCanvas(me, offset, players, crates);
  5394. }
  5395.  
  5396. tickCount++;
  5397.  
  5398. //simplified next tick delay function
  5399. if (RF.list[0]) RF.list[0].check();
  5400.  
  5401. //guarantees that the next tick will happen in 16 since when this tick started
  5402. //NOTE: nope it fucking doesnt, setTimeout is inaccurate
  5403. renderTime = Date.now() - start;
  5404. setTimeout(a41, (40 / advanced[ADVANCED_TPS]) - renderTime);
  5405. };
  5406.  
  5407. a45 = () => {
  5408. if (!b15) a93();
  5409. a4();
  5410. a75();
  5411. b4 = null;
  5412. b38 = null;
  5413. selfPremiumMember = 0;
  5414. b3 = 0;
  5415. b2 = 0;
  5416. b1 = 0;
  5417. $('#hostServerTabLi').hide();
  5418. $('#playButton').hide();
  5419. applyStyle(getElementById('gametypeDropdown'), {
  5420. [css_key_display]: css_value_misc_block
  5421. });
  5422. applyStyle(getElementById('serversBtn'), {
  5423. [css_key_display]: css_value_misc_flex
  5424. });
  5425. a99();
  5426. };
  5427.  
  5428. reloadGame = () => a120(o4.server, c22);
  5429.  
  5430. play = () => {
  5431. let socket = RF.list[multiBox[MULTIBOX_SELECTEDSOCKET]];
  5432. if (socket === undefVar) return;
  5433. if (!c4) socket.send(a59('c1', {class: c1.weapon, armor: c1.armor, color: c1.color}));
  5434. b21 = 1;
  5435. c8 = {1: 0, 2: 0, 3: 0};
  5436. o3 = {1: '', 2: '', 3: ''};
  5437. a2('c1', c1.weapon + ',' + c1.armor + ',' + c1.armorBtn + ',' + c1.color, 365);
  5438. };
  5439.  
  5440. //make the hack menu
  5441. loadSettings();
  5442. createMenu();
  5443.  
  5444. //keeping track of the mouse's actual position
  5445. document.onmousemove = mouseEvent => {
  5446.  
  5447. //future proofing
  5448. if (!mouseEvent.isTrusted) return;
  5449.  
  5450. cursor.x = mouseEvent.clientX;
  5451. cursor.y = mouseEvent.clientY;
  5452. for (let movableWindow of movableWindows) {
  5453. if (movableWindow.enable) {
  5454. applyStyle(movableWindow.element, {
  5455. [css_key_left]: (cursor.x - movableWindow.offsetX) + 'px',
  5456. [css_key_top]: (cursor.y - movableWindow.offsetY) + 'px'
  5457. });
  5458. }
  5459. }
  5460. fixWindowPositions();
  5461. };
  5462.  
  5463. window.onresize = () => {
  5464. fixWindowPositions();
  5465. a1();
  5466. if (null == c3) return;
  5467. c2[ATTRIBUTE_UPDATE](1);
  5468. drawFloor(ctx, c2);
  5469. for (let entity of getPool(RA)) if (entity.activated || entity.type == 'landMine') entity[ATTRIBUTE_DRAW]();
  5470. for (let bullet of getPool(RC)) if (bullet.activated) bullet[ATTRIBUTE_DRAW]();
  5471. for (let crate of getPool(RB)) if (crate.activated) crate[ATTRIBUTE_DRAW]();
  5472. for (let entity of getPool(RA)) if (entity.activated && entity.type != 'landMine') entity[ATTRIBUTE_DRAW]();
  5473. for (let player of getPool(RD)) {
  5474. if (!player.activated || (c28 && player.id == c3)) continue;
  5475. player[ATTRIBUTE_DRAWBODY]();
  5476. player[ATTRIBUTE_DRAWGUN]();
  5477. }
  5478. for (let gas of getPool(RA)) if (gas.activated) gas.drawEmission(ctx, c2);
  5479. for (let i in j27) {
  5480. let hitParticle = j27[i];
  5481. if (hitParticle.c42 < 5) {
  5482. j26(c2, hitParticle.x, hitParticle.y);
  5483. } else {
  5484. delete hitParticle[i];
  5485. }
  5486. }
  5487.  
  5488. a55(ctx, c2);
  5489. j9 = [cursor.x, cursor.y];
  5490. let me = RD.pool[c3];
  5491. a9(me);
  5492. drawMinimap(me);
  5493. a13(ctx, c8);
  5494. drawLeaderBoard(ctx, j38);
  5495. showFeatures();
  5496. };
  5497.  
  5498. //adblock
  5499. a36=a119=a78=a79=a80=()=>{};
  5500. for (let ad of j36) {
  5501. //to make it work with Gats.io Adblocker without it crashing
  5502. let element = getElementById(ad.pl);
  5503. if (element) element.remove();
  5504. }
  5505.  
  5506. if (c2) c2 = new RE(c2);
  5507.  
  5508. document.onmouseup=()=>{};
  5509. document.onmousedown=()=>{};
  5510. canvas.onmouseup = gameMouseUp;
  5511. canvas.onmousedown = gameMouseDown;
  5512.  
  5513. canvas.onwheel = E => {
  5514. if (esp[ESP_ZOOM] != 1) return;
  5515. E.preventDefault();
  5516. let dir = sign(E.deltaY);
  5517. if (dir == 1) {
  5518. j7 *= esp[ESP_SCROLLSENSITIVITY];
  5519. j8 *= esp[ESP_SCROLLSENSITIVITY];
  5520. }
  5521. if (dir == -1) {
  5522. j7 /= esp[ESP_SCROLLSENSITIVITY];
  5523. j8 /= esp[ESP_SCROLLSENSITIVITY];
  5524. }
  5525. a1();
  5526. };
  5527.  
  5528. window.onbeforeunload = event => {
  5529. if (b3 && !misc[MISC_DISABLECLOSEPOPUP]) {
  5530. event.preventDefault();
  5531. return event.returnValue = "You're still logged in. Are you sure you want to leave?";
  5532. }
  5533. };
  5534.  
  5535. //if loading during a game, hook the game socket
  5536. if (RF.list && RF.list[0] && RF.list[0].socket && RF.list[0].socket.url == RF.list[0].connectHostname) RF.list[0].socket.onmessage = function (wsMsgEvent) {
  5537. if (recorder[RECORDER_ISRECORDING]) recorder[RECORDER_CURRENT].push([Date.now(), wsMsgEvent.data]);
  5538. handleMessage(0, wsMsgEvent);
  5539. };
  5540.  
  5541. //sync player attributes to prevent fatal bugs
  5542. for (let player of getPool(RD)) {
  5543. if (player.activated) {
  5544. player[ATTRIBUTE_RADIUS] = player.radius;
  5545. player[ATTRIBUTE_HPRADIUS] = player.hpRadius;
  5546. player[ATTRIBUTE_ACCX] = player[ATTRIBUTE_ACCY] = 0;
  5547. setNameVariations(player, player.username);
  5548. }
  5549. }
  5550.  
  5551. //instant reconnect attempt on load
  5552. if (getElementById('reconnectButton').style[css_key_display] == css_value_misc_block) reloadGame();
  5553.  
  5554. //just making some stuff look better
  5555. applyStyle(getElementById('playButton'), {
  5556. [css_key_height]: css_value_length_px55,
  5557. [css_key_marginTop]: css_value_length_px0,
  5558. [css_key_borderWidth]: css_value_length_px4
  5559. });
  5560. applyStyle(getElementById('reconnectButton'), {
  5561. [css_key_height]: css_value_length_px55,
  5562. [css_key_marginTop]: css_value_length_px0,
  5563. [css_key_borderWidth]: css_value_length_px4,
  5564. [css_key_borderColor]: css_value_color_777f
  5565. });
  5566.  
  5567. })();