tutorbot and teamplay..

Discuss programming in the QuakeC language.
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

tutorbot and teamplay..

Post by drm_wayne »

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;

};

r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Post by r00k »

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)...
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Post by drm_wayne »

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 :(
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Post by r00k »

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;
         }
      }
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Post by drm_wayne »

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)
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Post by r00k »

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
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Re: tutorbot and teamplay..

Post by ceriux »

arent you only changing the color mapping of the bots? not the model ?
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Post by drm_wayne »

well the bots should at least work offline for singleplayer dm...
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: tutorbot and teamplay..

Post by frag.machine »

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)
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Post by r00k »

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

Re: tutorbot and teamplay..

Post by Spike »

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.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: tutorbot and teamplay..

Post by frag.machine »

@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)
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: tutorbot and teamplay..

Post by drm_wayne »

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);
};
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: tutorbot and teamplay..

Post by r00k »

i dont reccomend that function for spawning bot entities
precache_model can only be called when the mod/map loads
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: tutorbot and teamplay..

Post by frag.machine »

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)
Post Reply