Veck.io Mod Menu - Ultimate Hack Client

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})();
Veck.io Mod Menu - Ultimate Hack Client | Robomonkey