How to run a Function on a Player GMOD DarkRP Lua - lua

I am trying to make a muting script that doesn't let players talk. At the moment I am at telling which player in the script with no commands but I cant work out or find how to run this function that I created on a specific player, not just mute the entire server.
sv_mute.lua:
util.AddNetworkString( "mute_message" )
ismuted == false
targetPlayer == "Xx_Player_xX"
function checkmute()
function SendMessage( ply, txt, pub )
net.Start( "mute_message" )
net.WriteString( "YOU ARE MUTED, SHUT UP" )
net.Send( ply )
return ""
end
hook.Add( "PlayerSay", "SendMessage", SendMessage, )
end
Player:checkmute(()targetPlayer)
cl_mute.lua:
function ReceiveMessage()
local txt = net.ReadString()
chat.AddText( Color( 0, 255, 0), txt)
end
I have so far got to using Player:checkmute(()targetPlayer) but I assume this is wrong

So at first a few mistakes I have seen on a first quick look.
You defined a function without a parameter but you try to call it with one
You did not used the tools Garry gave you already to send messages to players
Things we will be using to achieve your desired task
GM:PlayerSay( Player sender, string text, boolean teamChat )
Player:PrintMessage( number type, string message )
The solution
-- sv_mute.lua
-- a list of muted players, you need to get them from somewhere (not part of this answer)
mutedPlayers = {
"StupidMan" = true,
"AnnoyingKid" = true,
"ExGirlfriend" = true
}
-- the function that will check if a user is muted
local function checkMuted(--[[ string ]] playername)
return mutedPlayers[playername]
-- you probably need to change the code to something else
-- based on how you store your muted players
end
hook.Add("PlayerSay", "VosemMute_PlayerSay", function(sender, message, teamChat)
if ( checkMuted(sender:GetName()) ) then
sender.PrintMessage(HUD_PRINTTALK, "You are muted!")
return "" -- this will suppress the message
end
end)
Some helpful links
HUD Enumerations (HUD_PRINTTALK)
Player:GetName()
hook.Add( string eventName, any identifier, function func )
Garry's Mod Wiki
Lua Reference Manual (sadly i do not know which lua version is used by gmod)
Disclaimer
This code is completely untested and written of my mind. If this does not work and throws some errors let me know that. I'll correct it then.

Related

Garry's mod lua errors

I keep getting this spammed in console:
MENU ERROR: lua/menu/mainmenu.lua:79: attempt to call global 'CanAddServerToFavorites' (a nil value)
lua/menu/mainmenu.lua:79 []
And this whenever I load a map (doesnt even let me play the map, kicks me out)
[ERROR] gamemodes/base/gamemode/animations.lua:333:
attempt to index local 'ply' (a nil value)
unknown - gamemodes/base/gamemode/animations.lua:333
I know the location of the files and I know that 333 or 79 means which line it is on, I just don't know how to fix the problem. Never coded in my life, but I tried changing the TranslateWeaponActivity to just TranslateActivity since I didnt see any other thing called TranslateWeaponActivity, that didn't work. Anyone with lua experience can help? Do I need to send the entire script?
function GM:TranslateActivity( ply, act )
local newact = ply:TranslateWeaponActivity( act )
-- select idle anims if the weapon didn't decide
if ( act == newact ) then
return IdleActivityTranslate[ act ]
end
return newact
end
and the code for favorites:
if ( self.CanAddServerToFavorites != CanAddServerToFavorites() ) then
self.CanAddServerToFavorites = CanAddServerToFavorites()
if ( self.CanAddServerToFavorites ) then
self.HTML:QueueJavascript( "SetShowFavButton( true )" )
else
self.HTML:QueueJavascript( "SetShowFavButton( false )" )
end
end
end

attempt to index global 'message' (a nil value) Lua Message script

