Improved Bullet Stacking By Mekhi Maragh

Makes some tanks more powerful (Tri-angle branch, spread shot, penta shot, octo tank, gunner trapper, streamliner).

  1. // ==UserScript==
  2. // @name Improved Bullet Stacking By Mekhi Maragh
  3. // @include *://arras.io/*
  4. // @author Mekhi MAragh
  5. // @description Makes some tanks more powerful (Tri-angle branch, spread shot, penta shot, octo tank, gunner trapper, streamliner).
  6. // @connect arras.io
  7. // @namespace aaa
  8. // @version 69
  9. // ==/UserScript==
  10. /*
  11. How to Use:
  12. Press Shift+R to cycle through the tanks.
  13. Press Shift+Q to disable/enable the script.
  14. Press I to hide the dialog. (The script remains functional, though).
  15. Hold rightclick to activate . For best results, leave autofire off for a bit before doing so.
  16. If necessary, press Shift+M to re-calibrate the script. Wait for the ms to stabilise.
  17. Note: This calibration may break for Triple Twin, and is unnecessary for Streamliner.
  18. */
  19. (function(){//info
  20. if(window.updateInfo) return;
  21. var info = {};
  22. var info_container = document.createElement("div");
  23. info_container.style.position = "fixed";
  24. info_container.style.color = "blue";
  25. info_container.style["pointer-events"] = "none";
  26. document.body.appendChild(info_container);
  27. function toggle_info_container(e){
  28. if(e.key == "i"){
  29. info_container.style.display = info_container.style.display=="block" ? "none" : "block";
  30. }
  31. }
  32. window.addEventListener("keyup", toggle_info_container);
  33. window.updateInfo = function(key, value){
  34. if(!value) delete info[key];
  35. else info[key] = value;
  36. var s = "";
  37. for(var _key in info){
  38. s += info[_key] + "\n";
  39. }
  40. info_container.innerText = s;
  41. };
  42. })();
  43. function MeasureCycle(){
  44. var canvas = document.getElementById("canvas");
  45. var ctx = canvas.getContext("2d");
  46. var real_arc = ctx.arc;
  47. var real_setTransform = ctx.setTransform;
  48. var a;
  49. var tx = 0, ty = 0;
  50. var a11 = 1;
  51. var state = false;
  52. var found = false;
  53. var inA = null;
  54. var direction = 1;
  55. var frameRequest;
  56. var intervalEMA = null; // ms
  57. function arc(){
  58. real_arc.apply(ctx, arguments);
  59. if(!found){
  60. var aimX = window.innerWidth / 2 + 50 * direction;
  61. var aimY = window.innerHeight / 2;
  62. found = (tx - a11 < aimX) && (tx + a11 > aimX) && (ty - a11 < aimY) && (ty + a11 > aimY);
  63. }
  64. }
  65. function setTransform(b11, b12, b21, b22, bx, by){
  66. real_setTransform.apply(ctx, arguments);
  67. tx = bx, ty = by, a11 = b11;
  68. }
  69. function onFrame(_a){
  70. frameRequest = window.requestAnimationFrame(onFrame);
  71. a = _a;
  72. if(!state && found){
  73. if(inA){
  74. var da = a - inA;
  75. inA = a;
  76. intervalEMA = intervalEMA ? 0.8 * intervalEMA + 0.2 * da : da;
  77. window.updateInfo && window.updateInfo(
  78. "intervalEMA",
  79. "Fire Period: " + intervalEMA.toString().substr(0, 5) + "ms"
  80. );
  81. }else{
  82. inA = a;
  83. }
  84. }
  85. state = found;
  86. found = false;
  87. }
  88. function onMouseEvent(e){
  89. e.stopPropagation();
  90. }
  91. this.start = function(_direction){
  92. _direction = _direction || 1;
  93. direction = _direction > 0 ? 1 : -1;
  94. inA = null;
  95. intervalEMA = null;
  96. state = found = false;
  97. ctx.setTransform = setTransform;
  98. ctx.arc = arc;
  99. var aimX = window.innerWidth / 2 + 50 * direction;
  100. var aimY = window.innerHeight / 2;
  101. canvas.dispatchEvent(new MouseEvent("mousemove", {clientX: aimX, clientY: aimY}));
  102. canvas.dispatchEvent(new MouseEvent("mousedown", {clientX: aimX, clientY: aimY}));
  103. window.addEventListener("mousemove", onMouseEvent, true);
  104. window.addEventListener("mouseup", onMouseEvent, true);
  105. window.addEventListener("mousedown", onMouseEvent, true);
  106. frameRequest = window.requestAnimationFrame(onFrame);
  107. window.updateInfo && window.updateInfo("measuring", "Measuring...");
  108. }
  109. this.terminate = function(){
  110. ctx.setTransform = real_setTransform;
  111. ctx.arc = real_arc;
  112. window.removeEventListener("mousemove", onMouseEvent, true);
  113. window.removeEventListener("mousedown", onMouseEvent, true);
  114. window.removeEventListener("mouseup", onMouseEvent, true);
  115. window.cancelAnimationFrame(frameRequest);
  116. canvas.dispatchEvent(new MouseEvent("mouseup", {clientX: 10, clientY: 10}));
  117. window.updateInfo && window.updateInfo("measuring", null);
  118. return intervalEMA;
  119. }
  120. };
  121. (function(){
  122. var cycleRate = 0.003125; // ms^-1
  123. var maxAngle = Math.PI * 45 / 180;
  124. var secAngle = 0;
  125. var cycleCounter = 1;
  126. var NCANNON = 3;
  127. var angleUnit = maxAngle / (NCANNON - 1);
  128. var secUnit = secAngle;
  129. var ax30945=1;
  130. var sec=false;
  131. var tankData = [
  132. {name: "Tri-angle Stack", cycleRate: 0.003125, maxAngle: Math.PI * 150 / 180, secondaryAngle: Math.PI * 150 / 180, NCANNON: 2},
  133. {name: "Fighter Stack", cycleRate: 0.003135, maxAngle: Math.PI * 90 / 175, secondaryAngle: Math.PI/2, NCANNON: 2},
  134. {name: "bycycle's retarded script", cycleRate: 0.003125, maxAngle: Math.PI, secondaryAngle: Math.PI, NCANNON: 2},
  135. {name: "Penta Stack broken", cycleRate: 0.003125, maxAngle: Math.PI/4, secondaryAngle: Math.PI/4, NCANNON: 3},
  136. {name: "Spread Stack boken", cycleRate: 0.001555, maxAngle: Math.PI * 75 / 180, secondaryAngle: Math.PI * 75 / 180, NCANNON: 6},
  137. {name: "Octo Stack", cycleRate: 0.003125, maxAngle: Math.PI/4, secondaryAngle: Math.PI/4, NCANNON: 2},
  138. {name: "GunnerTrapper",cycleRate: 0.0125, maxAngle: Math.PI, secondaryAngle: Math.PI, NCANNON: 2},
  139. {name: "Streamliner Spread", cycleRate: 0.0625, maxAngle: Math.PI * 15 / 180, secondaryAngle: Math.PI * 15 / 180, NCANNON: 3},
  140. {name: "random spinny flick shit idk", cycleRate: 0.001, maxAngle: 0, secondaryAngle: 0, NCANNON: 2},
  141. ];
  142. var tankIndex = 0;
  143. var measure = new MeasureCycle();
  144. var measuring = false;
  145. var effective = false;
  146. var frameRequest;
  147. var toggle1 = true;
  148. var toggle2 = false;
  149. var canvas = window.document.getElementById("canvas");
  150. var mouseX;
  151. var mouseY;
  152. var a = 0;
  153. var startA = 0;
  154. var artificialMouseMove = false;
  155. var disabled = false;
  156. function onMouseDown(e){
  157. if(e.button == 2){
  158. sec=false;
  159. if(!effective){
  160. startA = a - 25;
  161. mouseX = e.clientX;
  162. mouseY = e.clientY;
  163. canvas.dispatchEvent(new MouseEvent("mousedown", {clientX: mouseX, clientY: mouseY}));
  164. }
  165. effective = true;
  166. cycleCounter=0;
  167. }
  168. }
  169. function onMouseUp(e){
  170. if(e.button == 2){
  171. if(effective){
  172. canvas.dispatchEvent(new MouseEvent("mouseup", {clientX: mouseX, clientY: mouseY}));
  173. }
  174. effective = false;
  175. }
  176. }
  177. function onMouseMove(e){
  178. if(effective){
  179. if(!artificialMouseMove){
  180. e.stopPropagation();
  181. mouseX = e.clientX;
  182. mouseY = e.clientY;
  183. }
  184. }else{
  185. mouseX = e.clientX;
  186. mouseY = e.clientY;
  187. }
  188. }
  189. function update(_a){
  190. frameRequest = window.requestAnimationFrame(update);
  191. a = _a;
  192. if(effective){
  193. var da = a - startA;
  194. var state = Math.floor(cycleRate * da * NCANNON) % (NCANNON * 2);
  195. var state1 = state % NCANNON;
  196. var state2 = Math.floor(state / NCANNON);
  197. var remainder=cycleRate*da*NCANNON-Math.floor(cycleRate*da*NCANNON);
  198. var angle = angleUnit * state1 * ax30945;
  199. var angle2 = secUnit * state1 * ax30945;
  200. var cx = window.innerWidth / 2;
  201. var cy = window.innerHeight / 2;
  202. window.updateInfo && window.updateInfo("reeeee", remainder);
  203. if (toggle2 && state1==0) {
  204. toggle2=false;
  205. cycleCounter++;
  206. }
  207. if (state1!=0) toggle2=true;
  208. if (cycleCounter%3==2) angle=angle2;
  209. //if (remainder>0.5) angle=0;
  210. //if (cycleCounter%2==1) angle=-angle;
  211. var sin = Math.sin(angle);
  212. var cos = Math.cos(angle);
  213. var x = mouseX - cx;
  214. var y = mouseY - cy;
  215. var _x = cos * x - sin * y;
  216. var _y = sin * x + cos * y;
  217. x = _x + cx;
  218. y = _y + cy;
  219. artificialMouseMove = true;
  220. canvas.dispatchEvent(new MouseEvent("mousemove", {clientX: x, clientY: y}));
  221. artificialMouseMove = false;
  222. } else {
  223. var data = tankData[tankIndex];
  224. if (data.name=="random spinny flick shit idk") {
  225. da = a - startA;
  226. state = Math.floor(0.01 * da * 4) % (4 * 2);
  227. state1 = state % 4;
  228. state2 = Math.floor(state / 4);
  229. angle = Math.PI/3 * state1;
  230. cx = window.innerWidth / 2;
  231. cy = window.innerHeight / 2;
  232. sin = Math.sin(angle);
  233. cos = Math.cos(angle);
  234. x = mouseX - cx;
  235. y = mouseY - cy;
  236. _x = cos * x - sin * y;
  237. _y = sin * x + cos * y;
  238. x = _x + cx;
  239. y = _y + cy;
  240. artificialMouseMove = true;
  241. canvas.dispatchEvent(new MouseEvent("mousemove", {clientX: x, clientY: y}));
  242. artificialMouseMove = false;
  243. }
  244. }
  245. }
  246. function onKeyUp(e){
  247. if(e.key == "Z") {
  248. ax30945=1;
  249. }
  250. if(e.key == "Q"){
  251. disabled = !disabled;
  252. if(disabled){
  253. if(measuring){
  254. cycleRate = 1 / measure.terminate();
  255. measuring = false;
  256. } else stop();
  257. }else start();
  258. window.updateInfo && window.updateInfo("off", disabled ? "Disabled." : null);
  259. return;
  260. }
  261. if(disabled) return;
  262. if(e.key == "N"){
  263. if(measuring){
  264. cycleRate = 1 / measure.terminate();
  265. start();
  266. measuring = false;
  267. }else{
  268. stop();
  269. measure.start(mouseX - window.innerWidth / 2);
  270. measuring = true;
  271. }
  272. }else if(e.key == "R"){
  273. changeTank((tankIndex + 1) % tankData.length);
  274. }
  275. }
  276. function changeTank(index){
  277. var data = tankData[index];
  278. tankIndex = index;
  279. cycleRate = data.cycleRate; // ms^-1
  280. maxAngle = data.maxAngle;
  281. secAngle = data.secondaryAngle;
  282. NCANNON = data.NCANNON;
  283. angleUnit = maxAngle / (NCANNON - 1);
  284. secUnit = secAngle / (NCANNON - 1);
  285. window.updateInfo && window.updateInfo("changeTank", "Tank: " + data.name);
  286. }
  287. function init(){
  288. window.addEventListener("keyup", onKeyUp);
  289. start();
  290. changeTank(0);
  291. }
  292. function start(){
  293. canvas.addEventListener("mousedown", onMouseDown);
  294. canvas.addEventListener("mouseup", onMouseUp);
  295. window.addEventListener("mousemove", onMouseMove, true);
  296. frameRequest = window.requestAnimationFrame(update);
  297. }
  298. function stop(){
  299. canvas.removeEventListener("mousedown", onMouseDown);
  300. canvas.removeEventListener("mouseup", onMouseUp);
  301. window.removeEventListener("mousemove", onMouseMove, true);
  302. window.cancelAnimationFrame(frameRequest);
  303. effective = false;
  304. }
  305. init();
  306. })();