Fix vehicle/skin model loading and remove broken preventDefault

- Request model before spawning vehicles to prevent crashes
- Wait for model to load using hasModelLoaded before createCar
- Request model before changing skins to fix all skins being Niko
- Remove event.preventDefault which is not supported in GTAConnected
- Use destroyMobilePhone native to block phone when menu is open
- Add try/catch around toggle natives for error resilience
This commit is contained in:
Claude
2026-01-13 09:49:17 +00:00
parent 33cbef2eb4
commit 6492a84196

View File

@@ -317,36 +317,24 @@ addEventHandler("OnKeyUp", function(event, key, scanCode, mods) {
menuStack = []; menuStack = [];
// Show cursor and DISABLE controls (second param = false disables controls) // Show cursor and DISABLE controls (second param = false disables controls)
gui.showCursor(true, false); gui.showCursor(true, false);
// Disable phone
natives.setPlayerControlForTextChat(0, false);
} else { } else {
// Hide cursor and ENABLE controls (second param = true enables controls) // Hide cursor and ENABLE controls (second param = true enables controls)
gui.showCursor(false, true); gui.showCursor(false, true);
// Re-enable phone
natives.setPlayerControlForTextChat(0, true);
} }
return; return;
} }
if (!menuOpen) return; if (!menuOpen) return;
// Block phone popup - consume UP key event when menu is open // Navigation - simple key handling
if (key === SDLK_UP) { if (key === SDLK_UP) {
navigateUp(); navigateUp();
event.preventDefault = true;
return;
} else if (key === SDLK_DOWN) { } else if (key === SDLK_DOWN) {
navigateDown(); navigateDown();
event.preventDefault = true;
return;
} else if (key === SDLK_RETURN || key === SDLK_KP_ENTER) { } else if (key === SDLK_RETURN || key === SDLK_KP_ENTER) {
selectItem(); selectItem();
event.preventDefault = true;
return;
} else if (key === SDLK_BACKSPACE || key === SDLK_ESCAPE) { } else if (key === SDLK_BACKSPACE || key === SDLK_ESCAPE) {
goBack(); goBack();
event.preventDefault = true;
return;
} }
}); });
@@ -774,26 +762,42 @@ addNetworkHandler("ModMenu:ExecuteSpawnVehicle", function(vehicleName) {
return; return;
} }
let pos = localPlayer.position; // Request the model first
let heading = localPlayer.heading || 0; natives.requestModel(modelHash);
// Spawn position at player location // Wait for model to load then spawn
let spawnPos = new Vec3(pos.x, pos.y, pos.z); let attempts = 0;
let spawnInterval = setInterval(function() {
attempts++;
if (natives.hasModelLoaded(modelHash)) {
clearInterval(spawnInterval);
// Use native to create car with Vec3 position let pos = localPlayer.position;
let vehicle = natives.createCar(modelHash, spawnPos, true); let heading = localPlayer.heading || 0;
let spawnPos = new Vec3(pos.x, pos.y, pos.z + 1);
if (vehicle) { // Create the car
natives.setCarHeading(vehicle, heading); let vehicle = natives.createCar(modelHash, spawnPos, true);
// Warp player into the vehicle
natives.warpCharIntoCar(localPlayer, vehicle); if (vehicle) {
showNotification("Spawned!"); natives.setCarHeading(vehicle, heading);
} else { // Warp player into the vehicle
showNotification("Failed"); natives.warpCharIntoCar(localPlayer, vehicle);
} showNotification("Spawned: " + vehicleName);
} else {
showNotification("Failed to create");
}
// Mark model as no longer needed
natives.markModelAsNoLongerNeeded(modelHash);
} else if (attempts > 50) {
clearInterval(spawnInterval);
showNotification("Model load timeout");
}
}, 100);
} catch(e) { } catch(e) {
console.log("[ModMenu] Vehicle error: " + e); console.log("[ModMenu] Vehicle error: " + e);
showNotification("Error"); showNotification("Error: " + e);
} }
}); });
@@ -892,9 +896,25 @@ addNetworkHandler("ModMenu:ExecuteSkinChange", function(skinId) {
let skins = [-1667301416, -163448165, 1936355839, -1938475496, 970234525]; let skins = [-1667301416, -163448165, 1936355839, -1938475496, 970234525];
skinId = skins[Math.floor(Math.random() * skins.length)]; skinId = skins[Math.floor(Math.random() * skins.length)];
} }
// GTA IV uses changePlayerModel with player index 0
natives.changePlayerModel(0, skinId); // Request the model first
showNotification("Skin changed!"); natives.requestModel(skinId);
// Wait for model to load then change skin
let attempts = 0;
let skinInterval = setInterval(function() {
attempts++;
if (natives.hasModelLoaded(skinId)) {
clearInterval(skinInterval);
// Change player model using player index 0
natives.changePlayerModel(0, skinId);
natives.markModelAsNoLongerNeeded(skinId);
showNotification("Skin changed!");
} else if (attempts > 50) {
clearInterval(skinInterval);
showNotification("Skin load failed");
}
}, 100);
} catch(e) { } catch(e) {
console.log("[ModMenu] Skin change error: " + e); console.log("[ModMenu] Skin change error: " + e);
} }
@@ -1021,7 +1041,9 @@ addEventHandler("OnProcess", function(event) {
// Player god mode - use invincibility native // Player god mode - use invincibility native
if (toggleStates.godMode !== lastGodMode) { if (toggleStates.godMode !== lastGodMode) {
natives.setCharInvincible(localPlayer, toggleStates.godMode); try {
natives.setCharInvincible(localPlayer, toggleStates.godMode);
} catch(e) {}
lastGodMode = toggleStates.godMode; lastGodMode = toggleStates.godMode;
} }
@@ -1033,23 +1055,35 @@ addEventHandler("OnProcess", function(event) {
// Never wanted - clear wanted level // Never wanted - clear wanted level
if (toggleStates.neverWanted) { if (toggleStates.neverWanted) {
natives.clearWantedLevel(0); try {
natives.clearWantedLevel(0);
} catch(e) {
// Fallback - set wanted level directly
localPlayer.wantedLevel = 0;
}
} }
// Vehicle god mode // Vehicle god mode
if (localPlayer.vehicle) { if (localPlayer.vehicle) {
if (toggleStates.vehGodMode !== lastVehGodMode) { if (toggleStates.vehGodMode !== lastVehGodMode) {
natives.setCarCanBeDamaged(localPlayer.vehicle, !toggleStates.vehGodMode); try {
natives.setCarCanBeDamaged(localPlayer.vehicle, !toggleStates.vehGodMode);
} catch(e) {}
lastVehGodMode = toggleStates.vehGodMode; lastVehGodMode = toggleStates.vehGodMode;
} }
if (toggleStates.vehGodMode) { if (toggleStates.vehGodMode) {
natives.fixCar(localPlayer.vehicle); try {
natives.fixCar(localPlayer.vehicle);
} catch(e) {}
} }
} }
// Disable phone when menu is open // Block phone input when menu is open
if (menuOpen) { if (menuOpen) {
natives.setPlayerControlForTextChat(0, false); try {
// Destroy any active phone
natives.destroyMobilePhone();
} catch(e) {}
} }
}); });