endless enemy spawn
Moderator: InsideQC Admins
26 posts
• Page 2 of 2 • 1, 2
why don't you do something like what frag.machine suggested above and create an entity and when the zombie dies it will look for the coordinates of that entity and spawn there?
-

Hazematman - Posts: 54
- Joined: Thu Jul 15, 2010 1:58 am
- Location: Canada
frag.machine wrote:No exactly. Ok, let's start from start.
What you need is to create a new map entity that works pretty much like the info_player_start: it's something that you put in a map to tell Quake "I want to spawn zombies in this place".
This thing (let's call it "info_zombie_start" to make things easier) will work in the following way:
1) when spawned, the first thing it does is precache all models and sounds used by the zombie;
2) we want to spawn a new zombie once ours is killed, so we need to track it. To do this, we can either create a specific field in the entity structure (for example, ".entity myzombie;" at the end of defs.qc) or reuse one of the already existing .entity fields. Since our info_zombie_start is not a monster, it won't have enemies, so we can reuse the .enemy field (and save a couple bytes);
3) we need to set a "think" function to the info_zombie_start to check, every fews seconds, if the zombie pointed by .enemy is dead:
- Code: Select all
if (self.enemy.health <= 0)
If that's the case, we create a new entity, set its origin to the info_zombie_start origin (plus a bit in the z axis so the zombie don't get stuck in ground) and we can repeat the initialization steps that you can see in zombie.qc (setmodel, setsize, etc). Then, we store a reference to the new zombie into our .enemy field, and we can schedule our return to the checking loop above.
There are a lot more of details, but this covers the main idea.
Heh. I did mine a bit differently. I spawned an object in the map that precaches all the Stuff for that monster, and then it removed itself from the world.
-

Mexicouger - Posts: 514
- Joined: Sat May 01, 2010 10:12 pm
There are many ways to do that. I'll show you how I did (yeah, I tested this in a map and worked like a charm, so feel free to use it):
Now all you need to do is create a map and place the info_zombie_start where you want the zombies to appear. If you want to make the just spawned zombies to follow paths, set the .target value to the info_zombie_spawn to point to a path_corner (like you usually would to a monster). Have fun.
- Code: Select all
/**
* info_zombie_start.qc
**/
void () info_zombie_think =
{
local entity zomb, oldself;
// do we have a zombie under our control ?
if (self.enemy != world)
{
// is it still alive ? (okay, it's a zombie, so
// it's an undead by definition, but you know
// what I mean :P )
if (self.enemy.health <= 0)
{
// it's dead, Jim. Clean up the mess.
self.enemy = world;
}
}
if (self.enemy == world)
{
// time for another zombie!
// we temporarily change the "self"
// reference to our new zombie
oldself = self;
self = spawn ();
// here we basically copy & paste the
// original monster_zombie code, with
// a couple changes
setorigin (self, oldself.origin);
self.origin_z = self.origin_z + 2;
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
setmodel (self, "progs/zombie.mdl");
setsize (self, '-16 -16 -24', '16 16 40');
self.health = 60;
self.th_stand = zombie_stand1;
self.th_walk = zombie_walk1;
self.th_run = zombie_run1;
self.th_pain = zombie_pain;
self.th_die = zombie_die;
self.th_missile = zombie_missile;
// this is a little trick, so we can make
// the just born zombie to follow a path,
// if we want (you'll find it useful to
// spread info_zombie_starts around
// a map and make them follow predefined
// routes, like if they were hunting the
// player from ewverywhere
if (oldself.target != string_null)
{
self.target = oldself.target;
}
walkmonster_start();
// we store a reference to our new zombie
oldself.enemy = self;
// then we restore "self" to point back to
// our info_zombie_start
self = oldself;
}
// finally, let's schedule the execution of our "think" function
self.think = info_zombie_think;
self.nextthink = time + 0.5;
};
void () info_zombie_start =
{
// if is deathmatch, we don't want zombies popping around (otherwise, just omit this part)
if (deathmatch)
{
remove (self);
}
// we need to precache all stuff used by the monster_zombie
precache_model ("progs/zombie.mdl");
precache_model ("progs/h_zombie.mdl");
precache_model ("progs/zom_gib.mdl");
precache_sound ("zombie/z_idle.wav");
precache_sound ("zombie/z_idle1.wav");
precache_sound ("zombie/z_shot1.wav");
precache_sound ("zombie/z_gib.wav");
precache_sound ("zombie/z_pain.wav");
precache_sound ("zombie/z_pain1.wav");
precache_sound ("zombie/z_fall.wav");
precache_sound ("zombie/z_miss.wav");
precache_sound ("zombie/z_hit.wav");
precache_sound ("zombie/idle_w2.wav");
// we will reuse one of the entity fields - in this case,
// the .enemy field - to keep a reference to our pet zombie,
// so we can know when to spawn another one. This field need
// to start with a blank reference, so let's point it to world
self.enemy = world;
// finally, let's schedule the execution of our "think" function
self.think = info_zombie_think;
self.nextthink = time + 0.1;
};
Now all you need to do is create a map and place the info_zombie_start where you want the zombies to appear. If you want to make the just spawned zombies to follow paths, set the .target value to the info_zombie_spawn to point to a path_corner (like you usually would to a monster). Have fun.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Thanks Frag.machine, I added that code to my mod, and it worked pretty well, except for the fact that the ai kinda messed up after you kill the zombie but I will look into that. Heres a video of the mod http://www.youtube.com/watch?v=-73d-cuFti4 (The quality is not that good.)
-

