From 33cbef2eb416e4809301bc6a0f1c10b1994f2b6f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Jan 2026 09:42:47 +0000 Subject: [PATCH] Fix mod menu issues: vehicle spawn, god mode, skins, and phone - Fix vehicle spawning to use Vec3 for position parameter - Warp player into spawned vehicle automatically - Fix skin change to use player index 0 for changePlayerModel - Fix suicide using explodeCharHead native - Fix god mode using setCharInvincible native properly - Fix vehicle god mode using setCarCanBeDamaged native - Rename "Indestructible" to "God Mode" in vehicle options - Fix nitro boost using vehicle velocity instead of force - Add ExecuteTeleportToPlayer handler for network teleport - Disable phone when menu is open using setPlayerControlForTextChat - Block UP arrow from triggering phone while menu is open --- resources/modmenu/client.js | 105 +++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 19 deletions(-) diff --git a/resources/modmenu/client.js b/resources/modmenu/client.js index 0e90178..ab3be63 100644 --- a/resources/modmenu/client.js +++ b/resources/modmenu/client.js @@ -190,7 +190,7 @@ const menuData = { { label: "Repair Vehicle", action: "veh_repair" }, { label: "Flip Vehicle", action: "veh_flip" }, { label: "Vehicle Colors", action: "submenu", target: "veh_colors" }, - { label: "Indestructible", action: "toggle", target: "vehGodMode", state: false }, + { label: "God Mode", action: "toggle", target: "vehGodMode", state: false }, { label: "Nitro Boost", action: "veh_nitro" } ] }, @@ -317,24 +317,36 @@ addEventHandler("OnKeyUp", function(event, key, scanCode, mods) { menuStack = []; // Show cursor and DISABLE controls (second param = false disables controls) gui.showCursor(true, false); + // Disable phone + natives.setPlayerControlForTextChat(0, false); } else { // Hide cursor and ENABLE controls (second param = true enables controls) gui.showCursor(false, true); + // Re-enable phone + natives.setPlayerControlForTextChat(0, true); } return; } if (!menuOpen) return; - // Navigation + // Block phone popup - consume UP key event when menu is open if (key === SDLK_UP) { navigateUp(); + event.preventDefault = true; + return; } else if (key === SDLK_DOWN) { navigateDown(); + event.preventDefault = true; + return; } else if (key === SDLK_RETURN || key === SDLK_KP_ENTER) { selectItem(); + event.preventDefault = true; + return; } else if (key === SDLK_BACKSPACE || key === SDLK_ESCAPE) { goBack(); + event.preventDefault = true; + return; } }); @@ -657,12 +669,14 @@ addNetworkHandler("ModMenu:ExecuteSelfOption", function(option) { showNotification("All weapons given!"); break; case "wanted": - natives.alterWantedLevel(localPlayer, 0); - natives.applyWantedLevelChangeNow(localPlayer); + natives.alterWantedLevel(0, 0); + natives.applyWantedLevelChangeNow(0); showNotification("Wanted cleared!"); break; case "suicide": - localPlayer.health = 0; + // Kill the player properly using explode head native + natives.explodeCharHead(localPlayer); + showNotification("Goodbye!"); break; } } catch(e) { @@ -684,6 +698,29 @@ addNetworkHandler("ModMenu:ExecuteTeleport", function(x, y, z) { } }); +// Execute teleport to player - get target player position and teleport +addNetworkHandler("ModMenu:ExecuteTeleportToPlayer", function(targetId) { + if (!localPlayer) return; + + try { + // Find the target player in the player list + let clients = getClients(); + for (let i = 0; i < clients.length; i++) { + if (clients[i].index == targetId && clients[i].player) { + let targetPos = clients[i].player.position; + let pos = new Vec3(targetPos.x + 2, targetPos.y, targetPos.z); + localPlayer.position = pos; + showNotification("Teleported to player!"); + return; + } + } + showNotification("Player not found"); + } catch(e) { + console.log("[ModMenu] Teleport to player error: " + e); + showNotification("Teleport failed"); + } +}); + // Vehicle model hashes for GTA IV const vehicleHashes = { "infernus": 0x18F25AC7, @@ -740,16 +777,16 @@ addNetworkHandler("ModMenu:ExecuteSpawnVehicle", function(vehicleName) { let pos = localPlayer.position; let heading = localPlayer.heading || 0; - // Spawn position slightly in front of player - let spawnX = pos.x + (Math.sin(heading) * 5); - let spawnY = pos.y + (Math.cos(heading) * 5); - let spawnZ = pos.z; + // Spawn position at player location + let spawnPos = new Vec3(pos.x, pos.y, pos.z); - // Use native to create car - let vehicle = natives.createCar(modelHash, spawnX, spawnY, spawnZ, true); + // Use native to create car with Vec3 position + let vehicle = natives.createCar(modelHash, spawnPos, true); if (vehicle) { natives.setCarHeading(vehicle, heading); + // Warp player into the vehicle + natives.warpCharIntoCar(localPlayer, vehicle); showNotification("Spawned!"); } else { showNotification("Failed"); @@ -780,8 +817,13 @@ addNetworkHandler("ModMenu:ExecuteVehicleOption", function(option) { showNotification("Vehicle flipped!"); break; case "nitro": - // Boost vehicle forward - natives.applyForceToCar(veh, 0, 0, 50, 0, 0, 0); + // Boost vehicle forward using velocity + let heading = veh.heading || 0; + let speed = 50.0; + let vx = Math.sin(heading) * speed * -1; + let vy = Math.cos(heading) * speed; + let vel = new Vec3(vx, vy, 5); + veh.velocity = vel; showNotification("NITRO!"); break; } @@ -850,7 +892,8 @@ addNetworkHandler("ModMenu:ExecuteSkinChange", function(skinId) { let skins = [-1667301416, -163448165, 1936355839, -1938475496, 970234525]; skinId = skins[Math.floor(Math.random() * skins.length)]; } - natives.changePlayerModel(localPlayer, skinId); + // GTA IV uses changePlayerModel with player index 0 + natives.changePlayerModel(0, skinId); showNotification("Skin changed!"); } catch(e) { console.log("[ModMenu] Skin change error: " + e); @@ -969,20 +1012,44 @@ addEventHandler("OnDrawnHUD", function(event) { // TOGGLE EFFECTS // ============================================================================ +// Track last god mode state to only call native when changed +let lastGodMode = false; +let lastVehGodMode = false; + addEventHandler("OnProcess", function(event) { if (!localPlayer) return; + // Player god mode - use invincibility native + if (toggleStates.godMode !== lastGodMode) { + natives.setCharInvincible(localPlayer, toggleStates.godMode); + lastGodMode = toggleStates.godMode; + } + + // Keep health topped up in god mode as backup if (toggleStates.godMode) { - localPlayer.health = 200; - localPlayer.armour = 100; + if (localPlayer.health < 200) localPlayer.health = 200; + if (localPlayer.armour < 100) localPlayer.armour = 100; } + // Never wanted - clear wanted level if (toggleStates.neverWanted) { - localPlayer.wantedLevel = 0; + natives.clearWantedLevel(0); } - if (localPlayer.vehicle && toggleStates.vehGodMode) { - localPlayer.vehicle.health = 1000; + // Vehicle god mode + if (localPlayer.vehicle) { + if (toggleStates.vehGodMode !== lastVehGodMode) { + natives.setCarCanBeDamaged(localPlayer.vehicle, !toggleStates.vehGodMode); + lastVehGodMode = toggleStates.vehGodMode; + } + if (toggleStates.vehGodMode) { + natives.fixCar(localPlayer.vehicle); + } + } + + // Disable phone when menu is open + if (menuOpen) { + natives.setPlayerControlForTextChat(0, false); } });