Help with a small problem.

Discuss programming in the QuakeC language.
Post Reply
evilmarshy
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Help with a small problem.

Post by evilmarshy »

I've start re-writing my quake mod from the ground up but I've ran into a problem. I made some code to randomize a location and spawn an enemy in that location, tested with the use of a button press for now. That part of it works perfectly, but the problem is, is when it is applied to the scrag/wizard.qc the game freezes for about 10 seconds then dumps me to the console.

For all walking monsters I've been calling walkmonster_start_go(); (that works great). Using that also works for the scrag, but it doesn't function as a flying monster.
So I attempt to use flymonster_start_go(); Which is no different to walkmonster apart that it contains 2 small difference (no droptofloor() and the additional self.flags = self.flags | FL_FLY;). But I get a crash.

Though I have isolated that self.flags = self.flags | FL_FLY; within flymonster_start_go is causing the crash, I don't know why.
Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Post by Dr. Shadowborg »

What error are you getting from the console?
evilmarshy
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Post by evilmarshy »

Dr. Shadowborg wrote:What error are you getting from the console?

Screenshot of my console.
Image
Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Post by Dr. Shadowborg »

Looks like you're getting some kind of runaway loop spawning entities. I'll need to see what your spawning code is doing.

EDIT:
Another thing to look at is whether you're precaching stuff at any time other than mapload. (The exception to this is the Hipnotic spawner method.) Some engines will forgive you when you do this (DP, FTE), most others WILL get upset if you try to precache midgame.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Help with a small problem.

Post by Cobalt »

Check the ticrate too and make sure nothing is thinking faster than it, otherwise I believe that can cause sv_getspace overflow as well as spawn alot of entities depending on the code.
evilmarshy
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Post by evilmarshy »

On one button press it will either be 1 monster that spawns or none at all (I know this because it works perfectly with all the other monsters).

Code: Select all

void() monspawn_wizard =
{
	local entity temp;
	local float posneg;
	local float attempt;
		
	posneg = random();
	
	precache_model ("progs/wizard.mdl");
	precache_model ("progs/h_wizard.mdl");
	precache_model ("progs/w_spike.mdl");

	precache_sound ("wizard/hit.wav");
	precache_sound ("wizard/wattack.wav");
	precache_sound ("wizard/wdeath.wav");
	precache_sound ("wizard/widle1.wav");
	precache_sound ("wizard/widle2.wav");
	precache_sound ("wizard/wpain.wav");
	precache_sound ("wizard/wsight.wav");
		
	//START SPAWN
	
	while (attempt <=100) //OVERFLOW PREVENTION
	{
	
	temp = self; 
	self = spawn ();
	
	if (posneg >= 0.0 && posneg < 0.5)
	{
		self.origin_x = random() * 4096; //RANDOM THINGYS (NOT SURE IF THE WHOLE RANGE IS COVERED)
		self.origin_y = random() * 4096;
		self.origin_z = random() * 4096;
	}
	if (posneg >= 0.5 && posneg <= 1.0)
	{
		self.origin_x = random() * -4096;
		self.origin_y = random() * -4096;
		self.origin_z = random() * -4096;
	}
	
	self.solid = SOLID_SLIDEBOX;
	self.movetype = MOVETYPE_STEP;
	setmodel (self, "progs/wizard.mdl");
	setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
	self.health = 80;
	
	self.classname = "monster_wizard";
	
	self.th_stand = wiz_stand1;
	self.th_walk = wiz_walk1;
	self.th_run = wiz_run1;
	self.th_missile = Wiz_Missile;
	self.th_pain = Wiz_Pain;
	self.th_die = wiz_die;
	
	flymonster_start_go();// self.flags = self.flags | FL_SWIM; causing the crash.
	//walkmonster_start_go();//OK! but not a fly monster anymore
	bprint("a scrag joins the game\n");
	
	
	if (!walkmove(0,0))
	{
		attempt = attempt + 1;
		bprint("DAVEBUG: TRYING AGAIN\n");
		remove(self);
		monspawn_wizard();//SHOULDN'T REALLY BE DOING THIS, BUT SEEMS TO WORK AS LONG AS I LIMIT IT.
		return;
	}
	
	if (walkmove(0,0))
	{
	bprint("DAVEBUG: PLUS 1\n");
	total_monsters = total_monsters + 1;
	}

}
	self = temp;
}
Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Post by Dr. Shadowborg »

Yeek, and Egad. No offense, but there is just SO MUCH wrong with that code... :shock:

I'll start with what's causing the crash first:
You are attempting to break out of a loop by doing this, and causing all kinds of evile in the process:

