Enhance Trident UI with advanced visual elements

- Add animated outer glow/shadow effects around menu
- Add decorative corner elements with pulsing animations
- Enhance header with shimmer effect and gradient backgrounds
- Add multi-layer selection highlight with glow effects
- Add animated scrollbar with thumb glow
- Add enhanced footer with styled navigation hints
- Add Player Status panel (health/armor bars, wanted level, vehicle status)
- Add real-time clock display with date
- Add active toggles indicator (shows when menu closed)
- Add bottom screen banner with branding
- Add floating particle effects around menu
- Add sparkle effects on menu corners
- Add Trident Edition badge above menu
- Improve info bar with styled border and label box
- Add page indicator for scrollable menus
This commit is contained in:
Claude
2026-01-19 02:54:58 +00:00
parent e9d93229c6
commit 983099e95e

View File

@@ -84,6 +84,19 @@ let Fading_100 = 100; // Fade in effect
let Fading_150 = 150; // Fade in effect let Fading_150 = 150; // Fade in effect
let dropdown_y = 1.2; // Dropdown animation let dropdown_y = 1.2; // Dropdown animation
// Enhanced UI Animation State
let borderGlow = 0; // Animated border glow (0-1)
let borderGlowIncrement = true;
let cornerPulse = 0; // Corner decoration pulse
let headerWaveOffset = 0; // Header wave animation
let scrollbarPulse = 0; // Scrollbar glow pulse
let logoRotation = 0; // Logo rotation angle
let statsUpdateTime = 0; // Stats panel update timer
let particleArray = []; // Particle system
let bannerShimmer = 0; // Banner shimmer effect
let footerPulse = 0; // Footer pulse animation
let itemHoverScale = []; // Per-item hover scale
// ============================================================================ // ============================================================================
// THEME SYSTEM // THEME SYSTEM
// ============================================================================ // ============================================================================
@@ -2454,6 +2467,33 @@ addEventHandler("OnProcess", function(event) {
if (dropdown_y > 0.96) dropdown_y -= 0.01; if (dropdown_y > 0.96) dropdown_y -= 0.01;
else dropdown_y = 0.95; else dropdown_y = 0.95;
// ===== Enhanced UI Animations =====
// Border glow effect (0-1 smooth pulse)
if (borderGlow >= 1) borderGlowIncrement = false;
else if (borderGlow <= 0) borderGlowIncrement = true;
borderGlow += borderGlowIncrement ? 0.015 : -0.015;
// Corner pulse effect
cornerPulse = (cornerPulse + 0.03) % (Math.PI * 2);
// Header wave animation
headerWaveOffset = (headerWaveOffset + 0.05) % (Math.PI * 2);
// Scrollbar pulse
scrollbarPulse = (scrollbarPulse + 0.08) % (Math.PI * 2);
// Logo rotation (slow spin)
logoRotation = (logoRotation + 0.5) % 360;
// Banner shimmer effect
bannerShimmer = (bannerShimmer + 0.04) % (Math.PI * 2);
// Footer pulse
footerPulse = (footerPulse + 0.05) % (Math.PI * 2);
// Stats update timer
statsUpdateTime += 0.02;
// Screen shake decay // Screen shake decay
if (screenShake > 0) { if (screenShake > 0) {
screenShake -= 0.1; screenShake -= 0.1;
@@ -2577,44 +2617,106 @@ addEventHandler("OnDrawnHUD", function(event) {
let baseX = menu.x + slideOffset; let baseX = menu.x + slideOffset;
let baseY = menu.y; let baseY = menu.y;
// ===== MDB WINDOW BACKGROUND - Steelblue (70,130,180) alpha 180 ===== // ===== ENHANCED OUTER GLOW/SHADOW =====
// Matches: DRAW_SPRITE(MAP_LOBBY, ..., 70,130,180, 180) let glowIntensity = 0.3 + borderGlow * 0.2;
let windowBgColor = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(180 * menuOpenAnim)); let outerGlowColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(40 * glowIntensity * menuOpenAnim));
drawRect(baseX - 8, baseY - 8, menu.width + 16, totalHeight + 26, outerGlowColor);
let shadowBg = toColour(0, 0, 0, Math.floor(120 * menuOpenAnim));
drawRect(baseX - 4, baseY - 4, menu.width + 8, totalHeight + 18, shadowBg);
// ===== MDB WINDOW BACKGROUND - Enhanced gradient-style =====
let windowBgColor = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(190 * menuOpenAnim));
drawRect(baseX, baseY, menu.width, totalHeight + 10, windowBgColor); drawRect(baseX, baseY, menu.width, totalHeight + 10, windowBgColor);
// ===== MDB HEADER SECTION ===== // Inner darker panel for depth
let headerY = baseY + 5; let innerBgColor = toColour(30, 50, 70, Math.floor(100 * menuOpenAnim));
drawRect(baseX + 3, baseY + 3, menu.width - 6, totalHeight + 4, innerBgColor);
// "MD" Prefix - Steelblue, large text (Version_Txt_Size equivalent) // ===== ANIMATED BORDER =====
// Shadow first let borderAlpha = Math.floor((180 + borderGlow * 75) * menuOpenAnim);
let borderColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, borderAlpha);
// Top border
drawRect(baseX, baseY, menu.width, 2, borderColor);
// Bottom border
drawRect(baseX, baseY + totalHeight + 8, menu.width, 2, borderColor);
// Left border
drawRect(baseX, baseY, 2, totalHeight + 10, borderColor);
// Right border
drawRect(baseX + menu.width - 2, baseY, 2, totalHeight + 10, borderColor);
// ===== DECORATIVE CORNER ELEMENTS =====
let cornerSize = 12;
let cornerAlpha = Math.floor((200 + Math.sin(cornerPulse) * 55) * menuOpenAnim);
let cornerColor = toColour(255, 200, 100, cornerAlpha);
// Top-left corner
drawRect(baseX, baseY, cornerSize, 3, cornerColor);
drawRect(baseX, baseY, 3, cornerSize, cornerColor);
// Top-right corner
drawRect(baseX + menu.width - cornerSize, baseY, cornerSize, 3, cornerColor);
drawRect(baseX + menu.width - 3, baseY, 3, cornerSize, cornerColor);
// Bottom-left corner
drawRect(baseX, baseY + totalHeight + 7, cornerSize, 3, cornerColor);
drawRect(baseX, baseY + totalHeight + 10 - cornerSize, 3, cornerSize, cornerColor);
// Bottom-right corner
drawRect(baseX + menu.width - cornerSize, baseY + totalHeight + 7, cornerSize, 3, cornerColor);
drawRect(baseX + menu.width - 3, baseY + totalHeight + 10 - cornerSize, 3, cornerSize, cornerColor);
// ===== ENHANCED HEADER BANNER =====
let headerY = baseY + 5;
// Header background gradient
let headerBg1 = toColour(40, 60, 90, Math.floor(220 * menuOpenAnim));
let headerBg2 = toColour(60, 90, 130, Math.floor(220 * menuOpenAnim));
drawRect(baseX + 4, headerY - 2, menu.width - 8, 55, headerBg1);
// Header shimmer effect
let shimmerX = baseX + 4 + ((Math.sin(bannerShimmer) + 1) * 0.5) * (menu.width - 80);
let shimmerColor = toColour(255, 255, 255, Math.floor(30 * menuOpenAnim));
drawRect(shimmerX, headerY - 2, 60, 55, shimmerColor);
// "MD" Prefix - Enhanced with glow
let shadowColor = toColour(0, 0, 0, Math.floor(255 * menuOpenAnim)); let shadowColor = toColour(0, 0, 0, Math.floor(255 * menuOpenAnim));
drawText("MD", baseX + 13, headerY + 3, shadowColor, 28);
drawText("MD", baseX + 11, headerY + 1, shadowColor, 28); drawText("MD", baseX + 11, headerY + 1, shadowColor, 28);
// Main "MD" in Steelblue // Main "MD" in bright Steelblue
let mdColor = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, animAlpha); let mdGlowColor = toColour(100, 160, 220, Math.floor(FlashingGhost * menuOpenAnim));
let mdColor = toColour(MDB.Steelblue.r + 30, MDB.Steelblue.g + 30, MDB.Steelblue.b + 30, animAlpha);
drawText("MD", baseX + 10, headerY, mdGlowColor, 28);
drawText("MD", baseX + 10, headerY, mdColor, 28); drawText("MD", baseX + 10, headerY, mdColor, 28);
// Menu Header Text - Gold with FlashingGhost alpha (Extend_Txt_Size equivalent) // "REVOLUTION" - Enhanced with glow effect
// Shadow drawText("REVOLUTION", baseX + 58, headerY + 8, shadowColor, 20);
drawText("REVOLUTION", baseX + 56, headerY + 6, shadowColor, 20); drawText("REVOLUTION", baseX + 56, headerY + 6, shadowColor, 20);
// Main header in Gold with FlashingGhost effect // Main header in Gold with enhanced FlashingGhost effect
let headerGoldColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(FlashingGhost * menuOpenAnim)); let headerGlowColor = toColour(255, 200, 100, Math.floor(FlashingGhost * 0.7 * menuOpenAnim));
let headerGoldColor = toColour(MDB.Gold.r + 40, MDB.Gold.g + 40, MDB.Gold.b, Math.floor(FlashingGhost * menuOpenAnim));
drawText("REVOLUTION", baseX + 55, headerY + 5, headerGlowColor, 20);
drawText("REVOLUTION", baseX + 55, headerY + 5, headerGoldColor, 20); drawText("REVOLUTION", baseX + 55, headerY + 5, headerGoldColor, 20);
// Version text - Steelblue (right side) // Version badge - Enhanced with box
let versionColor = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, animAlpha); let badgeX = baseX + menu.width - 78;
drawText("TRIDENT", baseX + menu.width - 70, headerY + 22, versionColor, 12); let badgeY = headerY + 18;
let badgeBg = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(200 * menuOpenAnim));
drawRect(badgeX - 4, badgeY - 2, 70, 18, badgeBg);
let versionColor = toColour(255, 255, 255, animAlpha);
drawText("TRIDENT", badgeX, badgeY + 2, versionColor, 11);
// Sub Header - centered, SubHeader color (58,95,205) // Sub Header - Enhanced with underline effect
let subHeaderColor = toColour(MDB.SubHeader.r, MDB.SubHeader.g, MDB.SubHeader.b, animAlpha); let subHeaderColor = toColour(MDB.SubHeader.r + 40, MDB.SubHeader.g + 40, MDB.SubHeader.b + 40, animAlpha);
let subHeaderText = currentMenu === "main" ? "MAJOR DISTRIBUTION" : title; let subHeaderText = currentMenu === "main" ? "MAJOR DISTRIBUTION" : title;
// Calculate center position let subHeaderX = baseX + (menu.width / 2) - (subHeaderText.length * 3.5);
let subHeaderX = baseX + (menu.width / 2) - (subHeaderText.length * 3); drawText(subHeaderText, subHeaderX + 1, headerY + 40, shadowColor, 12);
drawText(subHeaderText, subHeaderX, headerY + 38, subHeaderColor, 12); drawText(subHeaderText, subHeaderX, headerY + 39, subHeaderColor, 12);
// ===== MDB WHITE LINE SEPARATOR ===== // ===== ENHANCED WHITE LINE SEPARATOR =====
// DRAW_RECT(..., Line_r=255, Line_g=255, Line_b=255, 255) // Gradient-style separator
let lineColor = toColour(MDB.Line.r, MDB.Line.g, MDB.Line.b, animAlpha); let lineColorL = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(200 * menuOpenAnim));
drawRect(baseX + 10, baseY + menu.headerHeight - 5, menu.width - 20, 2, lineColor); let lineColorC = toColour(MDB.Line.r, MDB.Line.g, MDB.Line.b, animAlpha);
let lineColorR = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(200 * menuOpenAnim));
drawRect(baseX + 10, baseY + menu.headerHeight - 5, 30, 2, lineColorL);
drawRect(baseX + 40, baseY + menu.headerHeight - 5, menu.width - 80, 2, lineColorC);
drawRect(baseX + menu.width - 40, baseY + menu.headerHeight - 5, 30, 2, lineColorR);
// Add glow line under
let glowLineColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(60 * borderGlow * menuOpenAnim));
drawRect(baseX + 10, baseY + menu.headerHeight - 3, menu.width - 20, 3, glowLineColor);
// ===== MDB MENU ITEMS ===== // ===== MDB MENU ITEMS =====
let yPos = baseY + menu.headerHeight; let yPos = baseY + menu.headerHeight;
@@ -2626,14 +2728,29 @@ addEventHandler("OnDrawnHUD", function(event) {
let itemY = yPos + (i - scrollOffset) * menu.itemHeight; let itemY = yPos + (i - scrollOffset) * menu.itemHeight;
if (isSelected) { if (isSelected) {
// ===== MDB SELECTED ITEM - Scrollbar with Glowing effect ===== // ===== ENHANCED SELECTED ITEM - Multi-layer glow effect =====
// DRAW_RECT(..., Glowing, Glowing, 200, 150) // Outer glow
let scrollbarColor = toColour(Glowing, Glowing, 200, Math.floor(150 * menuOpenAnim)); let outerGlowAlpha = Math.floor((80 + Math.sin(scrollbarPulse) * 40) * menuOpenAnim);
let outerGlowCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, outerGlowAlpha);
drawRect(baseX + 4, itemY - 2, menu.width - 8, menu.itemHeight + 2, outerGlowCol);
// Main selection background with enhanced Glowing effect
let scrollbarAlpha = Math.floor((160 + Math.sin(scrollbarPulse) * 30) * menuOpenAnim);
let scrollbarColor = toColour(Glowing, Glowing + 30, 220, scrollbarAlpha);
drawRect(baseX + 6, itemY, menu.width - 12, menu.itemHeight - 2, scrollbarColor); drawRect(baseX + 6, itemY, menu.width - 12, menu.itemHeight - 2, scrollbarColor);
// Inner highlight line (top)
let highlightLineColor = toColour(255, 255, 255, Math.floor(100 * menuOpenAnim));
drawRect(baseX + 8, itemY + 1, menu.width - 16, 1, highlightLineColor);
// Left accent bar
let accentColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, animAlpha);
drawRect(baseX + 6, itemY + 2, 3, menu.itemHeight - 6, accentColor);
} else if (item.action === "none") { } else if (item.action === "none") {
// ===== MDB Separator/JumpOver ===== // ===== MDB Separator/JumpOver - Enhanced with subtle line =====
// No background, just different text color let sepLineColor = toColour(MDB.JumpOver.r, MDB.JumpOver.g, MDB.JumpOver.b, Math.floor(80 * menuOpenAnim));
drawRect(baseX + 20, itemY + menu.itemHeight - 4, menu.width - 40, 1, sepLineColor);
} }
// Normal items have no background in MDB style (transparent over Steelblue window) // Normal items have no background in MDB style (transparent over Steelblue window)
@@ -2687,18 +2804,59 @@ addEventHandler("OnDrawnHUD", function(event) {
} }
} }
// ===== MDB HELPER TEXT (Bottom of screen style) ===== // ===== ENHANCED FOOTER =====
// In MDB this appears at bottom of screen, we'll put in footer area
let footerY = yPos + visibleCount * menu.itemHeight; let footerY = yPos + visibleCount * menu.itemHeight;
// Simple footer with MDB style helper text // Footer background with gradient effect
let helperColor = toColour(MDB.Orange.r, MDB.Orange.g, MDB.Orange.b, animAlpha); let footerBgColor = toColour(30, 50, 70, Math.floor(180 * menuOpenAnim));
let helperTextColor = toColour(MDB.StatsItem.r, MDB.StatsItem.g, MDB.StatsItem.b, Math.floor(200 * menuOpenAnim)); drawRect(baseX + 4, footerY + 2, menu.width - 8, menu.footerHeight - 4, footerBgColor);
drawText("[UP/DOWN] Navigate [ENTER] Select [BACKSPACE] Back", baseX + 15, footerY + 10, helperTextColor, 10); // Footer top line
let footerLineColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor((150 + Math.sin(footerPulse) * 50) * menuOpenAnim));
drawRect(baseX + 10, footerY + 2, menu.width - 20, 1, footerLineColor);
// ===== MDB SCROLL INDICATORS ===== // Navigation hints with icons
let helperTextColor = toColour(MDB.StatsItem.r, MDB.StatsItem.g, MDB.StatsItem.b, Math.floor(220 * menuOpenAnim));
let helperAccentColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(220 * menuOpenAnim));
// Draw key hints
drawText("[", baseX + 12, footerY + 12, helperAccentColor, 10);
drawText("UP/DOWN", baseX + 18, footerY + 12, helperTextColor, 10);
drawText("]", baseX + 68, footerY + 12, helperAccentColor, 10);
drawText("Navigate", baseX + 76, footerY + 12, helperTextColor, 9);
drawText("[", baseX + 130, footerY + 12, helperAccentColor, 10);
drawText("ENTER", baseX + 136, footerY + 12, helperTextColor, 10);
drawText("]", baseX + 172, footerY + 12, helperAccentColor, 10);
drawText("Select", baseX + 180, footerY + 12, helperTextColor, 9);
drawText("[", baseX + 225, footerY + 12, helperAccentColor, 10);
drawText("BACK", baseX + 231, footerY + 12, helperTextColor, 10);
drawText("]", baseX + 260, footerY + 12, helperAccentColor, 10);
drawText("Return", baseX + 268, footerY + 12, helperTextColor, 9);
// ===== ENHANCED SCROLLBAR (RIGHT SIDE) =====
if (items.length > menu.maxVisibleItems) { if (items.length > menu.maxVisibleItems) {
let scrollbarX = baseX + menu.width - 10;
let scrollbarY = baseY + menu.headerHeight + 5;
let scrollbarH = visibleCount * menu.itemHeight - 10;
let maxScroll = items.length - visibleCount;
let scrollProgress = scrollOffset / maxScroll;
let thumbH = Math.max(30, scrollbarH * (visibleCount / items.length));
let thumbY = scrollbarY + scrollProgress * (scrollbarH - thumbH);
// Scrollbar track
let trackColor = toColour(40, 40, 50, Math.floor(150 * menuOpenAnim));
drawRect(scrollbarX, scrollbarY, 5, scrollbarH, trackColor);
// Scrollbar thumb with glow
let thumbGlowAlpha = Math.floor((60 + Math.sin(scrollbarPulse) * 30) * menuOpenAnim);
let thumbGlowColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, thumbGlowAlpha);
drawRect(scrollbarX - 1, thumbY - 1, 7, thumbH + 2, thumbGlowColor);
let thumbColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(220 * menuOpenAnim));
drawRect(scrollbarX, thumbY, 5, thumbH, thumbColor);
// Up arrow - Gold color, show when not at top // Up arrow - Gold color, show when not at top
if (scrollOffset > 0) { if (scrollOffset > 0) {
let upArrowY = baseY + menu.headerHeight + 2; let upArrowY = baseY + menu.headerHeight + 2;
@@ -2707,34 +2865,49 @@ addEventHandler("OnDrawnHUD", function(event) {
} }
// Down arrow - Gold color, show when not at bottom // Down arrow - Gold color, show when not at bottom
let maxScroll = items.length - visibleCount;
if (scrollOffset < maxScroll) { if (scrollOffset < maxScroll) {
let downArrowY = footerY - 16; let downArrowY = footerY - 16;
let downArrowColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(FlashingGhost * menuOpenAnim)); let downArrowColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(FlashingGhost * menuOpenAnim));
drawText("v", baseX + menu.width / 2 - 5, downArrowY, downArrowColor, 14); drawText("v", baseX + menu.width / 2 - 5, downArrowY, downArrowColor, 14);
} }
// Page indicator
let pageText = (scrollOffset + 1) + "/" + (maxScroll + 1);
let pageColor = toColour(150, 150, 160, Math.floor(180 * menuOpenAnim));
drawText(pageText, baseX + menu.width - 45, footerY + 12, pageColor, 9);
} }
// ===== MDB INFO BAR ===== // ===== ENHANCED INFO BAR =====
if (currentDescription && currentDescription.length > 0) { if (currentDescription && currentDescription.length > 0) {
let infoY = baseY + totalHeight + 15; let infoY = baseY + totalHeight + 15;
let infoBarHeight = infoBar.height; let infoBarHeight = infoBar.height + 5;
// Background - Steelblue like window // Shadow
let infoBgColor = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(160 * menuOpenAnim)); let infoShadow = toColour(0, 0, 0, Math.floor(100 * menuOpenAnim));
drawRect(baseX - 2, infoY - 2, menu.width + 4, infoBarHeight + 4, infoShadow);
// Background - Enhanced with gradient look
let infoBgColor = toColour(MDB.Steelblue.r - 20, MDB.Steelblue.g - 20, MDB.Steelblue.b - 20, Math.floor(200 * menuOpenAnim));
drawRect(baseX, infoY, menu.width, infoBarHeight, infoBgColor); drawRect(baseX, infoY, menu.width, infoBarHeight, infoBgColor);
// White line at top // Border
let infoLineColor = toColour(MDB.Line.r, MDB.Line.g, MDB.Line.b, animAlpha); let infoBorderColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(180 * menuOpenAnim));
drawRect(baseX + 10, infoY + 2, menu.width - 20, 2, infoLineColor); drawRect(baseX, infoY, menu.width, 2, infoBorderColor);
drawRect(baseX, infoY + infoBarHeight - 2, menu.width, 2, infoBorderColor);
drawRect(baseX, infoY, 2, infoBarHeight, infoBorderColor);
drawRect(baseX + menu.width - 2, infoY, 2, infoBarHeight, infoBorderColor);
// "INFO" label in Gold // "INFO" label box
let infoLabelColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, animAlpha); let infoLabelBg = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(200 * menuOpenAnim));
drawText("INFO", baseX + 12, infoY + 6, infoLabelColor, 10); drawRect(baseX + 8, infoY + 6, 40, 16, infoLabelBg);
let infoLabelColor = toColour(0, 0, 0, animAlpha);
drawText("INFO", baseX + 12, infoY + 8, infoLabelColor, 10);
// Description text - white // Description text - white with shadow
let descShadow = toColour(0, 0, 0, Math.floor(200 * menuOpenAnim));
let descColor = toColour(MDB.StatsItem.r, MDB.StatsItem.g, MDB.StatsItem.b, animAlpha); let descColor = toColour(MDB.StatsItem.r, MDB.StatsItem.g, MDB.StatsItem.b, animAlpha);
drawText(currentDescription, baseX + 12, infoY + 20, descColor, 11); drawText(currentDescription, baseX + 13, infoY + 28, descShadow, 11);
drawText(currentDescription, baseX + 12, infoY + 27, descColor, 11);
} }
}); });
@@ -2829,6 +3002,346 @@ addEventHandler("OnDrawnHUD", function(event) {
} }
}); });
// ============================================================================
// PLAYER STATS PANEL - Shows player info when menu is open
// ============================================================================
addEventHandler("OnDrawnHUD", function(event) {
if (menuOpenAnim <= 0) return;
if (!localPlayer) return;
let alpha = Math.floor(255 * menuOpenAnim);
let theme = getTheme();
// Panel position (top-left of screen)
let panelX = 30;
let panelY = 100;
let panelW = 220;
let panelH = 240;
// Slide in animation from left
let slideOffset = (1 - menuOpenAnim) * -100;
panelX += slideOffset;
// ===== PANEL SHADOW =====
let shadowColor = toColour(0, 0, 0, Math.floor(100 * menuOpenAnim));
drawRect(panelX - 3, panelY - 3, panelW + 6, panelH + 6, shadowColor);
// ===== PANEL BACKGROUND =====
let bgColor = toColour(MDB.Steelblue.r - 30, MDB.Steelblue.g - 30, MDB.Steelblue.b - 30, Math.floor(200 * menuOpenAnim));
drawRect(panelX, panelY, panelW, panelH, bgColor);
// Inner panel
let innerBg = toColour(20, 35, 55, Math.floor(150 * menuOpenAnim));
drawRect(panelX + 3, panelY + 3, panelW - 6, panelH - 6, innerBg);
// ===== PANEL BORDER =====
let borderCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor((180 + borderGlow * 50) * menuOpenAnim));
drawRect(panelX, panelY, panelW, 2, borderCol);
drawRect(panelX, panelY + panelH - 2, panelW, 2, borderCol);
drawRect(panelX, panelY, 2, panelH, borderCol);
drawRect(panelX + panelW - 2, panelY, 2, panelH, borderCol);
// Corner accents
let cornerCol = toColour(255, 200, 100, Math.floor((200 + Math.sin(cornerPulse) * 55) * menuOpenAnim));
drawRect(panelX, panelY, 10, 2, cornerCol);
drawRect(panelX, panelY, 2, 10, cornerCol);
drawRect(panelX + panelW - 10, panelY, 10, 2, cornerCol);
drawRect(panelX + panelW - 2, panelY, 2, 10, cornerCol);
// ===== HEADER =====
let headerBg = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(220 * menuOpenAnim));
drawRect(panelX + 4, panelY + 4, panelW - 8, 28, headerBg);
let titleCol = toColour(255, 255, 255, alpha);
let titleShadow = toColour(0, 0, 0, alpha);
drawText("PLAYER STATUS", panelX + 11, panelY + 10, titleShadow, 13);
drawText("PLAYER STATUS", panelX + 10, panelY + 9, titleCol, 13);
// ===== STATS CONTENT =====
let contentY = panelY + 40;
let labelCol = toColour(MDB.Item.r, MDB.Item.g, MDB.Item.b, alpha);
let valueCol = toColour(255, 255, 255, alpha);
let rowH = 24;
// Health bar
drawText("Health", panelX + 12, contentY, labelCol, 10);
let health = localPlayer.health || 0;
let maxHealth = 200;
let healthPct = Math.min(1, health / maxHealth);
let healthBarBg = toColour(40, 40, 50, alpha);
drawRect(panelX + 12, contentY + 14, panelW - 24, 8, healthBarBg);
let healthCol = healthPct > 0.5 ? toColour(50, 200, 50, alpha) : healthPct > 0.25 ? toColour(255, 200, 0, alpha) : toColour(255, 50, 50, alpha);
drawRect(panelX + 12, contentY + 14, (panelW - 24) * healthPct, 8, healthCol);
drawText(Math.floor(health), panelX + panelW - 40, contentY, valueCol, 10);
contentY += rowH + 4;
// Armor bar
drawText("Armor", panelX + 12, contentY, labelCol, 10);
let armor = localPlayer.armour || 0;
let armorPct = Math.min(1, armor / 100);
drawRect(panelX + 12, contentY + 14, panelW - 24, 8, healthBarBg);
let armorCol = toColour(100, 150, 255, alpha);
drawRect(panelX + 12, contentY + 14, (panelW - 24) * armorPct, 8, armorCol);
drawText(Math.floor(armor), panelX + panelW - 40, contentY, valueCol, 10);
contentY += rowH + 8;
// Separator line
let sepCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(100 * menuOpenAnim));
drawRect(panelX + 10, contentY, panelW - 20, 1, sepCol);
contentY += 8;
// Wanted Level
drawText("Wanted Level", panelX + 12, contentY, labelCol, 10);
let wanted = 0;
try { wanted = localPlayer.wantedLevel || 0; } catch(e) {}
// Draw stars
for (let i = 0; i < 6; i++) {
let starCol = i < wanted ? toColour(255, 200, 0, alpha) : toColour(60, 60, 70, alpha);
drawRect(panelX + 100 + i * 18, contentY + 2, 12, 12, starCol);
}
contentY += rowH;
// Vehicle Status
drawText("Vehicle", panelX + 12, contentY, labelCol, 10);
let vehStatus = "On Foot";
let vehStatusCol = toColour(150, 150, 150, alpha);
if (localPlayer.vehicle) {
vehStatus = "In Vehicle";
vehStatusCol = toColour(100, 255, 100, alpha);
}
drawText(vehStatus, panelX + 100, contentY, vehStatusCol, 10);
contentY += rowH;
// Active Toggles Counter
drawText("Active Mods", panelX + 12, contentY, labelCol, 10);
let activeCount = 0;
for (let key in toggleStates) {
if (toggleStates[key]) activeCount++;
}
let modCountCol = activeCount > 0 ? toColour(MDB.ItemHighlight.r, MDB.ItemHighlight.g, MDB.ItemHighlight.b, alpha) : valueCol;
drawText(activeCount.toString(), panelX + 100, contentY, modCountCol, 10);
contentY += rowH + 8;
// ===== CLOCK / TIME DISPLAY =====
let clockY = panelY + panelH - 35;
drawRect(panelX + 10, clockY - 5, panelW - 20, 1, sepCol);
// Get current time
let now = new Date();
let hours = now.getHours().toString().padStart(2, '0');
let mins = now.getMinutes().toString().padStart(2, '0');
let secs = now.getSeconds().toString().padStart(2, '0');
let timeStr = hours + ":" + mins + ":" + secs;
// Time display with pulsing colon effect
let clockBg = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, Math.floor(180 * menuOpenAnim));
drawRect(panelX + panelW / 2 - 45, clockY, 90, 22, clockBg);
let clockCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, alpha);
let clockShadow = toColour(0, 0, 0, alpha);
drawText(timeStr, panelX + panelW / 2 - 35, clockY + 5, clockShadow, 14);
drawText(timeStr, panelX + panelW / 2 - 36, clockY + 4, clockCol, 14);
// Date
let dateCol = toColour(150, 150, 160, Math.floor(180 * menuOpenAnim));
let dateStr = (now.getMonth() + 1) + "/" + now.getDate() + "/" + now.getFullYear();
drawText(dateStr, panelX + 12, clockY + 6, dateCol, 9);
});
// ============================================================================
// ACTIVE TOGGLES INDICATOR - Shows active mods in corner
// ============================================================================
addEventHandler("OnDrawnHUD", function(event) {
if (menuOpen) return; // Don't show when menu is open
if (!localPlayer) return;
// Count active toggles
let activeToggles = [];
if (toggleStates.godMode) activeToggles.push("GOD");
if (toggleStates.invincible) activeToggles.push("INV");
if (toggleStates.superRun) activeToggles.push("SPD");
if (toggleStates.neverWanted) activeToggles.push("NW");
if (toggleStates.invisible) activeToggles.push("INV");
if (toggleStates.vehGodMode) activeToggles.push("VGOD");
if (toggleStates.driftMode) activeToggles.push("DRFT");
if (toggleStates.rainbowCar) activeToggles.push("RGB");
if (toggleStates.flyMode) activeToggles.push("FLY");
if (activeToggles.length === 0) return;
// Position in top-right corner
let indicatorX = 1680;
let indicatorY = 20;
// Background
let bgColor = toColour(0, 0, 0, 150);
let bgWidth = 80;
let bgHeight = 20 + activeToggles.length * 16;
drawRect(indicatorX, indicatorY, bgWidth, bgHeight, bgColor);
// Border
let borderColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, 180);
drawRect(indicatorX, indicatorY, bgWidth, 2, borderColor);
drawRect(indicatorX, indicatorY + bgHeight - 2, bgWidth, 2, borderColor);
drawRect(indicatorX, indicatorY, 2, bgHeight, borderColor);
drawRect(indicatorX + bgWidth - 2, indicatorY, 2, bgHeight, borderColor);
// Title
let titleColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, 255);
drawText("ACTIVE", indicatorX + 18, indicatorY + 4, titleColor, 9);
// List active toggles
let listY = indicatorY + 20;
for (let i = 0; i < activeToggles.length; i++) {
let toggleColor = toColour(MDB.ItemHighlight.r, MDB.ItemHighlight.g, MDB.ItemHighlight.b, Math.floor(200 + Math.sin(animTime * 3 + i) * 55));
drawText(activeToggles[i], indicatorX + 8, listY + i * 16, toggleColor, 10);
}
});
// ============================================================================
// BOTTOM SCREEN BANNER - Shows when menu is open
// ============================================================================
addEventHandler("OnDrawnHUD", function(event) {
if (menuOpenAnim <= 0) return;
let screenWidth = 1920;
let screenHeight = 1080;
try {
screenWidth = game.width || 1920;
screenHeight = game.height || 1080;
} catch(e) {}
let alpha = Math.floor(255 * menuOpenAnim);
let bannerH = 45;
let bannerY = screenHeight - bannerH - 10;
// Slide up animation
let slideOffset = (1 - menuOpenAnim) * 60;
bannerY += slideOffset;
// Banner background
let bannerBg = toColour(0, 0, 0, Math.floor(180 * menuOpenAnim));
drawRect(0, bannerY, screenWidth, bannerH, bannerBg);
// Top border with gradient
let borderL = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor((180 + borderGlow * 50) * menuOpenAnim));
let borderC = toColour(MDB.Steelblue.r, MDB.Steelblue.g, MDB.Steelblue.b, alpha);
drawRect(0, bannerY, screenWidth * 0.3, 2, borderL);
drawRect(screenWidth * 0.3, bannerY, screenWidth * 0.4, 2, borderC);
drawRect(screenWidth * 0.7, bannerY, screenWidth * 0.3, 2, borderL);
// Left logo
let logoShadow = toColour(0, 0, 0, alpha);
let logoGold = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, alpha);
let logoBlue = toColour(MDB.Steelblue.r + 40, MDB.Steelblue.g + 40, MDB.Steelblue.b + 40, alpha);
drawText("MD", 21, bannerY + 12, logoShadow, 18);
drawText("MD", 20, bannerY + 11, logoBlue, 18);
drawText("REVOLUTION", 58, bannerY + 15, logoShadow, 14);
drawText("REVOLUTION", 57, bannerY + 14, logoGold, 14);
// Center text - server info
let centerText = "GTA CONNECTED";
let centerX = screenWidth / 2 - centerText.length * 4;
let centerCol = toColour(MDB.SubHeader.r, MDB.SubHeader.g, MDB.SubHeader.b, alpha);
drawText(centerText, centerX + 1, bannerY + 16, logoShadow, 12);
drawText(centerText, centerX, bannerY + 15, centerCol, 12);
// Right side - F5 hint
let hintCol = toColour(150, 150, 160, alpha);
let keyCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, alpha);
drawText("Press", screenWidth - 150, bannerY + 15, hintCol, 10);
drawText("[F5]", screenWidth - 115, bannerY + 15, keyCol, 10);
drawText("to close", screenWidth - 80, bannerY + 15, hintCol, 10);
// Animated bottom line
let lineAlpha = Math.floor((150 + Math.sin(footerPulse) * 60) * menuOpenAnim);
let lineCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, lineAlpha);
drawRect(0, bannerY + bannerH - 2, screenWidth, 2, lineCol);
});
// ============================================================================
// MENU PARTICLE EFFECTS - Subtle floating particles
// ============================================================================
addEventHandler("OnDrawnHUD", function(event) {
if (menuOpenAnim <= 0.1) return;
let baseX = menu.x;
let baseY = menu.y;
let alpha = Math.floor(255 * menuOpenAnim);
// Generate particles around the menu
for (let i = 0; i < 8; i++) {
let angle = (animTime * 0.5 + i * 0.785) % (Math.PI * 2);
let radius = 180 + Math.sin(animTime + i) * 30;
let px = baseX + menu.width / 2 + Math.cos(angle) * radius;
let py = baseY + 250 + Math.sin(angle) * 100;
// Floating particle
let particleAlpha = Math.floor((40 + Math.sin(animTime * 2 + i) * 25) * menuOpenAnim);
let particleSize = 3 + Math.sin(animTime + i * 0.5) * 2;
// Gold particles
let pColor = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, particleAlpha);
drawRect(px, py, particleSize, particleSize, pColor);
}
// Subtle sparkle effects on corners
let sparkleTime = animTime * 3;
for (let i = 0; i < 4; i++) {
let sparkleAlpha = Math.floor(Math.max(0, Math.sin(sparkleTime + i * 1.57) * 80) * menuOpenAnim);
if (sparkleAlpha > 10) {
let sx, sy;
switch(i) {
case 0: sx = baseX - 5; sy = baseY - 5; break;
case 1: sx = baseX + menu.width + 2; sy = baseY - 5; break;
case 2: sx = baseX - 5; sy = baseY + 450; break;
case 3: sx = baseX + menu.width + 2; sy = baseY + 450; break;
}
let sparkleCol = toColour(255, 255, 200, sparkleAlpha);
drawRect(sx, sy, 4, 4, sparkleCol);
drawRect(sx - 1, sy + 1, 6, 2, sparkleCol);
drawRect(sx + 1, sy - 1, 2, 6, sparkleCol);
}
}
});
// ============================================================================
// MENU TITLE BADGE (Above main menu)
// ============================================================================
addEventHandler("OnDrawnHUD", function(event) {
if (menuOpenAnim <= 0) return;
let alpha = Math.floor(255 * menuOpenAnim);
let slideOffset = (1 - menuOpenAnim) * 120;
let baseX = menu.x + slideOffset;
let baseY = menu.y - 50;
// Slide down animation
let slideDown = (1 - menuOpenAnim) * -30;
baseY += slideDown;
// Badge background
let badgeBg = toColour(MDB.DevilsRed.r, MDB.DevilsRed.g, MDB.DevilsRed.b, Math.floor(220 * menuOpenAnim));
drawRect(baseX + menu.width / 2 - 80, baseY, 160, 35, badgeBg);
// Border glow
let borderGlowCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor((100 + borderGlow * 80) * menuOpenAnim));
drawRect(baseX + menu.width / 2 - 82, baseY - 2, 164, 2, borderGlowCol);
drawRect(baseX + menu.width / 2 - 82, baseY + 35, 164, 2, borderGlowCol);
drawRect(baseX + menu.width / 2 - 82, baseY - 2, 2, 39, borderGlowCol);
drawRect(baseX + menu.width / 2 + 80, baseY - 2, 2, 39, borderGlowCol);
// Badge text
let badgeShadow = toColour(0, 0, 0, alpha);
let badgeText = toColour(255, 255, 255, alpha);
drawText("TRIDENT EDITION", baseX + menu.width / 2 - 60, baseY + 11, badgeShadow, 13);
drawText("TRIDENT EDITION", baseX + menu.width / 2 - 61, baseY + 10, badgeText, 13);
// Version number
let versionCol = toColour(MDB.Gold.r, MDB.Gold.g, MDB.Gold.b, Math.floor(FlashingGhost * menuOpenAnim));
drawText("v2.0", baseX + menu.width / 2 + 48, baseY + 12, versionCol, 10);
});
// Draw rectangle using graphics API // Draw rectangle using graphics API
function drawRect(x, y, w, h, colour) { function drawRect(x, y, w, h, colour) {
try { try {