diff --git a/resources/modmenu/client.js b/resources/modmenu/client.js index 1606ddf..7c4bd53 100644 --- a/resources/modmenu/client.js +++ b/resources/modmenu/client.js @@ -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 // ============================================================================