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!
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.