Code: Select all

if (!walkmove(0,0))
   {
      attempt = attempt + 1;
      bprint("DAVEBUG: TRYING AGAIN\n");
      remove(self);
      monspawn_wizard();//SHOULDN'T REALLY BE DOING THIS, BUT SEEMS TO WORK AS LONG AS I LIMIT IT.
      return;
   }
Bad, bad, bad. attempt will NEVER reach 100 like this, thus infinite loop, thus crash to console.

Try this instead:

Code: Select all

void() monspawn_wizard =
{
   local entity temp;
   local float posneg;
   local float attempt, success; // DRS: for 100 attempt failure check later
      
   posneg = random();
   
   precache_model ("progs/wizard.mdl");
   precache_model ("progs/h_wizard.mdl");
   precache_model ("progs/w_spike.mdl");

   precache_sound ("wizard/hit.wav");
   precache_sound ("wizard/wattack.wav");
   precache_sound ("wizard/wdeath.wav");
   precache_sound ("wizard/widle1.wav");
   precache_sound ("wizard/widle2.wav");
   precache_sound ("wizard/wpain.wav");
   precache_sound ("wizard/wsight.wav");
      
   //START SPAWN
  
  // DRS: set up the monster most of the way first.
  temp = self; 
   self = spawn ();

   self.solid = SOLID_SLIDEBOX;
   self.movetype = MOVETYPE_STEP;
   setmodel (self, "progs/wizard.mdl");
   setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
   self.health = 80;
   
   self.classname = "monster_wizard";
   
   self.th_stand = wiz_stand1;
   self.th_walk = wiz_walk1;
   self.th_run = wiz_run1;
   self.th_missile = Wiz_Missile;
   self.th_pain = Wiz_Pain;
   self.th_die = wiz_die;
 
   while (attempt <=100) //OVERFLOW PREVENTION
   {   
   if (posneg >= 0.0 && posneg < 0.5)
   {
      self.origin_x = random() * 4096; //RANDOM THINGYS (NOT SURE IF THE WHOLE RANGE IS COVERED)
      self.origin_y = random() * 4096;
      self.origin_z = random() * 4096;
   }
   if (posneg >= 0.5 && posneg <= 1.0)
   {
      self.origin_x = random() * -4096;
      self.origin_y = random() * -4096;
      self.origin_z = random() * -4096;
   }

//DRS: Good idea to use setorigin.
 setorigin(self, self.origin);   
 
   if (!walkmove(0,0))
   {
      attempt = attempt + 1;
      bprint("DAVEBUG: TRYING AGAIN\n");
   }
 else 
   {
   bprint("DAVEBUG: PLUS 1\n");
   total_monsters = total_monsters + 1;
   // DRS: Break out of while loop.
   attempt = 100;
   success = TRUE; // DRS: SUCCESS!
   }
}
// DRS: check for success
if(success == FALSE)
 {
  bprint("DRS NOTIFY: random monster location failed\n");
  remove(self);
  return;
 }
// DRS: Successful location found, finish setting up monster.
   flymonster_start_go();// self.flags = self.flags | FL_SWIM; causing the crash.
   //walkmonster_start_go();//OK! but not a fly monster anymore

 bprint("a scrag joins the game\n");

   self = temp;
}
That doesn't address all the problems I have with the code, but it should get you up and running. :wink:

If it works, but doesn't spawn any monsters...you might have to set self.flags = self.flags | FL_FLY; before running the while loop, flying and swimming monsters are odd this way.
evilmarshy
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Post by evilmarshy »

No offence taken at all, it's all a learning process. (I'm fairly noobish at coding in general, plus my friend has already gave me a lecture about how much is wrong with this code hahah.). Thanks a lot for this, it will help me clean up my other spawner's up a little as-well. (Well I suppose this is what I get for having a large ambition with crappy coding skills lol)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Help with a small problem.

Post by Spike »

one programming guideline is to take the view that more than one return from a function is poor design.
the idea being something along the lines of:

Code: Select all

entity ret = world;
a = createobject();
if (a)
{
  b = createobjectfrom(a);
  if (b)
  {
    ret = createobjectfrom(b);
  }
  releaseobject(b);
}
releaseobject(a);
return ret;
essentually, the idea is to cascade out of the function on either success or error. this keeps the two cases equivelent to each other and avoids bugs arising within the error cases (within the function itself, but not the caller) .
the creates and releases synced across the top and the bottom of the block. much of the work to do with freeing anything you allocated becomes mechanical rather than anything you actually need to think about.
in qc terms, 'release' is the act of restoring a global to the value it originally was. yay globals!...
Post Reply