Inside3D!
     

True client bots?

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Artificial Intelligence
View previous topic :: View next topic  
Author Message
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Wed Dec 12, 2007 3:58 am    Post subject: True client bots? Reply with quote

Is there a way to implement bot functions (AI, waypointing, ...) on a true client?
Let's say I'm playing QW DM and I want to get a beer?
Can I switch to auto-pilot until I get back?
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Entar



Joined: 05 Nov 2004
Posts: 422
Location: At my computer

PostPosted: Wed Dec 12, 2007 5:04 am    Post subject: Reply with quote

I imagine this could be done with CSQC for clients that support it and on servers that don't have any protection against third party CSQC progs.dat's, but that kind of thing is generally considered cheating, to my knowledge.
_________________
woh... feelin woozy... too much cider...
http://entar.quakedev.com
games fascination - My Game Development Blog/Journal
Back to top
View user's profile Send private message Visit poster's website AIM Address MSN Messenger
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Wed Dec 12, 2007 7:07 am    Post subject: Reply with quote

You could do it serverside as well, which is easier to protect against cheating too. Just add a cvar check in say PlayerPreThink, or SV_PlayerPhysics, if on, run AI code on client. Not harder than making a regular bot. Which, ofcourse, is very hard Smile
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Electro



Joined: 29 Dec 2004
Posts: 241
Location: Brisbane, Australia

PostPosted: Wed Dec 12, 2007 11:41 pm    Post subject: Reply with quote

shockbot has this option already Smile
_________________
Unit reporting!
http://www.bendarling.net/
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Wed Dec 12, 2007 11:44 pm    Post subject: Reply with quote

Has the Shockbot been released yet?
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Electro



Joined: 29 Dec 2004
Posts: 241
Location: Brisbane, Australia

PostPosted: Thu Dec 13, 2007 1:09 am    Post subject: Reply with quote

nope, i'm currently without internet at home (i check this occassionally at work)

Redoing a heap of the core navigation stuff in shockbot at the moment. There's a bunch of things I want to make nicer, and how I was doing things was really limiting (pick a goal, then route to a goal).

Whereas with the new system, i should hopefully be able to get it working where it can know how to get to everything, then decide which one it wants to go for. The difference being that real travel distances can be taken into account rather than just a straight distance check to items. Also this will allow for a better way to do item respawn prediction. Wink
_________________
Unit reporting!
http://www.bendarling.net/
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Orion



Joined: 12 Jan 2007
Posts: 413
Location: Brazil

PostPosted: Thu Dec 13, 2007 4:25 pm    Post subject: Reply with quote

Redrum, I just made a human bot.

BUT, it's not smart as a player, and it has perfect aim with instant weapons, so the shotguns and sniper rifle are undodgeable.

Impulse 150 will toggle between on and off.

It will respawn automatically when dead and will shoot the enemies.

Another thing is that he won't choose a weapon too, he'll fire with the current weapon until the ammo depletes.

I made it to be simple.


So let's do it.

Open world.qc and add this before StartFrame():

Code:

float() FindEnemy =
{
   local entity head;
   
   head = findradius(self.origin, 2000);
   while (head)
   {
      if (head != self)
      if (!(head.flags & FL_ITEM))
      if (head.health > 0)
      if (head.takedamage == DAMAGE_AIM)
      if (visible(head))
         self.enemy = head;
      head = head.chain;
   }
   
   if (self.enemy != world)
      return TRUE;
   
   return FALSE;
};

.float goleft, goright;
void() Autopilot =
{
   if (self.health <= 0)
   {
      stuffcmd (self, "-forward\n");
      stuffcmd (self, "-moveleft\n");
      stuffcmd (self, "-moveright\n");
      return;
   }
   
   self.fixangle = TRUE;
   
   if (self.enemy == world)
   {
      if (FindEnemy())
         return;
      
      self.angles_x = 0;
      stuffcmd (self, "+forward\n");
      stuffcmd (self, "-moveleft\n");
      stuffcmd (self, "-moveright\n");
      
      if (random() < 0.02)
      {
         if (self.turndir == 45)
            self.turndir = -45;
         else
            self.turndir = 45;
      }
      
      traceline (self.origin, self.origin + v_forward*320, TRUE, self);
      if (trace_fraction < 0.2)
         self.angles_y = self.angles_y - self.turndir;
   }
   
   if (self.enemy != world)
   {
      if (self.enemy.health <= 0 || !visible(self.enemy))
      {
         self.enemy = world;
         return;
      }
      
      stuffcmd (self, "-forward\n");
      
      traceline (self.origin, self.origin + v_right*320, TRUE, self);
      if (trace_fraction < 0.2)
      {
         self.goleft = TRUE;
         self.goright = FALSE;
      }
      
      traceline (self.origin, self.origin - v_right*320, TRUE, self);
      if (trace_fraction < 0.2)
      {
         self.goleft = FALSE;
         self.goright = TRUE;
      }
      
      self.angles = vectoangles(self.enemy.origin - self.origin);
      self.angles_x = self.angles_x * -1;
      
      if (self.goleft)
      {
         stuffcmd (self, "+moveleft\n");
         stuffcmd (self, "-moveright\n");
      }
      if (self.goright)
      {
         stuffcmd (self, "-moveleft\n");
         stuffcmd (self, "+moveright\n");
      }
      
      if (infront(self.enemy) && self.attack_finished < time)
         W_Attack ();
   }
};


Ok, now add this at the very bottom of StartFrame(), before framecount line:

Code:

local entity plr, oself;
plr = find(world, classname, "player");
while (plr != world)
{
   if (plr.autopilot)
   {
      oself = self;
      self = plr;
      Autopilot ();
      self = oself;
   }
   plr = find(plr, classname, "player");
}


Now go to the very top of world.qc, and add these 2 lines:

Code:

float(entity targ) visible;
float(entity targ) infront;



Now save and close the file. Open defs.qc and add this to the very bottom:

Code:

.float autopilot, turndir;


Save and close.
Now open client.qc, scroll down to PlayerPreThink() and find:

Code:

if (self.deadflag >= DEAD_DEAD)
{
   PlayerDeathThink ();
   return;
}


Replace the whole statement with this:

Code:

if (self.deadflag >= DEAD_DEAD)
{
   if (self.autopilot)
   {
      respawn();
      return;
   }
   PlayerDeathThink ();
   return;
}


Now scroll up to PutClientInServer(), and add this before DecodeLevelParms():

Code:

self.enemy = world;
self.turndir = 45;


Save and close client.qc and open player.qc, scroll down to player_nail1().
Replace these 4 functions with these:

Code:

void() player_nail1   =[$nailatt1, player_nail2  ]
{
   muzzleflash();

   if (self.autopilot)
   {
      if (self.enemy == world || intermission_running || self.impulse || self.ammo_nails < 1)
         {player_run ();return;}
   }
   else
   {
      if (!self.button0 || intermission_running || self.impulse || self.ammo_nails < 1)
         {player_run ();return;}
   }
   self.weaponframe = self.weaponframe + 1;
   if (self.weaponframe == 9)
      self.weaponframe = 1;
   SuperDamageSound();
   W_FireSpikes (4);
   self.attack_finished = time + .2;
        self.fired_nails = self.fired_nails + 1;
};
void() player_nail2   =[$nailatt2, player_nail1  ]
{
   muzzleflash();

   if (self.autopilot)
   {
      if (self.enemy == world || intermission_running || self.impulse || self.ammo_nails < 1)
         {player_run ();return;}
   }
   else
   {
      if (!self.button0 || intermission_running || self.impulse || self.ammo_nails < 1)
         {player_run ();return;}
   }
   self.weaponframe = self.weaponframe + 1;
   if (self.weaponframe == 9)
      self.weaponframe = 1;
   SuperDamageSound();
   W_FireSpikes (-4);
   self.attack_finished = time + .2;
        self.fired_nails = self.fired_nails + 1;
};

//============================================================================

void() player_light1   =[$light1, player_light2  ]
{
   muzzleflash();

   if (self.autopilot)
   {
      if (self.enemy == world || intermission_running || self.impulse || self.ammo_cells < 1)
         {player_run ();return;}
   }
   else
   {
      if (!self.button0 || intermission_running || self.impulse || self.ammo_cells < 1)
         {player_run ();return;}
   }
   self.weaponframe = self.weaponframe + 1;
   if (self.weaponframe == 5)
      self.weaponframe = 1;
   SuperDamageSound();
   W_FireLightning();
   self.attack_finished = time + 0.2;
};
void() player_light2   =[$light2, player_light1  ]
{
   muzzleflash();

   if (self.autopilot)
   {
      if (self.enemy == world || intermission_running || self.impulse || self.ammo_cells < 1)
         {player_run ();return;}
   }
   else
   {
      if (!self.button0 || intermission_running || self.impulse || self.ammo_cells < 1)
         {player_run ();return;}
   }
   self.weaponframe = self.weaponframe + 1;
   if (self.weaponframe == 5)
      self.weaponframe = 1;
   SuperDamageSound();
   W_FireLightning();
   self.attack_finished = time + 0.2;
};


Lastly, save and close player.qc and open weapons.qc, add this to ImpulseCommands():

Code:

if (self.impulse == 150)
{
   if (!self.autopilot)
   {
      self.autopilot = 1;
      sprint (self, PRINT_HIGH, "Autopilot engaged.\n");
   }
   else
   {
      self.autopilot = 0;
      sprint (self, PRINT_HIGH, "Autopilot disengaged.\n");
      stuffcmd (self, "-forward\n");
      stuffcmd (self, "-moveleft\n");
      stuffcmd (self, "-moveright\n");
   }
}



There you go!
_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Thu Dec 13, 2007 10:30 pm    Post subject: Reply with quote

Thanks man!
Won't be home till tomorrow to check it out.
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Thu Dec 13, 2007 11:16 pm    Post subject: Reply with quote

Redrum (from work PC)

Orion, I made the necessary changes and it compiled Smile
BUT, I got this error message when launching the server:

SV_Error: You must have the progs.dat from QuakeWorld installed

I do have that file. What's up?
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Orion



Joined: 12 Jan 2007
Posts: 413
Location: Brazil

PostPosted: Thu Dec 13, 2007 11:20 pm    Post subject: Reply with quote

What the hell?

Did you test at work?
Your code could be different. Try at home.

I tested here and nothing happened. Really weird.
_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Fri Dec 14, 2007 1:55 am    Post subject: Reply with quote

redrum wrote:
SV_Error: You must have the progs.dat from QuakeWorld installed

Means that the crc inside the progs.dat was not recognised for that platform. You get this error if you run an nq mod in a qw server.

The message should actually read 'qwprogs.dat'... The engine uses qwprogs.dat first if it can, and progs.dat after. But that's just a naming convention.

If it worked before, then you've probably wrongly modified defs.qc and added/removed/changed something before end_sys_fields. Restore the top two sections of that file to the previous version.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Fri Dec 14, 2007 3:16 am    Post subject: Reply with quote

Only modified defs.qc at the bottom though?
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Artificial Intelligence All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group