• Question / Answer Bot
    11 replies, posted
Hello, I'm looking for something like this: - When a player types something, if x amount of words match some keywords, specified in a table or two, and is prefixed by "!ask" the bot responds with an answer to such question. For example: Player: !ask How do I get VIP? -scans a table for keywords and finds "How", "VIP", and "get" in one record, so then finds following response from other table: Bot: ANSWER to Player: Visit our website at [url]www.example.com[/url] I could see the tables looking something like: [lua] local keywords = { [1] = {"How", "VIP", "Get" }, [2] = {"Something", "else" }, } local answers = { [1] = "Visit our website at www.example.com", [2] = "Something", } [/lua] Not sure if that's the best way to go about it, but I'm not sure exactly how to hook the playersay features, and scan for such keywords.
PlayerSay hook string.find usermessages / player.PrintMessage / player.ChatPrint
-snip- Ninja'd
[b]Server: [/b] [lua] local keywords = { {"How", "VIP", "Get" }, {"Something", "else" }, } local answers = { "Visit our website at www.example.com", "Something", } function AskBot( ply, strText, team ) -- Search for '/ask' local strS = -1 local strE = -1 strS, strE = string.find( strText, "/ask" ) if ( strS==1 ) then -- If we find '/ask' then search the question keywords for k, v in pairs( keywords ) do -- A count we use to match the number finds to the maximum possible results local x=0 for n, e in pairs( keywords[k] ) do -- Check first keyword table -- More temporary string search variables local strSB=-1 local strEB=-1 -- keywords[k].[n] (?) possible invalid strSB, strEB = string.find( strText, keywords[k].n ) -- If we found a keyword, add a number to the count if ( strSB!=-1 ) then x=x+1 end end -- If the count is equal to the number of search keywords, we have a match! if ( x==#keywords[k] ) then -- Print the answer to everyone ( send this to specifically to the asking client? ) chat.AddText( Color(255,100,100), "[Q/A Bot]: ", Color(240,240,240), answers[k] ) -- Print the original text, and exit this function and these confounding for loops return strText end end end -- If we're not searching, or if we found nothing, print the original chat and exit the function return strText end -- Hook this function to the PlayerSay function for access to chat hook.Add( "PlayerSay", "AskBot", AskBot )[/lua] Hope that helps!
Very useful. Thanks for the help :) EDIT: Hmm, line 25 is reporting: '<name>' expected near '[' Using just "e" seems to fix it. :)
Except for PlayerSay hook is serverside and chat.AddText is clientside.
[QUOTE=zzaacckk;29174679]Except for PlayerSay hook is serverside and chat.AddText is clientside.[/QUOTE] Credits to Overv: [lua] if SERVER then chat = { } function chat.AddText( ... ) if ( type( arg[1] ) == "Player" ) then ply = arg[1] end umsg.Start( "AddText", ply ) umsg.Short( #arg ) for _, v in pairs( arg ) do if ( type( v ) == "string" ) then umsg.String( v ) elseif ( type ( v ) == "table" ) then umsg.Short( v.r ) umsg.Short( v.g ) umsg.Short( v.b ) umsg.Short( v.a ) end end umsg.End( ) end else usermessage.Hook( "AddText", function( um ) local argc = um:ReadShort( ) local args = { } for i = 1, argc / 2, 1 do table.insert( args, Color( um:ReadShort( ), um:ReadShort( ), um:ReadShort( ), um:ReadShort( ) ) ) table.insert( args, um:ReadString( ) ) end chat.AddText( unpack( args ) ) end ) end [/lua] EDIT: Here's the updated code I'm using now. Thanks again TeeHelee :) [lua] function AskBot( ply, strText, team ) if ( string.find( strText, "/ask" ) ) then for k, v in pairs(keywords) do local x = 0 for n, e in pairs(keywords[k]) do if ( string.find( strText, e ) ) then x = x + 1 print(e .. " found") end end if ( x == #keywords[k] ) then chat.AddText( ply, Color(255,100,100), "[Q/A Bot]: ", Color(240,240,240), answers[k] ) return "" end end chat.AddText( ply, Color(255,100,100), "[Q/A Bot]: ", Color(240,240,240), "No question matched." ) return "" end end hook.Add( "PlayerSay", "AskBot", AskBot ) [/lua]
No offence Tehelee, but your code makes my eyes bleed. Neatness never hurt anyone.
[QUOTE=FlapadarV2;29175350]No offence Tehelee, but your code makes my eyes bleed. Neatness never hurt anyone.[/QUOTE] I fixed it up, sorry about that, I'm not used to having others look at my code. Any other tips on cleanliness that I can improve? I'm very curious to know, and thanks for the constructive criticism btw! :3
imo I think you should put comments next to your code, and not above / below. If you decide not to, please use -- instead of //, it seems to all blend together.
I wasn't meaning double line spacing, more so meaningful variable names - "strS" is a bit cryptic. Also, you should declare your variable and equal it directly to string.find, rather than declaring it first (Looks way neater, but makes no real difference) Your method for checking keywords is a bit.. odd. It should work though.
[QUOTE=Derek_SM;29175783]imo I think you should put comments next to your code, and not above / below. If you decide not to, please use -- instead of //, it seems to all blend together.[/QUOTE] I kinda prefer the comment to be right before what it does. In my mind it just looks a bit neater to have comments and actual code separated.
Sorry, you need to Log In to post a reply to this thread.