From 82525ea32c1ed203b4d8a2eb5f49b87586eff992 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Jan 2026 12:07:43 +0000 Subject: [PATCH 1/3] Add color-coded toggle labels and remove old notifications - Toggle items now show state in label with GTAConnected color tags - Example: "God Mode: <#00FF00>ON" or "God Mode: <#FF0000>OFF" - Labels update dynamically when clicked - Remove rainbow notification system on left side - Remove old ON/OFF indicator boxes from menu - Keep status indicator at bottom for active toggles --- resources/modmenu/client.js | 151 +++++++++++++----------------------- 1 file changed, 53 insertions(+), 98 deletions(-) diff --git a/resources/modmenu/client.js b/resources/modmenu/client.js index 7c4bd53..591a92d 100644 --- a/resources/modmenu/client.js +++ b/resources/modmenu/client.js @@ -215,11 +215,11 @@ const menuData = { { label: "Give All Weapons", action: "self_weapons" }, { label: "Clear Wanted Level", action: "self_wanted" }, { label: "--- Toggles ---", action: "none" }, - { label: "God Mode", action: "toggle", target: "godMode", state: false }, - { label: "Invincible", action: "toggle", target: "invincible", state: false }, - { label: "Super Run", action: "toggle", target: "superRun", state: false }, - { label: "No Ragdoll", action: "toggle", target: "noRagdoll", state: false }, - { label: "Never Wanted", action: "toggle", target: "neverWanted", state: false }, + { label: "God Mode: <#FF0000>OFF", action: "toggle", target: "godMode", state: false }, + { label: "Invincible: <#FF0000>OFF", action: "toggle", target: "invincible", state: false }, + { label: "Super Run: <#FF0000>OFF", action: "toggle", target: "superRun", state: false }, + { label: "No Ragdoll: <#FF0000>OFF", action: "toggle", target: "noRagdoll", state: false }, + { label: "Never Wanted: <#FF0000>OFF", action: "toggle", target: "neverWanted", state: false }, { label: "--- Actions ---", action: "none" }, { label: "Respawn", action: "self_respawn" }, { label: "Suicide", action: "self_suicide" }, @@ -445,21 +445,21 @@ const menuData = { { label: "Repair Vehicle", action: "veh_repair" }, { label: "Flip Vehicle", action: "veh_flip" }, { label: "Vehicle Colors", action: "submenu", target: "veh_colors" }, - { label: "God Mode", action: "toggle", target: "vehGodMode", state: false }, + { label: "God Mode: <#FF0000>OFF", action: "toggle", target: "vehGodMode", state: false }, { label: "Nitro Boost", action: "veh_nitro" }, - { label: "Drive On Water", action: "toggle", target: "driveOnWater", state: false }, - { label: "Rainbow Color", action: "toggle", target: "rainbowCar", state: false }, - { label: "Drift Mode", action: "toggle", target: "driftMode", state: false }, + { label: "Drive On Water: <#FF0000>OFF", action: "toggle", target: "driveOnWater", state: false }, + { label: "Rainbow Color: <#FF0000>OFF", action: "toggle", target: "rainbowCar", state: false }, + { label: "Drift Mode: <#FF0000>OFF", action: "toggle", target: "driftMode", state: false }, { label: "Neon Lights", action: "submenu", target: "veh_neons" }, - { label: "Fly Mode", action: "toggle", target: "flyMode", state: false }, - { label: "Shoot RPG", action: "toggle", target: "vehShootRPG", state: false } + { label: "Fly Mode: <#FF0000>OFF", action: "toggle", target: "flyMode", state: false }, + { label: "Shoot RPG: <#FF0000>OFF", action: "toggle", target: "vehShootRPG", state: false } ] }, veh_neons: { title: "NEON LIGHTS", items: [ - { label: "Toggle Neons", action: "toggle", target: "neonLights", state: false }, + { label: "Toggle Neons: <#FF0000>OFF", action: "toggle", target: "neonLights", state: false }, { label: "Red Neons", action: "neon_color", value: { r: 255, g: 0, b: 0 } }, { label: "Blue Neons", action: "neon_color", value: { r: 0, g: 100, b: 255 } }, { label: "Green Neons", action: "neon_color", value: { r: 0, g: 255, b: 0 } }, @@ -647,9 +647,9 @@ const menuData = { { label: "--- Visual Effects ---", action: "none" }, { label: "Screen Shake", action: "fun_screen_shake" }, { label: "Flash Screen", action: "fun_flash" }, - { label: "Matrix Mode", action: "toggle", target: "matrixMode", state: false }, - { label: "Thermal Vision", action: "toggle", target: "thermalVision", state: false }, - { label: "Night Vision", action: "toggle", target: "nightVision", state: false } + { label: "Matrix Mode: <#FF0000>OFF", action: "toggle", target: "matrixMode", state: false }, + { label: "Thermal Vision: <#FF0000>OFF", action: "toggle", target: "thermalVision", state: false }, + { label: "Night Vision: <#FF0000>OFF", action: "toggle", target: "nightVision", state: false } ] } }; @@ -677,6 +677,40 @@ let toggleStates = { nightVision: false }; +// Base labels for toggles (used to generate color-coded labels) +const toggleBaseLabels = { + godMode: "God Mode", + invincible: "Invincible", + superRun: "Super Run", + noRagdoll: "No Ragdoll", + neverWanted: "Never Wanted", + vehGodMode: "God Mode", + driveOnWater: "Drive On Water", + rainbowCar: "Rainbow Color", + driftMode: "Drift Mode", + neonLights: "Toggle Neons", + flyMode: "Fly Mode", + vehShootRPG: "Shoot RPG", + rainbowSky: "Rainbow Sky", + explosiveAmmo: "Explosive Ammo", + moonGravity: "Moon Gravity", + drunkMode: "Drunk Mode", + matrixMode: "Matrix Mode", + thermalVision: "Thermal Vision", + nightVision: "Night Vision" +}; + +// Helper function to get toggle label with GTAConnected color tags +function getToggleLabel(toggleKey) { + let baseName = toggleBaseLabels[toggleKey] || toggleKey; + let isOn = toggleStates[toggleKey]; + if (isOn) { + return baseName + ": <#00FF00>ON"; + } else { + return baseName + ": <#FF0000>OFF"; + } +} + // Neon objects storage let neonObjects = []; let neonColor = { r: 255, g: 0, b: 255 }; // Default purple @@ -909,8 +943,9 @@ function selectItem() { case "toggle": toggleStates[item.target] = !toggleStates[item.target]; item.state = toggleStates[item.target]; + // Update label with color-coded state + item.label = getToggleLabel(item.target); triggerNetworkEvent("ModMenu:Toggle", item.target, toggleStates[item.target]); - showNotification(item.label + ": " + (toggleStates[item.target] ? "ON" : "OFF")); break; case "spawn_vehicle": @@ -2114,36 +2149,6 @@ addEventHandler("OnDrawnHUD", function(event) { drawText(item.label, textX, itemY + 12, textColor, 14); } - // ===== TOGGLE INDICATORS ===== - if (item.action === "toggle") { - let isOn = toggleStates[item.target]; - let stateText = isOn ? "ON" : "OFF"; - let stateX = baseX + menu.width - 60; - - if (isOn) { - // GREEN ON - Smooth Pulsing - let greenPulse = Math.sin(animTime * 3) * 40 + 215; - let onBgColor = toColour(30, Math.floor(greenPulse * 0.4), 30, animAlpha); - let onTextColor = toColour(80, Math.floor(greenPulse), 80, animAlpha); - drawRect(stateX - 8, itemY + 8, 52, 24, onBgColor); - // Green border - let onBorderColor = toColour(50, Math.floor(greenPulse), 50, animAlpha); - drawRect(stateX - 8, itemY + 8, 52, 2, onBorderColor); - drawRect(stateX - 8, itemY + 30, 52, 2, onBorderColor); - drawText(stateText, stateX + 5, itemY + 12, onTextColor, 13); - } else { - // RED OFF - let offBgColor = toColour(80, 25, 30, animAlpha); - let offTextColor = toColour(255, 90, 90, animAlpha); - drawRect(stateX - 8, itemY + 8, 52, 24, offBgColor); - // Red border - let offBorderColor = toColour(150, 40, 50, animAlpha); - drawRect(stateX - 8, itemY + 8, 52, 2, offBorderColor); - drawRect(stateX - 8, itemY + 30, 52, 2, offBorderColor); - drawText(stateText, stateX + 2, itemY + 12, offTextColor, 13); - } - } - // Submenu arrow - smoother (themed) if (item.action === "submenu") { let arrowX = baseX + menu.width - 32 + (isSelected ? Math.sin(animTime * 5) * 3 : 0); @@ -2296,63 +2301,13 @@ function drawText(text, x, y, colour, size) { } // ============================================================================ -// NOTIFICATIONS - Animated +// NOTIFICATIONS (stub - notifications removed, function kept for compatibility) // ============================================================================ -let notifications = []; - function showNotification(text) { - notifications.push({ - text: text, - time: Date.now(), - duration: 1500 - }); + // Notifications removed - toggle states now shown in menu labels } -addEventHandler("OnDrawnHUD", function(event) { - let now = Date.now(); - let yPos = 180; - - for (let i = 0; i < notifications.length; i++) { - let notif = notifications[i]; - let elapsed = now - notif.time; - - if (elapsed < notif.duration) { - // Animated notification - let progress = elapsed / notif.duration; - let slideIn = Math.min(1, elapsed / 200) * 300; - let fadeOut = elapsed > notif.duration - 300 ? (notif.duration - elapsed) / 300 : 1; - let alpha = Math.floor(220 * fadeOut); - - // Rainbow border - let notifHue = (animTime * 80 + i * 60) % 360; - let notifRGB = hsvToRgb(notifHue, 0.8, 0.8); - - // Glow - let glowCol = toColour(notifRGB.r, notifRGB.g, notifRGB.b, Math.floor(40 * fadeOut)); - drawRect(10 - slideIn + 300, yPos - 3, 290, 36, glowCol); - - // Background - let bgColor = toColour(20, 20, 30, alpha); - drawRect(15 - slideIn + 300, yPos, 280, 30, bgColor); - - // Border - let borderCol = toColour(notifRGB.r, notifRGB.g, notifRGB.b, alpha); - drawRect(15 - slideIn + 300, yPos, 3, 30, borderCol); - - // Text - let textColor = toColour(255, 255, 255, alpha); - drawText(notif.text, 25 - slideIn + 300, yPos + 8, textColor, 13); - - yPos += 40; - } - } - - notifications = notifications.filter(function(n) { - return now - n.time < n.duration; - }); -}); - // ============================================================================ // STATUS INDICATOR - Shows active toggles at bottom of screen // ============================================================================ From d25945937fd83f9a2b94f4bcea84991c902ea47c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Jan 2026 12:15:35 +0000 Subject: [PATCH 2/3] Restore toggle indicators and add BetterIV-style status display - Restore ON/OFF toggle indicator boxes inside menu - Add BetterIV-style status at bottom center of screen - Shows "God Mode: On" (with On in cyan) or "God Mode: Off" (with Off in red) - Status displays for 3 seconds after toggling - Keep color-coded labels in menu items --- resources/modmenu/client.js | 106 +++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/resources/modmenu/client.js b/resources/modmenu/client.js index 591a92d..2af7d34 100644 --- a/resources/modmenu/client.js +++ b/resources/modmenu/client.js @@ -945,6 +945,10 @@ function selectItem() { item.state = toggleStates[item.target]; // Update label with color-coded state item.label = getToggleLabel(item.target); + // Set status indicator variables for bottom display + lastToggledItem = item.target; + lastToggleTime = Date.now(); + lastToggleState = toggleStates[item.target]; triggerNetworkEvent("ModMenu:Toggle", item.target, toggleStates[item.target]); break; @@ -2149,6 +2153,36 @@ addEventHandler("OnDrawnHUD", function(event) { drawText(item.label, textX, itemY + 12, textColor, 14); } + // ===== TOGGLE INDICATORS ===== + if (item.action === "toggle") { + let isOn = toggleStates[item.target]; + let stateText = isOn ? "ON" : "OFF"; + let stateX = baseX + menu.width - 60; + + if (isOn) { + // GREEN ON - Smooth Pulsing + let greenPulse = Math.sin(animTime * 3) * 40 + 215; + let onBgColor = toColour(30, Math.floor(greenPulse * 0.4), 30, animAlpha); + let onTextColor = toColour(80, Math.floor(greenPulse), 80, animAlpha); + drawRect(stateX - 8, itemY + 8, 52, 24, onBgColor); + // Green border + let onBorderColor = toColour(50, Math.floor(greenPulse), 50, animAlpha); + drawRect(stateX - 8, itemY + 8, 52, 2, onBorderColor); + drawRect(stateX - 8, itemY + 30, 52, 2, onBorderColor); + drawText(stateText, stateX + 5, itemY + 12, onTextColor, 13); + } else { + // RED OFF + let offBgColor = toColour(80, 25, 30, animAlpha); + let offTextColor = toColour(255, 90, 90, animAlpha); + drawRect(stateX - 8, itemY + 8, 52, 24, offBgColor); + // Red border + let offBorderColor = toColour(150, 40, 50, animAlpha); + drawRect(stateX - 8, itemY + 8, 52, 2, offBorderColor); + drawRect(stateX - 8, itemY + 30, 52, 2, offBorderColor); + drawText(stateText, stateX + 2, itemY + 12, offTextColor, 13); + } + } + // Submenu arrow - smoother (themed) if (item.action === "submenu") { let arrowX = baseX + menu.width - 32 + (isSelected ? Math.sin(animTime * 5) * 3 : 0); @@ -2309,13 +2343,15 @@ function showNotification(text) { } // ============================================================================ -// STATUS INDICATOR - Shows active toggles at bottom of screen +// STATUS INDICATOR - Shows active toggles at bottom of screen (BetterIV style) // ============================================================================ -addEventHandler("OnDrawnHUD", function(event) { - // Get active toggles - let activeToggles = []; +// Track last toggled item for display +let lastToggledItem = null; +let lastToggleTime = 0; +let lastToggleState = false; +addEventHandler("OnDrawnHUD", function(event) { // Define display names for toggles let toggleDisplayNames = { godMode: "God Mode", @@ -2339,42 +2375,36 @@ addEventHandler("OnDrawnHUD", function(event) { nightVision: "Night Vision" }; - // Collect active toggles - for (let key in toggleStates) { - if (toggleStates[key] === true && toggleDisplayNames[key]) { - activeToggles.push(toggleDisplayNames[key]); + // Show last toggled item for 3 seconds after toggle + let now = Date.now(); + if (lastToggledItem && (now - lastToggleTime) < 3000) { + let displayName = toggleDisplayNames[lastToggledItem] || lastToggledItem; + let stateText = lastToggleState ? "On" : "Off"; + + // Screen dimensions + let screenWidth = 1920; + let screenHeight = 1080; + + // Calculate text width and position at bottom center + let fullText = displayName + ": " + stateText; + let textWidth = fullText.length * 9; + let boxX = (screenWidth - textWidth) / 2 - 10; + let boxY = screenHeight - 50; + + // Draw name part in white + let nameColor = toColour(255, 255, 255, 255); + drawText(displayName + ": ", boxX, boxY, nameColor, 16); + + // Draw state in green (On) or red (Off) + let stateX = boxX + (displayName.length + 2) * 9; + if (lastToggleState) { + let onColor = toColour(0, 255, 200, 255); // Cyan-green like BetterIV + drawText(stateText, stateX, boxY, onColor, 16); + } else { + let offColor = toColour(255, 80, 80, 255); // Red + drawText(stateText, stateX, boxY, offColor, 16); } } - - // 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); }); // ============================================================================ From 46d868ab6542b6caf06a93c770244772aed4378c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Jan 2026 13:36:48 +0000 Subject: [PATCH 3/3] Remove color tags from menu labels, keep bottom status only - Menu toggle labels now show plain names (God Mode, Invincible, etc.) - ON/OFF indicator boxes remain in menu - Bottom status shows "God Mode: On/Off" with colored state text - Removed unused getToggleLabel function and toggleBaseLabels --- resources/modmenu/client.js | 66 +++++++++---------------------------- 1 file changed, 15 insertions(+), 51 deletions(-) diff --git a/resources/modmenu/client.js b/resources/modmenu/client.js index 2af7d34..26c830d 100644 --- a/resources/modmenu/client.js +++ b/resources/modmenu/client.js @@ -215,11 +215,11 @@ const menuData = { { label: "Give All Weapons", action: "self_weapons" }, { label: "Clear Wanted Level", action: "self_wanted" }, { label: "--- Toggles ---", action: "none" }, - { label: "God Mode: <#FF0000>OFF", action: "toggle", target: "godMode", state: false }, - { label: "Invincible: <#FF0000>OFF", action: "toggle", target: "invincible", state: false }, - { label: "Super Run: <#FF0000>OFF", action: "toggle", target: "superRun", state: false }, - { label: "No Ragdoll: <#FF0000>OFF", action: "toggle", target: "noRagdoll", state: false }, - { label: "Never Wanted: <#FF0000>OFF", action: "toggle", target: "neverWanted", state: false }, + { label: "God Mode", action: "toggle", target: "godMode", state: false }, + { label: "Invincible", action: "toggle", target: "invincible", state: false }, + { label: "Super Run", action: "toggle", target: "superRun", state: false }, + { label: "No Ragdoll", action: "toggle", target: "noRagdoll", state: false }, + { label: "Never Wanted", action: "toggle", target: "neverWanted", state: false }, { label: "--- Actions ---", action: "none" }, { label: "Respawn", action: "self_respawn" }, { label: "Suicide", action: "self_suicide" }, @@ -445,21 +445,21 @@ const menuData = { { label: "Repair Vehicle", action: "veh_repair" }, { label: "Flip Vehicle", action: "veh_flip" }, { label: "Vehicle Colors", action: "submenu", target: "veh_colors" }, - { label: "God Mode: <#FF0000>OFF", action: "toggle", target: "vehGodMode", state: false }, + { label: "God Mode", action: "toggle", target: "vehGodMode", state: false }, { label: "Nitro Boost", action: "veh_nitro" }, - { label: "Drive On Water: <#FF0000>OFF", action: "toggle", target: "driveOnWater", state: false }, - { label: "Rainbow Color: <#FF0000>OFF", action: "toggle", target: "rainbowCar", state: false }, - { label: "Drift Mode: <#FF0000>OFF", action: "toggle", target: "driftMode", state: false }, + { label: "Drive On Water", action: "toggle", target: "driveOnWater", state: false }, + { label: "Rainbow Color", action: "toggle", target: "rainbowCar", state: false }, + { label: "Drift Mode", action: "toggle", target: "driftMode", state: false }, { label: "Neon Lights", action: "submenu", target: "veh_neons" }, - { label: "Fly Mode: <#FF0000>OFF", action: "toggle", target: "flyMode", state: false }, - { label: "Shoot RPG: <#FF0000>OFF", action: "toggle", target: "vehShootRPG", state: false } + { label: "Fly Mode", action: "toggle", target: "flyMode", state: false }, + { label: "Shoot RPG", action: "toggle", target: "vehShootRPG", state: false } ] }, veh_neons: { title: "NEON LIGHTS", items: [ - { label: "Toggle Neons: <#FF0000>OFF", action: "toggle", target: "neonLights", state: false }, + { label: "Toggle Neons", action: "toggle", target: "neonLights", state: false }, { label: "Red Neons", action: "neon_color", value: { r: 255, g: 0, b: 0 } }, { label: "Blue Neons", action: "neon_color", value: { r: 0, g: 100, b: 255 } }, { label: "Green Neons", action: "neon_color", value: { r: 0, g: 255, b: 0 } }, @@ -647,9 +647,9 @@ const menuData = { { label: "--- Visual Effects ---", action: "none" }, { label: "Screen Shake", action: "fun_screen_shake" }, { label: "Flash Screen", action: "fun_flash" }, - { label: "Matrix Mode: <#FF0000>OFF", action: "toggle", target: "matrixMode", state: false }, - { label: "Thermal Vision: <#FF0000>OFF", action: "toggle", target: "thermalVision", state: false }, - { label: "Night Vision: <#FF0000>OFF", action: "toggle", target: "nightVision", state: false } + { label: "Matrix Mode", action: "toggle", target: "matrixMode", state: false }, + { label: "Thermal Vision", action: "toggle", target: "thermalVision", state: false }, + { label: "Night Vision", action: "toggle", target: "nightVision", state: false } ] } }; @@ -677,40 +677,6 @@ let toggleStates = { nightVision: false }; -// Base labels for toggles (used to generate color-coded labels) -const toggleBaseLabels = { - godMode: "God Mode", - invincible: "Invincible", - superRun: "Super Run", - noRagdoll: "No Ragdoll", - neverWanted: "Never Wanted", - vehGodMode: "God Mode", - driveOnWater: "Drive On Water", - rainbowCar: "Rainbow Color", - driftMode: "Drift Mode", - neonLights: "Toggle Neons", - flyMode: "Fly Mode", - vehShootRPG: "Shoot RPG", - rainbowSky: "Rainbow Sky", - explosiveAmmo: "Explosive Ammo", - moonGravity: "Moon Gravity", - drunkMode: "Drunk Mode", - matrixMode: "Matrix Mode", - thermalVision: "Thermal Vision", - nightVision: "Night Vision" -}; - -// Helper function to get toggle label with GTAConnected color tags -function getToggleLabel(toggleKey) { - let baseName = toggleBaseLabels[toggleKey] || toggleKey; - let isOn = toggleStates[toggleKey]; - if (isOn) { - return baseName + ": <#00FF00>ON"; - } else { - return baseName + ": <#FF0000>OFF"; - } -} - // Neon objects storage let neonObjects = []; let neonColor = { r: 255, g: 0, b: 255 }; // Default purple @@ -943,8 +909,6 @@ function selectItem() { case "toggle": toggleStates[item.target] = !toggleStates[item.target]; item.state = toggleStates[item.target]; - // Update label with color-coded state - item.label = getToggleLabel(item.target); // Set status indicator variables for bottom display lastToggledItem = item.target; lastToggleTime = Date.now();