Forum

tutorbot and teamplay..

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

tutorbot and teamplay..

Postby drm_wayne » Thu Jul 25, 2013 10:39 am

Hey there,

I need some help with my custombots based on the tutorbot by coffee...
Afaik they understand teamplay and they are working good in teamplay, but i dont really understand how
the bot detects the teamthing..

The real player can choose between 2 teams (USMC Team and German Team) via ingame menu and observermode at the games start,
and they will get a different playermodel for each team..

Its still not coded in, but i will use something like "self.teambase == 1" or something (1 is USMC, 2 is german team)..

So how can i make the bots to get the same models for the team?

Here is the code, its based on tutorbot....
(all is coded from scratch using enders scratch qc, so some stuff might look strange..)

thx for the help.


Code: Select all
// ------------------------------------------------
void(float teem) create_bot =
// ------------------------------------------------
{
   if (!deathmatch) // no bots in SP.
   {
   bprint("bots can only added in multiplayer\n");
   return;
   }
local entity bot, spot, plr;

// initializing the entity
   bot = spawn();
   spot = GetSpawnPoint();
   bot.origin = spot.origin + '0 0 10';
   bot.angles = spot.angles;
   bot.fixangle = #TRUE;   
   bot.incam = FALSE;
   bot.solid = #SOLID_SLIDEBOX;
   bot.movetype = #MOVETYPE_STEP;

// defining his animation

   setmodel(bot, "progs/p_usmc.md2"); // just for test, for teampaly he needs to get a different model.
   bot.frame = $idle1;
   bot.th_stand = thebot_stand1;
   bot.th_walk = thebot_walk1;
   bot.th_run = thebot_run1;
   bot.th_pain = bot_pain;
   bot.th_die = thebot_die;
   bot.th_missile = thebot_mp1;

// arming and naming him
   bot.CurrentSlot = "Main";  // dr_mabuse1981: only give bots PRIMARY weapons!
   give_random_weapon(bot); // dr_mabuse1981: only give bots PRIMARY weapons!
   bot.health = 100;
   bot.classname = "bot";

   if (teamplay) // dr_mabuse1981: so how does this exactly work??
      {
      plr = find(world, classname, "player");
      plr.team = 1;
      bot.team = teem;
      if (teem == plr.team)
         {
         bot.colormap = plr.colormap;
         }
      }

   bot.netname = bot_name();
   bprint(bot.netname);
   bprint(" enters the game\n");

// polishing him up
   setsize (bot, #VEC_HULL_MIN, #VEC_HULL_MAX);
   bot.ideal_yaw = bot.angles * '0 1 0';
   bot.yaw_speed = 120;
   bot.view_ofs = '0 0 22';
   bot.takedamage = DAMAGE_AIM;
   bot.attack_state = 0;
   bot.button1 = 90;
   bot.nextthink = time + 0.1 + random();
   bot.think = bot.th_walk;

};

User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Postby r00k » Thu Jul 25, 2013 4:13 pm

here's how i select teams in CAx (ignore most the specific CA code)

Code: Select all
//---------------------------------------------------------------------------------------------
void () Teamplay_Select_Team =
{
   if (boss.busy == TRUE)
   {
      sprint(self,"Cleaning up match end. Re-join in 3 seconds.\n");
      return;
   }

   clear_name();
   self.style = self.style - (self.style & CA_AFK_CLIENT);
   self.afk_time = time;

   if (ca_gametype & CA_MATCH_MODE)
   {
      if (self.impulse == 1)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_BLUE);
         else
         Request_Join_Team (TEAM_BLUE);
      }
      else if (self.impulse == 2)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_RED);
         else
         Request_Join_Team (TEAM_RED);
      }
      else if (self.impulse == 3)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_YELLOW);
         else
         Request_Join_Team (TEAM_YELLOW);
      }
      else if (self.impulse == 4)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_GREEN);
         else
         Request_Join_Team (TEAM_GREEN);
      }
   }
   else if (mode_ffa ())
   {
      if (self.impulse == 4)
      Join_FFA_Team();
   }
   else
   if (mode_speedball())
   {
      if (self.impulse == 1)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_BLUE);
         else
         Request_Join_Team (TEAM_BLUE);
      }
      else if (self.impulse == 2)
      {
         if (boss.state == CA_MATCH_WAITING)
         Join_Team(TEAM_RED);
         else
         Request_Join_Team (TEAM_RED);
      }
   }

   // We don't want this team anymore
   if (self.impulse == 5)
   {
      if (self.cc_queue_vote)
      {
         if ((vote_request.classname == "cc_vote") && (vote_request.owner == self))
         {
            vote_reject();
            self.cc_queue_vote = 0;
         }
      }

      if (boss.state == CA_MATCH_WAITING)
      {
         if (self.next_team != world)
         RemoveFromTeam ();
      }

      if (self.cc_queue)
      {
         if (self.next_team != world)
         RemoveFromTeam ();

         sprint (self, "Cancelling \bColor-Change\b...\n");
         self.cc_queue = 0;
         self.cc_queue_vote = 0;
      }

      if (self.style & CA_CONNECTED)
      {
         stuffcmd(self,";color 0;\n");
      }
   }

   self.impulse = 0;
};


