• Remove entities by class?
    13 replies, posted
Say I spawned a bunch of the same entities on the map and I want to get rid of them after a certain time how would I do that? I've tried something like this: function ENT:Think()     for k,v in pairs(ents.GetAll()) do     print(v)         if v:GetClass() == "scav_common" then             timer.Simple(10, function()             if IsValid(v) then v:Remove()              end             end)         end     end end Which returns the error: Tried to use a NULL entity! Timer Failed. I'm just trying to remove all the entities with the same class name after a while and then respawn them. Sorry for the terrible code.
Why are you looping through all entities in a entity think hook? Thats going to create a lot of timers because entity:think will be called every clock cycle, this is bad. If you're trying to oscillate the remove / respawn then you'd want something like this: // Assuming the entity is initialized and spawned elsewhere in the code local isSpawned = true  local lastTime = CurTime() local timeInterval = 5  local function respawnRemoveEnts( ) if ( CurTime() < lastTime + timeInterval ) then return else lastTime = CurTime() end if (isSpawned) then -- remove code here else -- spawn code here end isSpawned = not isSpawned end hook.Add("Think", "my_think_hook", respawnRemoveEnts)eEnts)
ah alright, thank you. How do I remove all the entities on the map with the same class name? If I put my loop in the "--remove code here" wouldn't that be the same thing as looping through all entities in a think since the Think Hook is referencing the respawnRemoveEnts() function?
Ah, I meant to ask why you were creating the timers in a loop in a think hook.
oh okay. Mainly because I'm not really accustomed to glua yet so the logic is very new to me. For example I'd never call a derma in a think hook/function but I didn't know the same concept applied to timers.
I probably should've mentioned this earlier, but this code will do the same thing and is much more condensed. A timer does something similar to what I did with the think hook above internally I believe. -- Assuming the entity is initialized and spawned elsewhere in the code local isSpawned = true local function respawnRemoveEnts( ) if ( isSpawned ) then -- remove code here else -- spawn code here end isSpawned = not isSpawned end timer.Create( "my_timer", 10, 0, respawnRemoveEnts )
If it's your entity you can code inside its ENT:Think
ENT:Initialize() timer.Create("removeEnt_" .. self:EntIndex(), 10, 1, function() self:Remove() end) end ENT:OnRemove() -- I'm assuming the entity can be picked up and/or destoryed -- This code may be optional depending on your usage of the entity timer.Remove("removeEnt_" .. self:EntIndex()) -- You could call the respawn logic within this function -- But I would use a EntityRemoved hook outside of the entity file end
Why then you need timer.Create even? Use timer.Simple in Initialize
I should probably specify this is an entity that spawns other entities.
So... I'm having an issue now. As I stated above this code is being put into an entirely separate entity (scav_main) that spawns other entities. It works like it's supposed to - until I spawn the individual entities that scav_main spawns. The behavior is that the code from scav_main is being autorun meaning that I don't have to spawn it for other entities to be removed by its code. Example: I spawn "scav_common" (an entirely different entity from an entirely different folder). I wait 10 seconds and scav_common is automatically removed. So for whatever reason timer.Create( "commontimer", 10, 0, respawnRemoveCommon ) Is automatically being run. local function respawnRemoveCommon( )     local ComisSpawned = true     if ComisSpawned == true  then         for k,v in pairs(ents.GetAll()) do             if v:GetClass() == "scav_common" then                 v:Remove()                 ComisSpawned = false             end         end     if ComisSpawned == false then         for i = 0, 13 do         local Coment = ents.Create("scav_common")         Coment:SetPos(commonPos[math.random(1, table.Count(commonPos))])         Coment:Spawn()         Coment:Activate()         ComisSpawned = true             end            end     end end timer.Create( "commontimer", 10, 0, respawnRemoveCommon ) I don't understand how the code is being run without me spawning scav_main (the entity the code above is inside)
You're going to want to move the local ComisSpawned = true outside of the function definition. Otherwise only the 'ComisSpawned == true' if statement body will be executed.
Also, this isn't a fix, just for optimization: ents.FindByClass( "scav_common" ) Instead of using v:Remove() use this: SafeRemoveEntity( v )
I don't believe there's any benefit of having a timer run logic if it wouldn't be required. If something other than the timer removes the entity then there's no reason to have the timer exist. However, If only the server can remove the entity then there's no reason not to use a simple timer. At this scale, you likely won't see any benefits with either route since it's roughly a dozen quick timers. However, It's only logical to remove what's no longer required.
Sorry, you need to Log In to post a reply to this thread.