mirror of
https://github.com/iDisaster/GTAConnected.git
synced 2026-03-15 12:51:49 +00:00
Merge pull request #4 from iDisaster/claude/enhance-gta-server-9Dezg
Claude/enhance gta server 9 dezg
This commit is contained in:
@@ -280,13 +280,21 @@ let toggleStates = {
|
|||||||
|
|
||||||
addEventHandler("OnResourceReady", function(event, resource) {
|
addEventHandler("OnResourceReady", function(event, resource) {
|
||||||
// Use built-in default font (no external TTF file needed)
|
// Use built-in default font (no external TTF file needed)
|
||||||
|
// Signature: lucasFont.createDefaultFont(float size, string family, [string style = "Regular"])
|
||||||
try {
|
try {
|
||||||
menuFont = lucasFont.createDefaultFont(16.0, "Tahoma", false, false);
|
menuFont = lucasFont.createDefaultFont(16.0, "Arial", "Regular");
|
||||||
if (menuFont != null) {
|
if (menuFont != null) {
|
||||||
console.log("[ModMenu] Default font created successfully");
|
console.log("[ModMenu] Default font created successfully");
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("[ModMenu] Could not create default font: " + e);
|
console.log("[ModMenu] Could not create default font: " + e);
|
||||||
|
// Try alternative font
|
||||||
|
try {
|
||||||
|
menuFont = lucasFont.createDefaultFont(16.0, "Tahoma");
|
||||||
|
console.log("[ModMenu] Fallback font created");
|
||||||
|
} catch(e2) {
|
||||||
|
console.log("[ModMenu] Fallback font also failed: " + e2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menuFont == null) {
|
if (menuFont == null) {
|
||||||
@@ -591,6 +599,264 @@ addNetworkHandler("ModMenu:Notification", function(msg) {
|
|||||||
showNotification(msg);
|
showNotification(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// EXECUTE HANDLERS - Client-side natives execution
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Execute weather change using GTA IV native
|
||||||
|
addNetworkHandler("ModMenu:ExecuteWeather", function(weatherId) {
|
||||||
|
try {
|
||||||
|
natives.forceWeatherNow(weatherId);
|
||||||
|
showNotification("Weather changed!");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Weather error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute time change using GTA IV native
|
||||||
|
addNetworkHandler("ModMenu:ExecuteTime", function(hour) {
|
||||||
|
try {
|
||||||
|
natives.forceTimeOfDay(hour, 0);
|
||||||
|
showNotification("Time: " + hour + ":00");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Time error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute self options using natives
|
||||||
|
addNetworkHandler("ModMenu:ExecuteSelfOption", function(option) {
|
||||||
|
if (!localPlayer) {
|
||||||
|
showNotification("Player not ready");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch(option) {
|
||||||
|
case "health":
|
||||||
|
localPlayer.health = 200;
|
||||||
|
showNotification("Health restored!");
|
||||||
|
break;
|
||||||
|
case "armor":
|
||||||
|
localPlayer.armour = 100;
|
||||||
|
showNotification("Armor restored!");
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
localPlayer.health = 200;
|
||||||
|
localPlayer.armour = 100;
|
||||||
|
showNotification("Max health & armor!");
|
||||||
|
break;
|
||||||
|
case "weapons":
|
||||||
|
// Give weapons using natives
|
||||||
|
natives.giveWeaponToChar(localPlayer, 5, 500, false); // Pistol
|
||||||
|
natives.giveWeaponToChar(localPlayer, 6, 500, false); // Deagle
|
||||||
|
natives.giveWeaponToChar(localPlayer, 9, 100, false); // Shotgun
|
||||||
|
natives.giveWeaponToChar(localPlayer, 12, 500, false); // SMG
|
||||||
|
natives.giveWeaponToChar(localPlayer, 14, 500, false); // AK
|
||||||
|
natives.giveWeaponToChar(localPlayer, 16, 50, false); // Sniper
|
||||||
|
natives.giveWeaponToChar(localPlayer, 18, 10, false); // RPG
|
||||||
|
showNotification("All weapons given!");
|
||||||
|
break;
|
||||||
|
case "wanted":
|
||||||
|
natives.alterWantedLevel(localPlayer, 0);
|
||||||
|
natives.applyWantedLevelChangeNow(localPlayer);
|
||||||
|
showNotification("Wanted cleared!");
|
||||||
|
break;
|
||||||
|
case "suicide":
|
||||||
|
localPlayer.health = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Self option error: " + e);
|
||||||
|
showNotification("Action failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute teleport
|
||||||
|
addNetworkHandler("ModMenu:ExecuteTeleport", function(x, y, z) {
|
||||||
|
if (!localPlayer) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let pos = new Vec3(x, y, z);
|
||||||
|
localPlayer.position = pos;
|
||||||
|
showNotification("Teleported!");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Teleport error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Vehicle model hashes for GTA IV
|
||||||
|
const vehicleHashes = {
|
||||||
|
"infernus": 0x18F25AC7,
|
||||||
|
"turismo": 0x185484E1,
|
||||||
|
"comet": 0x067BC037,
|
||||||
|
"banshee": 0xC1E908D2,
|
||||||
|
"sultan": 0x39DA2754,
|
||||||
|
"coquette": 0x067BC037,
|
||||||
|
"feltzer": 0x8911B9F5,
|
||||||
|
"buffalo": 0xEDD516C6,
|
||||||
|
"sabregt": 0x9B909C94,
|
||||||
|
"stalion": 0x72A4C31E,
|
||||||
|
"vigero": 0xCEC6B9B7,
|
||||||
|
"dukes": 0x2B26F456,
|
||||||
|
"phoenix": 0x831A21D5,
|
||||||
|
"patriot": 0xCFCFEB3B,
|
||||||
|
"cavalcade": 0x779F23AA,
|
||||||
|
"huntley": 0x1D06D681,
|
||||||
|
"landstalker": 0x4BA4E8DC,
|
||||||
|
"nrg900": 0x6F039A67,
|
||||||
|
"pcj600": 0xC9CEAF06,
|
||||||
|
"sanchez": 0x2EF89E46,
|
||||||
|
"faggio": 0x9229E4EB,
|
||||||
|
"police": 0x79FBB0C5,
|
||||||
|
"police2": 0x9F05F101,
|
||||||
|
"fbi": 0x432EA949,
|
||||||
|
"ambulance": 0x45D56ADA,
|
||||||
|
"firetruk": 0x73920F8E,
|
||||||
|
"annihilator": 0x31F0B376,
|
||||||
|
"maverick": 0x9D0450CA,
|
||||||
|
"polmav": 0x1517D4D9,
|
||||||
|
"jetmax": 0x33581161,
|
||||||
|
"predator": 0xE2E7D4AB,
|
||||||
|
"tropic": 0x1149422F,
|
||||||
|
"taxi": 0xC703DB5F,
|
||||||
|
"stretch": 0x8B13F083,
|
||||||
|
"bus": 0xD577C962
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute vehicle spawn using natives
|
||||||
|
addNetworkHandler("ModMenu:ExecuteSpawnVehicle", function(vehicleName) {
|
||||||
|
try {
|
||||||
|
if (!localPlayer) {
|
||||||
|
showNotification("Not ready");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let modelHash = vehicleHashes[vehicleName];
|
||||||
|
if (!modelHash) {
|
||||||
|
showNotification("Unknown vehicle");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Use native to create car
|
||||||
|
let vehicle = natives.createCar(modelHash, spawnX, spawnY, spawnZ, true);
|
||||||
|
|
||||||
|
if (vehicle) {
|
||||||
|
natives.setCarHeading(vehicle, heading);
|
||||||
|
showNotification("Spawned!");
|
||||||
|
} else {
|
||||||
|
showNotification("Failed");
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Vehicle error: " + e);
|
||||||
|
showNotification("Error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute vehicle options
|
||||||
|
addNetworkHandler("ModMenu:ExecuteVehicleOption", function(option) {
|
||||||
|
if (!localPlayer || !localPlayer.vehicle) {
|
||||||
|
showNotification("Get in a vehicle first!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let veh = localPlayer.vehicle;
|
||||||
|
switch(option) {
|
||||||
|
case "repair":
|
||||||
|
natives.fixCar(veh);
|
||||||
|
showNotification("Vehicle repaired!");
|
||||||
|
break;
|
||||||
|
case "flip":
|
||||||
|
let rot = veh.rotation;
|
||||||
|
veh.rotation = new Vec3(0, 0, rot.z);
|
||||||
|
showNotification("Vehicle flipped!");
|
||||||
|
break;
|
||||||
|
case "nitro":
|
||||||
|
// Boost vehicle forward
|
||||||
|
natives.applyForceToCar(veh, 0, 0, 50, 0, 0, 0);
|
||||||
|
showNotification("NITRO!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Vehicle option error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute vehicle color change
|
||||||
|
addNetworkHandler("ModMenu:ExecuteVehicleColor", function(color1, color2) {
|
||||||
|
if (!localPlayer || !localPlayer.vehicle) {
|
||||||
|
showNotification("Get in a vehicle first!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
natives.changeCarColour(localPlayer.vehicle, color1, color2);
|
||||||
|
showNotification("Color changed!");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Color change error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute weapon give
|
||||||
|
addNetworkHandler("ModMenu:ExecuteGiveWeapon", function(weaponId) {
|
||||||
|
if (!localPlayer) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
natives.giveWeaponToChar(localPlayer, weaponId, 500, false);
|
||||||
|
showNotification("Weapon given!");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Weapon error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute fun options
|
||||||
|
addNetworkHandler("ModMenu:ExecuteFun", function(option) {
|
||||||
|
if (!localPlayer) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let pos = localPlayer.position;
|
||||||
|
switch(option) {
|
||||||
|
case "launch":
|
||||||
|
let launchPos = new Vec3(pos.x, pos.y, pos.z + 50);
|
||||||
|
localPlayer.position = launchPos;
|
||||||
|
showNotification("LAUNCH!");
|
||||||
|
break;
|
||||||
|
case "explode":
|
||||||
|
natives.addExplosion(pos.x, pos.y, pos.z, 0, 5.0, true, false, 1.0);
|
||||||
|
break;
|
||||||
|
case "ragdoll":
|
||||||
|
natives.switchPedToRagdoll(localPlayer, 1000, 1000, 0, true, true, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Fun option error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute skin change
|
||||||
|
addNetworkHandler("ModMenu:ExecuteSkinChange", function(skinId) {
|
||||||
|
if (!localPlayer) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (skinId === "random") {
|
||||||
|
let skins = [-1667301416, -163448165, 1936355839, -1938475496, 970234525];
|
||||||
|
skinId = skins[Math.floor(Math.random() * skins.length)];
|
||||||
|
}
|
||||||
|
natives.changePlayerModel(localPlayer, skinId);
|
||||||
|
showNotification("Skin changed!");
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[ModMenu] Skin change error: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// RENDERING
|
// RENDERING
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -670,7 +936,7 @@ function showNotification(text) {
|
|||||||
notifications.push({
|
notifications.push({
|
||||||
text: text,
|
text: text,
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
duration: 3000
|
duration: 1000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +949,8 @@ addEventHandler("OnDrawnHUD", function(event) {
|
|||||||
let elapsed = now - notif.time;
|
let elapsed = now - notif.time;
|
||||||
|
|
||||||
if (elapsed < notif.duration) {
|
if (elapsed < notif.duration) {
|
||||||
let alpha = elapsed < notif.duration - 500 ? 200 : Math.floor(200 * (notif.duration - elapsed) / 500);
|
// Quick fade: start fading at 700ms, fully gone by 1000ms
|
||||||
|
let alpha = elapsed < 700 ? 200 : Math.floor(200 * (notif.duration - elapsed) / 300);
|
||||||
let bgColor = toColour(20, 20, 20, alpha);
|
let bgColor = toColour(20, 20, 20, alpha);
|
||||||
let textColor = toColour(255, 255, 100, Math.min(255, alpha + 55));
|
let textColor = toColour(255, 255, 100, Math.min(255, alpha + 55));
|
||||||
|
|
||||||
|
|||||||
@@ -7,125 +7,20 @@
|
|||||||
const COLOUR_ORANGE = toColour(255, 200, 100, 255);
|
const COLOUR_ORANGE = toColour(255, 200, 100, 255);
|
||||||
const COLOUR_WORLD = toColour(100, 200, 255, 255);
|
const COLOUR_WORLD = toColour(100, 200, 255, 255);
|
||||||
|
|
||||||
// Vehicle model hashes for spawning
|
// Vehicle model names (will use game's model loading)
|
||||||
const vehicleModels = {
|
const vehicleModels = [
|
||||||
// Sports Cars
|
"infernus", "turismo", "comet", "banshee", "sultan", "coquette",
|
||||||
"infernus": -1461482751,
|
"feltzer", "buffalo", "sabregt", "stalion", "vigero", "dukes",
|
||||||
"turismo": -982130927,
|
"phoenix", "patriot", "cavalcade", "huntley", "landstalker",
|
||||||
"comet": 1063483177,
|
"nrg900", "pcj600", "sanchez", "faggio", "police", "fbi",
|
||||||
"banshee": -1823484407,
|
"ambulance", "firetruk", "annihilator", "maverick", "polmav",
|
||||||
"sultan": 970598228,
|
"jetmax", "predator", "tropic", "taxi", "stretch", "bus"
|
||||||
"coquette": 108773431,
|
|
||||||
"feltzer": -349601129,
|
|
||||||
"f620": -591651781,
|
|
||||||
"buffalo": -304802106,
|
|
||||||
|
|
||||||
// Super Cars
|
|
||||||
"entityxf": -1291952903,
|
|
||||||
"adder": -1216765807,
|
|
||||||
"vacca": 338562499,
|
|
||||||
"bullet": -1696146015,
|
|
||||||
"cheetah": -1311154784,
|
|
||||||
|
|
||||||
// Muscle Cars
|
|
||||||
"sabregt": 1357660823,
|
|
||||||
"stalion": 1923400478,
|
|
||||||
"vigero": -825837129,
|
|
||||||
"dukes": 723973206,
|
|
||||||
"ruiner": -227741703,
|
|
||||||
"phoenix": -2095439403,
|
|
||||||
"gauntlet": -1800170043,
|
|
||||||
"dominator": 80636076,
|
|
||||||
|
|
||||||
// SUVs
|
|
||||||
"patriot": -808457413,
|
|
||||||
"cavalcade": 2006918058,
|
|
||||||
"granger": 1269098716,
|
|
||||||
"huntley": 486987393,
|
|
||||||
"landstalker": 1269098716,
|
|
||||||
"habanero": 884422927,
|
|
||||||
"serrano": 1337041428,
|
|
||||||
"rebla": 83136452,
|
|
||||||
|
|
||||||
// Sedans
|
|
||||||
"oracle": 1348744438,
|
|
||||||
"schafter": -888242983,
|
|
||||||
"admiral": -1645064850,
|
|
||||||
"vincent": -884237051,
|
|
||||||
"presidente": -1150599089,
|
|
||||||
"cognoscenti": -2030171296,
|
|
||||||
"blista": -344943009,
|
|
||||||
"premier": -1883869285,
|
|
||||||
|
|
||||||
// Motorcycles
|
|
||||||
"nrg900": -1706076364,
|
|
||||||
"pcj600": -909201658,
|
|
||||||
"sanchez": 788045382,
|
|
||||||
"faggio": 55628203,
|
|
||||||
"bati": -891462355,
|
|
||||||
"akuma": 1672195559,
|
|
||||||
"double": -1670998136,
|
|
||||||
"hakuchou": 1265391242,
|
|
||||||
"hexer": 301427732,
|
|
||||||
"daemon": 2006142190,
|
|
||||||
|
|
||||||
// Emergency
|
|
||||||
"police": 2046537925,
|
|
||||||
"police2": -1627000575,
|
|
||||||
"fbi": 1127131465,
|
|
||||||
"noose": -1683328900,
|
|
||||||
"ambulance": 1171614426,
|
|
||||||
"firetruk": 1938952078,
|
|
||||||
"enforcer": 2046537925,
|
|
||||||
|
|
||||||
// Aircraft
|
|
||||||
"annihilator": 837858166,
|
|
||||||
"maverick": -1660661558,
|
|
||||||
"polmav": 353883353,
|
|
||||||
"buzzard": 788747387,
|
|
||||||
"shamal": -1214293858,
|
|
||||||
|
|
||||||
// Boats
|
|
||||||
"jetmax": 861409633,
|
|
||||||
"marquis": -1043459709,
|
|
||||||
"predator": -488123221,
|
|
||||||
"tropic": 290013743,
|
|
||||||
"dinghy": 1033245328,
|
|
||||||
"squalo": 400514754,
|
|
||||||
"reefer": 1016996501,
|
|
||||||
|
|
||||||
// Special
|
|
||||||
"taxi": -956048545,
|
|
||||||
"stretch": -1961627517,
|
|
||||||
"bus": -713569950,
|
|
||||||
"trashmaster": 1917016601,
|
|
||||||
"forklift": 1491375716,
|
|
||||||
"caddy": 1147287684,
|
|
||||||
"bulldozer": 1886712733,
|
|
||||||
"phantom": -2137348917
|
|
||||||
};
|
|
||||||
|
|
||||||
// Player skin models
|
|
||||||
const skinModels = [
|
|
||||||
-1667301416, // Niko
|
|
||||||
-163448165, // Roman
|
|
||||||
1936355839, // Jacob
|
|
||||||
-1938475496, // Brucie
|
|
||||||
970234525, // Playboy X
|
|
||||||
-1784875845, // Johnny
|
|
||||||
-1403507487, // Luis
|
|
||||||
-1320879687, // Cop
|
|
||||||
-1306011498, // NOOSE
|
|
||||||
2136829318, // Paramedic
|
|
||||||
1616659040, // Firefighter
|
|
||||||
-268651930, // Business
|
|
||||||
1943617350 // Hobo
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Store spawned vehicles per player
|
// Store spawned vehicles per player
|
||||||
let playerVehicles = {};
|
let playerVehicles = {};
|
||||||
|
|
||||||
// Player toggle states (for server-validated features)
|
// Player toggle states
|
||||||
let playerToggles = {};
|
let playerToggles = {};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -159,57 +54,16 @@ addEventHandler("OnPlayerQuit", function(event, client, reason) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NETWORK HANDLERS - Self Options
|
// NETWORK HANDLERS - Self Options (No spawn check - handled client-side)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:SelfOption", function(client, option) {
|
addNetworkHandler("ModMenu:SelfOption", function(client, option) {
|
||||||
if (!client.player) {
|
// These actions are handled client-side via natives
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
// Server just logs and can do additional processing if needed
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(option) {
|
|
||||||
case "health":
|
|
||||||
client.player.health = 200;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "armor":
|
|
||||||
client.player.armour = 100;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "max":
|
|
||||||
client.player.health = 200;
|
|
||||||
client.player.armour = 100;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "weapons":
|
|
||||||
giveAllWeapons(client);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "wanted":
|
|
||||||
client.player.wantedLevel = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "respawn":
|
|
||||||
// Respawn at random location
|
|
||||||
let spawns = [
|
|
||||||
{ x: -252.0, y: 947.0, z: 15.0 },
|
|
||||||
{ x: 932.0, y: -495.0, z: 15.0 },
|
|
||||||
{ x: -365.0, y: 1163.0, z: 14.0 },
|
|
||||||
{ x: 1243.0, y: -196.0, z: 26.0 }
|
|
||||||
];
|
|
||||||
let spawn = spawns[Math.floor(Math.random() * spawns.length)];
|
|
||||||
let spawnPos = new Vec3(spawn.x, spawn.y, spawn.z);
|
|
||||||
client.despawnPlayer();
|
|
||||||
client.spawnPlayer(spawnPos, 0.0, -1667301416);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "suicide":
|
|
||||||
client.player.health = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[ModMenu] " + client.name + " used self option: " + option);
|
console.log("[ModMenu] " + client.name + " used self option: " + option);
|
||||||
|
|
||||||
|
// Tell client to execute the action
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteSelfOption", client, option);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -220,7 +74,6 @@ addNetworkHandler("ModMenu:Toggle", function(client, feature, state) {
|
|||||||
if (!playerToggles[client.index]) {
|
if (!playerToggles[client.index]) {
|
||||||
playerToggles[client.index] = {};
|
playerToggles[client.index] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
playerToggles[client.index][feature] = state;
|
playerToggles[client.index][feature] = state;
|
||||||
console.log("[ModMenu] " + client.name + " toggled " + feature + ": " + state);
|
console.log("[ModMenu] " + client.name + " toggled " + feature + ": " + state);
|
||||||
});
|
});
|
||||||
@@ -230,17 +83,8 @@ addNetworkHandler("ModMenu:Toggle", function(client, feature, state) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:ChangeSkin", function(client, skinId) {
|
addNetworkHandler("ModMenu:ChangeSkin", function(client, skinId) {
|
||||||
if (!client.player) {
|
console.log("[ModMenu] " + client.name + " requested skin change: " + skinId);
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
triggerNetworkEvent("ModMenu:ExecuteSkinChange", client, skinId);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinId === "random") {
|
|
||||||
skinId = skinModels[Math.floor(Math.random() * skinModels.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
client.player.modelIndex = skinId;
|
|
||||||
console.log("[ModMenu] " + client.name + " changed skin to: " + skinId);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -248,62 +92,14 @@ addNetworkHandler("ModMenu:ChangeSkin", function(client, skinId) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:SpawnVehicle", function(client, vehicleName) {
|
addNetworkHandler("ModMenu:SpawnVehicle", function(client, vehicleName) {
|
||||||
if (!client.player) {
|
console.log("[ModMenu] " + client.name + " requested vehicle: " + vehicleName);
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let modelHash = vehicleModels[vehicleName];
|
// Tell client to spawn vehicle (client-side has position info)
|
||||||
if (!modelHash) {
|
triggerNetworkEvent("ModMenu:ExecuteSpawnVehicle", client, vehicleName);
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Vehicle not found!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete previous vehicles (limit to 1 per player)
|
|
||||||
deletePlayerVehicles(client);
|
|
||||||
|
|
||||||
// Get spawn position
|
|
||||||
let pos = client.player.position;
|
|
||||||
let heading = client.player.heading;
|
|
||||||
|
|
||||||
let spawnX = pos.x + (Math.sin(heading) * 4);
|
|
||||||
let spawnY = pos.y + (Math.cos(heading) * 4);
|
|
||||||
let spawnZ = pos.z + 1;
|
|
||||||
|
|
||||||
// Create vehicle
|
|
||||||
let spawnPos = new Vec3(spawnX, spawnY, spawnZ);
|
|
||||||
let vehicle = gta.createVehicle(modelHash, spawnPos, heading);
|
|
||||||
|
|
||||||
if (vehicle) {
|
|
||||||
if (!playerVehicles[client.index]) {
|
|
||||||
playerVehicles[client.index] = [];
|
|
||||||
}
|
|
||||||
playerVehicles[client.index].push(vehicle);
|
|
||||||
|
|
||||||
// Set vehicle properties
|
|
||||||
vehicle.health = 1000;
|
|
||||||
vehicle.locked = false;
|
|
||||||
vehicle.engine = true;
|
|
||||||
|
|
||||||
// Random color
|
|
||||||
let c1 = Math.floor(Math.random() * 132);
|
|
||||||
let c2 = Math.floor(Math.random() * 132);
|
|
||||||
vehicle.colour1 = c1;
|
|
||||||
vehicle.colour2 = c2;
|
|
||||||
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Vehicle spawned: " + vehicleName.toUpperCase());
|
|
||||||
console.log("[ModMenu] " + client.name + " spawned " + vehicleName);
|
|
||||||
} else {
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Failed to spawn vehicle!");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:DeleteVehicles", function(client) {
|
addNetworkHandler("ModMenu:DeleteVehicles", function(client) {
|
||||||
deletePlayerVehicles(client);
|
// Delete server-tracked vehicles
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Your vehicles have been deleted!");
|
|
||||||
});
|
|
||||||
|
|
||||||
function deletePlayerVehicles(client) {
|
|
||||||
if (playerVehicles[client.index]) {
|
if (playerVehicles[client.index]) {
|
||||||
for (let i = 0; i < playerVehicles[client.index].length; i++) {
|
for (let i = 0; i < playerVehicles[client.index].length; i++) {
|
||||||
let veh = playerVehicles[client.index][i];
|
let veh = playerVehicles[client.index][i];
|
||||||
@@ -313,85 +109,21 @@ function deletePlayerVehicles(client) {
|
|||||||
}
|
}
|
||||||
playerVehicles[client.index] = [];
|
playerVehicles[client.index] = [];
|
||||||
}
|
}
|
||||||
}
|
triggerNetworkEvent("ModMenu:Notification", client, "Vehicles deleted!");
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NETWORK HANDLERS - Vehicle Options
|
// NETWORK HANDLERS - Vehicle Options
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:VehicleOption", function(client, option) {
|
addNetworkHandler("ModMenu:VehicleOption", function(client, option) {
|
||||||
if (!client.player || !client.player.vehicle) {
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to be in a vehicle!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let vehicle = client.player.vehicle;
|
|
||||||
|
|
||||||
switch(option) {
|
|
||||||
case "repair":
|
|
||||||
vehicle.health = 1000;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "flip":
|
|
||||||
let rot = vehicle.rotation;
|
|
||||||
vehicle.rotation = new Vec3(0, 0, rot.z);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "clean":
|
|
||||||
vehicle.dirtLevel = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "upgrade":
|
|
||||||
// Max out visual mods if supported
|
|
||||||
vehicle.health = 1000;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "nitro":
|
|
||||||
// Boost vehicle forward
|
|
||||||
let pos = vehicle.position;
|
|
||||||
let heading = vehicle.heading;
|
|
||||||
let boost = 50;
|
|
||||||
let newPos = new Vec3(
|
|
||||||
pos.x + (Math.sin(heading) * boost),
|
|
||||||
pos.y + (Math.cos(heading) * boost),
|
|
||||||
pos.z
|
|
||||||
);
|
|
||||||
vehicle.position = newPos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[ModMenu] " + client.name + " used vehicle option: " + option);
|
console.log("[ModMenu] " + client.name + " used vehicle option: " + option);
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteVehicleOption", client, option);
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:VehicleColor", function(client, color1, color2) {
|
addNetworkHandler("ModMenu:VehicleColor", function(client, color1, color2) {
|
||||||
if (!client.player || !client.player.vehicle) {
|
console.log("[ModMenu] " + client.name + " changed vehicle color");
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to be in a vehicle!");
|
triggerNetworkEvent("ModMenu:ExecuteVehicleColor", client, color1, color2);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.player.vehicle.colour1 = color1;
|
|
||||||
client.player.vehicle.colour2 = color2;
|
|
||||||
console.log("[ModMenu] " + client.name + " changed vehicle color to: " + color1 + ", " + color2);
|
|
||||||
});
|
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:Handling", function(client, property, value) {
|
|
||||||
// Store handling modifications for the player
|
|
||||||
// Note: Actual handling modification depends on GTAC's native support
|
|
||||||
if (!playerToggles[client.index]) {
|
|
||||||
playerToggles[client.index] = {};
|
|
||||||
}
|
|
||||||
playerToggles[client.index]["handling_" + property] = value;
|
|
||||||
console.log("[ModMenu] " + client.name + " set handling " + property + " to: " + value);
|
|
||||||
});
|
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:HandlingReset", function(client) {
|
|
||||||
if (playerToggles[client.index]) {
|
|
||||||
delete playerToggles[client.index].handling_grip;
|
|
||||||
delete playerToggles[client.index].handling_acceleration;
|
|
||||||
delete playerToggles[client.index].handling_topSpeed;
|
|
||||||
delete playerToggles[client.index].handling_braking;
|
|
||||||
}
|
|
||||||
console.log("[ModMenu] " + client.name + " reset vehicle handling");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -399,55 +131,21 @@ addNetworkHandler("ModMenu:HandlingReset", function(client) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:Teleport", function(client, x, y, z) {
|
addNetworkHandler("ModMenu:Teleport", function(client, x, y, z) {
|
||||||
if (!client.player) {
|
console.log("[ModMenu] " + client.name + " teleporting to: " + x + ", " + y + ", " + z);
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
triggerNetworkEvent("ModMenu:ExecuteTeleport", client, x, y, z);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newPos = new Vec3(x, y, z);
|
|
||||||
if (client.player.vehicle) {
|
|
||||||
client.player.vehicle.position = newPos;
|
|
||||||
} else {
|
|
||||||
client.player.position = newPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[ModMenu] " + client.name + " teleported to: " + x + ", " + y + ", " + z);
|
|
||||||
});
|
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:TeleportWaypoint", function(client) {
|
|
||||||
// Teleport to map waypoint - requires client-side waypoint data
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Set a waypoint on the map first!");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:TeleportToPlayer", function(client, targetId) {
|
addNetworkHandler("ModMenu:TeleportToPlayer", function(client, targetId) {
|
||||||
if (!client.player) {
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
let target = null;
|
|
||||||
|
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
if (clients[i].index == targetId) {
|
if (clients[i].index == targetId) {
|
||||||
target = clients[i];
|
triggerNetworkEvent("ModMenu:Notification", client, "Teleporting to: " + clients[i].name);
|
||||||
break;
|
// Client will handle the actual teleport
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteTeleportToPlayer", client, targetId);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
triggerNetworkEvent("ModMenu:Notification", client, "Player not found!");
|
||||||
if (target && target.player) {
|
|
||||||
let pos = target.player.position;
|
|
||||||
let newPos = new Vec3(pos.x + 3, pos.y, pos.z);
|
|
||||||
if (client.player.vehicle) {
|
|
||||||
client.player.vehicle.position = newPos;
|
|
||||||
} else {
|
|
||||||
client.player.position = newPos;
|
|
||||||
}
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Teleported to: " + target.name);
|
|
||||||
console.log("[ModMenu] " + client.name + " teleported to " + target.name);
|
|
||||||
} else {
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Player not found or not spawned!");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -459,10 +157,9 @@ addNetworkHandler("ModMenu:GetPlayers", function(client) {
|
|||||||
let playerList = [];
|
let playerList = [];
|
||||||
|
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
let c = clients[i];
|
|
||||||
playerList.push({
|
playerList.push({
|
||||||
id: c.index,
|
id: clients[i].index,
|
||||||
name: c.name
|
name: clients[i].name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,19 +167,31 @@ addNetworkHandler("ModMenu:GetPlayers", function(client) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NETWORK HANDLERS - World Options
|
// NETWORK HANDLERS - World Options (Weather & Time)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:WorldTime", function(client, hour) {
|
addNetworkHandler("ModMenu:WorldTime", function(client, hour) {
|
||||||
gta.time = [hour, 0];
|
|
||||||
message("[WORLD] " + client.name + " changed time to: " + hour + ":00", COLOUR_WORLD);
|
|
||||||
console.log("[ModMenu] " + client.name + " changed time to: " + hour);
|
console.log("[ModMenu] " + client.name + " changed time to: " + hour);
|
||||||
|
|
||||||
|
// Broadcast to all clients to change time
|
||||||
|
let clients = getClients();
|
||||||
|
for (let i = 0; i < clients.length; i++) {
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteTime", clients[i], hour);
|
||||||
|
}
|
||||||
|
|
||||||
|
message("[WORLD] " + client.name + " changed time to: " + hour + ":00", COLOUR_WORLD);
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:WorldWeather", function(client, weatherId) {
|
addNetworkHandler("ModMenu:WorldWeather", function(client, weatherId) {
|
||||||
gta.weather = weatherId;
|
|
||||||
message("[WORLD] " + client.name + " changed the weather", COLOUR_WORLD);
|
|
||||||
console.log("[ModMenu] " + client.name + " changed weather to: " + weatherId);
|
console.log("[ModMenu] " + client.name + " changed weather to: " + weatherId);
|
||||||
|
|
||||||
|
// Broadcast to all clients to change weather
|
||||||
|
let clients = getClients();
|
||||||
|
for (let i = 0; i < clients.length; i++) {
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteWeather", clients[i], weatherId);
|
||||||
|
}
|
||||||
|
|
||||||
|
message("[WORLD] " + client.name + " changed the weather", COLOUR_WORLD);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -490,90 +199,17 @@ addNetworkHandler("ModMenu:WorldWeather", function(client, weatherId) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:GiveWeapon", function(client, weaponId) {
|
addNetworkHandler("ModMenu:GiveWeapon", function(client, weaponId) {
|
||||||
if (!client.player) {
|
console.log("[ModMenu] " + client.name + " requested weapon: " + weaponId);
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
triggerNetworkEvent("ModMenu:ExecuteGiveWeapon", client, weaponId);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.player.giveWeapon(weaponId, 500);
|
|
||||||
console.log("[ModMenu] " + client.name + " got weapon: " + weaponId);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function giveAllWeapons(client) {
|
|
||||||
if (!client.player) return;
|
|
||||||
|
|
||||||
// GTA IV Weapons
|
|
||||||
client.player.giveWeapon(1, 1); // Bat
|
|
||||||
client.player.giveWeapon(2, 1); // Knife
|
|
||||||
client.player.giveWeapon(5, 500); // Pistol
|
|
||||||
client.player.giveWeapon(6, 500); // Deagle
|
|
||||||
client.player.giveWeapon(9, 200); // Shotgun
|
|
||||||
client.player.giveWeapon(10, 200); // Combat Shotgun
|
|
||||||
client.player.giveWeapon(11, 500); // Micro SMG
|
|
||||||
client.player.giveWeapon(12, 500); // SMG
|
|
||||||
client.player.giveWeapon(14, 500); // AK47
|
|
||||||
client.player.giveWeapon(15, 500); // M4
|
|
||||||
client.player.giveWeapon(16, 100); // Sniper
|
|
||||||
client.player.giveWeapon(18, 20); // RPG
|
|
||||||
client.player.giveWeapon(19, 20); // Grenades
|
|
||||||
client.player.giveWeapon(20, 20); // Molotov
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NETWORK HANDLERS - Fun Options
|
// NETWORK HANDLERS - Fun Options
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
addNetworkHandler("ModMenu:Fun", function(client, option) {
|
addNetworkHandler("ModMenu:Fun", function(client, option) {
|
||||||
if (!client.player) {
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "You need to spawn first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pos = client.player.position;
|
|
||||||
|
|
||||||
switch(option) {
|
|
||||||
case "launch":
|
|
||||||
let launchPos = new Vec3(pos.x, pos.y, pos.z + 50);
|
|
||||||
client.player.position = launchPos;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "explode":
|
|
||||||
gta.createExplosion(pos, 0, 5.0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "ped":
|
|
||||||
// Spawn a random ped near player
|
|
||||||
let pedSkin = skinModels[Math.floor(Math.random() * skinModels.length)];
|
|
||||||
let pedPos = new Vec3(pos.x + 3, pos.y + 3, pos.z);
|
|
||||||
let ped = gta.createPed(pedSkin, pedPos, 0);
|
|
||||||
if (ped) {
|
|
||||||
console.log("[ModMenu] " + client.name + " spawned a ped");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "ragdoll":
|
|
||||||
// Trigger ragdoll via health damage
|
|
||||||
let currentHealth = client.player.health;
|
|
||||||
client.player.health = currentHealth - 10;
|
|
||||||
setTimeout(function() {
|
|
||||||
if (client.player) {
|
|
||||||
client.player.health = currentHealth;
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "clearpeds":
|
|
||||||
// Clear peds in area - limited implementation
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Area clearing requested");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "clearvehicles":
|
|
||||||
// Clear vehicles in area - limited implementation
|
|
||||||
triggerNetworkEvent("ModMenu:Notification", client, "Vehicle clearing requested");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[ModMenu] " + client.name + " used fun option: " + option);
|
console.log("[ModMenu] " + client.name + " used fun option: " + option);
|
||||||
|
triggerNetworkEvent("ModMenu:ExecuteFun", client, option);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -27,12 +27,7 @@
|
|||||||
|
|
||||||
<!-- Resources to Load -->
|
<!-- Resources to Load -->
|
||||||
<resources>
|
<resources>
|
||||||
<resource src="freeroam" />
|
<!-- Only mod menu for now -->
|
||||||
<resource src="admin" />
|
|
||||||
<resource src="world" />
|
|
||||||
<resource src="chat" />
|
|
||||||
<resource src="teleport" />
|
|
||||||
<resource src="vehicles" />
|
|
||||||
<resource src="modmenu" />
|
<resource src="modmenu" />
|
||||||
</resources>
|
</resources>
|
||||||
</server>
|
</server>
|
||||||
|
|||||||
Reference in New Issue
Block a user