Lua question: ENT. vs self.

Hello!

I’ve started to code a few entities in lua for Garry’s mod just recently, and I need a little enlightenment about the following matter.

In case of defining variables for an entity, what is the difference between doing it before the ENT:Initialize() function like this:

  • ENT.variable = …*
    or doing it inside the ENT:Initialize() function like:
  • self.variable = …*

In both cases it should run only once, right?
The real question is that are both types removed when the entity is removed, or not?
I experienced strange things when I defined a table in the first way.

Thanks in advance for any helpful comments.

ENT refers to the ENT table before it is applied to an entity, self refers to the table after. You should only ever define things on ENT when outside of the function (global scope), to make a variable that applies to all entities created from this table. You should only ever modify variables created with ENT using self. Example

[lua]
ENT.FunStuff = 1 – Good usage
self.FunStuff = false – BAD, do not do this!!

function ENT:Think()
print (self.FunStuff)
self.FunStuff = self.FunStuff + 1 – Good usage

ENT.FunStuff = false -- BAD, do not do this!!

end

[/lua]

So if I modify variables in the functions with self., that should not affect the global ENT table. Is that correct?

[editline]6th May 2015[/editline]

Thank you for the answer, I now understand more how it should work.

Here is the problem I couldn’t figure out:
I have an entity in where I define a table globally, I create and put a prop in the table, I remove the created prop (the table will now contain a NULL entity), then I remove the entity that is doing all this.
If I now create said entity again, the new entity’s table will not be empty.

[lua]
AddCSLuaFile()

ENT.Base = “base_entity”
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.Author = “klujby”
ENT.Type = “anim”

if SERVER then

ENT.TableToTest = {}

function ENT:Initialize()
	print(table.ToString(self.TableToTest,'TableToTest',true))
	local ent = ents.Create("prop_physics")
	Msg('Created prop: ') MsgN(ent)
	self.TableToTest[#self.TableToTest+1]=ent
	print(table.ToString(self.TableToTest,'TableToTest',true))
	ent:Remove()
	self:Remove()
end

end
[/lua]

Every time I create the entity the table contains more and more NULL entities.
It seems that in this case the global ENT table is affected by the entity.

But please correct me if I made an error somewhere, this language is quite new to me after all.

Think of it this way: “ENT” is a parent to each spawned instance of the entity. You never create their own instance of TableToTest for children (ie. the spawned instances of the entity) of the “ENT”, which means that when you do eg. “print(self.TableToTest)” inside ENT:Initialize(), you still refer to the parent’s TableToTest field.

If you want to have a unique table per entity you should create the table inside ENT:Initialize(), ie. self.TableToTest = {}

Replicated the error, that happens with tables. Tables aren’t ordinary things like numbers or strings in lua. If you make a new reference to them, they don’t copy, they simply refer to the same data. This is what I mean:

[lua]
local i = 1
local b = i
b = b + 3

print( i, b ) – prints 1 and 4

local t = {“Hello”}
local y = t
y[2] = “World!”

PrintTable( t )
PrintTable( y )

– Both print the same thing
[/lua]

I don’t know why it’s set up like this, but it sounds like a bug in how the ENT table is copied to define the entity.

Yes, that’s how tables should be created, but it’s weird how the tables are only referenced instead of copied. I’m sure there’s a reason for why it works this way though.

Gmod has table.Copy

It’s pretty standard when you consider how inheritance is usually done in Lua.



local parent = {}
parent.sub = {a = 42}

local child = setmetatable({}, {__index = parent})
child.sub.a = 12

print(child.sub.a)


Another reason why it works this way is because it’s “cheaper” performance-wise, storing tables by value would make them copy each time you pass a table to a function or access a subtable.

That is probably the case. I’ve checked more data types and it seems that every object that has more than one element behaves this way: tables, vectors, angles …

[lua]
local A, B
A=Vector(1,2,3)
B=A
B.x=0
– Result: A=(0,2,3)
[/lua]
This is very good to know, it might save me from creating some bugs.
(Though, the entity I’m workin on is a bug itself :smile:)

Thank you all for the replies, I get how it works now.