mirror of
https://github.com/iDisaster/GTAConnected.git
synced 2026-03-08 09:25:23 +00:00
Merge pull request #8 from iDisaster/claude/enhance-gta-server-9Dezg
Claude/enhance gta server 9 dezg
This commit is contained in:
@@ -25,6 +25,26 @@ let screenShake = 0;
|
||||
let flashAlpha = 0;
|
||||
let currentDescription = "";
|
||||
|
||||
// ============================================================================
|
||||
// THEME SYSTEM
|
||||
// ============================================================================
|
||||
let currentTheme = "red"; // Default theme
|
||||
|
||||
const themes = {
|
||||
black: { primary: { r: 80, g: 80, b: 80 }, accent: { r: 150, g: 150, b: 150 }, name: "Black" },
|
||||
red: { primary: { r: 200, g: 30, b: 30 }, accent: { r: 255, g: 80, b: 80 }, name: "Red" },
|
||||
blue: { primary: { r: 30, g: 80, b: 200 }, accent: { r: 80, g: 150, b: 255 }, name: "Blue" },
|
||||
green: { primary: { r: 30, g: 160, b: 60 }, accent: { r: 80, g: 220, b: 100 }, name: "Green" },
|
||||
purple: { primary: { r: 120, g: 40, b: 180 }, accent: { r: 180, g: 100, b: 255 }, name: "Purple" },
|
||||
pink: { primary: { r: 200, g: 60, b: 120 }, accent: { r: 255, g: 120, b: 180 }, name: "Pink" },
|
||||
gold: { primary: { r: 180, g: 140, b: 30 }, accent: { r: 255, g: 200, b: 80 }, name: "Gold" },
|
||||
gray: { primary: { r: 100, g: 100, b: 110 }, accent: { r: 160, g: 160, b: 170 }, name: "Gray" }
|
||||
};
|
||||
|
||||
function getTheme() {
|
||||
return themes[currentTheme] || themes.red;
|
||||
}
|
||||
|
||||
// Info bar configuration
|
||||
let infoBar = {
|
||||
height: 50
|
||||
@@ -166,7 +186,23 @@ const menuData = {
|
||||
{ label: "Teleport Locations", action: "submenu", target: "teleport" },
|
||||
{ label: "World Options", action: "submenu", target: "world" },
|
||||
{ label: "Weapons", action: "submenu", target: "weapons" },
|
||||
{ label: "Fun Options", action: "submenu", target: "fun" }
|
||||
{ label: "Fun Options", action: "submenu", target: "fun" },
|
||||
{ label: "--- Settings ---", action: "none" },
|
||||
{ label: "Mod Menu Theme", action: "submenu", target: "themes" }
|
||||
]
|
||||
},
|
||||
|
||||
themes: {
|
||||
title: "MOD MENU THEME",
|
||||
items: [
|
||||
{ label: "Black", action: "theme", value: "black" },
|
||||
{ label: "Red", action: "theme", value: "red" },
|
||||
{ label: "Blue", action: "theme", value: "blue" },
|
||||
{ label: "Green", action: "theme", value: "green" },
|
||||
{ label: "Purple", action: "theme", value: "purple" },
|
||||
{ label: "Pink", action: "theme", value: "pink" },
|
||||
{ label: "Gold", action: "theme", value: "gold" },
|
||||
{ label: "Gray", action: "theme", value: "gray" }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1253,6 +1289,11 @@ function selectItem() {
|
||||
flashAlpha = 1.0;
|
||||
showNotification("FLASH!");
|
||||
break;
|
||||
|
||||
case "theme":
|
||||
currentTheme = item.value;
|
||||
showNotification("Theme: " + themes[item.value].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,126 +1486,133 @@ const vehicleModels = [
|
||||
"taxi", "taxi2", "romantaxi"
|
||||
];
|
||||
|
||||
// Vehicle model hashes for GTA IV (matching clean names)
|
||||
// Vehicle model hashes - SIGNED 32-bit integers from GTAConnected wiki
|
||||
// DO NOT use 0x prefix with decimal numbers! Use actual values.
|
||||
const vehicleHashes = {
|
||||
// Sports Cars
|
||||
"infernus": 0x18F25AC7,
|
||||
"turismo": 0x8EF34547, // Fixed hash
|
||||
"comet": 0x3F637729, // Fixed hash
|
||||
"banshee": 0xC1E908D2,
|
||||
"sultan": 0x39DA2754,
|
||||
"coquette": 0x108773431,
|
||||
"infernus": 418536135,
|
||||
"turismo": -1896659641,
|
||||
"comet": 1063483177,
|
||||
"banshee": -1041692462,
|
||||
"sultan": 970598228,
|
||||
"coquette": 108773431,
|
||||
"supergt": 1821991593,
|
||||
"futo": 2016857647,
|
||||
// Muscle Cars
|
||||
"buccaneer": 0x682211828,
|
||||
"dukes": 0x2B26F456,
|
||||
"faction": 0x2119578145,
|
||||
"ruiner": 0x227741703,
|
||||
"sabre": 0x449022887,
|
||||
"sabregt": 0x9B909C94,
|
||||
"vigero": 0xCEC6B9B7,
|
||||
"buccaneer": -682211828,
|
||||
"dukes": 723973206,
|
||||
"faction": -2119578145,
|
||||
"fortune": 627033353,
|
||||
"ruiner": -227741703,
|
||||
"sabre": -449022887,
|
||||
"sabregt": -1685021548,
|
||||
"stallion": 1923400478,
|
||||
"vigero": -825837129,
|
||||
// Sedans
|
||||
"admiral": 0x1264341792,
|
||||
"cavalcade": 0x2006918058,
|
||||
"cognoscenti": 0x2030171296,
|
||||
"emperor": 0x685276541,
|
||||
"esperanto": 0x276900515,
|
||||
"feroci": 0x974744810,
|
||||
"feltzer": 0x8911B9F5,
|
||||
"intruder": 0x886934177,
|
||||
"landstalker": 0x1269098716,
|
||||
"lokus": 0x37030056,
|
||||
"marbella": 0x1304597482,
|
||||
"merit": 0x1260881538,
|
||||
"oracle": 0x1348744438,
|
||||
"pinnacle": 0x131140572,
|
||||
"premiere": 0x1883869285,
|
||||
"presidente": 0x1962071130,
|
||||
"primo": 0x1150599089,
|
||||
"rebla": 0x83136452,
|
||||
"romero": 0x627094268,
|
||||
"schafter": 0x322343873,
|
||||
"sentinel": 0x1349725314,
|
||||
"solair": 0x1344573448,
|
||||
"stratum": 0x1723137093,
|
||||
"stretch": 0x1961627517,
|
||||
"vincent": 0x583281407,
|
||||
"virgo": 0x498054846,
|
||||
"willard": 0x1937616578,
|
||||
"washington": 0x1777363799,
|
||||
"admiral": 1264341792,
|
||||
"cognoscenti": -2030171296,
|
||||
"emperor": -685276541,
|
||||
"esperanto": -276900515,
|
||||
"feroci": 974744810,
|
||||
"feltzer": -1097828879,
|
||||
"intruder": 886934177,
|
||||
"lokus": -37030056,
|
||||
"marbella": 1304597482,
|
||||
"merit": -1260881538,
|
||||
"oracle": 1348744438,
|
||||
"pinnacle": 131140572,
|
||||
"premier": -1883869285,
|
||||
"presidente": -1962071130,
|
||||
"primo": -1150599089,
|
||||
"rebla": 83136452,
|
||||
"romero": 627094268,
|
||||
"schafter": -322343873,
|
||||
"sentinel": 1349725314,
|
||||
"solair": 1344573448,
|
||||
"stratum": 1723137093,
|
||||
"stretch": -1961627517,
|
||||
"vincent": -583281407,
|
||||
"virgo": -498054846,
|
||||
"willard": 1937616578,
|
||||
"washington": 1777363799,
|
||||
// SUVs & Trucks
|
||||
"bobcat": 0x1075851868,
|
||||
"boxville": 0x1987130134,
|
||||
"biff": 0x850991848,
|
||||
"burrito": 0x1346687836,
|
||||
"chavos": 0x67282078,
|
||||
"dilettante": 0x1130810103,
|
||||
"flatbed": 0x1353720154,
|
||||
"forklift": 0x1491375716,
|
||||
"habanero": 0x884422927,
|
||||
"huntley": 0x486987393,
|
||||
"moonbeam": 0x525509695,
|
||||
"mule": 0x904750859,
|
||||
"packer": 0x569305213,
|
||||
"patriot": 0x808457413,
|
||||
"perennial": 0x2077743597,
|
||||
"pony": 0x119658072,
|
||||
"rancher": 0x1390084576,
|
||||
"speedo": 0x810318068,
|
||||
"stockade": 0x1747439474,
|
||||
"trashmaster": 0x1917016601,
|
||||
"yankee": 0x1099960214,
|
||||
"bobcat": 1075851868,
|
||||
"cavalcade": 2006918058,
|
||||
"habanero": 884422927,
|
||||
"huntley": 486987393,
|
||||
"landstalker": 1269098716,
|
||||
"patriot": -808457413,
|
||||
"rancher": 1390084576,
|
||||
// Vans & Commercial
|
||||
"benson": 2053223216,
|
||||
"biff": 850991848,
|
||||
"boxville": -1987130134,
|
||||
"burrito": -1346687836,
|
||||
"burrito2": -907477130,
|
||||
"cabby": 1884962369,
|
||||
"flatbed": 1353720154,
|
||||
"forklift": 1491375716,
|
||||
"moonbeam": 525509695,
|
||||
"mule": 904750859,
|
||||
"packer": 569305213,
|
||||
"perennial": -2077743597,
|
||||
"pony": -119658072,
|
||||
"speedo": -810318068,
|
||||
"stockade": 1747439474,
|
||||
"trashmaster": 1917016601,
|
||||
"yankee": -1099960214,
|
||||
// Compacts
|
||||
"blista": 0x344943009,
|
||||
"futo": 0x2016857647,
|
||||
"ingot": 0x1289722222,
|
||||
"pmp600": 0x1376298265,
|
||||
"sultanrs": 0x295689028,
|
||||
"blista": -344943009,
|
||||
"chavos": -67282078,
|
||||
"dilettante": -1130810103,
|
||||
"ingot": -1289722222,
|
||||
"pmp600": 1376298265,
|
||||
"sultanrs": -295689028,
|
||||
// Motorcycles
|
||||
"faggio": 0x1842748181,
|
||||
"hellfury": 0x584879743,
|
||||
"nrg900": 0x6F039A67,
|
||||
"pcj600": 0x909201658,
|
||||
"sanchez": 0x788045382,
|
||||
"zombie": 0x570033273,
|
||||
"bobber": -1830458836,
|
||||
"faggio": -1842748181,
|
||||
"freeway": 1534326199,
|
||||
"hellfury": 584879743,
|
||||
"nrg900": 1203311498,
|
||||
"pcj600": -909201658,
|
||||
"sanchez": 788045382,
|
||||
"zombie": -570033273,
|
||||
// Emergency
|
||||
"ambulance": 0x1171614426,
|
||||
"firetruk": 0x1938952078,
|
||||
"police": 0x2046537925,
|
||||
"police2": 0x1627000575,
|
||||
"police3": 0x350085182,
|
||||
"police4": 0x1127131465,
|
||||
"nstockade": 0x1900572838,
|
||||
"pstockade": 0x1911513875,
|
||||
"fbi": 0x432EA949,
|
||||
"noose": 0x148777611,
|
||||
"ambulance": 1171614426,
|
||||
"firetruk": 1938952078,
|
||||
"police": 2046537925,
|
||||
"police2": -1627000575,
|
||||
"policepatriot": -350085182,
|
||||
"fbi": 1127131465,
|
||||
"noose": 148777611,
|
||||
"nstockade": -1900572838,
|
||||
"pstockade": 1911513875,
|
||||
// Helicopters
|
||||
"annihilator": 0x837858166,
|
||||
"maverick": 0x1660661558,
|
||||
"polmav": 0x353883353,
|
||||
"tourmav": 0x2027357303,
|
||||
"annihilator": 837858166,
|
||||
"maverick": -1660661558,
|
||||
"polmav": 353883353,
|
||||
"tourmav": 2027357303,
|
||||
// Boats
|
||||
"dinghy": 0x1033245328,
|
||||
"jetmax": 0x861409633,
|
||||
"marquis": 0x1043459709,
|
||||
"predator": 0x488123221,
|
||||
"reefer": 0x1759673526,
|
||||
"squalo": 0x400514754,
|
||||
"tropic": 0x290013743,
|
||||
"tuga": 0x1064455782,
|
||||
// Commercial
|
||||
"airtug": 0x1560980623,
|
||||
"benson": 0x2053223216,
|
||||
"burrito2": 0x907477130,
|
||||
"cabby": 0x1884962369,
|
||||
// Special
|
||||
"mrtasty": 0x583100975,
|
||||
"cablecar": 0x960289747,
|
||||
"subway": 0x800869680,
|
||||
"eltrain": 0x1953988645,
|
||||
"dinghy": 1033245328,
|
||||
"jetmax": 861409633,
|
||||
"marquis": -1043459709,
|
||||
"predator": -488123221,
|
||||
"reefer": 1759673526,
|
||||
"squalo": 400514754,
|
||||
"tropic": 290013743,
|
||||
"tuga": 1064455782,
|
||||
// Commercial & Special
|
||||
"airtug": 1560980623,
|
||||
"bus": -713569950,
|
||||
"mrtasty": 583100975,
|
||||
// Trains (may not spawn)
|
||||
"cablecar": -960289747,
|
||||
"subway": 800869680,
|
||||
"eltrain": -1953988645,
|
||||
// Taxis
|
||||
"taxi": 0x956048545,
|
||||
"taxi2": 0x1208856469,
|
||||
"romantaxi": 0x1932515764
|
||||
"taxi": -956048545,
|
||||
"taxi2": 1208856469,
|
||||
"romantaxi": -1932515764
|
||||
};
|
||||
|
||||
// Execute vehicle spawn using natives
|
||||
@@ -1603,9 +1651,11 @@ addNetworkHandler("ModMenu:ExecuteSpawnVehicle", function(vehicleName) {
|
||||
let spawnY = pos.y + Math.cos(-heading) * 5;
|
||||
let spawnZ = pos.z + 0.5;
|
||||
|
||||
// Create the car using x, y, z coordinates
|
||||
// GTA IV native: CREATE_CAR(hash, x, y, z, outVehicle, bool)
|
||||
let vehicle = natives.createCar(modelHash, spawnX, spawnY, spawnZ, true);
|
||||
// Create spawn position as Vec3 (GTAConnected requires Vec3)
|
||||
let spawnPos = new Vec3(spawnX, spawnY, spawnZ);
|
||||
|
||||
// Create the car - GTAConnected: createCar(hash, Vec3, bool)
|
||||
let vehicle = natives.createCar(modelHash, spawnPos, true);
|
||||
|
||||
if (vehicle) {
|
||||
// Set vehicle heading to match player
|
||||
@@ -1850,15 +1900,21 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let baseX = menu.x + slideOffset;
|
||||
let baseY = menu.y;
|
||||
|
||||
// ===== SMOOTH PULSING RED OUTER GLOW =====
|
||||
// ===== SMOOTH PULSING OUTER GLOW (THEMED) =====
|
||||
let theme = getTheme();
|
||||
let glowPulse = Math.sin(animTime * 2) * 0.3 + 0.7;
|
||||
let glowSize = 10 + Math.sin(animTime * 1.5) * 4;
|
||||
|
||||
// Red glow with smooth pulse
|
||||
let redIntensity = Math.floor(200 + Math.sin(animTime * 2) * 45);
|
||||
// Theme-colored glow with smooth pulse
|
||||
let glowIntensityMult = 0.8 + Math.sin(animTime * 2) * 0.2;
|
||||
for (let g = 4; g >= 1; g--) {
|
||||
let gAlpha = Math.floor((40 / g) * glowPulse * menuOpenAnim);
|
||||
let gCol = toColour(redIntensity, 0, 0, gAlpha);
|
||||
let gCol = toColour(
|
||||
Math.floor(theme.primary.r * glowIntensityMult),
|
||||
Math.floor(theme.primary.g * glowIntensityMult),
|
||||
Math.floor(theme.primary.b * glowIntensityMult),
|
||||
gAlpha
|
||||
);
|
||||
drawRect(baseX - glowSize * g, baseY - glowSize * g,
|
||||
menu.width + glowSize * g * 2, totalHeight + glowSize * g * 2 + 10, gCol);
|
||||
}
|
||||
@@ -1867,9 +1923,14 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let bgColor = toColour(8, 8, 12, Math.floor(245 * menuOpenAnim));
|
||||
drawRect(baseX, baseY, menu.width, totalHeight + 10, bgColor);
|
||||
|
||||
// ===== SMOOTH ANIMATED RED BORDER =====
|
||||
let borderPulse = Math.sin(animTime * 3) * 40 + 200;
|
||||
let borderColor = toColour(Math.floor(borderPulse), 20, 30, Math.floor(220 * menuOpenAnim));
|
||||
// ===== SMOOTH ANIMATED BORDER (THEMED) =====
|
||||
let borderPulse = Math.sin(animTime * 3) * 0.2 + 0.8;
|
||||
let borderColor = toColour(
|
||||
Math.floor(theme.primary.r * borderPulse),
|
||||
Math.floor(theme.primary.g * borderPulse),
|
||||
Math.floor(theme.primary.b * borderPulse),
|
||||
Math.floor(220 * menuOpenAnim)
|
||||
);
|
||||
|
||||
// Smooth border thickness
|
||||
let borderW = 3 + Math.sin(animTime * 3) * 0.8;
|
||||
@@ -1878,9 +1939,9 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
drawRect(baseX, baseY, borderW, totalHeight + 10, borderColor); // Left
|
||||
drawRect(baseX + menu.width - borderW, baseY, borderW, totalHeight + 10, borderColor); // Right
|
||||
|
||||
// Corner accents - smooth brighter red
|
||||
// Corner accents - smooth brighter theme color
|
||||
let cornerSize = 15 + Math.sin(animTime * 2) * 4;
|
||||
let cornerColor = toColour(255, 50, 50, Math.floor(200 * menuOpenAnim));
|
||||
let cornerColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(200 * menuOpenAnim));
|
||||
drawRect(baseX, baseY, cornerSize, 3, cornerColor);
|
||||
drawRect(baseX, baseY, 3, cornerSize, cornerColor);
|
||||
drawRect(baseX + menu.width - cornerSize, baseY, cornerSize, 3, cornerColor);
|
||||
@@ -1890,23 +1951,33 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
drawRect(baseX + menu.width - cornerSize, baseY + totalHeight + 7, cornerSize, 3, cornerColor);
|
||||
drawRect(baseX + menu.width - 3, baseY + totalHeight + 10 - cornerSize, 3, cornerSize, cornerColor);
|
||||
|
||||
// ===== HEADER - Smooth Black to Red Gradient =====
|
||||
let headerRed = Math.floor(180 + Math.sin(animTime * 2) * 30);
|
||||
let headerLeft = toColour(headerRed, 15, 25, animAlpha);
|
||||
let headerRight = toColour(60, 5, 10, animAlpha);
|
||||
// ===== HEADER - Smooth Black to Theme Gradient =====
|
||||
let headerMult = 0.7 + Math.sin(animTime * 2) * 0.15;
|
||||
let headerLeft = toColour(
|
||||
Math.floor(theme.primary.r * headerMult),
|
||||
Math.floor(theme.primary.g * headerMult * 0.3),
|
||||
Math.floor(theme.primary.b * headerMult * 0.3),
|
||||
animAlpha
|
||||
);
|
||||
let headerRight = toColour(
|
||||
Math.floor(theme.primary.r * 0.3),
|
||||
Math.floor(theme.primary.g * 0.1),
|
||||
Math.floor(theme.primary.b * 0.1),
|
||||
animAlpha
|
||||
);
|
||||
drawGradientRect(baseX + 4, baseY + 4, menu.width - 8, menu.headerHeight - 4, headerLeft, headerRight);
|
||||
|
||||
// Header smooth glow line
|
||||
let lineGlow = Math.sin(animTime * 4) * 0.3 + 0.7;
|
||||
let headerLineColor = toColour(255, 80, 80, Math.floor(150 * lineGlow * menuOpenAnim));
|
||||
let headerLineColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(150 * lineGlow * menuOpenAnim));
|
||||
drawRect(baseX + 4, baseY + menu.headerHeight - 2, menu.width - 8, 2, headerLineColor);
|
||||
|
||||
// ===== ANIMATED TITLE =====
|
||||
let titleY = baseY + 10;
|
||||
|
||||
// Title glow effect
|
||||
// Title glow effect (themed)
|
||||
let titleGlowPulse = Math.sin(titlePulse) * 0.5 + 0.5;
|
||||
let titleGlowColor = toColour(255, 50, 50, Math.floor(100 * titleGlowPulse * menuOpenAnim));
|
||||
let titleGlowColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(100 * titleGlowPulse * menuOpenAnim));
|
||||
drawText("REVOLUTION", baseX + 14, titleY + 2, titleGlowColor, 24);
|
||||
drawText("REVOLUTION", baseX + 8, titleY + 2, titleGlowColor, 24);
|
||||
|
||||
@@ -1914,10 +1985,14 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let shadowColor = toColour(0, 0, 0, Math.floor(200 * menuOpenAnim));
|
||||
drawText("REVOLUTION", baseX + 12, titleY + 3, shadowColor, 24);
|
||||
|
||||
// Main title - pulsing red to white
|
||||
let titleRed = Math.floor(255);
|
||||
let titleOther = Math.floor(180 + Math.sin(titlePulse * 2) * 75);
|
||||
let titleColor = toColour(titleRed, titleOther, titleOther, animAlpha);
|
||||
// Main title - pulsing theme to white
|
||||
let titlePulseVal = Math.sin(titlePulse * 2) * 0.3 + 0.7;
|
||||
let titleColor = toColour(
|
||||
Math.floor(255 * titlePulseVal + theme.accent.r * (1 - titlePulseVal)),
|
||||
Math.floor(255 * titlePulseVal + theme.accent.g * (1 - titlePulseVal)),
|
||||
Math.floor(255 * titlePulseVal + theme.accent.b * (1 - titlePulseVal)),
|
||||
animAlpha
|
||||
);
|
||||
drawText("REVOLUTION", baseX + 10, titleY, titleColor, 24);
|
||||
|
||||
// Subtitle with flicker
|
||||
@@ -1925,10 +2000,15 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let betaColor = toColour(180, 180, 180, Math.floor(180 * betaFlicker * menuOpenAnim));
|
||||
drawText("ModMenu (Beta)", baseX + 12, titleY + 30, betaColor, 11);
|
||||
|
||||
// Smooth animated line under title
|
||||
// Smooth animated line under title (themed)
|
||||
let lineWidth = 100 + Math.sin(animTime * 3) * 30;
|
||||
let linePulse = Math.sin(animTime * 4) * 40 + 200;
|
||||
let underlineColor = toColour(Math.floor(linePulse), 30, 40, Math.floor(220 * menuOpenAnim));
|
||||
let linePulseMult = Math.sin(animTime * 4) * 0.2 + 0.8;
|
||||
let underlineColor = toColour(
|
||||
Math.floor(theme.primary.r * linePulseMult),
|
||||
Math.floor(theme.primary.g * linePulseMult),
|
||||
Math.floor(theme.primary.b * linePulseMult),
|
||||
Math.floor(220 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + (menu.width - lineWidth) / 2, baseY + menu.headerHeight - 6, lineWidth, 2, underlineColor);
|
||||
|
||||
// ===== MENU ITEMS =====
|
||||
@@ -1949,41 +2029,71 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
// ===== SELECTED ITEM - Pulsing Red =====
|
||||
let selRed = Math.floor(150 + selectGlow * 80);
|
||||
let selColor = toColour(selRed, 20, 30, Math.floor(230 * menuOpenAnim));
|
||||
// ===== SELECTED ITEM - Pulsing Theme Color =====
|
||||
let selMult = 0.6 + selectGlow * 0.35;
|
||||
let selColor = toColour(
|
||||
Math.floor(theme.primary.r * selMult),
|
||||
Math.floor(theme.primary.g * selMult * 0.3),
|
||||
Math.floor(theme.primary.b * selMult * 0.3),
|
||||
Math.floor(230 * menuOpenAnim)
|
||||
);
|
||||
|
||||
// Outer glow
|
||||
let selGlowColor = toColour(255, 40, 50, Math.floor(50 * menuOpenAnim));
|
||||
let selGlowColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(50 * menuOpenAnim));
|
||||
drawRect(baseX + 2, itemY - 3, menu.width - 4, menu.itemHeight + 6, selGlowColor);
|
||||
|
||||
// Main selection background
|
||||
drawRect(baseX + 6 + selectOffset, itemY, menu.width - 12, menu.itemHeight - 2, selColor);
|
||||
|
||||
// Left indicator bar - smooth bright red pulsing
|
||||
let barPulse = Math.sin(selectedPulse * 1.5) * 40 + 200;
|
||||
let barColor = toColour(255, Math.floor(barPulse - 150), Math.floor(barPulse - 150), animAlpha);
|
||||
// Left indicator bar - smooth bright theme pulsing
|
||||
let barPulse = Math.sin(selectedPulse * 1.5) * 0.2 + 0.8;
|
||||
let barColor = toColour(
|
||||
Math.floor(theme.accent.r * barPulse),
|
||||
Math.floor(theme.accent.g * barPulse),
|
||||
Math.floor(theme.accent.b * barPulse),
|
||||
animAlpha
|
||||
);
|
||||
drawRect(baseX + 6, itemY, 5, menu.itemHeight - 2, barColor);
|
||||
|
||||
// Right edge highlight
|
||||
let rightColor = toColour(255, 80, 80, Math.floor(100 * menuOpenAnim));
|
||||
let rightColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(100 * menuOpenAnim));
|
||||
drawRect(baseX + menu.width - 8, itemY, 2, menu.itemHeight - 2, rightColor);
|
||||
|
||||
} else if (item.action === "none") {
|
||||
// Separator
|
||||
let sepColor = toColour(40, 15, 20, Math.floor(180 * menuOpenAnim));
|
||||
// Separator (themed)
|
||||
let sepColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.2),
|
||||
Math.floor(theme.primary.g * 0.1),
|
||||
Math.floor(theme.primary.b * 0.1),
|
||||
Math.floor(180 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 6, itemY, menu.width - 12, menu.itemHeight - 2, sepColor);
|
||||
// Separator line
|
||||
let sepLineColor = toColour(100, 30, 40, Math.floor(150 * menuOpenAnim));
|
||||
let sepLineColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.5),
|
||||
Math.floor(theme.primary.g * 0.2),
|
||||
Math.floor(theme.primary.b * 0.2),
|
||||
Math.floor(150 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 20, itemY + menu.itemHeight/2 - 1, menu.width - 40, 1, sepLineColor);
|
||||
} else {
|
||||
// Normal item - dark with subtle red tint
|
||||
let normRed = 25 + (i % 2) * 5;
|
||||
let normColor = toColour(normRed, 12, 15, Math.floor(200 * menuOpenAnim));
|
||||
// Normal item - dark with subtle theme tint
|
||||
let normTint = 0.1 + (i % 2) * 0.02;
|
||||
let normColor = toColour(
|
||||
Math.floor(theme.primary.r * normTint + 15),
|
||||
Math.floor(theme.primary.g * normTint * 0.5 + 10),
|
||||
Math.floor(theme.primary.b * normTint * 0.5 + 12),
|
||||
Math.floor(200 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 6, itemY, menu.width - 12, menu.itemHeight - 2, normColor);
|
||||
|
||||
// Subtle left border on hover area
|
||||
let leftBorderColor = toColour(80, 20, 25, Math.floor(100 * menuOpenAnim));
|
||||
// Subtle left border on hover area (themed)
|
||||
let leftBorderColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.4),
|
||||
Math.floor(theme.primary.g * 0.1),
|
||||
Math.floor(theme.primary.b * 0.1),
|
||||
Math.floor(100 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 6, itemY, 2, menu.itemHeight - 2, leftBorderColor);
|
||||
}
|
||||
|
||||
@@ -1993,7 +2103,12 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let textColor = toColour(textBright, textBright, textBright, animAlpha);
|
||||
|
||||
if (item.action === "none") {
|
||||
let sepTextColor = toColour(150, 100, 110, Math.floor(200 * menuOpenAnim));
|
||||
let sepTextColor = toColour(
|
||||
Math.floor(theme.accent.r * 0.6),
|
||||
Math.floor(theme.accent.g * 0.5),
|
||||
Math.floor(theme.accent.b * 0.5),
|
||||
Math.floor(200 * menuOpenAnim)
|
||||
);
|
||||
drawText(item.label, baseX + 20, itemY + 12, sepTextColor, 11);
|
||||
} else {
|
||||
drawText(item.label, textX, itemY + 12, textColor, 14);
|
||||
@@ -2029,31 +2144,51 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
}
|
||||
}
|
||||
|
||||
// Submenu arrow - smoother
|
||||
// Submenu arrow - smoother (themed)
|
||||
if (item.action === "submenu") {
|
||||
let arrowX = baseX + menu.width - 32 + (isSelected ? Math.sin(animTime * 5) * 3 : 0);
|
||||
let arrowBright = isSelected ? 255 : 150;
|
||||
let arrowColor = toColour(arrowBright, arrowBright * 0.6, arrowBright * 0.6, animAlpha);
|
||||
let arrowBright = isSelected ? 1.0 : 0.6;
|
||||
let arrowColor = toColour(
|
||||
Math.floor(theme.accent.r * arrowBright),
|
||||
Math.floor(theme.accent.g * arrowBright),
|
||||
Math.floor(theme.accent.b * arrowBright),
|
||||
animAlpha
|
||||
);
|
||||
drawText(">>", arrowX, itemY + 12, arrowColor, 14);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== FOOTER =====
|
||||
// ===== FOOTER (THEMED) =====
|
||||
let footerY = yPos + visibleCount * menu.itemHeight;
|
||||
let footerColor = toColour(20, 8, 12, Math.floor(230 * menuOpenAnim));
|
||||
let footerColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.1),
|
||||
Math.floor(theme.primary.g * 0.05),
|
||||
Math.floor(theme.primary.b * 0.05 + 8),
|
||||
Math.floor(230 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 4, footerY, menu.width - 8, menu.footerHeight, footerColor);
|
||||
|
||||
// Footer top line
|
||||
let footerLineColor = toColour(120, 40, 50, Math.floor(180 * menuOpenAnim));
|
||||
// Footer top line (themed)
|
||||
let footerLineColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.6),
|
||||
Math.floor(theme.primary.g * 0.2),
|
||||
Math.floor(theme.primary.b * 0.25),
|
||||
Math.floor(180 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + 4, footerY, menu.width - 8, 2, footerLineColor);
|
||||
|
||||
// Footer text
|
||||
let footerTextColor = toColour(180, 150, 150, Math.floor(200 * menuOpenAnim));
|
||||
let footerTextColor = toColour(180, 170, 170, Math.floor(200 * menuOpenAnim));
|
||||
drawText("UP/DOWN | ENTER | BACK", baseX + 25, footerY + 10, footerTextColor, 11);
|
||||
|
||||
// ===== SCROLL BAR =====
|
||||
// ===== SCROLL BAR (THEMED) =====
|
||||
if (items.length > menu.maxVisibleItems) {
|
||||
let scrollTrackColor = toColour(40, 15, 20, Math.floor(150 * menuOpenAnim));
|
||||
let scrollTrackColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.2),
|
||||
Math.floor(theme.primary.g * 0.08),
|
||||
Math.floor(theme.primary.b * 0.1),
|
||||
Math.floor(150 * menuOpenAnim)
|
||||
);
|
||||
let scrollTrackY = baseY + menu.headerHeight + 5;
|
||||
let scrollTrackH = visibleCount * menu.itemHeight - 10;
|
||||
drawRect(baseX + menu.width - 12, scrollTrackY, 6, scrollTrackH, scrollTrackColor);
|
||||
@@ -2062,51 +2197,73 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
let scrollBarH = Math.max(30, scrollTrackH * (visibleCount / items.length));
|
||||
let scrollBarY = scrollTrackY + scrollPct * (scrollTrackH - scrollBarH);
|
||||
|
||||
let scrollPulse = Math.sin(animTime * 2) * 30 + 180;
|
||||
let scrollBarColor = toColour(Math.floor(scrollPulse), 50, 60, Math.floor(220 * menuOpenAnim));
|
||||
let scrollPulse = Math.sin(animTime * 2) * 0.15 + 0.85;
|
||||
let scrollBarColor = toColour(
|
||||
Math.floor(theme.primary.r * scrollPulse),
|
||||
Math.floor(theme.primary.g * scrollPulse * 0.3),
|
||||
Math.floor(theme.primary.b * scrollPulse * 0.35),
|
||||
Math.floor(220 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX + menu.width - 12, scrollBarY, 6, scrollBarH, scrollBarColor);
|
||||
}
|
||||
|
||||
// ===== INFO BAR =====
|
||||
// ===== INFO BAR (THEMED) =====
|
||||
if (currentDescription && currentDescription.length > 0) {
|
||||
let infoY = baseY + totalHeight + 15;
|
||||
let infoBarHeight = infoBar.height;
|
||||
|
||||
// Background with glow effect
|
||||
let infoGlowPulse = Math.sin(animTime * 2) * 0.3 + 0.7;
|
||||
let infoBgColor = toColour(20, 10, 15, Math.floor(220 * menuOpenAnim));
|
||||
let infoBgColor = toColour(
|
||||
Math.floor(theme.primary.r * 0.1),
|
||||
Math.floor(theme.primary.g * 0.05),
|
||||
Math.floor(theme.primary.b * 0.07 + 10),
|
||||
Math.floor(220 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX, infoY, menu.width, infoBarHeight, infoBgColor);
|
||||
|
||||
// Animated red border (matching menu style)
|
||||
let infoBorderPulse = Math.sin(animTime * 3) * 40 + 200;
|
||||
let infoBorderColor = toColour(Math.floor(infoBorderPulse), 30, 40, Math.floor(200 * menuOpenAnim));
|
||||
// Animated themed border (matching menu style)
|
||||
let infoBorderPulse = Math.sin(animTime * 3) * 0.2 + 0.8;
|
||||
let infoBorderColor = toColour(
|
||||
Math.floor(theme.primary.r * infoBorderPulse),
|
||||
Math.floor(theme.primary.g * infoBorderPulse * 0.2),
|
||||
Math.floor(theme.primary.b * infoBorderPulse * 0.25),
|
||||
Math.floor(200 * menuOpenAnim)
|
||||
);
|
||||
drawRect(baseX, infoY, menu.width, 3, infoBorderColor); // Top
|
||||
drawRect(baseX, infoY + infoBarHeight - 3, menu.width, 3, infoBorderColor); // Bottom
|
||||
drawRect(baseX, infoY, 3, infoBarHeight, infoBorderColor); // Left
|
||||
drawRect(baseX + menu.width - 3, infoY, 3, infoBarHeight, infoBorderColor); // Right
|
||||
|
||||
// Corner accents (matching menu style)
|
||||
let cornerSize = 12 + Math.sin(animTime * 2) * 3;
|
||||
let cornerColor = toColour(255, 60, 60, Math.floor(180 * menuOpenAnim));
|
||||
drawRect(baseX, infoY, cornerSize, 3, cornerColor);
|
||||
drawRect(baseX, infoY, 3, cornerSize, cornerColor);
|
||||
drawRect(baseX + menu.width - cornerSize, infoY, cornerSize, 3, cornerColor);
|
||||
drawRect(baseX + menu.width - cornerSize, infoY, 3, cornerSize, cornerColor);
|
||||
drawRect(baseX, infoY + infoBarHeight - cornerSize, infoY, 3, cornerSize, cornerColor);
|
||||
drawRect(baseX + menu.width - cornerSize, infoY + infoBarHeight - cornerSize, infoY, 3, cornerSize, cornerColor);
|
||||
// Corner accents (themed)
|
||||
let infoCornerSize = 12 + Math.sin(animTime * 2) * 3;
|
||||
let infoCornerColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(180 * menuOpenAnim));
|
||||
drawRect(baseX, infoY, infoCornerSize, 3, infoCornerColor);
|
||||
drawRect(baseX, infoY, 3, infoCornerSize, infoCornerColor);
|
||||
drawRect(baseX + menu.width - infoCornerSize, infoY, infoCornerSize, 3, infoCornerColor);
|
||||
drawRect(baseX + menu.width - 3, infoY, 3, infoCornerSize, infoCornerColor);
|
||||
drawRect(baseX, infoY + infoBarHeight - 3, infoCornerSize, 3, infoCornerColor);
|
||||
drawRect(baseX, infoY + infoBarHeight - infoCornerSize, 3, infoCornerSize, infoCornerColor);
|
||||
drawRect(baseX + menu.width - infoCornerSize, infoY + infoBarHeight - 3, infoCornerSize, 3, infoCornerColor);
|
||||
drawRect(baseX + menu.width - 3, infoY + infoBarHeight - infoCornerSize, 3, infoCornerSize, infoCornerColor);
|
||||
|
||||
// Description text with glow effect
|
||||
let textGlow = Math.sin(animTime * 4) * 0.4 + 0.6;
|
||||
let glowColor = toColour(255, 80, 80, Math.floor(30 * textGlow * menuOpenAnim));
|
||||
let glowColor = toColour(theme.accent.r, theme.accent.g, theme.accent.b, Math.floor(30 * textGlow * menuOpenAnim));
|
||||
drawText(currentDescription, baseX + 14, infoY + 18, glowColor, 14);
|
||||
|
||||
// Main description text
|
||||
let textColor = toColour(255, 255, 255, Math.floor(255 * menuOpenAnim));
|
||||
drawText(currentDescription, baseX + 12, infoY + 18, textColor, 12);
|
||||
|
||||
// "INFO" label
|
||||
let labelColor = toColour(200, 100, 100, Math.floor(200 * menuOpenAnim));
|
||||
drawText("ℹ INFO", baseX + 12, infoY + 2, labelColor, 10);
|
||||
// "INFO" label (themed)
|
||||
let labelColor = toColour(
|
||||
Math.floor(theme.accent.r * 0.8),
|
||||
Math.floor(theme.accent.g * 0.5),
|
||||
Math.floor(theme.accent.b * 0.5),
|
||||
Math.floor(200 * menuOpenAnim)
|
||||
);
|
||||
drawText("INFO", baseX + 12, infoY + 2, labelColor, 10);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2196,6 +2353,75 @@ addEventHandler("OnDrawnHUD", function(event) {
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// STATUS INDICATOR - Shows active toggles at bottom of screen
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnDrawnHUD", function(event) {
|
||||
// Get active toggles
|
||||
let activeToggles = [];
|
||||
|
||||
// Define display names for toggles
|
||||
let toggleDisplayNames = {
|
||||
godMode: "God Mode",
|
||||
invincible: "Invincible",
|
||||
superRun: "Super Run",
|
||||
noRagdoll: "No Ragdoll",
|
||||
neverWanted: "Never Wanted",
|
||||
vehGodMode: "Vehicle God Mode",
|
||||
driveOnWater: "Drive On Water",
|
||||
rainbowCar: "Rainbow Car",
|
||||
driftMode: "Drift Mode",
|
||||
neonLights: "Neon Lights",
|
||||
flyMode: "Fly Mode",
|
||||
vehShootRPG: "Vehicle RPG",
|
||||
rainbowSky: "Rainbow Sky",
|
||||
explosiveAmmo: "Explosive Ammo",
|
||||
moonGravity: "Moon Gravity",
|
||||
drunkMode: "Drunk Mode",
|
||||
matrixMode: "Matrix Mode",
|
||||
thermalVision: "Thermal Vision",
|
||||
nightVision: "Night Vision"
|
||||
};
|
||||
|
||||
// Collect active toggles
|
||||
for (let key in toggleStates) {
|
||||
if (toggleStates[key] === true && toggleDisplayNames[key]) {
|
||||
activeToggles.push(toggleDisplayNames[key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Only draw if there are active toggles
|
||||
if (activeToggles.length === 0) return;
|
||||
|
||||
// Screen dimensions (approximate - GTAConnected usually uses 1920x1080 ref)
|
||||
let screenWidth = 1920;
|
||||
let screenHeight = 1080;
|
||||
|
||||
// Position at bottom center
|
||||
let statusText = activeToggles.join(" | ");
|
||||
let textWidth = statusText.length * 7; // Approximate character width
|
||||
let boxWidth = textWidth + 40;
|
||||
let boxHeight = 28;
|
||||
let boxX = (screenWidth - boxWidth) / 2;
|
||||
let boxY = screenHeight - 45;
|
||||
|
||||
// Background - dark semi-transparent
|
||||
let bgColor = toColour(15, 15, 20, 180);
|
||||
drawRect(boxX, boxY, boxWidth, boxHeight, bgColor);
|
||||
|
||||
// Border - green to indicate active
|
||||
let borderColor = toColour(50, 200, 80, 220);
|
||||
drawRect(boxX, boxY, boxWidth, 2, borderColor); // Top
|
||||
drawRect(boxX, boxY + boxHeight - 2, boxWidth, 2, borderColor); // Bottom
|
||||
drawRect(boxX, boxY, 2, boxHeight, borderColor); // Left
|
||||
drawRect(boxX + boxWidth - 2, boxY, 2, boxHeight, borderColor); // Right
|
||||
|
||||
// Text - bright green for ON status
|
||||
let textColor = toColour(80, 255, 120, 255);
|
||||
drawText(statusText, boxX + 20, boxY + 6, textColor, 12);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// TOGGLE EFFECTS
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user