Need help with entity

I’ve created various loot crates for my gamemode, now I want an invisible entity that I could spawn in certain locations of my map which will turn into a random loot crate at a random time, I know how to do all the random stuff using tables but how do I make an entity turn into a different entity?

You can just create an invisible “spawner” entity that spawns crate entities like normal, but I recommend just having a table of spawning points and skip the auxillary entity all together.

True that, thanks i’ll give it a try

Create a new entity, copying pos/ang of the current entity. Delete current entity.

[editline]2nd September 2016[/editline]

For gamemode purposes this is bad and should be avoided, hardcoded stuff is always bad.
This stops mappers from placing those invisible entities in Hammer, without having to edit the code.

If it’s for a gamemode then I’d say make an entity – misread the OP.

So i’ve made this:


timer.Simple( math.random( 60, 300 ), function()
	randomcrate = { "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate4", "ent_lootcrate4", "ent_lootcrate5" }
	local crate = ents.Create( table.Random( randomcrate ) )
		
	PrintMessage( HUD_PRINTCENTER, "A loot crate has spawned somewhere on the map!")
	
	crate:SetPos( Vector( 75.105141, 1007.274597, 65) )
	crate:Spawn()
end )

timer.Simple( math.random( 60, 300 ), function()
	randomcrate = { "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate4", "ent_lootcrate4", "ent_lootcrate5" }
	local crate = ents.Create( table.Random( randomcrate ) )
		
	PrintMessage( HUD_PRINTCENTER, "A loot crate has spawned somewhere on the map!")
	
	crate:SetPos( Vector( -1197.077026, 257.994049, 160.031250) )
	crate:Spawn()
end )

But multiple of them can spawn on the same location, would there be a way I could make them only spawn one and then wait until somebody takes it to activate the timer again? This is why I wanted to make them change entity to a different one.

[editline]2nd September 2016[/editline]

Bump

Like Robotboy said, you should make a spawner entity if it’s a gamemode then track everything from there. Anyway, the way you’re doing it with table.Random and a bunch of table entries is really inefficient. You could just say if a math.Rand(0, 10) call is less than four spawn crate 1, etc.

Oh and your spawning them in different places with 2 different timers?
Ok, instead of using table.Random use:


randomcrate[ math.Random( #randomcrate ) ]

and dont use timer.Simple it dosent work aswell as timer.Create


timer.Create( "CrateTimer", math.Random( 60, 300 ), 1, CrateSpawnFunction )

then I would build it up to this:


randomcrate = { "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate1", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate2", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate3", "ent_lootcrate4", "ent_lootcrate4", "ent_lootcrate5" }
local cratespawn = ents.Create( currentcrate )
local lootboxisspawned = {}
local currentcrate = {}

function IntializeEntities()
timer.Create( "CrateTimer", math.Random( 60, 300 ), 1, CrateSpawnFunction )
end
hook.Add( "Initialize", "Initialize", InitializeEntities ) 

local function CrateSpawnFunction()
    if table.HasValue( lootboxisspawned, "no" ) then
        table.insert( currentcrate, randomcrate[ math.Random( #randomcrate ) ] )
        PrintMessage( HUD_PRINTCENTER, "A loot crate has spawned somewhere on the map!")
       	cratespawn:SetPos( Vector( 75.105141, 1007.274597, 65) )
	cratespawn:Spawn()
        table.insert( lootboxisspawned, "yes" ) 
    else
        table.insert( lootboxisspawned, "no" ) 
        crate:Remove()
        table.Empty( currentcrate )
    end
end



Why not just use crate indexes with booleans instead of table.HasValue? That’s more inefficient than the table.Random call.

This sounds efficient enough, could you explain more how to do this?



if math.random(0,10) < 4 then
    ents.Create( 'crate' )
end


[editline]2nd September 2016[/editline]

Sorry, not really sure what’s going on with this thread, I’ll shut up now :stuck_out_tongue:

Your help is appreciated, i’m quite confused still.

At the moment, I don’t need more ways to spawn the crates, just need to know how to make them not spawn if there is already one there. My friend gave me this but it still doesn’t seem to work:


local ents01 = ents.FindInSphere (Vector ( 75.105141, 1007.274597, 65 ), 50)
local ents02 = ents.FindInSphere (Vector ( -1197.077026, 257.994049, 95 ), 50)

for k, v in pairs( ents01 ) do if v:GetClass() == "ent_lootcrate1" then foundcrate = true break 
	end
end


local iRand = math.random(1, 10)
local pCrate

-- Esentially <= 3, but no need to do a less and equals check if it's an integer
-- 30% chance of spawning crate1
if ( iRand < 4 ) then
   pCrate = ents.Create( "ent_lootcrate1" )
-- 30% chance
elseif ( iRand < 7 ) then
   pCrate = ents.Create( "ent_lootcrate2" )
-- 30% chance
elseif ( iRand < 10 ) then
   pCrate = ents.Create( "ent_lootcrate3" )
-- 10% chance
else -- == 10
   pCrate = ents.Create( "ent_lootcrate4" )
end

-- crate code...

[editline]2nd September 2016[/editline]

You could have the crate fire to a crate manager entity if it’s removed by using https://wiki.garrysmod.com/page/Entity/Fire. If you’re intent on doing it your current way, check if the previous entity is still valid after the timer.


local pCurEntity = NULL

timer.Create( "Crate Spawner", time, reps, function()
   if ( pCurEntity == NULL ) then
      pCurEntity = ents.Create( "loot_crate_w/e" )
      -- extra code, determining which loot crate to spawn
   end
end )

Can’t you just add them to a list?



local CRATELIST = {}

-- to spawn a crate
local vec = Vector( -1197.077026, 257.994049, 95 )

local CRATE = ents.Create( 'ent_lootcrate1' )
CRATE:SetPos( vec )

CRATELIST[ vec ] = true -- add the vector to the list

if CRATELIST[ Vector( SOMEVECTOR ) ] then
-- there's already a crate at that location


I’m probably missing something

I’m actual so confused. If I can just get this loop working then it will function properly, anyone know why it’s not working?


local ents01 = ents.FindInSphere (Vector ( 75.105141, 1007.274597, 65 ), 50)
local ents02 = ents.FindInSphere (Vector ( -1197.077026, 257.994049, 95 ), 50)

for k, v in pairs( ents01 ) do if v:GetClass() == "ent_lootcrate1" then foundcrate = true break 
	end
end

I made the first spawn only spawn “ent_lootcrate1” as a test btw.

That’s a very inefficient and error-prone way to search for crates. Follow the latter examples.