Advanced mod menu with infinite ammo, rapid fire, speed hacks, jump boost, and ESP wallhack
Size
43.5 KB
Version
1.2.2
Created
Mar 23, 2026
Updated
23 days ago
1// ==UserScript==
2// @name Veck.io Mod Menu - Ultimate Hack Client
3// @description Advanced mod menu with infinite ammo, rapid fire, speed hacks, jump boost, and ESP wallhack
4// @version 1.2.2
5// @match https://*.veck.io/*
6// @icon https://veck.io/favicon/favicon.ico
7// @grant GM.getValue
8// @grant GM.setValue
9// ==/UserScript==
10(function() {
11 'use strict';
12
13 console.log('[VECK.IO ADVANCED MOD] Initializing...');
14
15 // ============================================
16 // CONFIGURATION
17 // ============================================
18 const CONFIG = {
19 infiniteAmmo: false,
20 rapidFire: false,
21 speedHack: false,
22 jumpBoost: false,
23 esp: false,
24 noRecoil: false,
25 aimbot: false,
26 speedMultiplier: 2.5,
27 jumpMultiplier: 2.0,
28 fireRateMultiplier: 5.0
29 };
30
31 // ============================================
32 // STATE MANAGEMENT
33 // ============================================
34 let gameInstance = null;
35 let unityInstance = null;
36 let webglContext = null;
37 let originalWebSocket = null;
38 let players = new Map();
39 let localPlayer = null;
40 let espCanvas = null;
41 let espContext = null;
42 let viewMatrix = null;
43 let projectionMatrix = null;
44
45 // ============================================
46 // UTILITY FUNCTIONS
47 // ============================================
48 function debounce(func, wait) {
49 let timeout;
50 return function executedFunction(...args) {
51 const later = () => {
52 clearTimeout(timeout);
53 func(...args);
54 };
55 clearTimeout(timeout);
56 timeout = setTimeout(later, wait);
57 };
58 }
59
60 // ============================================
61 // LOAD/SAVE SETTINGS
62 // ============================================
63 async function loadSettings() {
64 try {
65 const saved = await GM.getValue('veckio_advanced_settings', null);
66 if (saved) {
67 Object.assign(CONFIG, JSON.parse(saved));
68 console.log('[MOD] Settings loaded:', CONFIG);
69 }
70 } catch (e) {
71 console.error('[MOD] Error loading settings:', e);
72 }
73 }
74
75 async function saveSettings() {
76 try {
77 await GM.setValue('veckio_advanced_settings', JSON.stringify(CONFIG));
78 } catch (e) {
79 console.error('[MOD] Error saving settings:', e);
80 }
81 }
82
83 // ============================================
84 // WEBGL CONTEXT INTERCEPTION
85 // ============================================
86 function interceptWebGL() {
87 console.log('[WEBGL] Intercepting WebGL context...');
88
89 const canvas = document.querySelector('canvas#unity-canvas');
90 if (!canvas) {
91 console.error('[WEBGL] Canvas not found!');
92 return;
93 }
94
95 // Store original getContext
96 const originalGetContext = HTMLCanvasElement.prototype.getContext;
97
98 HTMLCanvasElement.prototype.getContext = function(type, attributes) {
99 const context = originalGetContext.call(this, type, attributes);
100
101 if ((type === 'webgl' || type === 'webgl2' || type === 'experimental-webgl') && this.id === 'unity-canvas') {
102 console.log('[WEBGL] Game WebGL context captured!');
103 webglContext = context;
104 hookWebGLFunctions(context);
105 }
106
107 return context;
108 };
109
110 // Try to get existing context
111 webglContext = canvas.getContext('webgl') || canvas.getContext('webgl2') || canvas.getContext('experimental-webgl');
112 if (webglContext) {
113 console.log('[WEBGL] Existing context found and hooked');
114 hookWebGLFunctions(webglContext);
115 }
116 }
117
118 // ============================================
119 // HOOK WEBGL FUNCTIONS FOR ESP
120 // ============================================
121 function hookWebGLFunctions(gl) {
122 console.log('[WEBGL] Hooking WebGL functions for ESP...');
123
124 // Hook drawArrays and drawElements to intercept rendering
125 const originalDrawArrays = gl.drawArrays;
126 const originalDrawElements = gl.drawElements;
127
128 gl.drawArrays = function(mode, first, count) {
129 if (CONFIG.esp) {
130 extractRenderData(gl, mode, first, count);
131 }
132 return originalDrawArrays.call(this, mode, first, count);
133 };
134
135 gl.drawElements = function(mode, count, type, offset) {
136 if (CONFIG.esp) {
137 extractRenderData(gl, mode, count, type, offset);
138 }
139 return originalDrawElements.call(this, mode, count, type, offset);
140 };
141
142 // Hook uniform setters to capture matrices
143 const originalUniformMatrix4fv = gl.uniformMatrix4fv;
144 gl.uniformMatrix4fv = function(location, transpose, value) {
145 if (value && value.length === 16) {
146 // Try to identify view and projection matrices
147 const matrixArray = Array.from(value);
148
149 // Store potential camera matrices
150 if (!viewMatrix || Math.abs(matrixArray[12]) > 0.01) {
151 viewMatrix = matrixArray;
152 }
153 if (!projectionMatrix || Math.abs(matrixArray[0]) < 10) {
154 projectionMatrix = matrixArray;
155 }
156 }
157 return originalUniformMatrix4fv.call(this, location, transpose, value);
158 };
159
160 console.log('[WEBGL] WebGL functions hooked successfully');
161 }
162
163 // ============================================
164 // EXTRACT RENDER DATA FOR ESP
165 // ============================================
166 function extractRenderData() {
167 // This would extract vertex data from buffers
168 // For now, we'll use a different approach with WebSocket data
169 }
170
171 // ============================================
172 // WEBSOCKET INTERCEPTION (ADVANCED)
173 // ============================================
174 function interceptWebSocket() {
175 console.log('[WEBSOCKET] Setting up advanced interception...');
176
177 originalWebSocket = window.WebSocket;
178
179 window.WebSocket = function(url, protocols) {
180 console.log('[WEBSOCKET] New connection intercepted:', url);
181
182 const ws = new originalWebSocket(url, protocols);
183
184 // Hook send method
185 const originalSend = ws.send.bind(ws);
186 ws.send = function(data) {
187 const modified = processOutgoingPacket(data);
188 return originalSend(modified);
189 };
190
191 // Hook message event with proper interception
192 const originalAddEventListener = ws.addEventListener.bind(ws);
193 ws.addEventListener = function(type, listener, ...args) {
194 if (type === 'message') {
195 const wrappedListener = function(event) {
196 processIncomingPacket(event);
197 return listener.call(this, event);
198 };
199 return originalAddEventListener(type, wrappedListener, ...args);
200 }
201 return originalAddEventListener(type, listener, ...args);
202 };
203
204 // Also hook onmessage property
205 Object.defineProperty(ws, 'onmessage', {
206 set: function(handler) {
207 this._onmessage = function(event) {
208 processIncomingPacket(event);
209 if (handler) handler.call(this, event);
210 };
211 },
212 get: function() {
213 return this._onmessage;
214 }
215 });
216
217 return ws;
218 };
219
220 console.log('[WEBSOCKET] Interception active');
221 }
222
223 // ============================================
224 // PROCESS OUTGOING PACKETS
225 // ============================================
226 function processOutgoingPacket(data) {
227 try {
228 // Handle binary data (most modern games use binary protocols)
229 if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
230 return modifyBinaryPacket(data);
231 }
232
233 // Handle string/JSON data
234 if (typeof data === 'string') {
235 return modifyTextPacket(data);
236 }
237
238 return data;
239 } catch (e) {
240 console.error('[PACKET] Error processing outgoing:', e);
241 return data;
242 }
243 }
244
245 // ============================================
246 // MODIFY BINARY PACKETS (ADVANCED)
247 // ============================================
248 function modifyBinaryPacket(data) {
249 const buffer = data instanceof ArrayBuffer ? data : data.buffer;
250 const view = new DataView(buffer);
251 const uint8View = new Uint8Array(buffer);
252
253 // Log packet for analysis
254 if (Math.random() < 0.01) { // Log 1% of packets
255 console.log('[PACKET] Binary packet:', {
256 length: buffer.byteLength,
257 first16Bytes: Array.from(uint8View.slice(0, 16))
258 });
259 }
260
261 // Apply hacks to binary data
262 if (CONFIG.speedHack || CONFIG.jumpBoost) {
263 // Scan for float values that might be movement data
264 for (let i = 0; i < view.byteLength - 4; i++) {
265 // Try little-endian
266 let value = view.getFloat32(i, true);
267
268 // Movement values are typically in range [-10, 10]
269 if (Math.abs(value) > 0.1 && Math.abs(value) < 10) {
270 if (CONFIG.speedHack && Math.abs(value) > 0.5) {
271 view.setFloat32(i, value * CONFIG.speedMultiplier, true);
272 }
273 if (CONFIG.jumpBoost && value > 1 && value < 8) {
274 view.setFloat32(i, value * CONFIG.jumpMultiplier, true);
275 }
276 }
277 }
278 }
279
280 return data;
281 }
282
283 // ============================================
284 // MODIFY TEXT PACKETS
285 // ============================================
286 function modifyTextPacket(data) {
287 try {
288 const packet = JSON.parse(data);
289
290 // Movement modifications
291 if (packet.type === 'move' || packet.type === 'input' || packet.type === 'player_input') {
292 if (CONFIG.speedHack && packet.velocity) {
293 if (packet.velocity.x) packet.velocity.x *= CONFIG.speedMultiplier;
294 if (packet.velocity.z) packet.velocity.z *= CONFIG.speedMultiplier;
295 }
296 if (CONFIG.jumpBoost && packet.velocity && packet.velocity.y > 0) {
297 packet.velocity.y *= CONFIG.jumpMultiplier;
298 }
299 }
300
301 // Weapon modifications
302 if (packet.type === 'fire' || packet.type === 'shoot' || packet.type === 'weapon_fire') {
303 if (CONFIG.infiniteAmmo) {
304 packet.ammo = 999;
305 packet.magazine = 999;
306 }
307 if (CONFIG.rapidFire) {
308 packet.fireRate = (packet.fireRate || 100) * CONFIG.fireRateMultiplier;
309 packet.delay = (packet.delay || 100) / CONFIG.fireRateMultiplier;
310 }
311 if (CONFIG.noRecoil) {
312 packet.recoil = 0;
313 packet.spread = 0;
314 }
315 }
316
317 return JSON.stringify(packet);
318 } catch {
319 // Not JSON, return as-is
320 return data;
321 }
322 }
323
324 // ============================================
325 // PROCESS INCOMING PACKETS
326 // ============================================
327 function processIncomingPacket(event) {
328 try {
329 const data = event.data;
330
331 // Handle binary data
332 if (data instanceof ArrayBuffer || data instanceof Blob) {
333 parseBinaryGameState(data);
334 return;
335 }
336
337 // Handle text data
338 if (typeof data === 'string') {
339 parseTextGameState(data);
340 }
341 } catch (e) {
342 console.error('[PACKET] Error processing incoming:', e);
343 }
344 }
345
346 // ============================================
347 // PARSE BINARY GAME STATE
348 // ============================================
349 async function parseBinaryGameState(data) {
350 try {
351 let buffer = data;
352 if (data instanceof Blob) {
353 buffer = await data.arrayBuffer();
354 }
355
356 const view = new DataView(buffer);
357
358 // Try to extract player positions
359 // This is game-specific and requires reverse engineering
360 // Look for patterns: player data often comes in groups
361
362 // Example: scan for coordinate triplets (x, y, z)
363 for (let i = 0; i < view.byteLength - 12; i += 4) {
364 const x = view.getFloat32(i, true);
365 const y = view.getFloat32(i + 4, true);
366 const z = view.getFloat32(i + 8, true);
367
368 // Valid game coordinates are usually in reasonable ranges
369 if (Math.abs(x) < 1000 && Math.abs(y) < 1000 && Math.abs(z) < 1000) {
370 // Potential player position found
371 updatePlayerPosition(i, x, y, z);
372 }
373 }
374 } catch (e) {
375 console.error('[BINARY] Error parsing:', e);
376 }
377 }
378
379 // ============================================
380 // PARSE TEXT GAME STATE
381 // ============================================
382 function parseTextGameState(data) {
383 try {
384 const packet = JSON.parse(data);
385
386 // Extract player data
387 if (packet.type === 'players' || packet.type === 'game_state' || packet.type === 'update') {
388 if (packet.players && Array.isArray(packet.players)) {
389 packet.players.forEach(player => {
390 updatePlayer(player);
391 });
392 }
393 }
394
395 // Track local player
396 if (packet.type === 'init' || packet.type === 'spawn' || packet.type === 'player_init') {
397 localPlayer = {
398 id: packet.id || packet.playerId || packet.player_id,
399 position: packet.position || { x: packet.x, y: packet.y, z: packet.z }
400 };
401 console.log('[PLAYER] Local player initialized:', localPlayer);
402 }
403
404 // Update player positions
405 if (packet.type === 'position' || packet.type === 'player_position') {
406 updatePlayer({
407 id: packet.id || packet.playerId,
408 x: packet.x,
409 y: packet.y,
410 z: packet.z,
411 name: packet.name,
412 health: packet.health
413 });
414 }
415
416 } catch {
417 // Not JSON or parsing error
418 }
419 }
420
421 // ============================================
422 // UPDATE PLAYER DATA
423 // ============================================
424 function updatePlayer(playerData) {
425 if (!playerData || !playerData.id) return;
426
427 const player = {
428 id: playerData.id,
429 x: playerData.x || playerData.position?.x || 0,
430 y: playerData.y || playerData.position?.y || 0,
431 z: playerData.z || playerData.position?.z || 0,
432 name: playerData.name || `Player ${playerData.id}`,
433 health: playerData.health || 100,
434 isEnemy: playerData.id !== localPlayer?.id,
435 lastUpdate: Date.now()
436 };
437
438 players.set(playerData.id, player);
439
440 // Clean up old players (not updated in 5 seconds)
441 const now = Date.now();
442 for (let [id, p] of players.entries()) {
443 if (now - p.lastUpdate > 5000) {
444 players.delete(id);
445 }
446 }
447 }
448
449 function updatePlayerPosition(offset, x, y, z) {
450 // Create a pseudo-ID based on position offset
451 const id = `player_${offset}`;
452
453 const player = players.get(id) || {};
454 player.id = id;
455 player.x = x;
456 player.y = y;
457 player.z = z;
458 player.lastUpdate = Date.now();
459
460 players.set(id, player);
461 }
462
463 // ============================================
464 // 3D TO 2D PROJECTION
465 // ============================================
466 function worldToScreen(worldPos, canvas) {
467 if (!viewMatrix || !projectionMatrix) {
468 return null;
469 }
470
471 try {
472 // Apply view matrix
473 const viewPos = multiplyMatrixVector(viewMatrix, [worldPos.x, worldPos.y, worldPos.z, 1]);
474
475 // Apply projection matrix
476 const clipPos = multiplyMatrixVector(projectionMatrix, viewPos);
477
478 // Perspective divide
479 if (clipPos[3] === 0) return null;
480
481 const ndcX = clipPos[0] / clipPos[3];
482 const ndcY = clipPos[1] / clipPos[3];
483 const ndcZ = clipPos[2] / clipPos[3];
484
485 // Check if behind camera
486 if (ndcZ < -1 || ndcZ > 1) return null;
487
488 // Convert to screen coordinates
489 const screenX = (ndcX + 1) * 0.5 * canvas.width;
490 const screenY = (1 - ndcY) * 0.5 * canvas.height;
491
492 return { x: screenX, y: screenY, visible: true };
493 } catch {
494 return null;
495 }
496 }
497
498 function multiplyMatrixVector(matrix, vector) {
499 const result = [0, 0, 0, 0];
500 for (let i = 0; i < 4; i++) {
501 for (let j = 0; j < 4; j++) {
502 result[i] += matrix[i * 4 + j] * vector[j];
503 }
504 }
505 return result;
506 }
507
508 // ============================================
509 // ESP CANVAS
510 // ============================================
511 function createESPCanvas() {
512 if (espCanvas) return;
513
514 espCanvas = document.createElement('canvas');
515 espCanvas.id = 'esp-overlay';
516 espCanvas.style.cssText = `
517 position: fixed;
518 top: 0;
519 left: 0;
520 width: 100%;
521 height: 100%;
522 pointer-events: none;
523 z-index: 999998;
524 `;
525 espCanvas.width = window.innerWidth;
526 espCanvas.height = window.innerHeight;
527 document.body.appendChild(espCanvas);
528
529 espContext = espCanvas.getContext('2d');
530
531 window.addEventListener('resize', () => {
532 if (espCanvas) {
533 espCanvas.width = window.innerWidth;
534 espCanvas.height = window.innerHeight;
535 }
536 });
537
538 renderESP();
539 console.log('[ESP] Canvas created and rendering started');
540 }
541
542 function removeESPCanvas() {
543 if (espCanvas) {
544 espCanvas.remove();
545 espCanvas = null;
546 espContext = null;
547 }
548 }
549
550 // ============================================
551 // RENDER ESP
552 // ============================================
553 function renderESP() {
554 if (!CONFIG.esp || !espCanvas || !espContext) return;
555
556 espContext.clearRect(0, 0, espCanvas.width, espCanvas.height);
557
558 const gameCanvas = document.querySelector('canvas#unity-canvas');
559 if (!gameCanvas) {
560 requestAnimationFrame(renderESP);
561 return;
562 }
563
564 // Draw ESP for each player
565 players.forEach((player) => {
566 if (player.id === localPlayer?.id) return; // Don't draw local player
567
568 // Try 3D to 2D projection if we have matrices
569 let screenPos = worldToScreen(player, gameCanvas);
570
571 // Fallback: use simple position mapping
572 if (!screenPos) {
573 screenPos = {
574 x: (player.x + 100) * 4,
575 y: (player.z + 100) * 4,
576 visible: true
577 };
578 }
579
580 if (screenPos && screenPos.visible) {
581 drawESPBox(screenPos.x, screenPos.y, player);
582 }
583 });
584
585 // Draw player count
586 espContext.fillStyle = '#00ff88';
587 espContext.font = 'bold 14px Arial';
588 espContext.fillText(`Players: ${players.size}`, 10, 30);
589
590 requestAnimationFrame(renderESP);
591 }
592
593 function drawESPBox(x, y, player) {
594 const width = 40;
595 const height = 60;
596
597 // Draw box
598 espContext.strokeStyle = player.isEnemy ? '#ff0000' : '#00ff00';
599 espContext.lineWidth = 2;
600 espContext.strokeRect(x - width/2, y - height/2, width, height);
601
602 // Draw health bar
603 if (player.health !== undefined) {
604 const healthPercent = player.health / 100;
605 const barWidth = width;
606 const barHeight = 4;
607
608 espContext.fillStyle = '#000000';
609 espContext.fillRect(x - barWidth/2, y - height/2 - 10, barWidth, barHeight);
610
611 espContext.fillStyle = healthPercent > 0.5 ? '#00ff00' : (healthPercent > 0.25 ? '#ffff00' : '#ff0000');
612 espContext.fillRect(x - barWidth/2, y - height/2 - 10, barWidth * healthPercent, barHeight);
613 }
614
615 // Draw name
616 if (player.name) {
617 espContext.fillStyle = '#ffffff';
618 espContext.font = '12px Arial';
619 espContext.textAlign = 'center';
620 espContext.fillText(player.name, x, y - height/2 - 15);
621 }
622
623 // Draw distance if we have local player position
624 if (localPlayer && localPlayer.position) {
625 const dx = player.x - localPlayer.position.x;
626 const dz = player.z - localPlayer.position.z;
627 const distance = Math.sqrt(dx * dx + dz * dz);
628
629 espContext.fillStyle = '#ffff00';
630 espContext.font = '10px Arial';
631 espContext.fillText(Math.round(distance) + 'm', x, y + height/2 + 15);
632 }
633 }
634
635 // ============================================
636 // MEMORY PATCHING
637 // ============================================
638 function patchGameMemory() {
639 console.log('[MEMORY] Patching game functions...');
640
641 // Patch timers for rapid fire
642 const originalSetInterval = window.setInterval;
643 const originalSetTimeout = window.setTimeout;
644
645 window.setInterval = function(callback, delay, ...args) {
646 if (CONFIG.rapidFire && delay > 10 && delay < 2000) {
647 delay = Math.max(10, delay / CONFIG.fireRateMultiplier);
648 }
649 return originalSetInterval.call(this, callback, delay, ...args);
650 };
651
652 window.setTimeout = function(callback, delay, ...args) {
653 if (CONFIG.rapidFire && delay > 10 && delay < 2000) {
654 delay = Math.max(10, delay / CONFIG.fireRateMultiplier);
655 }
656 return originalSetTimeout.call(this, callback, delay, ...args);
657 };
658
659 // Patch requestAnimationFrame for speed hacks
660 const originalRAF = window.requestAnimationFrame;
661 window.requestAnimationFrame = function(callback) {
662 return originalRAF.call(this, function(timestamp) {
663 if (CONFIG.speedHack) {
664 // Speed up game time
665 timestamp *= CONFIG.speedMultiplier;
666 }
667 return callback(timestamp);
668 });
669 };
670
671 console.log('[MEMORY] Game functions patched');
672 }
673
674 // ============================================
675 // SCAN FOR GAME OBJECTS
676 // ============================================
677 function scanForGameObjects() {
678 console.log('[SCAN] Scanning for game objects...');
679
680 const checkInterval = setInterval(() => {
681 // Look for Unity instance
682 if (typeof unityInstance !== 'undefined' && !gameInstance) {
683 gameInstance = unityInstance;
684 console.log('[SCAN] Unity instance found!');
685 hookUnityInstance(gameInstance);
686 }
687
688 // Look for game objects in window
689 const keys = Object.keys(window);
690 for (let key of keys) {
691 const obj = window[key];
692 if (obj && typeof obj === 'object') {
693 // Look for player objects
694 if (obj.player || obj.players || obj.localPlayer) {
695 console.log('[SCAN] Found game object:', key);
696 hookGameObject(obj);
697 }
698
699 // Look for weapon objects
700 if (obj.weapon || obj.weapons || obj.currentWeapon) {
701 console.log('[SCAN] Found weapon object:', key);
702 hookWeaponObject(obj);
703 }
704 }
705 }
706 }, 2000);
707
708 // Stop after 30 seconds
709 setTimeout(() => clearInterval(checkInterval), 30000);
710 }
711
712 function hookUnityInstance(instance) {
713 console.log('[UNITY] Hooking Unity instance...');
714
715 try {
716 // Try to access Unity's SendMessage function
717 if (instance.SendMessage) {
718 const originalSendMessage = instance.SendMessage;
719 instance.SendMessage = function(gameObject, method, value) {
720 console.log('[UNITY] SendMessage:', gameObject, method, value);
721
722 // Modify messages for hacks
723 if (CONFIG.infiniteAmmo && method.toLowerCase().includes('ammo')) {
724 value = 999;
725 }
726
727 return originalSendMessage.call(this, gameObject, method, value);
728 };
729 }
730 } catch (e) {
731 console.error('[UNITY] Error hooking:', e);
732 }
733 }
734
735 function hookGameObject(obj) {
736 try {
737 if (obj.player) {
738 const player = obj.player;
739
740 // Hook speed
741 if (player.speed !== undefined) {
742 Object.defineProperty(player, 'speed', {
743 get: function() {
744 return this._speed * (CONFIG.speedHack ? CONFIG.speedMultiplier : 1);
745 },
746 set: function(value) {
747 this._speed = value;
748 }
749 });
750 }
751
752 // Hook jump force
753 if (player.jumpForce !== undefined) {
754 Object.defineProperty(player, 'jumpForce', {
755 get: function() {
756 return this._jumpForce * (CONFIG.jumpBoost ? CONFIG.jumpMultiplier : 1);
757 },
758 set: function(value) {
759 this._jumpForce = value;
760 }
761 });
762 }
763 }
764 } catch (e) {
765 console.error('[HOOK] Error hooking game object:', e);
766 }
767 }
768
769 function hookWeaponObject(obj) {
770 try {
771 const weapon = obj.weapon || obj.currentWeapon;
772 if (!weapon) return;
773
774 // Hook ammo
775 if (weapon.ammo !== undefined) {
776 Object.defineProperty(weapon, 'ammo', {
777 get: function() {
778 return CONFIG.infiniteAmmo ? 999 : this._ammo;
779 },
780 set: function(value) {
781 this._ammo = CONFIG.infiniteAmmo ? 999 : value;
782 }
783 });
784 }
785
786 // Hook fire rate
787 if (weapon.fireRate !== undefined) {
788 Object.defineProperty(weapon, 'fireRate', {
789 get: function() {
790 return this._fireRate * (CONFIG.rapidFire ? CONFIG.fireRateMultiplier : 1);
791 },
792 set: function(value) {
793 this._fireRate = value;
794 }
795 });
796 }
797
798 // Hook recoil
799 if (weapon.recoil !== undefined) {
800 Object.defineProperty(weapon, 'recoil', {
801 get: function() {
802 return CONFIG.noRecoil ? 0 : this._recoil;
803 },
804 set: function(value) {
805 this._recoil = value;
806 }
807 });
808 }
809 } catch (e) {
810 console.error('[HOOK] Error hooking weapon:', e);
811 }
812 }
813
814 // ============================================
815 // GUI CREATION
816 // ============================================
817 function createModMenu() {
818 const existing = document.getElementById('veckio-advanced-mod');
819 if (existing) existing.remove();
820
821 const menu = document.createElement('div');
822 menu.id = 'veckio-advanced-mod';
823 menu.innerHTML = `
824 <div class="mod-header">
825 <span class="mod-title">⚡ VECK.IO ADVANCED MOD</span>
826 <div class="mod-controls">
827 <button class="mod-minimize" id="mod-minimize">_</button>
828 <button class="mod-close" id="mod-close">×</button>
829 </div>
830 </div>
831 <div class="mod-body" id="mod-body">
832 <div class="mod-section">
833 <h3>⚔️ WEAPON HACKS</h3>
834 <label><input type="checkbox" id="infinite-ammo" ${CONFIG.infiniteAmmo ? 'checked' : ''}> Infinite Ammo</label>
835 <label><input type="checkbox" id="rapid-fire" ${CONFIG.rapidFire ? 'checked' : ''}> Rapid Fire</label>
836 <label><input type="checkbox" id="no-recoil" ${CONFIG.noRecoil ? 'checked' : ''}> No Recoil</label>
837 </div>
838
839 <div class="mod-section">
840 <h3>🏃 MOVEMENT HACKS</h3>
841 <label><input type="checkbox" id="speed-hack" ${CONFIG.speedHack ? 'checked' : ''}> Speed Hack</label>
842 <label><input type="checkbox" id="jump-boost" ${CONFIG.jumpBoost ? 'checked' : ''}> Jump Boost</label>
843 </div>
844
845 <div class="mod-section">
846 <h3>👁️ VISUAL HACKS</h3>
847 <label><input type="checkbox" id="esp-hack" ${CONFIG.esp ? 'checked' : ''}> ESP Wallhack</label>
848 </div>
849
850 <div class="mod-section">
851 <h3>⚙️ SETTINGS</h3>
852 <div class="mod-slider-group">
853 <label>Speed: <span id="speed-val">${CONFIG.speedMultiplier}x</span></label>
854 <input type="range" id="speed-slider" min="1" max="10" step="0.5" value="${CONFIG.speedMultiplier}">
855 </div>
856 <div class="mod-slider-group">
857 <label>Jump: <span id="jump-val">${CONFIG.jumpMultiplier}x</span></label>
858 <input type="range" id="jump-slider" min="1" max="5" step="0.5" value="${CONFIG.jumpMultiplier}">
859 </div>
860 <div class="mod-slider-group">
861 <label>Fire Rate: <span id="fire-val">${CONFIG.fireRateMultiplier}x</span></label>
862 <input type="range" id="fire-slider" min="1" max="10" step="0.5" value="${CONFIG.fireRateMultiplier}">
863 </div>
864 </div>
865
866 <div class="mod-footer">
867 <div class="mod-status">🟢 Active | Players: <span id="player-count">0</span></div>
868 <div class="mod-hint">Press ~ or INSERT to toggle</div>
869 </div>
870 </div>
871 `;
872
873 const style = document.createElement('style');
874 style.textContent = `
875 #veckio-advanced-mod {
876 position: fixed;
877 top: 20px;
878 right: 20px;
879 width: 300px;
880 background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
881 border: 2px solid #00ff88;
882 border-radius: 10px;
883 box-shadow: 0 10px 40px rgba(0, 255, 136, 0.4);
884 font-family: 'Consolas', 'Monaco', monospace;
885 color: #fff;
886 z-index: 999999;
887 user-select: none;
888 }
889
890 .mod-header {
891 background: linear-gradient(90deg, #00ff88 0%, #00cc6a 100%);
892 padding: 10px 15px;
893 border-radius: 8px 8px 0 0;
894 display: flex;
895 justify-content: space-between;
896 align-items: center;
897 cursor: move;
898 }
899
900 .mod-controls {
901 display: flex;
902 gap: 5px;
903 }
904
905 .mod-title {
906 font-weight: bold;
907 font-size: 13px;
908 color: #000;
909 letter-spacing: 1px;
910 }
911
912 .mod-minimize {
913 background: rgba(0,0,0,0.3);
914 border: none;
915 color: #000;
916 width: 22px;
917 height: 22px;
918 border-radius: 3px;
919 cursor: pointer;
920 font-weight: bold;
921 }
922
923 .mod-minimize:hover {
924 background: rgba(0,0,0,0.5);
925 }
926
927 .mod-close {
928 background: rgba(0,0,0,0.3);
929 border: none;
930 color: #000;
931 width: 22px;
932 height: 22px;
933 border-radius: 3px;
934 cursor: pointer;
935 font-weight: bold;
936 font-size: 18px;
937 line-height: 18px;
938 }
939
940 .mod-close:hover {
941 background: rgba(255,0,0,0.5);
942 }
943
944 .mod-body {
945 padding: 15px;
946 max-height: 500px;
947 overflow-y: auto;
948 }
949
950 .mod-body.hidden {
951 display: none;
952 }
953
954 .mod-section {
955 margin-bottom: 15px;
956 padding-bottom: 15px;
957 border-bottom: 1px solid rgba(0, 255, 136, 0.2);
958 }
959
960 .mod-section:last-of-type {
961 border-bottom: none;
962 }
963
964 .mod-section h3 {
965 margin: 0 0 10px 0;
966 font-size: 12px;
967 color: #00ff88;
968 text-transform: uppercase;
969 }
970
971 .mod-section label {
972 display: block;
973 padding: 6px 8px;
974 margin: 4px 0;
975 background: rgba(0, 255, 136, 0.05);
976 border-radius: 4px;
977 cursor: pointer;
978 font-size: 12px;
979 transition: all 0.2s;
980 }
981
982 .mod-section label:hover {
983 background: rgba(0, 255, 136, 0.15);
984 }
985
986 .mod-section input[type="checkbox"] {
987 margin-right: 8px;
988 accent-color: #00ff88;
989 }
990
991 .mod-slider-group {
992 margin: 10px 0;
993 padding: 8px;
994 background: rgba(0, 255, 136, 0.05);
995 border-radius: 4px;
996 }
997
998 .mod-slider-group label {
999 display: block;
1000 font-size: 11px;
1001 color: #00ff88;
1002 margin-bottom: 6px;
1003 padding: 0;
1004 background: none;
1005 }
1006
1007 .mod-slider-group input[type="range"] {
1008 width: 100%;
1009 height: 4px;
1010 background: rgba(255,255,255,0.1);
1011 border-radius: 2px;
1012 outline: none;
1013 cursor: pointer;
1014 }
1015
1016 .mod-slider-group input[type="range"]::-webkit-slider-thumb {
1017 appearance: none;
1018 width: 14px;
1019 height: 14px;
1020 background: #00ff88;
1021 border-radius: 50%;
1022 cursor: pointer;
1023 }
1024
1025 .mod-footer {
1026 margin-top: 15px;
1027 padding-top: 15px;
1028 border-top: 1px solid rgba(0, 255, 136, 0.2);
1029 }
1030
1031 .mod-status {
1032 font-size: 11px;
1033 color: #00ff88;
1034 margin-bottom: 6px;
1035 }
1036
1037 .mod-hint {
1038 font-size: 10px;
1039 color: #666;
1040 text-align: center;
1041 }
1042
1043 .mod-body::-webkit-scrollbar {
1044 width: 5px;
1045 }
1046
1047 .mod-body::-webkit-scrollbar-track {
1048 background: rgba(0,0,0,0.2);
1049 }
1050
1051 .mod-body::-webkit-scrollbar-thumb {
1052 background: #00ff88;
1053 border-radius: 3px;
1054 }
1055 `;
1056
1057 document.head.appendChild(style);
1058 document.body.appendChild(menu);
1059
1060 makeDraggable(menu);
1061 setupEventListeners();
1062
1063 console.log('[GUI] Mod menu created');
1064 }
1065
1066 function makeDraggable(element) {
1067 const header = element.querySelector('.mod-header');
1068 let isDragging = false;
1069 let offsetX, offsetY;
1070
1071 header.addEventListener('mousedown', (e) => {
1072 if (e.target.classList.contains('mod-minimize') || e.target.classList.contains('mod-close')) return;
1073 isDragging = true;
1074 offsetX = e.clientX - element.offsetLeft;
1075 offsetY = e.clientY - element.offsetTop;
1076 });
1077
1078 document.addEventListener('mousemove', (e) => {
1079 if (isDragging) {
1080 element.style.left = (e.clientX - offsetX) + 'px';
1081 element.style.top = (e.clientY - offsetY) + 'px';
1082 element.style.right = 'auto';
1083 }
1084 });
1085
1086 document.addEventListener('mouseup', () => {
1087 isDragging = false;
1088 });
1089 }
1090
1091 function setupEventListeners() {
1092 // Minimize button
1093 document.getElementById('mod-minimize').addEventListener('click', () => {
1094 document.getElementById('mod-body').classList.toggle('hidden');
1095 });
1096
1097 // Close button
1098 document.getElementById('mod-close').addEventListener('click', () => {
1099 const menu = document.getElementById('veckio-advanced-mod');
1100 if (menu) {
1101 menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
1102 }
1103 });
1104
1105 // Checkboxes
1106 document.getElementById('infinite-ammo').addEventListener('change', (e) => {
1107 CONFIG.infiniteAmmo = e.target.checked;
1108 saveSettings();
1109 console.log('[MOD] Infinite Ammo:', CONFIG.infiniteAmmo);
1110 });
1111
1112 document.getElementById('rapid-fire').addEventListener('change', (e) => {
1113 CONFIG.rapidFire = e.target.checked;
1114 saveSettings();
1115 console.log('[MOD] Rapid Fire:', CONFIG.rapidFire);
1116 });
1117
1118 document.getElementById('no-recoil').addEventListener('change', (e) => {
1119 CONFIG.noRecoil = e.target.checked;
1120 saveSettings();
1121 console.log('[MOD] No Recoil:', CONFIG.noRecoil);
1122 });
1123
1124 document.getElementById('speed-hack').addEventListener('change', (e) => {
1125 CONFIG.speedHack = e.target.checked;
1126 saveSettings();
1127 console.log('[MOD] Speed Hack:', CONFIG.speedHack);
1128 });
1129
1130 document.getElementById('jump-boost').addEventListener('change', (e) => {
1131 CONFIG.jumpBoost = e.target.checked;
1132 saveSettings();
1133 console.log('[MOD] Jump Boost:', CONFIG.jumpBoost);
1134 });
1135
1136 document.getElementById('esp-hack').addEventListener('change', (e) => {
1137 CONFIG.esp = e.target.checked;
1138 saveSettings();
1139 if (CONFIG.esp) {
1140 createESPCanvas();
1141 } else {
1142 removeESPCanvas();
1143 }
1144 console.log('[MOD] ESP:', CONFIG.esp);
1145 });
1146
1147 // Sliders
1148 document.getElementById('speed-slider').addEventListener('input', (e) => {
1149 CONFIG.speedMultiplier = parseFloat(e.target.value);
1150 document.getElementById('speed-val').textContent = CONFIG.speedMultiplier + 'x';
1151 saveSettings();
1152 });
1153
1154 document.getElementById('jump-slider').addEventListener('input', (e) => {
1155 CONFIG.jumpMultiplier = parseFloat(e.target.value);
1156 document.getElementById('jump-val').textContent = CONFIG.jumpMultiplier + 'x';
1157 saveSettings();
1158 });
1159
1160 document.getElementById('fire-slider').addEventListener('input', (e) => {
1161 CONFIG.fireRateMultiplier = parseFloat(e.target.value);
1162 document.getElementById('fire-val').textContent = CONFIG.fireRateMultiplier + 'x';
1163 saveSettings();
1164 });
1165
1166 // Keyboard shortcut
1167 document.addEventListener('keydown', (e) => {
1168 if (e.key === 'Insert') {
1169 e.preventDefault();
1170 document.getElementById('mod-body').classList.toggle('hidden');
1171 }
1172 // Alternative: Use ~ key (tilde/backtick)
1173 if (e.key === '~' || e.key === '`') {
1174 e.preventDefault();
1175 const menu = document.getElementById('veckio-advanced-mod');
1176 if (menu) {
1177 menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
1178 }
1179 }
1180 });
1181
1182 // Update player count
1183 setInterval(() => {
1184 const countEl = document.getElementById('player-count');
1185 if (countEl) {
1186 countEl.textContent = players.size;
1187 }
1188 }, 1000);
1189 }
1190
1191 // ============================================
1192 // INITIALIZATION
1193 // ============================================
1194 async function init() {
1195 console.log('[MOD] Initializing advanced mod menu...');
1196
1197 await loadSettings();
1198
1199 if (document.readyState === 'loading') {
1200 document.addEventListener('DOMContentLoaded', initAfterLoad);
1201 } else {
1202 initAfterLoad();
1203 }
1204 }
1205
1206 function initAfterLoad() {
1207 console.log('[MOD] Page loaded, starting initialization...');
1208
1209 // Create GUI
1210 createModMenu();
1211
1212 // Intercept WebGL
1213 interceptWebGL();
1214
1215 // Intercept WebSocket
1216 interceptWebSocket();
1217
1218 // Patch memory
1219 patchGameMemory();
1220
1221 // Scan for game objects
1222 scanForGameObjects();
1223
1224 // Create ESP if enabled
1225 if (CONFIG.esp) {
1226 setTimeout(createESPCanvas, 2000);
1227 }
1228
1229 console.log('[MOD] ✅ Advanced mod menu fully initialized!');
1230 console.log('[MOD] Press INSERT to toggle menu');
1231 }
1232
1233 // Start initialization
1234 init();
1235
1236})();