• Could I get some criticism on my code snippet?
    11 replies, posted
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.