Problem with ents.create and a table.

Before I tell you my problem, here’s the code.

[lua]
for k, v in pairs(self.Entity.Contents) do
local vclass = v:GetClass()
local vmodel = v:GetModel()
if !v:IsValid() then return end
local vspawn = ents.Create(vclass)
vspawn:SetPos(self:GetPos())
vspawn:SetModel(vmodel)
vspawn:Spawn()
vspawn:Activate()
end
table.Empty(self.Entity.Contents)
[/lua]

As you can see for each entity/weapon in the table it spawns it and empties the table.
I cannot understand why but what it does is spawn two values (entities) instead of one even if there’s only one in the table.
I put two of the same entities into the table, it generates four.
And so on.
Any ideas?

[editline]30th September 2013[/editline]

Also, if I press E on the other entity it spawns then it throws this error:


bad argument #1 to 'Create' (string expected, got nil) 

vclass is nil. Means v:GetClass() doesn’t return anything. Post contents of your table.

The contents are dynamic, it’s a box. You grav gun entities in, it keeps them untill destroyed or taken out using a VGUI.
I don’t understand though, how can vclass be nil if it does spawn the correct weapon/entity?

I assume this is called from ENT:Use?

If so, you must put self:SetUseType(SIMPLE_USE) in your ENT:Initialize

My upper post is about the error only.

There are two ways to get the entities out, one is using it (ENT:Use) and the other is destroying the box.
Using it opens the VGUI and I can spawn the weapon/entities just fine.
But if I destroy the box, it executes the code in OP and works.
The problem is that while it does work, even if the table contains only one entry (entity/value/whatever) it duplicates it and spawns 2 entities.

Basically, destroy crate with one weapon in it, code in op gets executed, creates two weapons instead of one. One weapon is use-able, second weapon throws the error in the OP. (the second weapon shouldn’t even spawn)

First of all move if !v:IsValid() then return end up so it looks like this: ( I also recommend using IsValid(ent), not ent:IsValid() )



for k, v in pairs(self.Entity.Contents) do
            if !IsValid(v) then break end
            local vclass = v:GetClass()
            local vmodel = v:GetModel()
            local vspawn = ents.Create(vclass)
            vspawn:SetPos(self:GetPos())
            vspawn:SetModel(vmodel)
            vspawn:Spawn()
            vspawn:Activate()
        end
        table.Empty(self.Entity.Contents)

“return end” might have prevented table.Empty from being called, and something else might have called the code twice, so we change it to “break end” which only breaks the loop and continues to run the code after it.

Sorry for the shit quality. Your code didn't change a thing sadly, and yeah thanks for the IsValid tip.

Show the whole entity code.

[lua]
if CLIENT then
function ENT:Initialize()
end
list.Set(“SpawnableEntities”, “npc_grenade_frag”,
{
PrintName = “Frag Grenade”,
ClassName = “npc_grenade_frag”,
Category = Category,
DropToFloor = true,
Author = “VALVe”,
AdminOnly = false
})
function ENT:Draw()
self.Entity:DrawModel()
local contents = self.Entity:GetNWInt(“HowManyInBox”)
local pos = (self.Entity:GetPos() + self.Entity:GetAngles():Up()*40):ToScreen()
local x = pos.x
local y = pos.y
x = x - string.len(contents…"/"…self:GetNWInt(“callowed”))*1.5 - 12
local angs = self.Entity:GetAngles()
angs:RotateAroundAxis(angs:Forward(), 90)
cam.Start3D2D(self.Entity:GetPos() + self.Entity:GetAngles():Right()*20.5,angs,0.5)
if self:GetNWInt(“callowed”) == 4 and contents >=3 then
draw.WordBox(6, 0 - string.len(contents…"/"…self:GetNWInt(“callowed”))*1.5 - 17, -34, contents…"/"…self:GetNWInt(“callowed”), “TargetID”,Color(100,100,100,0),Color(255,0,0,255))
elseif self:GetNWInt(“callowed”) == 6 and contents >=5 then
draw.WordBox(6, 0 - string.len(contents…"/"…self:GetNWInt(“callowed”))*1.5 - 17, -34, contents…"/"…self:GetNWInt(“callowed”), “TargetID”,Color(100,100,100,0),Color(255,0,0,255))
elseif self:GetNWInt(“callowed”) == 6 and contents < 5 then
draw.WordBox(6, 0 - string.len(contents…"/"…self:GetNWInt(“callowed”))1.5 - 17, -34, contents…"/"…self:GetNWInt(“callowed”), “TargetID”,Color(100,100,100,0),Color(255,225,0,255))
else
draw.WordBox(6, 0 - string.len(contents…"/"…self:GetNWInt(“callowed”))1.5 - 17, -34, contents…"/"…self:GetNWInt(“callowed”), “TargetID”,Color(100,100,100,0),Color(0,255,255,255))
end
cam.End3D2D()
end
net.Receive(“forsaken_crateopen”, function(len)
local my_table = net.ReadTable()
local CrateEnt = net.ReadEntity()
local DermaPanel = vgui.Create( “DFrame” )
local Pos = Vector(ScrW()/2 + 1,ScrH()/2 + 1)
DermaPanel:SetSize( 555 + 5
2, 310 + 25
2 )
DermaPanel:SetTitle( “Crate” )
DermaPanel:SetVisible( true )
DermaPanel:SetPos( ScrW() / 2 - 320, ScrH() / 2 - 180)
DermaPanel:SetDraggable( true )
DermaPanel:ShowCloseButton( true )
DermaPanel:MakePopup()
DermaPanel.Paint = function() draw.RoundedBox( 8, 0, 0, DermaPanel:GetWide(), DermaPanel:GetTall(), Color( 0, 0, 0, 150 )) end
local BG = vgui.Create( “DImage”,DermaPanel)
BG:SetPos(5, 25)
BG.Paint = function() draw.RoundedBox( 8, 0, 0, BG:GetWide(), BG:GetTall(), Color( 0, 0, 0, 200 )) end
BG:SetSize( 555, 328 ) – Set the size of the panel
local Scroll = vgui.Create( “DScrollPanel”, DermaPanel ) //Create the Scroll panel
Scroll:SetSize( 550, 300 )
Scroll:SetPos( 10, 30 )
Scroll:SetBGColor(255,255,0,255)
Scroll:SetPaintBackgroundEnabled(true)

local List = vgui.Create( “DIconLayout”, Scroll ) //Create the DIconLayout and put it inside of the Scroll Panel.
List:SetSize( 550, 300 )
List:SetPos( 0, 0 )
List:SetSpaceY( 5 ) //Sets the space inbetween the panels on the X Axis by 5
List:SetSpaceX( 5 ) //Sets the space inbetween the panels on the Y Axis by 5
List:SetBGColor(255,255,0,255)
List:SetPaintBackgroundEnabled(true)

for k,v in pairs(my_table) do
local icon = List:Add(“SpawnIcon”, button)
icon:SetModel(v:GetModel())
icon:SetTooltip(v:GetClass())
icon.DoClick = function()
net.Start(“forsaken_cratespawn”)
net.WriteEntity(CrateEnt)
net.WriteFloat(k)
net.SendToServer()
DermaPanel:Close()
end
end
DermaPanel:SizeToContents()
end)

end
function ENT:SpawnFunction( Player, Trace )

if ( !Trace.Hit ) then return end

local SpawnPos = Trace.HitPos + ( Trace.HitNormal * 32 );

local Entity = ents.Create( "forsaken_crate" );
Entity:SetPos( SpawnPos );
Entity:Spawn();
Entity:Activate();

return Entity;

end
if SERVER then
util.AddNetworkString(“forsaken_crateopen”)
util.AddNetworkString(“forsaken_cratespawn”)
AddCSLuaFile(“forsaken_crate.lua”)
ENT.Contents = {}
net.Receive(“forsaken_cratespawn”, function(len,ply)
local Crate = net.ReadEntity()
local indx = net.ReadFloat()

local Ent = Crate.Contents[indx]
Ent:GetPhysicsObject():EnableMotion(false)
table.remove(Crate.Contents,indx)
constraint.RemoveAll(Ent)
Ent:SetPos(Crate:GetPos() + Vector(0,0,30))
Ent:SetGravity(1)
Ent:GetPhysicsObject():EnableMotion(true)
net.Start(“forsaken_crateopen”)
net.WriteTable(Crate.Contents)
net.WriteEntity(Crate)
net.Send(ply)
end)
function ENT:Initialize()
self.Entity.Contents = {}
self.Entity:SetModel(“models/props_junk/wood_crate001a.mdl”)
self.Entity:PhysicsInit(SOLID_VPHYSICS)
self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
self.Entity:SetSolid(SOLID_VPHYSICS)
self.Entity:SetUseType(SIMPLE_USE)
self:SetNWInt(“callowed”, 4)
self.damage = 100
local phys = self.Entity:GetPhysicsObject()

if phys and phys:IsValid() then
	phys:Wake()
end

end

function ENT:Use(ply)
if ply:IsValid() and ply:IsPlayer() then
net.Start(“forsaken_crateopen”)
net.WriteTable(self.Entity.Contents)
net.WriteEntity(self.Entity)
net.Send(ply)
end
end

function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
if(self.damage <= 0) then return end

self.damage = self.damage - dmg:GetDamage()

if 0 &gt; self.damage then
	self:GibBreakServer(Vector(10, 10, 10))
	for k, v in pairs(self.Entity.Contents) do
        if !IsValid(v) then break end
        local vclass = v:GetClass()
        local vmodel = v:GetModel()
        local vspawn = ents.Create(vclass)
        vspawn:SetPos(self:GetPos())
        vspawn:SetModel(vmodel)
        vspawn:Spawn()
        vspawn:Activate()
    end
    table.Empty(self.Entity.Contents)
	self:Remove()
end

end

function ENT:Think()
local weight = 30
self.Entity:SetNWInt(“HowManyInBox”,#self.Entity.Contents)
for k,v in pairs(self.Entity.Contents) do
if !v:IsValid() then
table.remove(self.Entity.Contents, k)
else
weight = weight + v:GetPhysicsObject():GetMass()
v:NextThink( CurTime() + 1 )
if v:GetPos():Distance(self.Entity:GetPos()) > 10 then
v:SetPos(self.Entity:GetPos())
for _,ENT in pairs(self.Entity.Contents) do
constraint.NoCollide(ENT,v,0,0)
end
constraint.Weld(v,self.Entity,0,0,0,true)
DropEntityIfHeld(v)
end

end
end
self.Entity:GetPhysicsObject():SetMass(weight + 50)
end
function ENT:PhysicsCollide(data, physobj)
local ent = data.HitEntity
if ent.IsCharge then
self:SetNWInt(“callowed”, 8)
ent:Remove()
end
if ent:IsValid() and !ent:IsWorld() and !ent.IsMoneyPrinter and !ent.IsCharge then
if ent:GetNWBool(“CanBePlaced”) and ent:BoundingRadius() < 25 and #self.Entity.Contents < 4 then
MsgN(ent:BoundingRadius())
table.insert(self.Entity.Contents, ent)
ent:SetNWBool(“CanBePlaced”, false)
ent:SetPos(self.Entity:GetPos())
ent:SetNWEntity(“CrateEnt”, self.Entity)
for k,v in pairs(self.Entity.Contents) do
constraint.NoCollide(v,ent,0,0)
end
constraint.Weld(ent,self.Entity,0,0,0,true)
DropEntityIfHeld(ent)
end
end
end
hook.Remove(“GravGunOnPickedUp”, “1944MakeObjectPlaceableInCrate”,function(pl, ent)
if pl:IsValid() and ent:IsValid() then
ent:SetNWBool(“CanBePlaced”, true)
end
end)
hook.Add(“GravGunOnDropped”, “UnMakeObjectPlaceableInCrate”,function(pl, ent)
if pl:IsValid() and ent:IsValid() then
ent:SetNWBool(“CanBePlaced”, false)
end
end)
hook.Add(“GravGunPickupAllowed”, “1944MakeObjectPlaceableInCrate”,function(pl, ent)
if pl:IsValid() and ent:IsValid() then
local IsInCrate = ent:GetNWBool(“IsInCrate”)
if !IsInCrate then
ent:SetNWBool(“CanBePlaced”, true)
else
return false
end
end
end)
timer.Create(“CheckIfEntIsInCrate”,1,0,function()
for k,v in pairs(ents.GetAll()) do
v:SetNetworkedBool(“IsInCrate”,false)
for _,ent in pairs(ents.FindByClass(“forsaken_crate”))do
if table.HasValue(ent.Contents,v) then
v:SetNetworkedBool(“IsInCrate”,true)
end
end
end
end)
hook.Add(“EntityTakeDamage”,“DamageCrate”,function(ent, dmginfo)
if ent:GetNWBool(“IsInCrate”) then
dmginfo:ScaleDamage(0)
end
end)
end

ENT.Type = “anim”
ENT.Base = “base_gmodentity”
ENT.PrintName = “Storage Crate”
ENT.Author = “Scarness”
ENT.Spawnable = true
ENT.AdminSpawnable = false[/lua]

-snip-

[editline]30th September 2013[/editline]

You don’t remove the weapons that are inside the box and you spawn new ones.

Oh man I completely forgot about that. Thanks!