Currently, I'm working on a simple Lua Roblox script that is supposed to turn the parent part blue when "/blue" is entered in the chat by ANY player. When run, it returns the error "attempt to index global 'message' (a nil value)" in the output. Also, when I hover my cursor over "message" it says "unknown global 'message'". I am sure I'm doing something terribly wrong as I am new to the language. I have tried moving the script into Workspace and Chat (of course changing local part when I do) but those don't help. I'm confident it's a code issue specifically defining a global variable.
local part = script.Parent
local function scan()
if message:sub(1,5) == "/blue" then
part.BrickColor = BrickColor.Blue()
end
end
scan()
First, you didn't define "message" because "message" is supposed to be an argument of
player.Chatted()
So instead of just running scan(), make multiple functions, here is the revised code:
local part = script.Parent
game.Players.PlayerAdded:Connect(function(plr)
plr.Chatted:Connect(function(message)
message = string.lower(message)
if message == "/blue" then
part.BrickColor = BrickColor.new("Blue")
end
end)
end)
Let me know if you need me to elaborate, I understand that sometimes this stuff can be confusing.

How do I do "io.read" twice on one variable after inputting the wrong type?

Heyo. I'm pretty new to Lua (although I do code with Java), so I don't really know anything on this. I'm basically trying to get a user's input, and if it's not the right type, then restart. Now, I'm not sure if it's just Lua or my IDE (I'm using ZeroBrane Studio if that helps), but it won't reinput for whatever reason. (it just loops, meaning it skips the io.read line)
::restart::
...
a = io.read("*number")
if unit == nil then
print("Error! Incorrect Input!\nRestarting...")
goto restart
end
Oh, and yes, I'm using goto commands for restart. I thought that might be what's causing the issue, but I also tried this:
a = io.read("*number") --input non-number
print(a) --prints
a = io.read("*number") --skips
print(a) --prints
When you input a number, it doesn't skip.
Any help would be nice. Thanks in advance.
nvm i solved it myself
local a
repeat
a = io.read(); a = tonumber(a)
if not a then
print("Incorrect Input!\n(Try using only numbers)")
end
until a
::restart::
local a = io.read("*n", "*l")
if a == nil then
io.read("*l") -- skip the erroneous input line
print("Error! Incorrect Input!\nRestarting...")
goto restart
end
P.S.
Feel free to use goto whenever it makes your code more understandable.
For example, using while of repeat-until loop in this code wouldn't make it better (you would need either additional local variable or break statement).
Instead of using the built-in filter of io.read() (which I do think is bugged sometimes) you should consider using an own little function to ensure that the correct data will be give by the user.
This is such a function:
function --[[ any ]] GetUserInput(--[[ string ]] expectedType, --[[ string ]] errorText)
local --[[ bool ]] needInput = true
local --[[ any ]] input = nil
while needInput do
input = GetData()
if ( type(input) == expectedType ) then
needInput = false
else
print(errorText)
end
end
return input
end
You can then call it with:
local userInput = GetUserInput("number", "Error: Incorrect Input! Please give a number.")
Oh and on a sidenote: Goto is considered bad practice.

Lua attempt to call field 'PlayFile' (a nil value)

I am trying to create an Lua addon for Garry's Mod but I keep coming across an error in my code.
This is my code:
function say (Player, text, ent)
s = "/misc/custom/"..text
s2 = s..".mp3"
sound.PlayFile(s2)
end
hook.Add("PlayerSay", "Say", say)
And this is the resulting error.
[saysoundtest25] lua/autorun/chatsounds.lua:4: attempt to call field 'PlayFile' (a nil value)
1. v - lua/autorun/chatsounds.lua:4
2. unknown - lua/includes/modules/hook.lua:84
Any ideas?
User Robotboy655 on Facepunch helped me solve this! The final code:
hook.Add( "PlayerSay", "Say", function( ply, text, team )
BroadcastLua( 'surface.PlaySound("misc/custom/' .. text .. '.mp3")' )
end )
Thanks everyone for the help!
The /lua/autorun file is serverside and there is a variable sound server-side Lua, however only in client side does sound.PlayFile exist.
if SERVER then
AddCSLuaFile() -- We're the server running this code! Let's send it to the client
else -- We're a client!
-- Your code here, only ran by the client!
end
See the Garry's Mod wiki for more info and note the orange box on the page which means it's client side.
Please remember to check what the function takes also:
sound.PlayFile( string path, string flags, function callback )
Example (taken from the wiki)
sound.PlayFile( "sound/music/vlvx_song22.mp3", "", function( station )
if ( IsValid( station ) ) then station:Play() end
end )
Also more easy way of searching the docs:
http://glua.me/
http://glua.me/docs/#?q=sound.PlayFile
How DarkRP handles this:
https://github.com/FPtje/DarkRP/blob/master/gamemode/modules/chatsounds.lua#L275

