Attempt to index "group" (A nill value) - lua

Im new to Lua and can only just really read it, mainly just interpreting. I was having an error with a modification for Garrys mod where a lightsaber mod I had installed worked on client side but was invisible on server side. This is because of settings, ect. I asked on his group and he told me this :
You must call these functions on the weapon right after spawning it:
self:SetMaxLength( 42 )
self:SetCrystalColor( Vector( 255, 0, 0 ) )
self:SetDarkInner( false )
self:SetWorldModel( "models/... etc" )
self:SetBladeWidth( 2 )
self.LoopSound = "sound/lightsaber/..."
self.SwingSound = "sound/lightsaber/..."
self:SetOnSound( "sound/lightsaber/..." )
self:SetOffSound( "sound/lightsaber/..." )
self.WeaponSynched = true
Where self is the weapon.
So I put it into the code. All this does is completely remove the lightsaber and give me this error:
[ERROR] lua/weapons/weapon_lightsaber.lua:44: attempt to index global 'self' (a nil value)
1. unknown - lua/weapons/weapon_lightsaber.lua:44
Here is the pastebin of the code : http://pastebin.com/Y8kmivuv

Try using 'SWEP' instead of 'self'. self is usually defined in object-orientated code, which uses metatables in Lua.

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

Lua - Repeat until recurent table to except 'attempt to index a nil value'

Ok so i will show an exemple
I want do this :
local x = {}
repeat
-- wait function
until x.lel.ciao
But i've this error :
input:3: attempt to index a nil value (field 'lel')
So i can just do this :
local x = {}
repeat
-- wait function
until x.lel and x.lel.ciao
but if i've a long path how can i do ?
like :
x.lel.ciao.value1.title1.text1
i dont want do :
local x = {}
repeat
-- wait function
until x.lel and x.lel.ciao and x.lel.ciao.value1 and x.lel.ciao.value1.title1 and x.lel.ciao.value1.title1.text1
Someone have an idea ? like a function safepath(x.lel.ciao.value1.title1.text1)
Just like Egor's comment (thanks Egor), debug.setmetatable allows you to set a metatable for object type (not object instance).
This comes with an issue,
All the objects of that type will also inherit the mtatable.
This means, you will experience issues that will make your code harder to debug, as it is definitely important to get this kind of feedback from nil values.
Take in example the following code:
debug.setmetatable(nil, { __index = {} })
repeat
. . . -- Your code goes here
until x.lel.ciao.value1.title1.text1
function getFrom(data, value)
return date[value]
end
. . . -- More code
From this simple scope perspective, you might quickly see the issue, but imagine this code being buried by thousands of lines and functions.
You will eventually run into insanity as it only returns nil, which shouldn't happen at all because, well, you are sure your data variable has such value, right?
In order to avoid such thing from happening, you should safely do it like this:
debug.setmetatable(nil, { __index = {} })
repeat
. . . -- Your code goes here
until x.lel.ciao.value1.title1.text1
debug.setmetatable(nil, nil)
According to the Lua reference, setting a metatable to nil will remove the metatable, this way you will only temporally ignore feedback from nil while running inside the repeat loop.

What causes "Tried to use a NULL physics object!" error in my Garry's Mod Lua script?

I've made a small script that makes ragdolls fly upwards. It works but it leaves an error message and I cant figure out why.
[ERROR] RunString:11: Tried to use a NULL physics object!
1. ApplyForceCenter - [C]:-1
2. fn - RunString:11
3. unknown - addons/ulib/lua/ulib/shared/hook.lua:179
The error is getting spammed in console until I delete all existing ragdolls
My code:
hook.Add("Think", "Fly", function()
ent = ents:GetAll()
for k, v in pairs(ent) do
local isRagdoll = v:IsRagdoll()
if isRagdoll == true then
phys = v:GetPhysicsObject()
phys:ApplyForceCenter(Vector(0, 0, 900))
end
end
end)
Thanks in advance.
Henrik's answer is spot on about logic. You do need to make sure the physics object is valid before trying to use it.
In GMod, the function for this is IsValid.
if IsValid(phys) then
I'd have added this as a comment to Henrik's answer but I don't quite have enough rep yet.
Edit: Thanks to MattJearnes for clarifying how to check gmod objects for NULL.
Without knowing anything about gmod's API, I'd guess that GetPhysicsObject can return a special value that depicts NULL, in which case you cannot call ApplyForceCenter on it. You should simply check for NULL before doing anything using IsValid:
hook.Add("Think", "Fly", function()
ent = ents:GetAll()
for k, v in pairs(ent) do
local isRagdoll = v:IsRagdoll()
if isRagdoll == true then
local phys = v:GetPhysicsObject()
if IsValid(phys) then
phys:ApplyForceCenter(Vector(0, 0, 900))
end
end
end
end)

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