Hazematman - Posts: 54
- Joined: Thu Jul 15, 2010 1:58 am
- Location: Canada
What exactly haven't worked as expected when you say "the ai kinda messed up" ? I can't tell what's wrong by your video.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Hazematman wrote:oh sorry, after the zombie dies, the new one won't attack you.
go to FindTarget in ai.qc and remove these lines
- Code: Select all
r = range (client);
if ( (r == RANGE_FAR) ) {
return ( FALSE );
}
if ( !visible (client) ) {
return ( FALSE );
}
if ( (r == RANGE_NEAR) ) {
if ( ((client.show_hostile < time) && !infront (client)) ) {
return ( FALSE );
}
} else {
if ( (r == RANGE_MID) ) {
if ( !infront (client) ) {
return ( FALSE );
}
}
}
this should make the monsters roam around
- hondobondo
- Posts: 207
- Joined: Tue Sep 26, 2006 2:48 am
Hmm, haven't observed that in my tests.
Does the first zombie attacks you ? You can do something like this to help the AI, when creating the new zombie:
Does the first zombie attacks you ? You can do something like this to help the AI, when creating the new zombie:
- Code: Select all
// after this line:
self.th_missile = zombie_missile;
// add this:
self.enemy = oldself.enemy.enemy;
// just to remember:
// self = the new zombie;
// oldself = the info_zombie_start
// oldself.enemy = the killed zombie
// oldself.enemy.enemy = who killed the zombie (usually, the player)
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
frag.machine wrote:The problem is a bit more complicated than this.
What you need is an entity that spawns another entity (the zombie), and keep checking if it stills alive. If is dead, then spawn another one, and repeat.
actually it's not.
i put a call to this function at the end of knight_die, whether or not he gets gibbed:
- Code: Select all
void() monster_knight_respawn =
{
local entity new,temp;
new = spawn();
traceline(self.origin,self.origin + '40 0 0',TRUE,self); //ignore monsters, telefrag if in the way
if (trace_fraction == TRUE) //no wall in the way
setorigin(new,trace_endpos+'0 0 32');
else
{
traceline(self.origin,self.origin + '0 40 0',TRUE,self); //ignore monsters, telefrag if in the way
if (trace_fraction == TRUE)
setorigin(new,trace_endpos+'0 0 32');
else
{
traceline(self.origin,self.origin + '0 -40 0',TRUE,self); //ignore monsters, telefrag if in the way
if (trace_fraction == TRUE)
setorigin(new,trace_endpos+'0 0 32');
else
{
traceline(self.origin,self.origin + '-40 0 0',TRUE,self); //ignore monsters, telefrag if in the way
if (trace_fraction == TRUE)
setorigin(new,trace_endpos+'0 0 32');
else
return; //can't spawn
}
}
}
spawn_tfog(new.origin);
spawn_tdeath (new.origin,new);
new.solid = SOLID_SLIDEBOX;
new.movetype = MOVETYPE_STEP;
setmodel (new, "progs/knight.mdl");
setsize (new, '-16 -16 -24', '16 16 40');
new.health = 75;
new.th_stand = knight_stand1;
new.th_walk = knight_walk1;
new.th_run = knight_run1;
new.th_melee = knight_atk1;
new.th_pain = knight_pain;
new.th_die = knight_die;
temp = self;
self = new;
walkmonster_start ();
new = self;
self = temp;
remove(self);
};
here's the die function:
- Code: Select all
void () monster_knight_respawn;
void() knight_die =
{
// check for gib
if (self.health < -40)
{
sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
ThrowHead ("progs/h_knight.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
self.think = monster_knight_respawn;
self.nextthink = time + random()*3 + 2;
return;
}
// regular death
sound (self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM);
if (random() < 0.5)
knight_die1 ();
else
knight_dieb1 ();
self.think = monster_knight_respawn;
self.nextthink = time + random()*3 + 2;
};
the respawn function checks around the spot where the knight dies, if a wall isn't nearby, it spawns a knight nearby. i had it spawning right on top of the dead knight but that caused problems, but i think that problem was solved with
- Code: Select all
remove(self);
but i didn't test that. anyway, try it
- hondobondo
- Posts: 207
- Joined: Tue Sep 26, 2006 2:48 am
Using hondobondo's code (thanks!) I now get monsters that arrange in a nice circle around me but stay on a distance. Is that a bug in the code above or did I screw up something (in my horrid code base)?
Improve Quaddicted, send me a pull request: https://github.com/SpiritQuaddicted/Quaddicted-reviews
- Spirit
- Posts: 1031
- Joined: Sat Nov 20, 2004 9:00 pm
Spirit wrote:Using hondobondo's code (thanks!) I now get monsters that arrange in a nice circle around me but stay on a distance. Is that a bug in the code above or did I screw up something (in my horrid code base)?
not sure what you mean. maybe you could post a screenshot
- hondobondo
- Posts: 207
- Joined: Tue Sep 26, 2006 2:48 am
26 posts
• Page 2 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 1 guest