A thought bubble notification system designed for immersive roleplay.
In traditional FiveM servers, notifications often break immersion with meta-gaming information: "Not enough police online" or "You don't have the required skill level." These messages force players to acknowledge game mechanics rather than staying in character.
mad-thoughts transforms this experience by displaying notifications as the character's inner thoughts. When a player encounters a locked door they can't pick, instead of seeing "Lockpicking skill too low," they'll think: "This lock looks too complex for me..."
Preview
Screenshots
Features & Benefits
๐ญ Immersive Thought Bubbles: Displays character thoughts above the player's head
๐จ Rich Customization: Icons, colors, and timing options
๐ Scenario System: Automatic thoughts based on gameplay situations
๐ฌ Message Variety: Random selection prevents repetition
๐ Location Awareness: Thoughts trigger in specific areas
๐ Sequential Thoughts: Create story-driven thought chains
๐ Server-Wide Thoughts: Send thoughts to all connected players
๐ป Developer-Friendly: Simple exports for easy implementation
โญ Perfect For:
Skill check feedback that doesn't break immersion
Subtle environmental storytelling
Replacing meta-gaming notifications with in-character thoughts
Adding personality and depth to player characters
Creating a more cinematic and immersive experience
Transform your server's notification system from immersion-breaking text to character-driven thoughts. Your players will feel more connected to their characters, and your world will feel more authentic and alive.
Scenarios & Locations
The real power of mad-thoughts comes from creating your own custom scenarios and locations. While the resource includes several pre-built examples, you're encouraged to create ones tailored to your server.
Scenario-Based Thoughts
Scenarios automatically trigger thoughts based on specific conditions that you define. The included examples cover:
Health status (low health)
Environmental conditions (rain, thunder, night time)
Player actions (swimming, running)
Character needs (hunger, thirst)
Each scenario uses a check function to determine when to trigger, plus the same customization options as regular thoughts (message, icon, color, duration, etc.).
Location-Based Thoughts
Location thoughts appear when players enter areas you've defined. The resource includes examples for:
Hospitals, police stations
Beaches, mountains, landmarks
Buildings, neighborhoods
You simply define coordinates and a trigger radius, along with the thought customization (message, icon, color, duration, etc.).
Both scenario and location-based features can be completely customized through the config.lua file or disabled entirely if you prefer to trigger thoughts only through direct exports.
How to Use
Basic Thoughts
-- Basic notification
exports['mad-thoughts']:thought("I can't do this right now...")
-- With duration (10 seconds)
exports['mad-thoughts']:thought("I wonder what that means...", 10)
-- With icon
exports['mad-thoughts']:thought("Something doesn't feel right about this...", 5, "fas fa-question-circle")
-- With icon and color
exports['mad-thoughts']:thought("I need to get out of here!", 8, "fas fa-exclamation", "#e74c3c")
Parameters
message: The text content of the thought (string)
duration: How long the thought displays in seconds (number, default: 5)
icon: Font Awesome icon class (string, default: "fas fa-comment-dots")
color: Hex color code for the icon and border (string, default: "#F2F2F2")
Using predefined types
exports['mad-thoughts']:info("I just remembered where I left my keys...", 5)
exports['mad-thoughts']:success("I finally figured it out!", 5)
exports['mad-thoughts']:warning("This doesn't look safe...", 5)
exports['mad-thoughts']:error("I've made a terrible mistake...", 5)
Predefined types use the following icons and colors:
info: "fas fa-info-circle" with blue color (#2B78FC)
success: "fas fa-check-circle" with green color (#06CE6B)
warning: "fas fa-exclamation-triangle" with orange color (#FB8607)
error: "fas fa-times-circle" with red color (#fe2436)
Sequential Thoughts
Display multiple thoughts in sequence:
exports['mad-thoughts']:thoughtChain({
{message = "That's strange...", duration = 3},
{message = "I wonder if anyone is here...", duration = 4, icon = "fas fa-question"},
{message = "Better be careful.", duration = 3, color = "#e74c3c"}
}, 4000)
Parameters
thoughts: Array of thought objects, each with message, duration, icon, and color
delay: Time between thoughts in milliseconds (default: 3s)
initialDelay: Optional delay before starting the sequence (default: 0s)
Dynamic Scenario and Location Triggers
The system allows you to dynamically create and remove thought triggers. This is especially useful for:
Thoughts that appear only during certain jobs/heists, etc
Temporary areas that should trigger thoughts for a limited time
-- Remove a scenario you previously registered
exports['mad-thoughts']:removeScenario('myResourceScenario')
-- Remove a location you previously registered
exports['mad-thoughts']:removeLocation('myResourceLocation')
Server-Wide Thoughts
You can send thoughts to all connected players:
From a Client Script
-- Send a thought to all players on the server
exports['mad-thoughts']:sendThoughtToAll(
"Everyone should see this message!", -- message
5, -- duration in seconds
"fas fa-bullhorn", -- icon
"#E67E22" -- color (orange)
)
From a Server Script
-- Send a thought directly from a server script
exports['mad-thoughts']:sendThoughtToAll(
"Server announcement as a thought", -- message
5, -- duration in seconds
"fas fa-server", -- icon
"#3498db" -- color (blue)
)
Via Command
-- Basic usage
/globalthought "This is a global announcement"
-- With custom duration (in seconds)
/globalthought "This is a global announcement" "10"
-- With custom icon
/globalthought "This is a global announcement" "10" "fa-solid fa-bell"
-- With custom color
/globalthought "This is a global announcement" "10" "fa-solid fa-bell" "#FF5733"
This command requires the group.admin permission.
Player-Specific Thoughts
You can send thoughts to specific players:
From a Client Script
-- Send a thought to a specific player
exports['mad-thoughts']:sendThoughtToPlayer(
1, -- target player's server ID
"This message is only for you", -- message
5, -- duration in seconds
"fas fa-user-secret", -- icon
"#9B59B6" -- color (purple)
)
From a Server Script
-- Send a thought directly from a server script
exports['mad-thoughts']:sendThoughtToPlayer(
1, -- target player's server ID
"This message is only for you", -- message
5, -- duration in seconds
"fas fa-envelope", -- icon
"#3498db" -- color (blue)
)
Via Command
-- Basic usage
/playerthought 1 "This is a private thought"
-- With custom duration (in seconds)
/playerthought 1 "This is a private thought" "10"
-- With custom icon
/playerthought 1 "This is a private thought" "10" "fa-solid fa-crown"
-- With custom color
/playerthought 1 "This is a private thought" "10" "fa-solid fa-crown" "#9B59B6"
This command requires the group.admin permission.
Examples
Making NPCs More Immersive
-- Example: When player approaches a mission NPC
exports['mad-thoughts']:thought("I wonder if I should talk to this stranger...", 5)
Skill Check Feedback
-- Example: Instead of "Lockpicking failed"
exports['mad-thoughts']:error("I can't seem to get these tumblers right...", 4)
Environmental Storytelling
-- Example: When entering an abandoned building
exports['mad-thoughts']:thoughtChain({
{message = "This place gives me the creeps...", duration = 4},
{message = "Feels like someone's watching me...", duration = 3, icon = "fas fa-eye"}
}, 3000)
Proximity
-- Example: Send a thought to nearby players
local function notifyNearbyPlayers(message, duration, icon, color)
local myCoords = GetEntityCoords(cache.ped)
local players = GetActivePlayers()
for _, playerId in ipairs(players) do
if playerId ~= PlayerId() then
local targetPed = GetPlayerPed(playerId)
local targetCoords = GetEntityCoords(targetPed)
local distance = #(myCoords - targetCoords)
if distance <= 10.0 then
exports['mad-thoughts']:sendThoughtToPlayer(
GetPlayerServerId(playerId),
message or "This guy looks suspicious",
duration or 5,
icon or "fas fa-exclamation",
color or "#e74c3c"
)
end
end
end
end
-- Example: When a player discovers something important
RegisterNetEvent('discovered')
AddEventHandler('discovered', function()
-- Thought for the player who made the discovery
exports['mad-thoughts']:thought("What's this strange artifact?", 5)
-- Send a different thought to nearby players
notifyNearbyPlayers(
"Did someone just find something?",
5,
"fas fa-question-circle",
"#9B59B6"
)
end)
Group Coordination
-- Example: Coordinating with specific team members
RegisterNetEvent('heist:beginOperation')
AddEventHandler('heist:beginOperation', function(teamMembers)
for role, playerId in pairs(teamMembers) do
if role == "hacker" then
exports['mad-thoughts']:sendThoughtToPlayer(
playerId,
"I need to focus on bypassing the security system...",
5,
"fas fa-laptop-code",
"#3498db"
)
elseif role == "lookout" then
exports['mad-thoughts']:sendThoughtToPlayer(
playerId,
"I should keep an eye out for guards...",
5,
"fas fa-eye",
"#f39c12"
)
elseif role == "driver" then
exports['mad-thoughts']:sendThoughtToPlayer(
playerId,
"Engine's running. Ready for a quick getaway...",
5,
"fas fa-car",
"#2ecc71"
)
end
end
end)
Dependencies
Installation
Ensure you have the required dependency
Place the folder in your server's resources directory
Add start mad-thoughts to your server.cfg
Configure scenarios & locations in the config.lua file to match your server's needs
Configuration
The resource comes with a comprehensive config.lua file that includes:
Ready-to-use templates for scenarios and locations
Detailed comments explaining every configuration option
Example scenarios for common situations (underwater, low health, weather conditions)
Example locations for popular spots around the map
Debug
The resource includes debug visualizations to help you set up and test your location triggers:
Visual indicators showing location trigger zones as red spheres
Location IDs displayed above each zone
This is particularly useful when:
Setting up new location triggers to ensure they're in the right place
Testing the detection radius of your locations
Support
Escrow Protection
This resource is protected by FiveM's escrow system to safeguard against unauthorised distribution. The core functionality is secured while maintaining full customisability through the extensive configuration system.
Despite the security measures:
All configuration options remain fully editable.
Server owners retain complete control over all settings.
No functionality is limited by the protection system.
This approach ensures you receive a premium, leak-protected resource while maintaining the freedom to customise it for your server's unique needs.
Watch the to see mad-thoughts in action, or view the screenshots below.
Join our for support, regular updates and to request new features.