Calling functions dynamically

What I’m trying to do is make a function to add a chat command, etc, code I’ve come up with is:
[lua]
function AddChatCmd( text, func )
local function Chat( ply, txt )
if string.lower( txt ) == text then
func
end
end
hook.Add( “PlayerSay”, Chat )
end
[/lua]

Should I be calling the local function with a hook inside the function?
And can you call a function contained in a variable by just typing the var name?

The problem is that you can’t make a function with the chatbox (unless you runstring some text from it.

Then how do you do it, and what is this runstring you speak of?

[lua]local commands = {}

function CreateChatFunction(Pl, Txt)
local exploded = string.Explode(" ", Txt)
local command, funcname = exploded[1], exploded[2]
if commands[funcname] then commandscmd return Txt end
if command == “createfunc” then
table.remove(exploded, 1)
table.remove(exploded, 1)
local func = table.concat(exploded, " ")
commands[funcname] = function() RunString(func) end
return “”
end
end
hook.Add(“PlayerSay”, “ChatFunctions”, CreateChatFunction)[/lua]
I have no idea if this will work.

[lua]local chatcommands = {};

function AddChatCommand(name, func)
chatcommands[name] = func;
end

hook.Add(“PlayerSay”, “ChatCommand”, function(ply, text)
local cmd, args = text:match("/(.+)%s(.+)"); – Unnecessary, could just use string.Explode here.
if cmd then
for name, func in pairs(chatcommands) do
if name:lower() == cmd:lower() then
func(ply, cmd, string.Explode(" ", args);
break;
end
end
return “”;
end
end);

AddChatCommand(“kick”, function(ply, cmd, args) – Example usage. (use like concommand.Add)
if ply:IsAdmin() and args[1] then
for _, p in ipairs(player.GetAll()) do
if p:Nick():find(args[1]) then
p:Kick();
return ;
end
end
end
end);[/lua]

Something like this would be better. Note that the string pattern match is unnecessary, you could just do the string.Explode there and use the first argument for the cmd and the rest for the arguments.

I really don’t understand what you’re doing there.
[lua]
local chatcommands = {};

function AddChatCommand(name, func)
chatcommands[name] = func;
end
[/lua]
Why are you making that table?
Is chatcommands[name] = func adding an entry to the table?
Why not use table.insert?

[lua]

hook.Add(“PlayerSay”, “ChatCommand”, function(ply, text)

local cmd, args = text:match("/(.+)%s(.+)"); – Where are you getting args from?

if cmd then – What is cmd? What is if cmd supposed to do?

for name, func in pairs(chatcommands) do – What are you doing with func? It’s an argument in a different function, so how are you calling it here?

if name:lower() == cmd:lower() then – What is name? Where is that defined?

func(ply, cmd, string.Explode(" ", args); – Again, what is func doing here.

break;

end

end

return “”;

end

end);

[/lua]

Really hate to come across as stupid or anything, but this doesn’t make sense to me and I want to be able to come up with this sort of thing on my own.
What my original question was is how you can pass a function as an argument in another function and call it in there, and your post just confused me even more.

[lua]function callfunc(f)
f()
end

function sayhi()
print(“hi!”)
end

callfunc(sayhi)[/lua]

[editline]05:07PM[/editline]

Didn’t mean to confuse you :eng99:

[editline]05:10PM[/editline]

I really suggest you read the Lua reference manual, it can be found here. Some of those questions in your comments will become much clearer once you have a better understanding of the syntax of Lua.

[editline]05:13PM[/editline]

You just need to add parenthesis after func in your first post for it to work, but it is not really a good way to go about this.

[lua]function AddChatCmd( text, func )
local function Chat( ply, txt )
if string.lower( txt ) == text then
func()
end
end
hook.Add( “PlayerSay”, Chat )
end
[/lua]

Thank you, that’s a lot clearer.

As to your earlier question

Yes, doing chatcommands[name] = func sets the key [name] of the chatcommands table to whatever the func variable is. The structure of the table would then look like (if name were “asdf” and func was a function):
chatcommands:
[lua] asdf = function(address in memory)[/lua]

But table.insert takes a parameter and inserts it at the lowest available numeric key in the table. If you did table.insert(chatcommands, func) then the table would look like:
chatcommands:
[lua] 1 = function(address in memory)[/lua]

As you can see, the string “asdf” as the key is much more helpful in this case for telling which function this is than the key 1, because you can take the first word in the chat string and see if it is “asdf”, and then call chatcommands[“asdf”] (or put the first word in a variable and call chatcommands[variablename], which is the way you would actually do it).

[lua]-- Different ways of using functions

– You don’t have to use the “function f() dosomething end” format, since functions are like regular variables
local f = function() print(“Hi!”) end

– This
function f2()
f()
end
– And this
f2 = f
– Produce the same output when run

local t = {}
t[“f3”] = f

– Both of these calls are valid:
t.f3()
t"f3"

– Remember, functions are just like any other variable in lua – you just need to remember to put a parentheses after the variable name
– If it doesn’t make sense, imagine a function as just a special kind of string that you run after using ()[/lua]

Hope that helps.

[lua]function f()
print(“Hi!”)
end

function f2()
f()
end

print(f==f2)[/lua]

Output:


false

No it isn’t, but I know what you mean. Calling f2 will yield the same results as calling f.

Sorry, I should have been more clear. Just talking about output here.

[lua]
function Test( ply, text )
ply:Kill()
ply:ConCommand( “say”…text )
end

AddChatCmd( Test, “/Test” )

function AddChatCmd( ply, text, func, cmd )
local expl = string.Explode( " ", text )
if string.lower( expl[1] ) == text then
if string.lower( expl[2] ) then
func( ply, expl[2] )
else
func( ply ) end
end
end
hook.Add( “PlayerSay”, AddChatCmd )

AddChatCmd( Test, “/test” )
[/lua]
I tried this and it doesn’t seem to work. Can someone explain what I’m doing wrong here?
I’m also not really sure how to pass the ply arguments for the function being passed inside the AddChatCmd function.

[lua]local commands = {}

function CreateChatFunction(Pl, Txt)
local exploded = string.Explode(" ", Txt)
local command, funcname = exploded[1], exploded[2]
if commands[command] then commandscommand return Txt end
if command == “createfunc” then
table.remove(exploded, 1)
table.remove(exploded, 1)
local func = table.concat(exploded, " ")
commands[funcname] = function() RunString(func) end
end
end
hook.Add(“PlayerSay”, “ChatFunctions”, CreateChatFunction) [/lua]

Tested working:



yakahughes: createfunc asdf print'lol'
yakahughes: asdf
lol