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