this code actually creates an entity for each team then creates a linklist of players on each team.
Code: Select all
void(float whichteam) Join_Team =
{
   local entity pteam;
   local string tmp;

   if ((boss.state == CA_MATCH_CLEANUP) || (boss.state == CA_MATCH_OVER))
   {
      sprint (self, "Try again in 5 seconds...\n");
      return;
   }

   if (boss.state != CA_MATCH_WAITING)
   {
      sprint(self,"\bYou may not join at this time.\n");
      return;
   }

   if (self.next_team != world)
   {
      sprint(self,"\bYou have already commited to a team.\n");
      return;//already on a team
   }

   pteam = find_team_entity(whichteam);

   if (pteam == world)
   {
      if (number_teams () < boss.max_teams)
      {
         pteam = spawn();

         pteam.classname    = "ca_team";
         pteam.team2      = whichteam;
         pteam.wins      = 0;
         pteam.losses       = 0;
         pteam.armorvalue    = 0;
         pteam.health      = 0;
         pteam.netname       = strings_get_teamname (pteam.team2);

         pteam.next_player   = world;//init entity
         pteam.chain_gang    = world;//init entity

         pteam.next_team      = boss.next_team;
         boss.next_team       = pteam;

         //announce2 ("creating the ", pteam.netname);
         announce3 (self.netname, " has joined the ", pteam.netname);
         pqc_new_team (world,((pteam.team2) * 16) + (pteam.team2));
      }
      else
      {
         //sound (self, CHAN_VOICE, "player/axhit2.wav", 1, ATTN_NORM);
         sprint (self, "The maximum amount of teams exists.\n");
         return;
      }
   }
   else
   {
      if (number_teammates (pteam) == boss.max_players)
      {
         //sound (self, CHAN_VOICE, "player/axhit2.wav", 1, ATTN_NORM);
         sprint (self, "That team is \bfull\b.\n");
         return;
      }

      announce3 (self.netname, " has joined the ", pteam.netname);
   }

   self.team2     = whichteam;
   self.next_team    = pteam;

   add_player_to_stat_list(pteam,self);
   add_player_to_chain(pteam,self);

   tmp = ftos(self.team2);

   setcolor(self,self.team2,self.team2);

   stuffcmd(self,";color ");
   stuffcmd(self,tmp);
   stuffcmd(self,";\n");

   motd_playercount();// R00k v1.53

   motd_top5 = string_null;
   motd_top6 = string_null;
   stats_reset_player (); //BAM MOVED
};


i know this might be overwhelming for a simple answer of "just use the .team variable for each team, and based on the player's choice via menu set their modelindex to a precached model assigned to a custom index."

in the above code i use a new variable .team2 to compare players' teams as spamming 'color x' in console can temporarily change one's team. (This is how ColorCheat all started then observers could spam color and the mod would spawn players based on .team value)...
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Postby drm_wayne » Thu Jul 25, 2013 4:21 pm

