Zombie Spawner

Hey all,recently I’ve started making a Zombie kind of Game mode.

I have only being using lua for a bit under a week although I do have experience in other code languages so some of the syntax may be wrong and things may be in wrong order etc.

OK, so firstly my goal is to produce a master entity that spawns zombies at a random zombie spawn. The zombie spawns are named info_zspawn which I’ll place into my maps using hammer.

Also, I want to set the relationship of the zombie towards prop_physics and each current player so that the Zombie hates them.

The base of the code is in init.lua

I’ve commented the code A LOT to help you help me. There is also a few other questions in the comments which I’d like some help with.

Last question, what is “ply”(I did try and find it in gmod wiki and google).

Thank you :slight_smile:

[lua]AddCSLuaFile(“cl_init.lua”) -------------------------------Tel client to download the client side lua file
AddCSLuaFile(“shared.lua”) -------------------------------Tel client to download the shared lua file

include(“shared.lua”) -------------------------------Tel client and/or server (I think?) to load the shared file

function ENT:Initialize() -------------------------------Initialize the master entity, the one that controls spawning and relations.
self:SetModel("") -------------------------------Set the model to nothing as it’s a logic entity(point entity) Do I have to do this or not?
self:SetSolid(SOLID_NONE) -------------------------------Set the model’s physical properties to nothing as it’s a logic entity(point entity) Do I have to do this or not?

end

function ZombieSpawnPos() -------------------------------This function calculates which info_zspawn entity the zombie should spawn at. (info_zspawn entitys will be placed in map using hammer)

ZombieSpawnPlaces={ ents.FindByClass(“info_zspawn”) } -------------------------------Finds all of the info_zspawn entitys in the current map and adds to an index/array.

count = math.random(1,ZombieSpawnPlaces.Count) -------------------------------Picks a random info_zspawn entitys for the zombie to spawn at

SpawnPos = ZombieSpawnPlaces[Count] -------------------------------Simply sets a variable to the entity indexed at the postion “Count”

SpawnPosVec = SpawnPos:GetPos( ) -------------------------------Sets the zombie spawn pos

end

function ZombieTarget(data)							-------------------------------This function is used to get, but not set the zombies target. We will make the npc hate/attack this target later on.

target_prop = ents.FindInSphere( data,5000)			-------------------------------data =='s the function argument which is the zombies position

end


data =              								-------------------------------zombie position, I need help setting this var pelase

Zombies={} -------------------------------Make an array/index named Zombies, amm i alowed to define it here, outside of a codeblock as i don’t want it to be run with the function.

function ZombieSpawn() -------------------------------This function deals with setting up the zombies position, relations and other and also spawns the entity

local ply = zombie -------------------------------In words, I have issues explainign this line, lol
local zombie = ents.Create(“npc_zombie”) -------------------------------I want to make a npc_zombie with teh following attributes defined below.
zombie:SetPos(SpawnPosVec) -------------------------------Where the Zombie will spawn, defined several lines up.
do return Entity end -------------------------------Returns the zombie I ahve spawned

Index=0 -------------------------------Sets A variable anmed Index to 0, for use with adding the zombies to an array/index
for i=index,Zombies.count do -------------------------------A For statement for adding zombies to a array/index
Index++ -------------------------------Increases the Variable index so that each time the for statement runs thorugh it adds the enxt zombie to a different slot of teh index/array
Zombies[index]= Entity -------------------------------Adds “Entity”, the zombie we returned previously 4 lines up to the Zombies index. Does this work? returning tog et the zombie as entity

end

for k,v in pairs(Zombies) do -------------------------------A for in statement to set the relationship of all the zombies in the array to hate “Target” which we defiend earlier
k:AddEntityRelationship(Target, D_FR, 99 ) -------------------------------yeah, umm… yeah

zombie:Spawn()										-------------------------------Finaly spawns the zombie with above attributes

end

end
end[/lua]

I don’t really get what you’re asking but, here is some commented code that will do what you want ( I think… untested ) with those info_zspawn entities. Make sure to read the comments or you won’t learn.

[lua]
hook.Add( “InitPostEntity”, “LoadZombies”, function( ) – Called when the map is initialized^
for k, v in pairs( ents.GetAll( ) ) – Loops through all entities^
if v:GetClass( ) == “info_zspawn” – Is it info_zspawn?^
local zombie = ents.Create( “npc_zombie” ); – Create our zombie^
zombie:SetPos( v:GetPos( ) + Vector( 0, 0, 20 ) ) – Set our zombies position and make it spawn slightly above the info_zspawn entity^
zombie:Spawn( ) – Spawn our zombie^
end;
end;
end );
[/lua]
Also, ply is just another alias of the _R.Player metatable.

Thanks Helix, your code will spawn a zombie at every spawn, how ever I only want to spawn 1 zombie, at a random spawn. Then every 1 secs or so another will spawn at another random spawn point. As the round goes on, zombies will spawn more frequently.

I’m also having difficulties getting the zombies spawned via the master entity into a table/array so that I can manipulate them. My next step will be getting them to attack a prop_physics or a player(Whichever is closest)

EDIT Thats why I had this to spawn at a random info_zspawn:

[lua]# function ZombieSpawnPos() -------------------------------This function calculates which info_zspawn entity the zombie should spawn at. (info_zspawn entitys will be placed in map using hammer)

ZombieSpawnPlaces={ ents.FindByClass(“info_zspawn”) } -------------------------------Finds all of the info_zspawn entitys in the current map and adds to an index/array.

count = math.random(1,ZombieSpawnPlaces.Count) -------------------------------Picks a random info_zspawn entitys for the zombie to spawn at

SpawnPos = ZombieSpawnPlaces[Count] -------------------------------Simply sets a variable to the entity indexed at the postion “Count”

SpawnPosVec = SpawnPos:GetPos( ) -------------------------------Sets the zombie spawn pos

end[/lua]

You can store basically anything in tables. Even entities. You can also create a think hook to spawn these zombies one at a time.
[lua]
Zombies = { }; – This variable is global^
local zinit = false; – Create a variable in the normal Lua scope^

hook.Add( “InitPostEntity”, “LoadZombies”, function( ) – Called when the map is initialized^
zinit = true;
end );

local NextZombieSpawn = CurTime( ) + math.random( 5 ) – math.random automatically has 1 as the minimum if only one argument is passed^
hook.Add( “Think”, “SpawnZombies”, function( ) – Called every tick^
if zinit then – Have we set up the map yet?^
if CurTime( ) >= NextZombieSpawn then
for k, v in pairs( ents.GetAll( ) ) – Loops through all entities^
if v:GetClass( ) == “info_zspawn” – Is it info_zspawn?^
local zombie = ents.Create( “npc_zombie” ); – Create our zombie^
zombie:SetPos( v:GetPos( ) + Vector( 0, 0, 20 ) ) – Set our zombies position and make it spawn slightly above the info_zspawn entity^
zombie:Spawn( ) – Spawn our zombie^
Zombies[ #Zombies + 1 ] = zombie;
NextZombieSpawn = CurTime( ) + math.random( 5 );
end;
end;
end;
end;
end );
[/lua]

Ok, I’ve fixed several errors that I was getting from Helix’s code but now I’ve come to a standstill.

[lua]ddCSLuaFile(“cl_init.lua”) --Tel client to download the client side lua file
AddCSLuaFile(“shared.lua”) --Tel client to download the shared lua file

include(“shared.lua”) --Tel client and/or server (I think?) to load the shared file

Zombies = { };

local zinit = false;

hook.Add( “InitPostEntity”, “LoadZombies”, function( ) – Called when the map is initialized
zinit = true;
end );

local NextZombieSpawn = CurTime( ) + math.random( 5 )
hook.Add( “Think”, “SpawnZombies”, function( ) – Called every tick^
if zinit then – Have we set up the map yet?
if CurTime( ) >= NextZombieSpawn then
for k, v in pairs( ents.GetAll( ) ) do – Loops through all entities^
if v:GetClass( ) == “info_zspawn” then-- Is it info_zspawn?
local zombie = ents.Create( “npc_zombie” ); – Create our zombie
zombie:SetPos( v:GetPos( ) + Vector( 0, 0, 20 ) ) – Set our zombies position and make it spawn slightly above the info_zspawn entity
zombie:Spawn( ) – Spawn our zombie^
// Zombies[ Zombies + 1 ] = zombie; – Wont let me use arithmatic on this :frowning:
ZombiesIndex = Zombies.count;
index = 1;
for i=1,zombiesIndex do --So instead we do this
index++
Zombies[ index ] = zombie;
end;

                 NextZombieSpawn = CurTime( ) + math.random( 6 );  
             end;  
         end;  
     end;  
 end;  

end ); [/lua]

The error I’m getting is:


 gamemodes\outbreak\entities\entities\zombie_spawner\init.lua:27: '=' expected near '+'
Folder	=	entities/zombie_spawner
Couldn't register Scripted Entity zombie_spawner - the Type field is empty!
 

How ever, if i comment out this:


 index++ --(Line 27) 

Then the error doesn’t appear, but I get a new one when I spawn the entity at which the zombie spawns at. The error is:


 
Hook 'SpawnZombies' Failed: ...s\outbreak\entities\entities\zombie_spawner\init.lua:26: 'for' limit must be a number
 

Thanks to anyone with an idea as to why I’m getting these.

First of all, You are missing an ‘A’ in the AddCSLuaFile in the first line. Second, you cannot use ++ in Lua. You have to do value = value + 1.
[lua]
ddCSLuaFile(“cl_init.lua”) --Tel client to download the client side lua file
AddCSLuaFile(“shared.lua”) --Tel client to download the shared lua file

include(“shared.lua”) --Tel client and/or server (I think?) to load the shared file

Zombies = { };

local zinit = false;

hook.Add( “InitPostEntity”, “LoadZombies”, function( ) – Called when the map is initialized
zinit = true;
end );

local NextZombieSpawn = CurTime( ) + math.random( 5 )
hook.Add( “Think”, “SpawnZombies”, function( ) – Called every tick^
if zinit then – Have we set up the map yet?
if CurTime( ) >= NextZombieSpawn then
for k, v in pairs( ents.GetAll( ) ) do – Loops through all entities^
if v:GetClass( ) == “info_zspawn” then-- Is it info_zspawn?
local zombie = ents.Create( “npc_zombie” ); – Create our zombie
zombie:SetPos( v:GetPos( ) + Vector( 0, 0, 20 ) ) – Set our zombies position and make it spawn slightly above the info_zspawn entity
zombie:Spawn( ) – Spawn our zombie^
// Zombies[ Zombies + 1 ] = zombie; – Wont let me use arithmatic on this :frowning:
ZombiesIndex = Zombies.count;
index = 1;
for i=1,zombiesIndex do
Zombies[ i ] = zombie;
end;

                 NextZombieSpawn = CurTime( ) + math.random( 6 );  
             end;  
         end;  
     end;  
 end;  

end );
[/lua]
I also don’t get why your using an ‘index’. You can just loop through all zombies with
[lua]
for k, v in pairs( ents.GetAll( ) ) do
if v:GetClass( ) == “npc_zombie” then
– Do stuff^
end;
end;
[/lua]
Also, at this comment
[lua]// Zombies[ Zombies + 1 ] = zombie; – Wont let me use arithmatic on this :([/lua]
To get the length of a table you do #TABLENAME so…
[lua]
local lol = { “a”, “s”, “d” }
print( #lol );
[/lua]
The output would be three.

OK, so just to get everyone on the same track.

  1. This entity will spawn a npc_zombie on top of a info_zspawn entity every couple of seconds.

  2. The info_zspawn entity that the zombie will spawn at is randomized by this entity.

3.Add the spawned zombies to a table.

4.Set the spawned zombies relationship towards a human and prop_physics so that it hates them.

I’m not receiving any errors in console, but no zombies are spawning…

Here is the code:

[lua]

AddCSLuaFile(“cl_init.lua”)

AddCSLuaFile(“shared.lua”)

include(“shared.lua”)

  Zombies = { }
  spawnPoints = {}   

  local zinit = false
 
   

  hook.Add( "InitPostEntity", "LoadZombies", function( ) -- Called when the map is initialized

          zinit = true  

  end )  

    

  local NextZombieSpawn = CurTime( ) + math.random( 6 )

  hook.Add( "Think", "SpawnZombies", function( ) -- Called every tick

          if zinit then -- Have we set up the map yet?

                  if CurTime( ) >= NextZombieSpawn then  

                         



                                
							spawns = 1	
                          for k, v in pairs( ents.GetAll( ) ) do -- Loops through all entities

                                           if v:GetClass( ) == "info_zspawn" then -- Is it info_zspawn?
										   
                                                  spawns = spawns + 1
												  

                                          end;
								

                          end    
												  
						whichSpawn = math.random( spawns )        --picks a random spawn
                          for k, v in pairs(spawnPoints) do -- Loops through all entities

                                  if k == WhichSpawn then                          -- Is it info_zspawn?

                   

                                          local zombie = ents.Create( "npc_zombie" ) -- Create our zombie

                                          zombie:SetPos( v:GetPos( ) + Vector( 0, 0, 20 ) ) -- Set our zombies position and make it spawn slightly above the info_zspawn entity

                                          zombie:Spawn( ) -- Spawn our zombie  

   

                                          NextZombieSpawn = CurTime( ) + math.random( 6 )

                                  end;

                          end;

                  end;

          end;

  end );

[/lua]