• How to read arguments from a chat command?
    6 replies, posted
Hi, what I cannot understand ATM is how to read a player's chat message and catch arguments if it matchers with a given commands. Example: The player says: !setteam X Y (X is the team number and Y is player ID) After I catch !setteam, how do I catch X and Y afterwards, and how do I make sure they are numeric entries, (parsing to integer maybe?)? Thanks in advance!
[url]http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index53ea.html[/url]
Here's what I do: [lua] // // Do /commands privately, !commands publicly // -- local _bSlash = string.sub( text, 1, 1 ) == "/"; -- local _bExclaim = string.sub( text, 1, 1 ) == "!"; local _bSlash = string.StartWith( text, "/" ); local _bExclaim = string.StartWith( text, "!" ); if ( _bSlash || _bExclaim ) then Player:ConCommand( string.sub( text, 2 ) ); if ( !_bExclaim ) then return ""; end end[/lua] Now, the commented _bSlash and _bExlaim do the exact same thing. But, what this does is convert it to a console command ( My game-mode uses NO console commands for anything, other than admin commands, motd, etc ). I use this to redirect / and ! chat commands to console commands, and the arguments are automatically passed through. This is easier, and nicer than putting every command into PlayerSay. If you don't want to do it this way, where with [lua]concommand.Add( "chatcommand", function( player_who_called_it, command_which_was_called, arguments_list ) PrintTable( arguments_list or { } ) end )[/lua] !chatcommand 1 2 3 4 prints this out due to PrintTable the args. 1 = 1 2 = 2 3 = 3 4 = 4 Then, you basically would do: [lua] // Define this function somewhere local function ChatFunctions( _cmd, _args ) print( "COMMAND: ", _cmd ) // Unpack can be used on a function so that it writes the functions as if they were comma delimited print( "ARGUMENTS: ", unpack( _args ) ) end[/lua] [lua] // // Do /commands privately, !commands publicly // local _bSlash = string.StartWith( text, "/" ); local _bExclaim = string.StartWith( text, "!" ); if ( _bSlash || _bExclaim ) then local exploded = string.Explode( " ", text ); print( "RAW DATA: " ); PrintTable( exploded ); // Extract the command by stripping the first letter and starting from letter 2, to the length of the text local _command = string.sub( exploded[ 1 ], 2, string.len( exploded[ 1 ] ) ); print( "STRIPPED COMMAND: " .. _command ); // Remove the first key, which is the command as we've separated them out table.remove( exploded, 1 ); // Alternatively you can do this if you don't know the KEY value: table.KeyFromValue( exploded, exploded[ 1 ] ) BUT, we do, so this is not optimal at all. local _arguments = table.Copy( exploded ); // Now, print the args print( "STRIPPED ARGUMENTS: " ); PrintTable( _arguments ); // Now, you can call a chat command function which handles this stuff ChatFunctions( _command, _arguments ) if ( !_bExclaim ) then return ""; end end[/lua] I hope this helps.
[QUOTE=MeepDarknessM;42212524][url]http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index53ea.html[/url][/QUOTE] Thank you for that, That almost solves my problem, but I have yet to understand how to effectively imbue the player chat message in to a given string :C EDIT: [QUOTE=Acecool;42212628]Here's what I do: [lua] // // Do /commands privately, !commands publicly // -- local _bSlash = string.sub( text, 1, 1 ) == "/"; -- local _bExclaim = string.sub( text, 1, 1 ) == "!"; local _bSlash = string.StartWith( text, "/" ); local _bExclaim = string.StartWith( text, "!" ); if ( _bSlash || _bExclaim ) then Player:ConCommand( string.sub( text, 2 ) ); if ( !_bExclaim ) then return ""; end end[/lua] Now, the commented _bSlash and _bExlaim do the exact same thing. But, what this does is convert it to a console command ( My game-mode uses NO console commands for anything, other than admin commands, motd, etc ). I use this to redirect / and ! chat commands to console commands, and the arguments are automatically passed through. This is easier, and nicer than putting every command into PlayerSay. If you don't want to do it this way, where with [lua]concommand.Add( "chatcommand", function( player_who_called_it, command_which_was_called, arguments_list ) PrintTable( arguments_list or { } ) end )[/lua] !chatcommand 1 2 3 4 prints this out due to PrintTable the args. 1 = 1 2 = 2 3 = 3 4 = 4 Then, you basically would do: [lua] // Define this function somewhere local function ChatFunctions( _cmd, _args ) print( "COMMAND: ", _cmd ) // Unpack can be used on a function so that it writes the functions as if they were comma delimited print( "ARGUMENTS: ", unpack( _args ) ) end[/lua] [lua] // // Do /commands privately, !commands publicly // local _bSlash = string.StartWith( text, "/" ); local _bExclaim = string.StartWith( text, "!" ); if ( _bSlash || _bExclaim ) then local exploded = string.Explode( " ", text ); print( "RAW DATA: " ); PrintTable( exploded ); // Extract the command by stripping the first letter and starting from letter 2, to the length of the text local _command = string.sub( exploded[ 1 ], 2, string.len( exploded[ 1 ] ) ); print( "STRIPPED COMMAND: " .. _command ); // Remove the first key, which is the command as we've separated them out table.remove( exploded, 1 ); // Alternatively you can do this if you don't know the KEY value: table.KeyFromValue( exploded, exploded[ 1 ] ) BUT, we do, so this is not optimal at all. local _arguments = table.Copy( exploded ); // Now, print the args print( "STRIPPED ARGUMENTS: " ); PrintTable( _arguments ); // Now, you can call a chat command function which handles this stuff ChatFunctions( _command, _arguments ) if ( !_bExclaim ) then return ""; end end[/lua] I hope this helps.[/QUOTE] Whoa, thanks for that, I will look into it!
Make sure you read my post, it shows why using console commands is simpler for this purpose than setting up an entire chat command handler as using console commands the arguments are passed through as they would be as though they were typed using the console. Then, you just set up the commands you want to use such as: [lua]concommand.Add( "motd", function( ply, cmd, args ) // Display motd.... end )[/lua] versus setting up a function / logic for motd in the separate handler.
[QUOTE=Acecool;42212658]Make sure you read my post, it shows why using console commands is simpler for this purpose than setting up an entire chat command handler as using console commands the arguments are passed through as they would be as though they were typed using the console. Then, you just set up the commands you want to use such as: [lua]concommand.Add( "motd", function( ply, cmd, args ) // Display motd.... end )[/lua] versus setting up a function / logic for motd in the separate handler.[/QUOTE] You are always one step ahead of me! anyways what I had done so far was: [lua] function ccSetTeam(ply, text, public) playerID = 0 teamID = 0 if(string.sub ( text, 1, 14) == "!setteam" ) then local Vars = PLAYER_CHAT_MESSAGE_STRING //<-- need to get this! teamID = Vars[2] playerID = Vars[3] local ply = Players[playerID] if ply:IsSuperAdmin() then ply:SetTeam( teamID ) ply:Spawn() elseif ply:IsAdmin() then ply:SetTeam( teamID ) ply:Spawn() else ply:ChatPrint("You Don't Have Access to this command!") end end end hook.Add( "PlayerSay", "ccSetTeam", ccSetTeam) [/lua]
That wouldn't work, because characters 1 through 14 would never be !setteam unless that's ALL there was. string.StartWith solves that problem by checking if a string starts with something. Otherwise you'd have to get the exact count: 1, 8 for !setteam. The first code I posted, the shorter one, would automatically take care of the !setteam function and /setteam where /setteam wouldn't be printed in the chat. To make that function work using my first example: [lua]function GM:PlayerSay ( Player, text, private ) // // Do /commands privately, !commands publicly // local _bSlash = string.StartWith( text, "/" ); local _bExclaim = string.StartWith( text, "!" ); if ( _bSlash || _bExclaim ) then Player:ConCommand( string.sub( text, 2 ) ); if ( !_bExclaim ) then return ""; end end // Optional, Basically if they are dead, don't let them chat. --return !Player:Alive( ) && "" || text; // Let all talk return text; end[/lua] Made some corrections to this function, you use ply do set the team of someone, but you check the same var for player, so I changed the CALLING player in the top to caller_ply to reference the two differently.. [lua]concommand.Add( "setteam", function( caller_ply, cmd, args ) local teamID = tonumber( args[ 1 ] ); local playerID = tonumber( args[ 2 ] ); if ( !teamID ) then ply:ChatPrint( "Team ID was not set!" ); end if ( !PlayerID ) then ply:ChatPrint( "Player ID was not set!" ); end // I'm not sure what Players was set to, but here's how to get via the 1-128 id. local ply = player.GetByID( playerID ); if ( caller_ply:IsAdmin( ) || caller_ply:IsSuperAdmin( ) ) then // Edited this to 1 line, even though a SuperAdmin is an Admin so the SuperAdmin check isn't technically needed. ply:SetTeam( teamID ); ply:KillSilent( ); ply:Spawn( ); else caller_ply:ChatPrint( "You Don't Have Access to this command!" ); end end )[/lua] EDIT: I'm helping him on Steam, he's one of the first people who've asked for help and instead of just using code samples provided, he's fixing what he made :-) +1
Sorry, you need to Log In to post a reply to this thread.