thx i will take a look...
this is one of the things i still cant do lol...
I can code almost everything in qc i want, but when it comes to teamplay stuff im basicially stuck :(
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Postby r00k » Thu Jul 25, 2013 4:32 pm

well you can create a new variable, .teambase or use .team, all that matters is where it compares in combat.qc.
But if you want to allow infighting among teamates then its not really important.

just add a
Code: Select all
if (teem == 1)
{
setmodel(bot, "progs/p_usmc.md2");
}
else
{
setmodel(bot, "progs/p_german.md2");
}


i'm not sure what is going on here
Code: Select all
  if (teamplay) // dr_mabuse1981: so how does this exactly work??
      {
      plr = find(world, classname, "player");
      plr.team = 1;
      bot.team = teem;
      if (teem == plr.team)
         {
         bot.colormap = plr.colormap;
         }
      }
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Postby drm_wayne » Thu Jul 25, 2013 4:39 pm

this is where i am stuck..

Code: Select all
   if (teamplay) // if teamplay is active
      {
      plr = find(world, classname, "player"); // finds player
      plr.team = 1; // assigns player to team 1??
      bot.team = teem; // what??
      if (teem == plr.team) // stuck...
         {
         bot.colormap = plr.colormap;
         }
      }



in impulses i have this:

Code: Select all
   if (self.impulse == 100)
      create_bot(1);
   if (self.impulse == 101)
      create_bot(2);


so impulse 100 adds a teammate in teamplay, but they should able to detect what the player has selected...
if the player has selected USMC the teambots should get it too and the "enemy bots" the other one..(and same with german)
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Postby r00k » Thu Jul 25, 2013 6:16 pm

im not sure why u need to create a team of bots with only 1 human player?
if thats what u want u just need to create a loop 1 to maxteamsize - 1
spawn a bot entity and setmodel skin etc each iteration

im typing this on my phone so its kinda vague
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Postby ceriux » Thu Jul 25, 2013 6:17 pm

arent you only changing the color mapping of the bots? not the model ?
User avatar
ceriux
 
Posts: 2223
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Re: tutorbot and teamplay..

Postby drm_wayne » Fri Jul 26, 2013 12:35 pm

well the bots should at least work offline for singleplayer dm...
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Postby frag.machine » Fri Jul 26, 2013 2:25 pm

Code: Select all
// precaches required models...
setmodel (self, "progs/pl1.mdl");
team1_mdl = self.mdl;
setmodel (self, "progs/pl2.mdl");
team2_mdl = self.mdl;


Code: Select all
// sets bot team to the same player team
bot.team = self.team; // assuming player = self
bot.mdl = self.mdl; // assuming all models were precached somewhere


Code: Select all
// sets bot team to the opposite team
if (self.team == 1) {
   bot.team = 2;
   bot.mdl = team2_mdl;
} else {
   bot.team = 1;
   bot.mdl = team1_mdl;
}


Unless I missed something, that's all you need... ?
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Re: tutorbot and teamplay..

Postby r00k » Fri Jul 26, 2013 5:38 pm

setmodel wont precache you know
best to precache in world spawn i assumed he had those
ive forgotten the diff between setmodel, self.mdl = , and self.modelindex =.
i thought they all just changed the ents model but in different ways but same result.
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Postby Spike » Fri Jul 26, 2013 6:00 pm

setmodel looks up the name->modelindex
sets the modelindex to that lookup result
sets the model string to match.
sets the entity's mins+maxs (QW: only on a "*.bsp" model as non.bsp models are not loaded on the server)
relinks the entity (like setorigin) (including settting absmin, absmax, size, and checking which pvs leafs the entity is inside, as well as updating the physics kd tree thing, thus you will likely want to avoid calling it within touch functions).

.modelindex is used for bsp/bbox collisions, and is also used for networking. the check to see if the entity is actually potentially visible uses .model as an early-out clause however. clear either and the entity will not be drawn.

.mdl is merely a backup for .model, so that the entity can get the proper .model field again once a grabbed item respawns. that's its typical use. it means nothing to the engine.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: tutorbot and teamplay..

Postby frag.machine » Fri Jul 26, 2013 11:53 pm

@rook: yeah, you're right; but I am assuming everyone on this discussion already knows that (I was replying from my phone while at the bus heading to my work, it's a PITA to write code on these conditions, so bear with me).
And I wrote ".mdl" but was thinking about .modelindex actually. So meh to me for trusting my flawed and rusty memory. :P

So here goes the correct, and more complete solution:

Code: Select all
// declare some globals
float  alliedmdl, axismdl;

// some constants
float ALLIED_TEAM = 1;
float AXIS_TEAM = 2;

(...)

// precache the models (preferentially in world.qc)
precache_model ("progs/pl_allied.mdl");
precache_model ("progs/pl_axis.mdl");

(...)

// somewhere in the player initialization
// we use the old eyes.mdl trick

  setmodel (self, "progs/pl_allied.mdl");
  alliedmdl = self.modelindex;
  setmodel (self, "progs/pl_axis.mdl");
  axismdl = self.modelindex;

(...)
// unified function to spawns bots.
// we pass the player who's spawning the
// bot, and a flag to define if we want a
// friendly or opposite bot

void (entity pl, float friendly) spawnBot =
{
  local entity  bot;

  bot = spawn ();
  // here goes all the other code to create your bots
  (...)
  // here we set the model and the bot team
  if (friendly)
  {
    bot.team = pl.team;
    bot.modelindex = pl.modelindex;
  }
  else
  {
    if (pl.team == ALLIED_TEAM)
    {
      bot.modelindex = axismdl;
      bot.team = AXIS_TEAM;
    }
    else
    {
      bot.modelindex = alliedmdl;
      bot.team = ALLIED_TEAM;
    }
  }
};
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Re: tutorbot and teamplay..

Postby drm_wayne » Sat Jul 27, 2013 3:32 pm

thxfrag.machine, this looks useable.
Im using a scratch QC so its abit more complex xD

setmodel wont precache you know


I have Precache_Set in scratch qc, but im not really using it (lol)

Code: Select all
void(string modelname) Precache_Set = // Precache model, and set myself to it
{
 precache_model(modelname);
 setmodel(self, modelname);
};
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Postby r00k » Sat Jul 27, 2013 9:41 pm

i dont reccomend that function for spawning bot entities
precache_model can only be called when the mod/map loads
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Postby frag.machine » Mon Jul 29, 2013 12:54 am

Right, that's why I suggest to precache in world.qc.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Next

Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest