Forum

Pseudo random monster spawning - Check spawn location.

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Pseudo random monster spawning - Check spawn location.

Postby Ace12GA » Fri Mar 02, 2012 2:31 am

I am using the existing monster spawn points, and randomly choosing a place around that monster spawn point (within 128 units currently) to randomly spawn between 1 and 4 extra monsters. I have then modified the monster walk code in MONSTER.QC to remove any entity that is stuck in a wall. This works. However it dumps a lot of errors to the console from droptofloor and the actual check if the monster is stuck in a wall.

I am trying to figure out how to check the random spawn location of a monster, prior to spawning it. I want to see if that location (origin plus bounding box extents) is in a wall, or if a monster is already spawned there. droptofloor takes care of some of the cases, and unsticks them for me, however I want to avoid all the errors, and have the monsters spawned in the clear.

Is findradius supposed to return the world?

Like I said, it works as is, but its not clean.

Thanks.
Ace12GA
 
Posts: 56
Joined: Sat Jan 28, 2012 12:08 am

Re: Pseudo random monster spawning - Check spawn location.

Postby leileilol » Fri Mar 02, 2012 2:42 am

Would using tracebox help?
i should not be here
leileilol
 
Posts: 2783
Joined: Fri Oct 15, 2004 3:23 am

Re: Pseudo random monster spawning - Check spawn location.

Postby Ace12GA » Fri Mar 02, 2012 3:13 am

Heh, oddly enough, after I posted this I found tracebox in dpextensions. It does help, and is a great suggestion. It does have limitations, which is it is tracing a volume from a start point (the original spawn) to the proposed new origin. That said, it helps a lot; I get fully 10% of the errors I was getting. Downside, I am running into loop overload initially, and once I expanded the area that a spawn can occur in, it went away, it concerns me. Any suggestions on my math to reduce while loops would be appreciated. As this code is only being run on level load to spawn the monsters, I am not that concerned, but it is potentially a problem.

Here is my new monster_army function.

Code: Select all
void() monster_army =
{
   if (deathmatch)
   {
      remove(self);
      return;
   }
   
   local float rand_x, rand_y, rand_int, spawncount, canspawn;
   local vector neworigin, oldorigin;
   local entity new, tmp;
   
   spawncount = 0;
   rand_int = rint((random() * 4) + 1);
   while (spawncount < rand_int)
   {
      canspawn = 0;
      while (canspawn == 0)
      {
         rand_x = 0;
         rand_y = 0;
         while (rand_x > -18 && rand_x < 18)
         {
            rand_x = -512 + random() * 1024;
         }
         while (rand_y > -18 && rand_y < 18)
         {
            rand_y = -512 + random() * 1024;
         }
         neworigin_x = self.origin_x + rand_x;
         neworigin_y = self.origin_y + rand_y;
         neworigin_z = self.origin_z + 16;
         tracebox(self.origin, '-16 -16 -24', '16 16 40', neworigin, FALSE, self);
         if (trace_fraction == 1)
         {
            canspawn = 1;
         }
      }
      new = spawn();
      new.classname = "monster_army";
      new.angles = self.angles;
      setorigin(new, neworigin);
      tmp = self;
      self = new;
      monster_army_spawn();
      new = self;
      self = tmp;
      spawncount = spawncount + 1;
   }
   // Spawn original monster in intended location still.
   new = spawn();
   new.classname = "monster_army";
   new.angles = self.angles;
   setorigin(new, self.origin);
   tmp = self;
   self = new;
   monster_army_spawn();
   new = self;
   self = tmp;
}


It is reasonably fun to have a whole load of weakened monsters in pseudo random places in the map.

Image
Ace12GA
 
Posts: 56
Joined: Sat Jan 28, 2012 12:08 am

Re: Pseudo random monster spawning - Check spawn location.

Postby andrewj » Fri Mar 02, 2012 3:45 am

I suggest moving the code to spawn an extra monster into a separate function (will be a lot more readable that way), and limiting the amount of places to try to 16 places (or whatever), the function can just 'return' when you reach the limit.

I also suggest spawning the extra monsters AFTER the original one.
andrewj
 
Posts: 133
Joined: Mon Aug 30, 2010 3:29 pm
Location: Australia

Re: Pseudo random monster spawning - Check spawn location.

Postby Ace12GA » Fri Mar 02, 2012 3:59 am

Thanks for the tips. The function monster_army is a new function that calls monster_army_spawn, the original function. This was done to allow the original map entities to work, and to make it easier to work with. That said, I am eliminating the monster spawn at the original origin. Its much more interesting when the monsters (soldiers and dogs so far) are not where you remember them, and they move each time. That also eliminates two of the while loops from the code outright.

My next potential hurtle will be not spawning too many monsters... I have crashed darkplaces twice now by trying to spawn too many entities... oops. I have already reduced the maximum possible to spawn, but I think I need a better way.

It looks like this now:

Code: Select all
// The original monster_army function
void() monster_army_spawn =
{
   precache_model ("progs/soldier.mdl");
   precache_model ("progs/h_guard.mdl");
   precache_model ("progs/gib1.mdl");
   precache_model ("progs/gib2.mdl");
   precache_model ("progs/gib3.mdl");

   precache_sound ("soldier/death1.wav");
   precache_sound ("soldier/idle.wav");
   precache_sound ("soldier/pain1.wav");
   precache_sound ("soldier/pain2.wav");
   precache_sound ("soldier/sattck1.wav");
   precache_sound ("soldier/sight1.wav");
   precache_sound ("player/udeath.wav");      // gib death

   self.solid = SOLID_SLIDEBOX;
   self.movetype = MOVETYPE_STEP;

   setmodel (self, "progs/soldier.mdl");
   setsize (self, '-16 -16 -24', '16 16 40');
   self.health = 10;

   self.th_stand = army_stand1;
   self.th_walk = army_walk1;
   self.th_run = army_run1;
   self.th_missile = army_atk1;
   self.th_pain = army_pain;
   self.th_die = army_die;

   walkmonster_start ();
};

// My new monster_army function, that calls the old one to actually spawn the monster.
void() monster_army =
{
   if (deathmatch)
   {
      remove(self);
      return;
   }
   
   local float rand_x, rand_y, rand_int, spawncount, canspawn;
   local vector neworigin, oldorigin;
   local entity new, tmp;

   spawncount = 0;
   rand_int = rint((random() * 3) + 1);
   while (spawncount < rand_int)
   {
      canspawn = 0;
      while (canspawn == 0)
      {
         rand_x = -256 + random() * 512;
         rand_y = -256 + random() * 512;
         neworigin_x = self.origin_x + rand_x;
         neworigin_y = self.origin_y + rand_y;
         neworigin_z = self.origin_z + 4;
         tracebox(self.origin, '-16 -16 -24', '16 16 40', neworigin, FALSE, self);
         if (trace_fraction == 1)
         {
            if (neworigin != '0 0 0')
            {
               canspawn = 1;
            }
         }
      }
      new = spawn();
      new.classname = "monster_army";
      new.angles = self.angles;
      setorigin(new, neworigin);
      tmp = self;
      self = new;
      monster_army_spawn();
      new = self;
      self = tmp;
      spawncount = spawncount + 1;
   }
}
Ace12GA
 
Posts: 56
Joined: Sat Jan 28, 2012 12:08 am


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest