FAQ  •  Register  •  Login

Host_Error: PRVM_Execute Program

Moderator: Inside3D Admins

<<

Ghost_Fang

Posts: 323

Joined: Thu Nov 12, 2009 4:37 am

Post Fri Sep 10, 2010 6:20 pm

Host_Error: PRVM_Execute Program

I have a new enemy coded in and it works great as long as you kill him in one hit. If he takes damage of any kind and he doesn't die quake (darkplaces) crashes with "Host_Error: PRVM_Execute Program: QC Function self.think is missing. Now it is clear what is wrong, or is it? I checked the whole new monster qc and all the nextthinks have thinks and everything matches up well. If it helps fitzkurok said "Host_Error: PR_Execute Program: Null function" What would cause this? I'll post code if i need to.
<<

frag.machine

User avatar

Posts: 1469

Joined: Sat Nov 25, 2006 1:49 pm

Post Fri Sep 10, 2010 8:04 pm

The only thing I can imagine causing the error is exactly what's stated in the message: it's very likely that in one of the frames of the death sequence you're setting self.nextthink = time + something with self.think not initialized correctly. Without seeing the code itself it's hard to tell, though.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
<<

Ghost_Fang

Posts: 323

Joined: Thu Nov 12, 2009 4:37 am

Post Sat Sep 11, 2010 5:00 pm

  Code:
/*
barnacle.qc
*/

void() barnacle_check;
void() barnacle_touch;



void() barnacle_push =
{
   if (self.t_width <= time)
   {
      if (self.walkframe >= 51)
         self.walkframe = 0;
      self.frame = 0 + self.walkframe;
      self.walkframe = self.walkframe + 1;
      self.t_width = time + 0.03;
   }
   
   if (self.enemy.health <= 0)
   {
      barnacle_check ();
      self.touch = barnacle_touch;
      return;
   }
   
   if (self.enemy.flags & FL_ONGROUND)
      self.enemy.flags = self.enemy.flags - FL_ONGROUND;
   
   self.enemy.velocity = '0 0 50';
   self.enemy.origin_x = self.origin_x;
   self.enemy.origin_y = self.origin_y;
   self.nextthink = time;
   self.think = barnacle_push;
};

void() barnacle_check =
{
   self.nextthink = time;
   self.think = barnacle_check;
   
   self.frame = 0;
   
   traceline (self.origin, self.origin - '0 0 1000', FALSE, self);
   if (trace_fraction == 1.0)
      return;
   
   if (trace_ent.takedamage == DAMAGE_AIM)
   {
      self.enemy = trace_ent;
      sound (self, CHAN_VOICE, "barnacle/alert2.wav", 1, ATTN_NORM);
      self.walkframe=0;
      barnacle_push ();
      
   }
};

void() barnacle_bite =
{
   if (self.t_width <= time)
   {
      if (self.walkframe >= 61)
      {
         self.walkframe = 0;
         if (random() < 0.3)
            sound (self, CHAN_BODY, "barnacle/chew1.wav", 1, ATTN_NORM);
         else if (random() < 0.6)
            sound (self, CHAN_BODY, "barnacle/chew2.wav", 1, ATTN_NORM);
         else
            sound (self, CHAN_BODY, "barnacle/chew3.wav", 1, ATTN_NORM);
         T_Damage (self.enemy, self, self, 60);
         if (self.enemy.health <= 0)
         {
            barnacle_check ();
            self.touch = barnacle_touch;
            return;
         }
      }
      
      self.frame = 51 + self.walkframe;
      self.walkframe = self.walkframe + 1;
      self.t_width = time + 0.03;
   }
   
   self.enemy.velocity = '0 0 50';
   self.enemy.origin_x = self.origin_x;
   self.enemy.origin_y = self.origin_y;
   
   self.nextthink = time;
   self.think = barnacle_bite;
};


void() barnacle_die_go = [112, barnacle_die_go]
{
   if (self.walkframe >= 100)
      self.walkframe = 100;
   self.frame = self.frame + self.walkframe;
   self.walkframe = self.walkframe + 1;
   self.nextthink = time + 0.03;
   self.think = barnacle_die_go;

};

void() throw_gibs =
{
   self.nextthink = time;
   self.think = throw_gibs;
   if (self.health < time)
   {
      remove(self);
      return;
   }
   
   if (self.attack_finished < time)
   {
      if (random() < 0.3)
         ThrowGib ("progs/gib1.mdl", 0);
      else if (random() < 0.6)
         ThrowGib ("progs/gib2.mdl", 0);
      else
         ThrowGib ("progs/gib3.mdl", 0);
      
      self.attack_finished = time + 0.15 + random()*0.2;
   }
};

void() barnacle_die =
{
   local entity o;
   
   self.solid = SOLID_NOT;
   
   if (random() < 0.5)
      sound (self, CHAN_VOICE, "barnacle/die1.wav", 1, ATTN_NORM);
   else
      sound (self, CHAN_VOICE, "barnacle/die3.wav", 1, ATTN_NORM);
   
   o = spawn ();
   o.origin = self.origin;
   o.health = time + 2;
   o.nextthink = time;
   o.think = throw_gibs;
   
   remove(self.owner);
   self.walkframe=0;
   self.nextthink = time + 0.1;
   self.think = barnacle_die_go;
};


void() barnacle_touch =
{
   if (other.takedamage == DAMAGE_AIM)
   {
      
      self.walkframe=0;
      barnacle_bite ();
      sound (self, CHAN_BODY, "barnacle/bite3.wav", 1, ATTN_NORM);
      self.touch = SUB_Null;
   }
};

void() ParseTongue =
{
   local entity tongue;
   local float tracedist, tsize;
   
   traceline (self.origin, self.origin - '0 0 1000', FALSE, self);
   
   tracedist = 1000*trace_fraction;
   while (tsize < tracedist)
   {
      tsize = tsize + 32;
      
      tongue = spawn ();
      tongue.origin = self.origin;
      tongue.origin_z = tongue.origin_z - tsize;
      tongue.nextthink = time + 0.2;
      tongue.think = SUB_Remove;
      setmodel (tongue, "progs/tongue.mdl");
   }
};

void() tongue_think =
{
   self.nextthink = time + 0.2;
   self.think = tongue_think;
   ParseTongue ();
};

void() monster_barnacle =
{
   local entity o;
   
   if (deathmatch)
   {
      remove(self);
      return;
   }
   
   precache_model ("progs/barnacle.mdl");
   precache_model ("progs/tongue.mdl");
   
   precache_sound ("barnacle/alert2.wav");
   precache_sound ("barnacle/bite3.wav");
   precache_sound ("barnacle/chew1.wav");
   precache_sound ("barnacle/chew2.wav");
   precache_sound ("barnacle/chew3.wav");
   precache_sound ("barnacle/die1.wav");
   precache_sound ("barnacle/die3.wav");
   
   self.solid = SOLID_SLIDEBOX;
   self.flags = FL_MONSTER;
   
   setmodel (self, "progs/barnacle.mdl");
   
   setsize (self, '-16 -16 -32', '16 16 0');
   
   self.health = 35;
   self.takedamage = DAMAGE_AIM;
   self.th_die = barnacle_die;
   self.th_stand = barnacle_check;
   
   self.nextthink = time + 0.1 + random()*0.5;
   self.think = barnacle_check;
   
   self.touch = barnacle_touch;
   
   total_monsters = total_monsters + 1;
   
   self.owner = spawn ();
   o = self.owner;
   o.origin = self.origin;
   o.nextthink = time + 0.2;
   o.think = tongue_think;
   setmodel (o, "progs/tongue.mdl");
};
<<

Sajt

Posts: 1216

Joined: Sat Oct 16, 2004 3:39 am

Post Sat Sep 11, 2010 7:44 pm

My guess is that you have FL_MONSTER flag set but no th_run. When you shoot the barnacle, T_Damage is called. Near the bottom of that function, it calls FoundTarget() if the target is FL_MONSTER. FoundTarget calls HuntTarget, which sets self.think to self.th_run.

You should remove the FL_MONSTER flag, or else add an extra check to return from that code path if classname is "barnacle". (IIRC you might want to keep FL_MONSTER for other reasons, for example the enlarged bbox for opposing traces?)

Or you could add a th_pain, since self.th_pain (if it isn't null) is called after FoundTarget. But your previous think function would still be getting overridden, which might mess up your specialized monster behaviour.
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
<<

Ghost_Fang

Posts: 323

Joined: Thu Nov 12, 2009 4:37 am

Post Sat Sep 11, 2010 8:53 pm

I tried both, either/or and at the same time. Still nothing. If it helps to narrow it down, when it is "sucking you up" you can shoot it and its fine, but if its just chillin there and you shoot it and you dont kill it it crashes.

EDIT: I got it now, I did it RIGHT thanks Sajt
<<

frag.machine

User avatar

Posts: 1469

Joined: Sat Nov 25, 2006 1:49 pm

Post Sun Sep 12, 2010 4:18 am

Sajt wrote:My guess is that you have FL_MONSTER flag set but no th_run. When you shoot the barnacle, T_Damage is called. Near the bottom of that function, it calls FoundTarget() if the target is FL_MONSTER. FoundTarget calls HuntTarget, which sets self.think to self.th_run.

You should remove the FL_MONSTER flag, or else add an extra check to return from that code path if classname is "barnacle". (IIRC you might want to keep FL_MONSTER for other reasons, for example the enlarged bbox for opposing traces?)

Or you could add a th_pain, since self.th_pain (if it isn't null) is called after FoundTarget. But your previous think function would still be getting overridden, which might mess up your specialized monster behaviour.


But the reported error was in self.think, not self.th_run (which AFAIK is not mandatory). Even if it was required, one could just set th_run = SUB_Null and everything should work with FL_MONSTER set.

EDIT: I think there's something wrong with this piece of code:
  Code:
void() barnacle_die_go = [112, barnacle_die_go]
{
   if (self.walkframe >= 100)
      self.walkframe = 100;
   self.frame = self.frame + self.walkframe;
   self.walkframe = self.walkframe + 1;
   self.nextthink = time + 0.03;
   self.think = barnacle_die_go;
};


You could/should remove the "[112, barnacle_die_go]" part, since you're doing all the animation by hand.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
<<

Sajt

Posts: 1216

Joined: Sat Oct 16, 2004 3:39 am

Post Sun Sep 12, 2010 5:50 pm

frag.machine wrote:But the reported error was in self.think, not self.th_run (which AFAIK is not mandatory). Even if it was required, one could just set th_run = SUB_Null and everything should work with FL_MONSTER set.


It's reporting "think" being null because HuntTarget sets self.think to self.th_run and sets nextthink, it doesn't call th_run directly.

You could add th_run (or th_pain) for the monster, but like I said it would still end up overriding the previous think, which might screw up his special monster behaviour (or it might not, I don't know).
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
<<

Ghost_Fang

Posts: 323

Joined: Thu Nov 12, 2009 4:37 am

Post Mon Sep 13, 2010 6:04 am

well what I did was make the th_walk, th_run, th_pain, etc just do barnacle_check and it seemed to work just fine. I'm pretty sure that was the issue since it had no th_XXXX other than th_die and and th_stand.

Thanks for the help guys!
AI, for some reason, I just can't get the hang of and it irritates me.

Return to Artificial Intelligence

Who is online

Users browsing this forum: No registered users and 0 guests

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Icons provided by Aha Soft