Sploop.io [Visual Extension]

New visuals elements [Tracers, HitBoxes, HP indicator, Setting menu]

  1. // ==UserScript==
  2. // @name Sploop.io [Visual Extension]
  3. // @name:ru Sploop.io [Визуальное расширение]
  4. // @description New visuals elements [Tracers, HitBoxes, HP indicator, Setting menu]
  5. // @description:ru Новые визуальные элементы [Tracers, HitBoxes, HP indicator, Setting menu]
  6. // @namespace https://greasyfork.org/ru/users/759782-nudo
  7. // @version 2.1
  8. // @author Nudo#3310
  9. // @match *://sploop.io/*
  10. // @require http://code.jquery.com/jquery-3.3.1.min.js
  11. // @require https://code.jquery.com/ui/1.12.0/jquery-ui.min.js
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. class Visuals {
  16. constructor() {
  17. this.text = {
  18. color: {
  19. all: "#fff",
  20. rainbow: false
  21. },
  22. visible: 1
  23. }
  24. this.tracers = {
  25. active: true,
  26. disttag: true,
  27. dashline: false,
  28. color: {
  29. entity: "#cc5151",
  30. ally: "#a4cc4f",
  31. rainbow: false
  32. },
  33. size: 1,
  34. visible: 1
  35. }
  36. this.hitboxes = {
  37. active: false,
  38. dashline: false,
  39. color: {
  40. all: "#5174cd",
  41. rainbow: false
  42. },
  43. size: 1,
  44. visible: 1
  45. }
  46. this.rainbow = {
  47. old: Date.now(),
  48. hue: 0,
  49. power: 3,
  50. time: 10
  51. }
  52. this.offset = [0, Date.now()]
  53. }
  54. rainbowColor() {
  55. if (!this.rainbow.old || Date.now() - this.rainbow.old >= this.rainbow.time) {
  56. this.rainbow.hue += this.rainbow.power * Math.random()
  57. this.rainbow.old = Date.now()
  58. }
  59. visuals.rb = `hsl(${this.rainbow.hue}, 100%, 50%)`
  60. }
  61. drawText(text, x, y) {
  62. Context.save()
  63. Context.font = '18px "Baloo Paaji"'
  64. Context.lineWidth = 8
  65. Context.strokeStyle = "#3d3f42"
  66. Context.globalAlpha = this.text.visible
  67. Context.textAlign = 'center'
  68. Context.fillStyle = this.text.color.rainbow ? visuals.rb : this.text.color.all
  69. Context.strokeText(text, x, y)
  70. Context.fillText(text, x, y)
  71. Context.restore()
  72. }
  73. updateOffset() {
  74. if (!this.offset[1] || Date.now() - this.offset[1] >= 10) {
  75. this.offset[0]++
  76. this.offset[1] = Date.now()
  77. }
  78. }
  79. dashLine() {
  80. Context.setLineDash([18, 6, 6, 6])
  81. Context.lineDashOffset = -visuals.offset[0]
  82. }
  83. }
  84.  
  85. let visuals = new Visuals()
  86.  
  87. class Tracers {
  88. constructor() {
  89. this.allAlly = []
  90. this.allEntity = []
  91. this.localPlayer = {
  92. active: false,
  93. x: 0,
  94. y: 0
  95. }
  96. }
  97. drawDistTag(x, y, dist) {
  98. if (!visuals.tracers.disttag) return
  99. Context.save()
  100. Context.font = '18px "Baloo Paaji"'
  101. Context.lineWidth = 8
  102. Context.strokeStyle = "#3d3f42"
  103. Context.globalAlpha = visuals.text.visible
  104. Context.fillStyle = visuals.text.color.rainbow ? visuals.rb : visuals.text.color.all
  105. Context.strokeText(dist, x, y)
  106. Context.fillText(dist, x, y)
  107. Context.restore()
  108. }
  109. draw(x, y, x2, y2, color) {
  110. if (!visuals.tracers.active) return
  111. Context.save()
  112. Context.lineCap = "round"
  113. Context.lineWidth = visuals.tracers.size
  114. Context.globalAlpha = visuals.tracers.visible
  115. Context.beginPath()
  116. if (visuals.tracers.dashline) visuals.dashLine()
  117. Context.strokeStyle = color
  118. Context.moveTo(x, y)
  119. Context.lineTo(x2, y2)
  120. Context.stroke()
  121. Context.restore()
  122. }
  123. }
  124.  
  125. let tracers = new Tracers()
  126.  
  127. class HitBoxes {
  128. static draw(x, y, width, height) {
  129. if (!visuals.hitboxes.active) return
  130. Context.save()
  131. Context.lineWidth = visuals.hitboxes.size
  132. Context.globalAlpha = visuals.hitboxes.visible
  133. if (visuals.hitboxes.dashline) visuals.dashLine()
  134. Context.strokeStyle = visuals.hitboxes.color.rainbow ? visuals.rb : visuals.hitboxes.color.all
  135. Context.strokeRect(x, y, width, height)
  136. Context.restore()
  137. }
  138. }
  139.  
  140. let Context;
  141.  
  142. let { clearRect, fillRect, fillText, drawImage } = CanvasRenderingContext2D.prototype
  143.  
  144. CanvasRenderingContext2D.prototype.clearRect = function(x, y, width, height) {
  145. if (this.canvas.id === "game-canvas") {
  146. Context = this.canvas.getContext("2d")
  147. visuals.rainbowColor()
  148. tracers.allEntity = []
  149. tracers.allAlly = []
  150. }
  151. return clearRect.apply(this, arguments);
  152. }
  153.  
  154. CanvasRenderingContext2D.prototype.drawImage = function(image, x, y, width, height, dx, dy, dwidth, dheight) {
  155. if (tracers.localPlayer.active && typeof image.src == 'string') {
  156. let ff = image.src.split("/")
  157. if (ff[4] == "skins"
  158. || ff[4] == "entity"
  159. && !ff[5].includes("inv_")
  160. && !ff[5].includes("map")
  161. && !ff[5].includes("resource")
  162. && !ff[5].includes("health")
  163. && !ff[5].includes("button")
  164. && !ff[5].includes("skull")) {
  165. HitBoxes.draw(x, y, width, height)
  166. }
  167. }
  168. return drawImage.apply(this, arguments);
  169. }
  170.  
  171. CanvasRenderingContext2D.prototype.fillRect = function(x, y, width, height) {
  172. if (document.getElementById("homepage").style.display == "none") {
  173. visuals.updateOffset()
  174. if (this.fillStyle == "#a4cc4f") {
  175. tracers.allAlly.push({
  176. x: x + 45,
  177. y: y - 70
  178. })
  179. tracers.localPlayer.active = true
  180. tracers.localPlayer.x = tracers.allAlly[0].x
  181. tracers.localPlayer.y = tracers.allAlly[0].y
  182. visuals.drawText(`HP: ${~~(width / 95 * 100)}%`, x + 45, y + 40)
  183. visuals.drawText(`VisualExtension`, tracers.localPlayer.x, tracers.localPlayer.y + 125)
  184. if (tracers.allAlly[1]) {
  185. tracers.allAlly.forEach(ally => {
  186. if (ally.x != tracers.localPlayer.x) {
  187. let color = (visuals.tracers.color.rainbow ? visuals.rb : visuals.tracers.color.ally)
  188. tracers.draw(tracers.localPlayer.x, tracers.localPlayer.y, ally.x, ally.y, color)
  189. tracers.drawDistTag((tracers.localPlayer.x + ally.x) / 2, (tracers.localPlayer.y + ally.y) / 2, ~~(Math.hypot(tracers.localPlayer.y - ally.y, tracers.localPlayer.x - ally.x)))
  190. }
  191. })
  192. }
  193. }
  194. if (this.fillStyle == "#cc5151" && tracers.localPlayer.active) {
  195. visuals.drawText(`HP: ${~~(width / 95 * 100)}%`, x + 45, y + 40)
  196. tracers.allEntity.push({
  197. x: x + 45,
  198. y: y - 70
  199. })
  200. tracers.allEntity.forEach(enemy => {
  201. let color = (visuals.tracers.color.rainbow ? visuals.rb : visuals.tracers.color.entity)
  202. tracers.draw(tracers.localPlayer.x, tracers.localPlayer.y, enemy.x, enemy.y, color)
  203. tracers.drawDistTag((tracers.localPlayer.x + enemy.x) / 2, (tracers.localPlayer.y + enemy.y) / 2, ~~(Math.hypot(tracers.localPlayer.y - enemy.y, tracers.localPlayer.x - enemy.x)))
  204. })
  205. }
  206. } else {
  207. tracers.localPlayer.active = false
  208. }
  209. return fillRect.apply(this, arguments)
  210. }
  211.  
  212. let Menu = `
  213. <div class="menu-holder flex-c">
  214. <div class="menu-wrapper">
  215. <div class="menu-container">
  216. <div class="menu-title flex-c text-shadowed-4">
  217. <span>VisualExtension</span>
  218. </div>
  219. <div class="menu-content scrollbar text-shadowed-3">
  220. <ul class="tracers-content">
  221. <li class="subcontent-subtitle" style="font-size: 18px;">Tracer</li>
  222. <li class="setting-box">
  223. <div class="name-box">Active</div>
  224. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="tracer-active" checked><div class="control_indicator"></div></label></div></div>
  225. </li>
  226. <li class="setting-box">
  227. <div class="name-box">RainbowColor</div>
  228. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="tracer-rainbow"><div class="control_indicator"></div></label></div></div>
  229. </li>
  230. <li class="setting-box" title="When there are a lot of tracers, it's a lower your FPS!">
  231. <div class="name-box">DashLine</div>
  232. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="tracer-dashline"><div class="control_indicator"></div></label></div></div>
  233. </li>
  234. <li class="setting-box">
  235. <div class="name-box">DistTag</div>
  236. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="tracer-disttag" checked><div class="control_indicator"></div></label></div></div>
  237. </li>
  238. <li class="setting-box">
  239. <div class="name-box">AllyColor</div>
  240. <div class="action-box"><input type="color" id="tracers-ally-color" value="#a4cc4f"></div>
  241. </li>
  242. <li class="setting-box">
  243. <div class="name-box">EntityColor</div>
  244. <div class="action-box"><input type="color" id="tracers-entity-color" value="#cc5151"></div>
  245. </li>
  246. <li class="setting-box">
  247. <div class="name-box">Size</div>
  248. <div class="action-box">
  249. <div class="range-wrapper"><input type="range" class="pointer" id="tracers-size" value="1" min="1" step="any" max="10"><div class="range-value flex-c text-shadowed-3" id="tracers-size-value">1</div></div>
  250. </div>
  251. </li>
  252. <li class="setting-box">
  253. <div class="name-box">Visible</div>
  254. <div class="action-box">
  255. <div class="range-wrapper"><input type="range" class="pointer" id="tracers-visible" value="1" min="0" step="any" max="1"><div class="range-value flex-c text-shadowed-3" id="tracers-visible-value">1</div></div>
  256. </div>
  257. </li>
  258. </ul>
  259. <ul class="text-content">
  260. <li class="subcontent-subtitle" style="font-size: 18px;">Text</li>
  261. <li class="setting-box">
  262. <div class="name-box">RainbowColor</div>
  263. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="text-rainbow"><div class="control_indicator"></div></label></div></div>
  264. </li>
  265. <li class="setting-box">
  266. <div class="name-box">Color</div>
  267. <div class="action-box"><input type="color" id="text-all-color" value="#ffffff"></div>
  268. </li>
  269. <li class="setting-box">
  270. <div class="name-box">Visible</div>
  271. <div class="action-box">
  272. <div class="range-wrapper"><input type="range" class="pointer" id="text-visible" value="1" min="0" step="any" max="1"><div class="range-value flex-c text-shadowed-3" id="text-visible-value">1</div></div>
  273. </div>
  274. </li>
  275. </ul>
  276. <ul class="hitboxes-content">
  277. <li class="subcontent-subtitle" style="font-size: 18px;">HitBox</li>
  278. <li class="setting-box">
  279. <div class="name-box">Active</div>
  280. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="hitbox-active"><div class="control_indicator"></div></label></div></div>
  281. </li>
  282. <li class="setting-box">
  283. <div class="name-box">RainbowColor</div>
  284. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="hitbox-rainbow"><div class="control_indicator"></div></label></div></div>
  285. </li>
  286. <li class="setting-box" title="When there are a lot of hitboxes, it's a lower your FPS!">
  287. <div class="name-box">DashLine</div>
  288. <div class="action-box"><div class="control-group"><label class="control control-checkbox" style="display:unset;padding-top:4px;"><input type="checkbox" id="hitbox-dashline"><div class="control_indicator"></div></label></div></div>
  289. </li>
  290. <li class="setting-box">
  291. <div class="name-box">Color</div>
  292. <div class="action-box"><input type="color" id="hitbox-all-color" value="#5174cd"></div>
  293. </li>
  294. <li class="setting-box">
  295. <div class="name-box">Size</div>
  296. <div class="action-box">
  297. <div class="range-wrapper"><input type="range" class="pointer" id="hitbox-size" value="1" min="1" step="any" max="10"><div class="range-value flex-c text-shadowed-3" id="hitbox-size-value">1</div></div>
  298. </div>
  299. </li>
  300. <li class="setting-box">
  301. <div class="name-box">Visible</div>
  302. <div class="action-box">
  303. <div class="range-wrapper"><input type="range" class="pointer" id="hitbox-visible" value="1" min="0" step="any" max="1"><div class="range-value flex-c text-shadowed-3" id="hitbox-visible-value">1</div></div>
  304. </div>
  305. </li>
  306. </ul>
  307. </div>
  308. </div>
  309. </div>
  310. </div>
  311. <style>
  312. .range-value {
  313. width: 26px;
  314. margin-left: 5px;
  315. margin-right: -5px;
  316. }
  317. .range-wrapper {
  318. display: flex;
  319. margin-right: 5px;
  320. align-items: center;
  321. }
  322. .name-box {
  323. dont-size: 16px;
  324. }
  325. .setting-box {
  326. margin-bottom: 8px;
  327. display: flex;
  328. justify-content: space-between;
  329. width: 100%;
  330. padding-left: 3px;
  331. padding-right: 3px;
  332. }
  333. .tracers-content, .text-content, .hitboxes-content {
  334. margin-left: 5px;
  335. }
  336. .menu-content {
  337. display: flex;
  338. flex-direction: column;
  339. width: 214px;
  340. height: 265px;
  341. background: rgb(20 20 20 / 30%);
  342. border-radius: 10px;
  343. overflow-y: scroll;
  344. overflow-x: hidden;
  345. border: 3px solid #141414;
  346. box-shadow: inset 0 5px 0 rgb(20 20 20 / 40%);
  347. margin-left: 3px;
  348. }
  349. .menu-title span {
  350. font-size: 20px;
  351. color: #f0ece0;
  352. }
  353. .menu-title {
  354. width: 100%;
  355. height: 40px;
  356. }
  357. .menu-container {
  358. position: relative;
  359. left: -215px;
  360. display: flex;
  361. flex-direction: column;
  362. }
  363. .menu-wrapper {
  364. width: 40px;
  365. height: 325px;
  366. background: rgba(40, 45, 34, 0.6);
  367. border-radius: 0 15px 15px 0;
  368. border: 5px solid #141414;
  369. border-left: none;
  370. box-shadow: none;
  371. opacity: .5;
  372. transition: .5s all;
  373. }
  374. .menu-wrapper:hover {
  375. box-shadow: inset 0 4px 0 #4e5645, inset 0 -4px 0 #384825, 0px 2px 0 5px rgb(20 20 20 / 30%), 0px 0px 0 15px rgb(20 20 20 / 10%);
  376. }
  377. .menu-holder {
  378. position: absolute;
  379. top: 0;
  380. height: 100%;
  381. }
  382. .flex-c {
  383. display: flex;
  384. justify-content: center;
  385. align-items: center;
  386. }
  387. .flex-sb-c {
  388. display: flex;
  389. justify-content: space-between;
  390. align-items: center;
  391. }
  392. input[type="color"] {
  393. -webkit-appearance: none;
  394. border: none;
  395. background: none;
  396. width: 20px;
  397. height: 20px;
  398. border: 4px solid #141414;
  399. border-radius: 50%;
  400. }
  401. input[type="color"]::-webkit-color-swatch-wrapper {
  402. padding: 0;
  403. }
  404. input[type="color"]::-webkit-color-swatch {
  405. border: none;
  406. border-radius: 50%;
  407. }
  408. input[type=color]::-moz-focus-inner {
  409. border: none;
  410. padding: 0;
  411. border-radius: 50%;
  412. }
  413. input[type=color]::-moz-color-swatch {
  414. border: none;
  415. border-radius: 50%;
  416. }
  417. input[type="range"] {
  418. -webkit-appearance: none;
  419. width: 80px;
  420. height: 12px;
  421. background: rgba(40, 45, 34, 0.6);;
  422. border: 3px solid #141414;
  423. outline: none;
  424. }
  425. input[type="range"]::-webkit-slider-thumb {
  426. cursor: url(img/ui/cursor-pointer.png) 6 0, pointer;
  427. -webkit-appearance: none;
  428. width: 20px;
  429. border-radius: 4px;
  430. height: 20px;
  431. background: #f0ece0;
  432. border: 4px solid #141414;
  433. position: relative;
  434. z-index: 3;
  435. }
  436. </style>
  437. `
  438.  
  439. $("body").append(Menu)
  440.  
  441. $(".menu-wrapper").mouseenter(() => {
  442. $(".menu-container").animate({left: "0px"}, 750)
  443. $(".menu-wrapper").animate({ width: "225px", opacity: "1" }, 250)
  444. }).mouseleave(() => {
  445. $(".menu-container").animate({left: "-215px"}, 750)
  446. $(".menu-wrapper").animate({ width: "40px", opacity: ".5" }, 250)
  447. })
  448.  
  449. $("#tracers-visible").on("input", () => {
  450. visuals.tracers.visible = $("#tracers-visible").val()
  451. let fn = String((parseInt(visuals.tracers.visible * 100)) / 100)
  452. $("#tracers-visible-value").text(fn.includes("0.0") ? "." + fn.split("0.")[1] : fn.includes("0.") ? fn.split("0")[1] : fn)
  453. })
  454.  
  455. $("#text-visible").on("input", () => {
  456. visuals.text.visible = $("#text-visible").val()
  457. let fn = String((parseInt(visuals.text.visible * 100)) / 100)
  458. $("#text-visible-value").text(fn.includes("0.0") ? "." + fn.split("0.")[1] : fn.includes("0.") ? fn.split("0")[1] : fn)
  459. })
  460.  
  461. $("#hitbox-visible").on("input", () => {
  462. visuals.hitboxes.visible = $("#hitbox-visible").val()
  463. let fn = String((parseInt(visuals.hitboxes.visible * 100)) / 100)
  464. $("#hitbox-visible-value").text(fn.includes("0.0") ? "." + fn.split("0.")[1] : fn.includes("0.") ? fn.split("0")[1] : fn)
  465. })
  466.  
  467. $("#hitbox-size").on("input", () => {
  468. visuals.hitboxes.size = $("#hitbox-size").val()
  469. let fn = String((parseInt(visuals.hitboxes.size * 100)) / 100)
  470. $("#hitbox-size-value").text(fn.includes("0.0") ? "." + fn.split("0.")[1] : fn.includes("0.") ? fn.split("0")[1] : fn)
  471. })
  472.  
  473. $("#tracers-size").on("input", () => {
  474. visuals.tracers.size = $("#tracers-size").val()
  475. let fn = String((parseInt(visuals.tracers.size * 100)) / 100)
  476. $("#tracers-size-value").text(fn.includes("0.0") ? "." + fn.split("0.")[1] : fn.includes("0.") ? fn.split("0")[1] : fn)
  477. })
  478.  
  479. $("#tracers-ally-color").on("input", () => visuals.tracers.color.ally = $("#tracers-ally-color").val())
  480.  
  481. $("#tracers-entity-color").on("input", () => visuals.tracers.color.entity = $("#tracers-entity-color").val())
  482.  
  483. $("#tracer-rainbow").on("input", () => visuals.tracers.color.rainbow = !visuals.tracers.color.rainbow)
  484.  
  485. $("#tracer-disttag").on("input", () => visuals.tracers.disttag = !visuals.tracers.disttag, )
  486.  
  487. $("#tracer-dashline").on("input", () => visuals.tracers.dashline = !visuals.tracers.dashline)
  488.  
  489. $("#text-all-color").on("input", () => visuals.text.color.all = $("#text-all-color").val())
  490.  
  491. $("#text-rainbow").on("input", () => visuals.text.color.rainbow = !visuals.text.color.rainbow)
  492.  
  493. $("#hitbox-all-color").on("input", () => visuals.hitboxes.color.all = $("#hitbox-all-color").val())
  494.  
  495. $("#hitbox-rainbow").on("input", () => visuals.hitboxes.color.rainbow = !visuals.hitboxes.color.rainbow)
  496.  
  497. $("#hitbox-dashline").on("input", () => visuals.hitboxes.dashline = !visuals.hitboxes.dashline)
  498.  
  499. $("#hitbox-active").on("input", () => visuals.hitboxes.active = !visuals.hitboxes.active)
  500.  
  501. $("#tracer-active").on("input", () => visuals.tracers.active = !visuals.tracers.active)