Forum

Help with a small problem.

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Help with a small problem.

Postby evilmarshy » Sat Dec 14, 2013 8:45 pm

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.
evilmarshy
 
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Postby Dr. Shadowborg » Sat Dec 14, 2013 9:42 pm

What error are you getting from the console?
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Postby evilmarshy » Sat Dec 14, 2013 10:25 pm

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



Screenshot of my console.
Image
evilmarshy
 
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Postby Dr. Shadowborg » Sat Dec 14, 2013 11:44 pm

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.
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Postby Cobalt » Sun Dec 15, 2013 5:55 am

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.
User avatar
Cobalt
 
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

Re: Help with a small problem.

Postby evilmarshy » Sun Dec 15, 2013 2:51 pm

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;
}
evilmarshy
 
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Postby Dr. Shadowborg » Sun Dec 15, 2013 6:56 pm

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.
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Re: Help with a small problem.

Postby evilmarshy » Sun Dec 15, 2013 11:51 pm

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)
evilmarshy
 
Posts: 6
Joined: Mon Aug 08, 2011 9:08 pm

Re: Help with a small problem.

Postby Spike » Mon Dec 16, 2013 1:25 am

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!...
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest