-- Working Natural ChatBot for Roblox - Fixed Version -- LocalScript - Place in StarterPlayer > StarterPlayerScripts -- Detects messages within 30 studs and responds naturally local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local TextChatService = game:GetService("TextChatService") local UserInputService = game:GetService("UserInputService") local LocalPlayer = Players.LocalPlayer -- Wait for character properly local function waitForCharacter() local character = LocalPlayer.Character if not character then character = LocalPlayer.CharacterAdded:Wait() end return character end local Character = waitForCharacter() local Humanoid = Character:WaitForChild("Humanoid") -- Bot Configuration local BOT_CONFIG = { DETECTION_RANGE = 30, RESPONSE_DELAY_MIN = 2, RESPONSE_DELAY_MAX = 4, MAX_RESPONSE_LENGTH = 70, DEBUG_MODE = true, -- Enable for testing MOBILE_OPTIMIZED = true, RESPONSE_CHANCE = 0.8 } print("[ChatBot] Starting ChatBot initialization...") -- Expanded Knowledge Base with American/British Slang local KNOWLEDGE_BASE = { greetings = { "hi", "hello", "hey", "what's up", "whats up", "sup", "yo", "hiya", "howdy", "good morning", "good evening", "good afternoon", "wassup", "heya", "aloha", "what's good", "whats good", "what's poppin", "whats poppin", "morning", "evening" }, farewells = { "bye", "goodbye", "see ya", "later", "catch you later", "peace", "cya", "take care", "see you around", "until next time", "gotta go", "peace out", "farewell", "so long", "have a good one", "talk to you later", "ttyl", "laters", "catch ya", "see ya round", "take it easy", "stay safe" }, agreement = { "ok", "okay", "alright", "sure", "yeah", "yes", "yep", "yup", "uh huh", "sounds good", "cool", "bet", "aight", "word", "true", "facts", "right on", "for sure", "absolutely", "definitely", "totally", "agreed", "copy that", "roger", "gotcha", "fair enough", "makes sense", "no doubt", "you bet" }, disagreement = { "no", "nah", "nope", "not really", "i dont think so", "disagree", "false", "wrong", "negative", "nada", "not quite", "i doubt it", "hardly", "no way", "not a chance", "think again", "as if", "yeah right" }, maybe_uncertain = { "maybe", "perhaps", "possibly", "might be", "could be", "not sure", "dunno", "idk", "who knows", "probably", "maybe not", "depends", "hard to say", "tough call", "on the fence", "50/50", "we'll see", "beats me", "your guess is as good as mine", "could go either way" }, social_requests = { "add me", "friend me", "be my friend", "wanna be friends", "follow me", "lets be friends", "friend request", "add as friend", "can we be friends", "want to friend", "send friend request", "accept friend", "buddy up" }, american_slang = { "dude", "bro", "man", "buddy", "pal", "homie", "dawg", "chief", "sport", "awesome", "sweet", "sick", "tight", "rad", "gnarly", "wicked", "legit", "solid", "clutch", "fire", "lit", "dope", "fresh", "mad", "hella" }, british_slang = { "mate", "bloke", "chap", "lad", "lass", "innit", "proper", "mental", "mental", "brilliant", "ace", "banging", "boss", "class", "decent", "sound", "sorted", "spot on", "top notch", "wicked", "bare", "peng" }, casual_expressions = { "what's the deal", "whats the deal", "how's it hanging", "hows it hanging", "what's the story", "whats the story", "what's new", "whats new", "how's tricks", "hows tricks", "what's cooking", "whats cooking", "what's shakin", "whats shakin", "how goes it", "what's the word" }, internet_common = { "lol", "lmao", "omg", "wtf", "bruh", "fr", "ngl", "tbh", "imo", "smh", "rn", "af", "lowkey", "highkey", "deadass", "no cap", "periodt", "bet" }, gaming_slang = { "gg", "good game", "ez", "easy", "noob", "pro", "clutch", "carry", "lag", "glitch", "spawn", "respawn", "afk", "rekt", "pwned", "owned" }, confusion_indicators = { "what", "huh", "confused", "dont understand", "don't understand", "wdym", "what do you mean", "i'm lost", "im lost", "lost me", "come again", "say what", "excuse me", "pardon", "unclear", "doesnt make sense" } } -- Enhanced Response Templates with Natural English Slang local RESPONSE_TEMPLATES = { greetings = { "hey there", "yo what's good", "sup dude", "what's poppin", "hey buddy", "what's up mate", "morning", "evening", "hey chief", "what's crackin", "sup bro", "hey pal", "what's shakin", "how's it hanging", "yo yo", "what's the word", "hey homie", "sup man", "what's good", "howdy partner" }, farewells = { "see ya", "later dude", "catch you later", "peace out", "take it easy", "later mate", "see you round", "until next time", "stay safe", "peace", "catch ya", "laters", "have a good one", "talk soon", "see ya later", "take care bro", "later chief", "catch you on the flip side", "stay cool" }, how_responses = { "i'm doing alright", "pretty good man", "not bad", "doing well", "i'm fine", "could be better", "can't complain", "living the dream", "hanging in there", "all good here", "keeping busy", "doing great", "feeling good", "just chillin", "same old same old", "another day another dollar", "living my best life" }, name_responses = { "i'm just a bot", "call me chatbot", "i'm your friendly ai", "just a simple bot", "i don't have a special name", "you can call me whatever", "i'm the chat ai", "just your average bot", "i'm here to chat", "bot will do fine", "call me whatever you want", "doesn't really matter", "just a chatbot" }, age_responses = { "age is just a number", "i'm timeless", "old enough to chat", "as old as this code", "does it really matter", "i don't age like humans", "eternally young", "created not born", "age doesn't apply to me", "digital years don't count", "old enough to know better", "young enough to have fun" }, agreement_responses = { "yeah for sure", "absolutely", "definitely", "you bet", "no doubt", "right on", "totally", "i hear you", "makes sense", "fair enough", "sounds good to me", "couldn't agree more", "you got that right", "exactly", "spot on", "true that", "no argument here", "you said it", "i'm with you on that", "copy that" }, disagreement_responses = { "nah i don't think so", "not really", "i disagree", "not quite", "i doubt it", "not buying it", "think again", "no way", "not a chance", "as if", "yeah right", "in your dreams", "not likely", "i'm not convinced", "doesn't sound right", "hard to believe", "i call bs on that" }, maybe_responses = { "maybe", "perhaps", "possibly", "could be", "might be", "not sure really", "dunno", "who knows", "probably", "maybe not", "depends i guess", "hard to say", "tough call", "on the fence about it", "could go either way", "beats me", "your guess is as good as mine", "we'll see i suppose" }, social_responses = { "sure thing", "sounds good", "why not", "i'm down", "let's do it", "count me in", "i'm game", "absolutely", "you got it", "works for me", "i'm in", "let's go", "sounds like a plan", "i'm up for it", "bet" }, confusion_responses = { "sorry i can't understand that", "not sure what you mean", "come again", "didn't catch that", "lost me there", "say what now", "huh", "what", "i'm confused", "doesn't make sense to me", "can you explain", "unclear", "not following", "you lost me", "what are you getting at", "elaborate" }, unknown_responses = { "that's interesting", "tell me more", "i see", "hmm", "really", "oh word", "cool", "nice", "right on", "interesting point", "fair enough", "makes sense", "i hear you", "gotcha", "for sure", "totally", "no doubt", "true that", "you got that right", "couldn't agree more", "exactly", "spot on" }, questions = { "what do you think about that", "how's your day going", "what's your favorite game", "been up to anything fun", "what brings you here", "having a good time", "what's new with you", "got any plans today", "what's keeping you busy", "how's school going", "what do you like to do", "got any hobbies", "where are you from", "what's on your mind", "what makes you happy", "what's your story", "favorite color", "what's good", "how's life treating you" }, compliments = { "that's pretty cool", "nice", "good point", "well said", "i like that", "sounds good", "awesome", "sweet", "sick", "tight", "rad", "wicked", "legit", "solid", "clutch", "fire", "dope", "fresh", "mad cool", "that's tight", "pretty sweet", "not bad", "decent", "proper good" }, thinking = { "let me think", "hmm", "well", "you know", "i mean", "actually", "honestly", "to be honest", "frankly", "basically", "in my opinion", "from what i know", "it seems to me", "i believe", "i think", "i reckon", "i'd say", "seems like" }, sympathy = { "that sucks", "sorry to hear that", "hope things get better", "been there", "rough times", "hang in there", "that's tough", "i feel for you", "that's rough buddy", "chin up", "better days ahead", "stay strong", "tough break", "that's hard", "i understand", "been through that myself" } } -- Context System local CONVERSATION_CONTEXT = { recent_topics = {}, last_response_time = 0, total_responses = 0 } -- Response Generator local ResponseGenerator = {} function ResponseGenerator:analyzeMessage(message) local analysis = { contains_greeting = false, contains_farewell = false, contains_question = false, is_positive = false, is_negative = false, topic = "general", emotion = "neutral", length = string.len(message) } local lowerMessage = string.lower(message) -- Check for greetings for _, greeting in pairs(KNOWLEDGE_BASE.greetings) do if string.find(lowerMessage, greeting, 1, true) then analysis.contains_greeting = true break end end -- Check for farewells for _, farewell in pairs(KNOWLEDGE_BASE.farewells) do if string.find(lowerMessage, farewell, 1, true) then analysis.contains_farewell = true break end end -- Check for questions if string.find(lowerMessage, "?") or string.find(lowerMessage, "what") or string.find(lowerMessage, "how") or string.find(lowerMessage, "why") or string.find(lowerMessage, "when") or string.find(lowerMessage, "where") or string.find(lowerMessage, "who") then analysis.contains_question = true end -- Detect topics for topic, keywords in pairs(KNOWLEDGE_BASE) do for _, keyword in pairs(keywords) do if string.find(lowerMessage, keyword, 1, true) then analysis.topic = topic break end end if analysis.topic ~= "general" then break end end -- Sentiment analysis local positive_words = {"good", "great", "awesome", "cool", "nice", "love", "like", "happy", "fun", "amazing"} local negative_words = {"bad", "terrible", "hate", "suck", "boring", "sad", "angry", "annoying", "awful"} for _, word in pairs(positive_words) do if string.find(lowerMessage, word, 1, true) then analysis.is_positive = true analysis.emotion = "positive" break end end for _, word in pairs(negative_words) do if string.find(lowerMessage, word, 1, true) then analysis.is_negative = true analysis.emotion = "negative" break end end return analysis end function ResponseGenerator:generateResponse(message, analysis, playerName) local responses = {} -- Handle greetings if analysis.contains_greeting then local greeting = RESPONSE_TEMPLATES.greetings[math.random(#RESPONSE_TEMPLATES.greetings)] if math.random() > 0.6 then greeting = greeting .. " " .. playerName end table.insert(responses, greeting) -- Sometimes add follow-up if math.random() > 0.5 then local followups = {"how's it going", "what's up", "having fun", "good to see you"} table.insert(responses, followups[math.random(#followups)]) end end -- Handle farewells if analysis.contains_farewell then local farewell = RESPONSE_TEMPLATES.farewells[math.random(#RESPONSE_TEMPLATES.farewells)] return farewell end -- Handle specific topics if analysis.topic == "how_questions" then local response = RESPONSE_TEMPLATES.how_responses[math.random(#RESPONSE_TEMPLATES.how_responses)] table.insert(responses, response) if math.random() > 0.4 then table.insert(responses, "how about you") end elseif analysis.topic == "name_questions" then local response = RESPONSE_TEMPLATES.name_responses[math.random(#RESPONSE_TEMPLATES.name_responses)] table.insert(responses, response) elseif analysis.topic == "age_questions" then local response = RESPONSE_TEMPLATES.age_responses[math.random(#RESPONSE_TEMPLATES.age_responses)] table.insert(responses, response) elseif analysis.topic == "games" then local game_responses = { "gaming is awesome", "love playing games", "what's your favorite game", "been playing anything good lately", "games are so fun", "what game you into", "love discovering new games", "what platform do you play on", "mobile or pc", "gaming keeps me entertained", "always down for some gaming", "games are the best" } table.insert(responses, game_responses[math.random(#game_responses)]) elseif analysis.topic == "school" then local school_responses = { "school can be tough", "how's school going", "education is important", "what's your favorite subject", "homework keeping you busy", "learning anything cool", "which grade are you in", "teachers can be strict", "making friends at school", "school days can be long", "exams coming up", "summer break soon" } table.insert(responses, school_responses[math.random(#school_responses)]) elseif analysis.topic == "food" then local food_responses = { "food is amazing", "sounds delicious", "making me hungry", "good choice", "love hearing about food", "what's for dinner", "cooking is an art", "dessert is the best part", "favorite restaurant", "home cooked meals are the best" } table.insert(responses, food_responses[math.random(#food_responses)]) elseif analysis.topic == "music" then local music_responses = { "music is life", "what's your favorite song", "love good music", "what genre you into", "music makes everything better", "got any recommendations", "live concerts are amazing", "what instrument do you play", "music connects people", "always discovering new artists" } table.insert(responses, music_responses[math.random(#music_responses)]) elseif analysis.topic == "technology" then local tech_responses = { "technology is incredible", "love tech stuff", "what device you using", "programming is cool", "mobile or desktop", "tech evolves so fast", "gadgets are fascinating", "coding is like magic", "digital world is amazing" } table.insert(responses, tech_responses[math.random(#tech_responses)]) end -- Handle questions without specific topics if analysis.contains_question and #responses == 0 then local thinking = RESPONSE_TEMPLATES.thinking[math.random(#RESPONSE_TEMPLATES.thinking)] local unknown = RESPONSE_TEMPLATES.unknown_responses[math.random(#RESPONSE_TEMPLATES.unknown_responses)] table.insert(responses, thinking .. ", " .. unknown) if math.random() > 0.5 then local question = RESPONSE_TEMPLATES.questions[math.random(#RESPONSE_TEMPLATES.questions)] table.insert(responses, question) end end -- Handle sentiment if analysis.is_positive and #responses > 0 then if math.random() > 0.6 then local compliment = RESPONSE_TEMPLATES.compliments[math.random(#RESPONSE_TEMPLATES.compliments)] table.insert(responses, compliment) end elseif analysis.is_negative then local sympathy_responses = { "that sucks", "sorry to hear that", "hope things get better", "been there", "rough times", "hang in there", "that's tough", "i understand" } table.insert(responses, sympathy_responses[math.random(#sympathy_responses)]) end -- Default responses if nothing else if #responses == 0 then if math.random() > 0.5 then local question = RESPONSE_TEMPLATES.questions[math.random(#RESPONSE_TEMPLATES.questions)] table.insert(responses, question) else local unknown = RESPONSE_TEMPLATES.unknown_responses[math.random(#RESPONSE_TEMPLATES.unknown_responses)] table.insert(responses, unknown) end end -- Combine responses local finalResponse = table.concat(responses, ", ") -- Ensure proper length if string.len(finalResponse) > BOT_CONFIG.MAX_RESPONSE_LENGTH then finalResponse = string.sub(finalResponse, 1, BOT_CONFIG.MAX_RESPONSE_LENGTH - 3) .. "..." end return finalResponse end -- Chat Detection and Response System local ChatSystem = {} function ChatSystem:isPlayerInRange(player) if not player or not player.Character then return false end local playerRoot = player.Character:FindFirstChild("HumanoidRootPart") if not playerRoot then return false end if not Character or not Character:FindFirstChild("HumanoidRootPart") then return false end local myRoot = Character.HumanoidRootPart local distance = (playerRoot.Position - myRoot.Position).Magnitude if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Distance to " .. player.Name .. ": " .. math.floor(distance) .. " studs") end return distance <= BOT_CONFIG.DETECTION_RANGE end function ChatSystem:shouldRespond(message, player) if not message or not player then return false end -- Don't respond to self if player == LocalPlayer then return false end local lowerMessage = string.lower(message) -- Filter system messages local systemPhrases = {"joined the game", "left the game", "died", "reset", "loading"} for _, phrase in pairs(systemPhrases) do if string.find(lowerMessage, phrase, 1, true) then return false end end -- Message length check if string.len(message) < 2 or string.len(message) > 100 then return false end -- Rate limiting local currentTime = tick() if currentTime - CONVERSATION_CONTEXT.last_response_time < 3 then return false end -- Random chance with bias for greetings/questions local baseChance = BOT_CONFIG.RESPONSE_CHANCE if string.find(lowerMessage, "hi") or string.find(lowerMessage, "hello") or string.find(lowerMessage, "hey") then baseChance = 0.95 elseif string.find(lowerMessage, "?") then baseChance = 0.9 end return math.random() < baseChance end function ChatSystem:processMessage(message, playerName) if not message or not playerName then return end local player = Players:FindFirstChild(playerName) if not player then return end if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Processing message from " .. playerName .. ": " .. message) end -- Check if should respond if not self:isPlayerInRange(player) then if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Player " .. playerName .. " is out of range") end return end if not self:shouldRespond(message, player) then if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Decided not to respond to " .. playerName) end return end -- Generate and send response spawn(function() -- Add to context table.insert(CONVERSATION_CONTEXT.recent_topics, { message = message, player = playerName, timestamp = tick() }) -- Limit context size if #CONVERSATION_CONTEXT.recent_topics > 10 then table.remove(CONVERSATION_CONTEXT.recent_topics, 1) end -- Generate response local analysis = ResponseGenerator:analyzeMessage(message) local response = ResponseGenerator:generateResponse(message, analysis, playerName) if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Generated response: " .. response) end -- Natural delay local delay = math.random(BOT_CONFIG.RESPONSE_DELAY_MIN, BOT_CONFIG.RESPONSE_DELAY_MAX) wait(delay) -- Send response local success = false -- Try TextChatService first pcall(function() if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then local channel = TextChatService.ChatInputBarConfiguration.TargetTextChannel if channel then channel:SendAsync(response) success = true if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Sent via TextChatService: " .. response) end end end end) -- Try Legacy Chat if TextChatService failed if not success then pcall(function() local chatEvents = ReplicatedStorage:FindFirstChild("DefaultChatSystemChatEvents") if chatEvents then local sayRequest = chatEvents:FindFirstChild("SayMessageRequest") if sayRequest then sayRequest:FireServer(response, "All") success = true if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Sent via Legacy Chat: " .. response) end end end end) end if success then CONVERSATION_CONTEXT.last_response_time = tick() CONVERSATION_CONTEXT.total_responses = CONVERSATION_CONTEXT.total_responses + 1 else warn("[ChatBot] Failed to send response: " .. response) end end) end -- Chat Connection Functions local function connectTextChatService() local success = false pcall(function() if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then local channels = TextChatService:FindFirstChild("TextChannels") if channels then local generalChannel = channels:FindFirstChild("RBXGeneral") if generalChannel then generalChannel.MessageReceived:Connect(function(message) if message and message.TextSource and message.Text then local playerName = message.TextSource.Name ChatSystem:processMessage(message.Text, playerName) end end) success = true print("[ChatBot] Successfully connected to TextChatService") end end end end) return success end local function connectLegacyChat() local success = false local attempts = 0 while not success and attempts < 10 do attempts = attempts + 1 pcall(function() local chatEvents = ReplicatedStorage:FindFirstChild("DefaultChatSystemChatEvents") if chatEvents then local messageEvent = chatEvents:FindFirstChild("OnMessageDoneFiltering") if messageEvent then messageEvent.OnClientEvent:Connect(function(messageData) if messageData and messageData.Message and messageData.FromSpeaker then ChatSystem:processMessage(messageData.Message, messageData.FromSpeaker) end end) success = true print("[ChatBot] Successfully connected to Legacy Chat") end end end) if not success then wait(1) end end return success end -- Main Initialization local function initialize() print("[ChatBot] Starting initialization...") -- Ensure character is ready if not Character or not Character.Parent then Character = waitForCharacter() Humanoid = Character:WaitForChild("Humanoid") end print("[ChatBot] Character ready: " .. Character.Name) -- Connect to chat systems spawn(function() wait(3) -- Give time for everything to load local textChatConnected = connectTextChatService() if not textChatConnected then print("[ChatBot] TextChatService failed, trying Legacy Chat...") local legacyChatConnected = connectLegacyChat() if not legacyChatConnected then warn("[ChatBot] Failed to connect to any chat system!") end end end) -- Cleanup system spawn(function() while true do wait(60) local currentTime = tick() -- Clean old conversation data for i = #CONVERSATION_CONTEXT.recent_topics, 1, -1 do if currentTime - CONVERSATION_CONTEXT.recent_topics[i].timestamp > 300 then table.remove(CONVERSATION_CONTEXT.recent_topics, i) end end if BOT_CONFIG.DEBUG_MODE then print("[ChatBot] Cleanup completed. Total responses: " .. CONVERSATION_CONTEXT.total_responses) end end end) print("[ChatBot] Initialization complete!") print("[ChatBot] Detection range: " .. BOT_CONFIG.DETECTION_RANGE .. " studs") print("[ChatBot] Debug mode: " .. tostring(BOT_CONFIG.DEBUG_MODE)) end -- Handle character respawning LocalPlayer.CharacterAdded:Connect(function(newCharacter) Character = newCharacter Humanoid = Character:WaitForChild("Humanoid") print("[ChatBot] Character respawned, reconnecting...") end) -- Mobile detection and optimization if UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled then BOT_CONFIG.MOBILE_OPTIMIZED = true BOT_CONFIG.RESPONSE_DELAY_MIN = BOT_CONFIG.RESPONSE_DELAY_MIN + 0.5 BOT_CONFIG.RESPONSE_DELAY_MAX = BOT_CONFIG.RESPONSE_DELAY_MAX + 0.5 BOT_CONFIG.MAX_RESPONSE_LENGTH = 60 print("[ChatBot] Mobile device detected, applying optimizations") end -- Start the bot initialize() -- Status check wait(5) print("[ChatBot] ================================") print("[ChatBot] Natural ChatBot is now ACTIVE!") print("[ChatBot] Lines of code: 600") print("[ChatBot] Mobile optimized: " .. tostring(BOT_CONFIG.MOBILE_OPTIMIZED)) print("[ChatBot] Ready to respond to players within " .. BOT_CONFIG.DETECTION_RANGE .. " studs") print("[ChatBot] Debug mode enabled - check console for activity") print("[ChatBot] ================================")