How to set name for function which is in the table

For example, I have a table
table.insert( t, 1, function()
print ("rock");
end );
Is there any way to get function name from this table. I know that I can store name like a key, but what if I want to keep numeric index and also I want to know function name?
Is there any way to do it?
Thanks, on advance.
Say you have this code:
t = {}
x = 5
table.insert(t, 1, x)
t would then be {[1] = 5}. "5" is just a number - it has no name, and isn't associated with the variable "x"; it's a value.
In Lua, functions are treated exactly the same way, as values:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)
The value of x is not associated with x in any way, shape, or form. If you want to manually name a function, you can do it by wrapping the function in a table, for example:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
name = "MyFunctionName",
func = x
})
That is how you would do it!
...unless..
..you break the rules!
When Lua was developed, the developers realised that the anonymous nature of functions would make productive error messages difficult to produce, if not impossible.
The best thing you'd see would be:
stdin: some error!
stdin: in function 'unknown'
stdin: in function 'unknown'
So, they made it so that when Lua code was parsed, it would record some debug information, to make life easier. To access this information from Lua itself, the debug library is provided.
Be very careful with functions in this library.
You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.
To achieve your desired effect, you must use the debug.getinfo function; an example:
x = function()
print("test!")
print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"
Unfortunately, the form of debug.getinfo that operates directly on a function doesn't fill the name argument (debug.getinfo(x, "n").name == nil) and the version above requires you to run the function.
It seems hopeless!
...unless..
..you really break the rules.
The debug.sethook function allows you to interrupt running Lua code at certain events, and even change things while it's all happening. This, combined with coroutines, allows you to do some interestingly hacky stuff.
Here is an implementation of debug.getfuncname:
function debug.getfuncname(f)
--[[If name found, returns
name source line
If name not found, returns
nil source line
If error, returns
nil nil error
]]
if type(f) == "function" then
local info = debug.getinfo(f, "S")
if not info or not info.what then
return nil, nil, "Invalid function"
elseif info.what == "C" then
-- cannot be called on C functions, as they would execute!
return nil, nil, "C function"
end
--[[Deep magic, look away!]]
local co = coroutine.create(f)
local name, source, linedefined
debug.sethook(co, function(event, line)
local info = debug.getinfo(2, "Sn")
name = info.namewhat ~= "" and info.name or nil
source, linedefined = info.short_src, info.linedefined
coroutine.yield() -- prevent function from executing code
end, "c")
coroutine.resume(co)
return name, source, linedefined
end
return nil, nil, "Not a function"
end
Example usage:
function test()
print("If this prints, stuff went really wrong!")
end
print("Name = ", debug.getfuncname(test))
This function isn't very reliable - it works sometimes, and doesn't others. The debug library is very touchy, so it's to be expected.
Note that you should never use this for actual release code! Only for debugging!
The most extreme case that is still acceptable is logging errors on piece of released software, to help the developer fix issues. No vital code should depend on functions from the debug library.
Good luck!
The function hasn't got any name. If you want you can assign it to a named variable:
theFunction = t[1]
-- Call it:
theFunction()
If what you want is storing a named function to the table, define it beforehand and use its name to store it:
theFunction = function()
print ("rock");
end
table.insert(t, 1, theFunction)
If this is not what you meant, give more details; for example how you would like to access the function. You're question is a bit misty.
The thing is table.insert considers the table as a sequence, only with numeric keys.
If you want to be able to call the function as t.fun() you'll have to use the table as an associative array and hence use a string as key. (BTW any type except nil or NaN are allowed as key)
t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.
You might also notice that functions are passed by reference. So all functions are actually anonymous, and are just stored as a value to a certain key or variable.
You can store the names in a separate table.
functions = {}
functionNames = {}
function addFunction(f, name)
table.insert(functions, f)
functionNames[name] = f
end
To get the function, you can use the index. Once you have the function, you can get its name from function_names:
f = functions[3]
name = functionNames[f]
Good luck!

Resources