1. // === FloydHax v3 ===
  2. // Paste into console on https://vortex.towerstats.com
  3. //
  4. // Position changes ARE visible to other players.
  5. //
  6. // F = fly N = noclip . = chat bypass
  7. // [ ] = +/-0.5x speed C = descend Backspace = reset speed
  8. // WASD = move Space = fly up / jump Mouse = look I/O = zoom
  9.  
  10. (function () {
  11. if (window.__floyd) return console.log("%cAlready active. Refresh to reset.", "color:#f80");
  12. window.__floyd = true;
  13.  
  14. var speedMul = 2;
  15. var MIN_SPD = 1;
  16. var MAX_SPD = 10;
  17. var BASE_WALK = 16;
  18. var BASE_FLY = 64;
  19. var JUMP_MUL = 1.8;
  20. var flying = false;
  21. var noclip = false;
  22. var bypassActive = false;
  23. var _velX = 0, _velZ = 0;
  24.  
  25. // ── Unicode bypass (Cyrillic homoglyphs + invisible separators) ─
  26. function bypassText(s) {
  27. var map = {
  28. a: "\u0430", c: "\u0441", e: "\u0435", i: "\u0456",
  29. o: "\u043E", p: "\u0440", x: "\u0445", y: "\u0443",
  30. A: "\u0410", B: "\u0412", C: "\u0421", E: "\u0415",
  31. H: "\u041D", I: "\u0406", K: "\u041A", M: "\u041C",
  32. O: "\u041E", P: "\u0420", T: "\u0422", X: "\u0425",
  33. Y: "\u04AE",
  34. };
  35. var out = "";
  36. for (var i = 0; i < s.length; i++) {
  37. out += (map[s[i]] || s[i]) + "\u200C";
  38. }
  39. return out;
  40. }
  41.  
  42. // ── draggable GUI ────────────────────────────────────────────
  43. var gui = document.createElement("div");
  44. gui.id = "floyd-gui";
  45. gui.style.cssText =
  46. "position:fixed;top:16px;right:16px;width:210px;z-index:2147483647;" +
  47. "border-radius:12px;overflow:hidden;" +
  48. "box-shadow:0 0 30px rgba(0,0,0,.6),0 0 8px rgba(253,224,0,.15);" +
  49. "font:12px system-ui;user-select:none;transition:opacity .2s";
  50.  
  51. // title bar
  52. var titleBar = document.createElement("div");
  53. titleBar.style.cssText =
  54. "background:linear-gradient(135deg,rgba(20,20,35,.95),rgba(10,10,25,.95));" +
  55. "color:#fde050;padding:10px 14px;font-weight:700;font-size:13px;" +
  56. "cursor:move;display:flex;align-items:center;justify-content:space-between;" +
  57. "border-bottom:1px solid rgba(253,224,0,.2);letter-spacing:.5px";
  58. titleBar.innerHTML = '<span>\u26a1 FloydHax v3</span>' +
  59. '<span id="floyd-collapse" style="cursor:pointer;font-size:16px;opacity:.6;padding:0 2px" title="Collapse">\u2013</span>';
  60. gui.appendChild(titleBar);
  61.  
  62. // body
  63. var body = document.createElement("div");
  64. body.id = "floyd-body";
  65. body.style.cssText =
  66. "background:rgba(8,8,22,.92);padding:12px 14px 14px;position:relative;overflow:hidden;transition:max-height .25s;max-height:200px";
  67. gui.appendChild(body);
  68.  
  69. // background image layer
  70. var bgImg = document.createElement("img");
  71. bgImg.src = "data:image/jpeg;base64,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";
  72. bgImg.style.cssText =
  73. "position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;opacity:.08;pointer-events:none;filter:grayscale(30%)";
  74. body.appendChild(bgImg);
  75.  
  76. var rowsWrap = document.createElement("div");
  77. rowsWrap.style.cssText = "position:relative;z-index:1;display:flex;flex-direction:column;gap:6px";
  78. body.appendChild(rowsWrap);
  79.  
  80. function _row(label, icon) {
  81. var r = document.createElement("div");
  82. r.style.cssText =
  83. "display:flex;justify-content:space-between;align-items:center;" +
  84. "padding:5px 8px;border-radius:6px;background:rgba(255,255,255,.03)";
  85. var left = document.createElement("span");
  86. left.style.cssText = "display:flex;align-items:center;gap:7px;color:#bbb";
  87. left.innerHTML = '<span style="font-size:13px">' + icon + '</span>' + label;
  88. var val = document.createElement("span");
  89. val.style.cssText = "font-weight:700;font-size:11px;letter-spacing:.3px;padding:2px 8px;border-radius:4px";
  90. val.textContent = "OFF";
  91. r.appendChild(left);
  92. r.appendChild(val);
  93. rowsWrap.appendChild(r);
  94. return val;
  95. }
  96.  
  97. var flyRow = _row("Fly", "\u2708");
  98. var noclipRow = _row("Noclip", "\u2b1b");
  99. var bypassRow = _row("Bypass", "\u2b1a");
  100. var speedRow = _row("Speed", "\u26a1");
  101. speedRow.textContent = "x2.0";
  102. speedRow.style.background = "rgba(253,224,0,.12)";
  103. speedRow.style.color = "#fde050";
  104.  
  105. document.body.appendChild(gui);
  106.  
  107. var collapsed = false;
  108. document.getElementById("floyd-collapse").addEventListener("mousedown", function (e) {
  109. e.stopPropagation();
  110. collapsed = !collapsed;
  111. this.textContent = collapsed ? "+" : "\u2013";
  112. body.style.maxHeight = collapsed ? "0" : "200px";
  113. body.style.padding = collapsed ? "0 14px" : "12px 14px 14px";
  114. });
  115.  
  116. function refreshGui() {
  117. function set(row, on, color) {
  118. row.textContent = on ? "ON" : "OFF";
  119. row.style.background = on ? color : "rgba(255,255,255,.04)";
  120. row.style.color = on ? "#111" : "#777";
  121. }
  122. set(flyRow, flying, "rgba(68,255,68,.85)");
  123. set(noclipRow, noclip, "rgba(255,136,0,.85)");
  124. set(bypassRow, bypassActive, "rgba(255,224,80,.85)");
  125. speedRow.textContent = "x" + speedMul.toFixed(1);
  126. }
  127. refreshGui();
  128.  
  129. // ── drag logic (works with pointer lock) ──────────────────────
  130. var dragging = false;
  131. var dragOffX = 0, dragOffY = 0;
  132.  
  133. titleBar.addEventListener("mousedown", function (e) {
  134. dragging = true;
  135. if (document.pointerLockElement) {
  136. dragOffX = 0; dragOffY = 0;
  137. } else {
  138. dragOffX = e.clientX - gui.offsetLeft;
  139. dragOffY = e.clientY - gui.offsetTop;
  140. }
  141. document.body.style.userSelect = "none";
  142. });
  143.  
  144. document.addEventListener("mousemove", function (e) {
  145. if (!dragging) return;
  146. if (document.pointerLockElement) {
  147. gui.style.left = (gui.offsetLeft + e.movementX) + "px";
  148. gui.style.top = (gui.offsetTop + e.movementY) + "px";
  149. } else {
  150. gui.style.left = (e.clientX - dragOffX) + "px";
  151. gui.style.top = (e.clientY - dragOffY) + "px";
  152. }
  153. gui.style.right = "auto";
  154. });
  155.  
  156. document.addEventListener("mouseup", function () {
  157. dragging = false;
  158. document.body.style.userSelect = "";
  159. });
  160.  
  161. // ── intercept chat Enter key in capture phase ──────────────────
  162. document.addEventListener("keydown", function (e) {
  163. if (!bypassActive) return;
  164. if (e.key !== "Enter") return;
  165. if (!window._chatFocused) return;
  166.  
  167. var inputEl = document.getElementById("chat-input");
  168. var text = (inputEl.textContent || "").trim();
  169. if (!text) return;
  170.  
  171. e.stopImmediatePropagation();
  172.  
  173. var safeText = bypassText(text);
  174.  
  175. var _origMp = window._mpSendChat;
  176. window._mpSendChat = function () {};
  177. window.Chat.send();
  178. window._mpSendChat = _origMp;
  179.  
  180. window._mpSendChat(safeText);
  181. }, true);
  182.  
  183. // ── save original update ──────────────────────────────────────
  184. var _orig = update;
  185.  
  186. // ── sweep collision helpers ───────────────────────────────────
  187. function _sweepX(dt) {
  188. var ch = character;
  189. var fy0 = ch.position.y - CHAR_FOOT_OFFSET;
  190. var acos = Math.abs(Math.cos(ch.rotation.y));
  191. var asin = Math.abs(Math.sin(ch.rotation.y));
  192. var halfX = CHAR_HALF_W * acos + CHAR_HALF_D * asin;
  193. var halfZ = CHAR_HALF_W * asin + CHAR_HALF_D * acos;
  194. var sw = getNearbyColliders(ch.position.x, ch.position.y, ch.position.z);
  195. var dx = _velX * dt;
  196. sw.forEach(function (b) {
  197. if (b.maxY <= fy0 + 0.05 || b.minY >= fy0 + CHAR_HEIGHT) return;
  198. if (ch.position.z + halfZ <= b.minZ || ch.position.z - halfZ >= b.maxZ) return;
  199. if (dx > 0) {
  200. var edge = ch.position.x + halfX;
  201. if (edge > b.minX) return;
  202. var allow = b.minX - edge;
  203. if (allow < dx) dx = Math.max(0, allow);
  204. } else if (dx < 0) {
  205. edge = ch.position.x - halfX;
  206. if (edge < b.maxX) return;
  207. allow = b.maxX - edge;
  208. if (allow > dx) dx = Math.min(0, allow);
  209. }
  210. });
  211. ch.position.x += dx;
  212. }
  213.  
  214. function _sweepZ(dt) {
  215. var ch = character;
  216. var fy0 = ch.position.y - CHAR_FOOT_OFFSET;
  217. var acos = Math.abs(Math.cos(ch.rotation.y));
  218. var asin = Math.abs(Math.sin(ch.rotation.y));
  219. var halfX = CHAR_HALF_W * acos + CHAR_HALF_D * asin;
  220. var halfZ = CHAR_HALF_W * asin + CHAR_HALF_D * acos;
  221. var sw = getNearbyColliders(ch.position.x, ch.position.y, ch.position.z);
  222. var dz = _velZ * dt;
  223. sw.forEach(function (b) {
  224. if (b.maxY <= fy0 + 0.05 || b.minY >= fy0 + CHAR_HEIGHT) return;
  225. if (ch.position.x + halfX <= b.minX || ch.position.x - halfX >= b.maxX) return;
  226. if (dz > 0) {
  227. var edge = ch.position.z + halfZ;
  228. if (edge > b.minZ) return;
  229. var allow = b.minZ - edge;
  230. if (allow < dz) dz = Math.max(0, allow);
  231. } else if (dz < 0) {
  232. edge = ch.position.z - halfZ;
  233. if (edge < b.maxZ) return;
  234. allow = b.maxZ - edge;
  235. if (allow > dz) dz = Math.min(0, allow);
  236. }
  237. });
  238. ch.position.z += dz;
  239. }
  240.  
  241. // ── helpers ──────────────────────────────────────────────────
  242. function _buildMove() {
  243. var m = new THREE.Vector3();
  244. if (keys["KeyW"] || keys["ArrowUp"]) m.z -= 1;
  245. if (keys["KeyS"] || keys["ArrowDown"]) m.z += 1;
  246. if (keys["KeyA"] || keys["ArrowLeft"]) m.x -= 1;
  247. if (keys["KeyD"] || keys["ArrowRight"]) m.x += 1;
  248. var hLen = Math.sqrt(m.x * m.x + m.z * m.z);
  249. if (hLen > 1) { m.x /= hLen; m.z /= hLen; }
  250. var yq = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), cam.yaw);
  251. m.applyQuaternion(yq);
  252. return { x: m.x, z: m.z, len: hLen };
  253. }
  254.  
  255. function _faceMove(ch, move, dt) {
  256. if (!shiftLock && move.len > 0.01) {
  257. ch.rotation.y = lerpAngle(ch.rotation.y, Math.atan2(move.x, move.z), Math.min(1, ROT_SPEED * dt));
  258. }
  259. if (shiftLock) ch.rotation.y = cam.yaw + Math.PI;
  260. }
  261.  
  262. // ── replacement update ────────────────────────────────────────
  263. update = function (dt) {
  264. var ch = character;
  265. if (!ch) return;
  266. if (keys["KeyI"]) cam.distance = Math.max(cam.minDist, cam.distance - 32 * dt);
  267. if (keys["KeyO"]) cam.distance = Math.min(cam.maxDist, cam.distance + 32 * dt);
  268.  
  269. if (flying) {
  270. climbState = "none";
  271. climbCooldown = 0;
  272. var move = _buildMove();
  273. var my = 0;
  274. if (keys["Space"]) my += 1;
  275. if (keys["KeyC"]) my -= 1;
  276. _faceMove(ch, move, dt);
  277. var spd = BASE_FLY * speedMul;
  278. ch.position.x += move.x * spd * dt;
  279. ch.position.z += move.z * spd * dt;
  280. ch.position.y += my * spd * dt;
  281. if (ch.position.y < CHAR_STAND_Y) ch.position.y = CHAR_STAND_Y;
  282. grounded = false;
  283. velY = 0;
  284. updateAnimations(dt, move.len > 0 || my !== 0);
  285. return;
  286. }
  287.  
  288. if (noclip) {
  289. climbState = "none";
  290. climbCooldown = Math.max(0, (climbCooldown || 0) - dt);
  291. move = _buildMove();
  292. var noclipMy = 0;
  293. if (keys["KeyC"]) noclipMy -= 1;
  294. _faceMove(ch, move, dt);
  295. spd = BASE_WALK * speedMul;
  296. ch.position.x += move.x * spd * dt;
  297. ch.position.z += move.z * spd * dt;
  298. ch.position.y += noclipMy * BASE_FLY * dt;
  299. if (keys["Space"]) jumpBuffer = JUMP_BUFFER;
  300. jumpBuffer = Math.max(0, (jumpBuffer || 0) - dt);
  301. velY += GRAVITY * dt;
  302. ch.position.y += velY * dt;
  303. grounded = false;
  304. if (ch.position.y <= CHAR_STAND_Y) {
  305. ch.position.y = CHAR_STAND_Y;
  306. velY = 0;
  307. grounded = true;
  308. }
  309. if (grounded) coyoteTimer = COYOTE_TIME;
  310. else coyoteTimer = Math.max(0, (coyoteTimer || 0) - dt);
  311. if (jumpBuffer > 0 && (grounded || coyoteTimer > 0)) {
  312. velY = JUMP_POWER * JUMP_MUL;
  313. grounded = false;
  314. coyoteTimer = 0;
  315. jumpBuffer = 0;
  316. }
  317. updateAnimations(dt, move.len > 0 || noclipMy !== 0);
  318. return;
  319. }
  320.  
  321. if (speedMul <= 1.01) return _orig(dt);
  322.  
  323. // boosted walk with collision
  324. climbState = "none";
  325. climbCooldown = Math.max(0, (climbCooldown || 0) - dt);
  326. var moveInput = new THREE.Vector3();
  327. if (keys["KeyW"] || keys["ArrowUp"]) moveInput.z -= 1;
  328. if (keys["KeyS"] || keys["ArrowDown"]) moveInput.z += 1;
  329. if (keys["KeyA"] || keys["ArrowLeft"]) moveInput.x -= 1;
  330. if (keys["KeyD"] || keys["ArrowRight"]) moveInput.x += 1;
  331. var moving = moveInput.lengthSq() > 0;
  332. if (moving) {
  333. moveInput.normalize();
  334. var yq = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), cam.yaw);
  335. moveInput.applyQuaternion(yq);
  336. _velX = moveInput.x * BASE_WALK * speedMul;
  337. _velZ = moveInput.z * BASE_WALK * speedMul;
  338. if (!shiftLock) {
  339. ch.rotation.y = lerpAngle(ch.rotation.y, Math.atan2(moveInput.x, moveInput.z), Math.min(1, ROT_SPEED * dt));
  340. }
  341. } else {
  342. _velX = 0;
  343. _velZ = 0;
  344. }
  345. _sweepX(dt);
  346. _sweepZ(dt);
  347. if (shiftLock) ch.rotation.y = cam.yaw + Math.PI;
  348. var nearby = getNearbyColliders(ch.position.x, ch.position.y, ch.position.z);
  349. resolveBlocksH(nearby);
  350. try { resolveOBBH(nearby); } catch (_) {}
  351. if ((stepUpTarget || -Infinity) > ch.position.y) {
  352. var rise = Math.min(stepUpTarget - ch.position.y, STEP_CLIMB_SPEED * dt);
  353. ch.position.y += rise;
  354. velY = 0;
  355. grounded = true;
  356. }
  357. if (grounded) coyoteTimer = COYOTE_TIME;
  358. else coyoteTimer = Math.max(0, (coyoteTimer || 0) - dt);
  359. if (keys["Space"]) jumpBuffer = JUMP_BUFFER;
  360. jumpBuffer = Math.max(0, (jumpBuffer || 0) - dt);
  361. velY += GRAVITY * dt;
  362. ch.position.y += velY * dt;
  363. grounded = false;
  364. if (ch.position.y <= CHAR_STAND_Y) {
  365. ch.position.y = CHAR_STAND_Y;
  366. velY = 0;
  367. grounded = true;
  368. }
  369. resolveBlocksV(nearby);
  370. try { resolveOBBV(nearby); } catch (_) {}
  371. if (jumpBuffer > 0 && (grounded || coyoteTimer > 0)) {
  372. velY = JUMP_POWER * JUMP_MUL;
  373. grounded = false;
  374. coyoteTimer = 0;
  375. jumpBuffer = 0;
  376. }
  377. updateAnimations(dt, moving);
  378. };
  379.  
  380. // ── keybinds ──────────────────────────────────────────────────
  381. document.addEventListener("keydown", function (e) {
  382. if (e.code === "Period") {
  383. if (window._chatFocused) return;
  384. bypassActive = !bypassActive;
  385. refreshGui();
  386. return;
  387. }
  388. if (window._chatFocused) return;
  389. if (e.code === "KeyF") {
  390. flying = !flying;
  391. if (flying) { velY = 0; grounded = false; noclip = false; }
  392. refreshGui();
  393. }
  394. if (e.code === "KeyN") {
  395. noclip = !noclip;
  396. if (noclip) { flying = false; velY = 0; }
  397. refreshGui();
  398. }
  399. if (e.code === "Backspace") { speedMul = 1; refreshGui(); }
  400. if (e.code === "BracketRight" || e.code === "BracketLeft") {
  401. var d = e.code === "BracketRight" ? 1 : -1;
  402. speedMul = Math.round((speedMul + d * 0.5) * 2) / 2;
  403. speedMul = Math.max(MIN_SPD, Math.min(MAX_SPD, speedMul));
  404. refreshGui();
  405. }
  406. });
  407.  
  408. console.log("%c\u26a1 FloydHax v3 %cready. F=fly N=noclip .=bypass []=speed C=descend",
  409. "font-size:14px;color:#fd0", "");
  410. })();