So I created a function that allows players to give other players coins. I was wondering if there was a way to speed up or reduce my code a little bit.
[lua]
COIN.Give = function(pl, text, public)
text = string.lower(text)
local command = string.Left(text, 5)
if command == "/give" || command == "!give" then --"/give PlayerA 100"
local length = string.len(text)
text = string.Right(text, length-6) --"PlayerA 100"
local text_table = string.Explode(" ", text) --"PlayerA", "100"
if #text_table > 1 then
local amount = tonumber(text_table[#text_table]) --100
if amount != nil then
if amount > 0 then
local length2 = string.len(amount)+1
local search = string.Left(text, string.len(text)-length2) --"PlayerA"
local list = {}
for _, v in pairs(player.GetAll()) do --Check if any player's name matches "PlayerA".
local player = string.lower(v:Nick())
if string.find(player, search) then
table.insert(list, v)
end
end
if #list > 0 and #list < 2 then --Make sure there is only one player with "PlayerA" in their name.
local retriever = list[1]
if (retriever:IsValid() and retriever != NULL) and (pl:IsValid() and pl != NULL) then--(pl, retriever, amount)
local fix = ""
if amount > 1 then
fix = "s"
end
pl:ChatPrint("You gave "..retriever:Nick().. " "..amount.." coin"..fix..".") --Take money from player.
retriever:ChatPrint(pl:Nick().." gave you "..amount.." coin"..fix.."!") --Give money to retriever.
end
end
end
end
end
end
end
hook.Add("PlayerSay", "Give coins.", COIN.Give)
[/lua]
This chat command works like so:
[quote]
/give PlayerA 100
or
!give PlayerA 100
[/quote]
If you're after cleaner code, you could just create a general chat command hook with a function to register chat commands. That'll mean if you ever want to add another chat command you won't need to copy all of what you've got there. If you do that you could create a function that gets player(s) based off of an argument given to the chat command too for the same reasons.
Example use of what I'm suggesting could be like:
[code]
chatcommand.Add("test", function(ply, args, argstr)
PrintTable(args)
print(argstr)
end
--[[
Where saying (/test Hello there "how are you today") outputs a table similar to {"Hello", "there", "how are you today"} and the string "Hello there \"how are you today\""
]]
[/code]
function(ply, cmd, text) would be better, since you can explode it yourself and if you use multiple commands for the same hook you may want to know what command was used
Thanks for the suggestions, better ways to dissect the chat commands was a little more of what I was looking for. I was thinking maybe it could be done with patterns than with all of these 'if/thens' and 'string.' commands. I'm not too bright with patterns but I've seen people do crazy things with them before so I figured why not ask.
Also I was planning on making this into a little machine with a usage similar to this, I think this is what you were suggesting Willox?
[lua]
CHAT:AddCommand("give", player, amount, function)
//Creates a chat command activated by !give or /give as long as a player, amount, and function are provided.
[/lua]
I edited this like 4 times :v:
[lua]COIN.Give = function( ply, text, public )
local args = string.Explode( " ", string.lower( text ) );
local cmd = args[1];
local target = args[2];
local amount = tonumber( args[3] );
-- If we have all 3 arguments and the amount is above zero.
if ( cmd ) then
-- Self explanitory.
if ( cmd == "/give" || cmd == "!give" ) then
-- If the arguments are correct.
if ( target && amount && amount > 0 ) then
local targets = {};
for k, v in pairs( player.GetAll() ) do
if ( string.find( target, string.lower( v:Nick() ) ) ) then
table.insert( targets, v );
end
end
-- If we have no targets
if ( #targets == 0 ) then
-- Say no player found?
else
-- If we have only one target
if ( #targets == 1 ) then
local giftee = targets[1];
-- We only need 'IsValid'.
if ( IsValid( giftee ) ) then
local postfix = "";
if ( amount > 1 ) then
postfix = "s";
end
ply:ChatPrint( "You gave " .. giftee:Nick() .. " " .. amount .. " coin" .. postfix .. "." );
giftee:ChatPrint( ply:Nick() .. " gave you " .. amount .. " coin" .. postfix .. "!" );
end
else
-- If there were 2 or more targets.
end
end
else -- If the arguments are incorrect.
-- We'll start from the last argument, and work our way to the first.
if ( amount == nil || amount == 0 ) then
ply:ChatPrint( "You have to enter a proper amount to give!" );
elseif ( target == nil || #target == 0 || #target == "" ) then
ply:ChatPrint( "You can't give any coin(s) to an invalid target. " );
end
end
end -- End of 'if cmd =='
end -- End of 'if ( cmd )
end
hook.Add( "PlayerSay", "Give coins.", COIN.Give );[/lua]
Minimalized:
[lua]COIN.Give = function( ply, text, public )
local args = string.Explode( " ", string.lower( text ) );
local cmd = args[1];
local target = args[2];
local amount = tonumber( args[3] );
if ( cmd ) then
if ( cmd == "/give" || cmd == "!give" ) then
if ( target && amount && amount > 0 ) then
local targets = {};
for k, v in pairs( player.GetAll() ) do
if ( string.find( target, string.lower( v:Nick() ) ) ) then
table.insert( targets, v );
end
end
if ( #targets == 0 ) then
ply:ChatPrint( "You can't give any coin(s) to a non-existant player." );
else
if ( #targets == 1 ) then
local giftee = targets[1];
if ( IsValid( giftee ) ) then
local postfix = "";
if ( amount > 1 ) then
postfix = "s";
end
ply:ChatPrint( "You gave " .. giftee:Nick() .. " " .. amount .. " coin" .. postfix .. "." );
giftee:ChatPrint( ply:Nick() .. " gave you " .. amount .. " coin" .. postfix .. "!" );
end
else
ply:ChatPrint( "There were too many people with a matching name to give coins to." );
end
end
else
if ( amount == nil || amount == 0 ) then
ply:ChatPrint( "You have to enter a proper amount to give!" );
elseif ( target == nil || #target == 0 || #target == "" ) then
ply:ChatPrint( "You can't give any coin(s) to an invalid target. " );
end
end
end
end
end
hook.Add( "PlayerSay", "Give coins.", COIN.Give );[/lua]
Doing [code]if ( string.find( target, string.lower( v:Nick() ) ) ) then[/code] Seems kinda unsafe considering if you're to give coins to your friend "Boo" and theres also a guy called "BooHoo" on the server, what would you do in order to give to him?
[QUOTE=Donkie;40345711]Doing [code]if ( string.find( target, string.lower( v:Nick() ) ) ) then[/code] Seems kinda unsafe considering if you're to give coins to your friend "Boo" and theres also a guy called "BooHoo" on the server, what would you do in order to give to him?[/QUOTE]
If you read a little bit harder; he checks to make sure there's only one result, otherwise nothing happens.
[QUOTE=Walrus Viking;40346807]If you read a little bit harder; he checks to make sure there's only one result, otherwise nothing happens.[/QUOTE]
Yeah I know, but what would you do in that case? Would you tell "BooHoo" to leave the server?
[QUOTE=Donkie;40346923]Yeah I know, but what would you do in that case? Would you tell "BooHoo" to leave the server?[/QUOTE]
I guess I can make a little screen that comes up when multiple people are found, does that sound like a decent idea?
If this is for community RP i would suggest that you make it use aim target instead, would also have a more of an RP vibe to it
[QUOTE=Ducky3426;40349186]If this is for community RP i would suggest that you make it use aim target instead, would also have a more of an RP vibe to it[/QUOTE]
About that... It might be awhile before I work on that since some things got in the way.
Just check if the name exactly matches the player's name first, THEN go into the string.find stuff. That way if you type "Boo" it will go to "Boo" because it's an exact match. No guarantees if you type "Bo" though.
Sorry, you need to Log In to post a reply to this thread.