Team shirt colors

Discuss programming in the QuakeC language.
Post Reply
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Team shirt colors

Post by Cobalt »

I want to improve the stock ctfbot TeamGetShirt() routine so that it can use bitflags on a teamshirt float to check if a certain color is used.
The stock code is:

Code: Select all

float (float t, entity ent) TeamGetShirt =
{
	if ((t == TEAM_COLOR1))
	{
		team1shirt = (team1shirt + FLAG_CARRIED);
		if ((team1shirt == (TEAM_COLOR2 - FLAG_CARRIED)))
		{
			team1shirt = (team1shirt + FLAG_CARRIED);
		}
		if ((team1shirt == 2))
		{
			team1shirt = (team1shirt + FLAG_CARRIED);
		}
		if ((team1shirt > TEAM_COLOR2))
		{
			team1shirt = 0;
		}
		return (team1shirt);
	}
	else
	{
		team2shirt = (team2shirt + FLAG_CARRIED);
		if ((team2shirt == (TEAM_COLOR1 - FLAG_CARRIED)))
		{
			team2shirt = (team2shirt + FLAG_CARRIED);
		}
		if ((team2shirt == 6))
		{
			team2shirt = (team2shirt + FLAG_CARRIED);
		}
		if ((team2shirt > TEAM_COLOR2))
		{
			team2shirt = 0;
		}
		return (team2shirt);
	}
	return ((t - FLAG_CARRIED));

...which seems to increment the floats, however once a player or bot leaves, that color is now freed, but this system wont consider that color is now available. What I have in mind is to make the team2shirt and team1shirt use bitflags, and I think that we could just check if (team2shirt && BLUE1) , for example, tells us if that shirtcolor 0 is available or not. I would make shirtcolor 0 the first float, and so fourth so that BLUE16 is 32768. Same for the RED team set. I would probably use scratch1 and scratch2 to keep these values known from level to level. I had also thought of merely cycling through the player and bot entities using ' find ' to check if a color is used, but the bitflag idea sounds more effective. Comments or ideas anyone?

EDIT: Other thing I forgot to mention is will need to check if the shirt color is the opposing teams pant color and disallow it. Whats a good explanation of what .colormap does?
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Re: Team shirt colors

Post by mankrip »

FrikBot does all kinds of checks like these, iirc you can even choose which team a bot should belong to. Its source code probably has all you need.
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Team shirt colors

Post by Cobalt »

Yea, probably right. Has he stopped developing Frikbot? I dont have any of the src's for that mod at all. Checked the usual spot /frikbot , but cant find a dl link......

mankrip wrote:FrikBot does all kinds of checks like these, iirc you can even choose which team a bot should belong to. Its source code probably has all you need.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Team shirt colors

Post by Cobalt »

Ok, heres what I came up with so far, kinda primitive, but works ' decent ' :

Code: Select all


float (float t, entity ent) TeamGetShirt =
{

local float x;


if ((t == TEAM_COLOR1))
{
do
			{
				x = (rint (random () * 15) + 1);
				if (x == 14) // illegal shirt color
				{
				if (random () < 0.5)
				x = (rint (random ()) + 15);
				else
				x = (rint (random () * 12) + 1);
				}
				
				

			} while ((team1shirt & x));
                      team1shirt = team1shirt | x - 1;
			 return x - 1;

}

if ((t == TEAM_COLOR2))
{
do
			{

                            x = (rint (random () * 15) + 1);
				if (x == 4) // illegal shirt color
				{
				if (random () < 0.5)
				x = (rint (random () * 11) + 5);
				else
				x = (rint (random () * 3));
				}			

			} while ((team2shirt & x));
                      team2shirt = team2shirt | x - 1;
			 return x - 1;

}


 

What I dont like is the team_shirt & x part, as it seems to allow duplicates of color 0 alot. My original plan was to float out values for shirt0 through shirt15 as global floats by bitflagging them all up to 32768 which would represent shirt 15. then I guess I would have to paste them all out again in another sub that is called within this code and bitflag them in. I am surprised that this code worked as well as it did.
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Re: Team shirt colors

Post by mankrip »

Cobalt wrote:I dont have any of the src's for that mod at all. Checked the usual spot /frikbot , but cant find a dl link......
Here.
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Team shirt colors

Post by r00k »

I thought .colormap in stock quake was just the client slot number like when you type status online.

heres a bit of code for ya

Code: Select all

void(entity ent, float clientshirt, float clientpants) setcolor =
{
	local float client;

	client = (ent.colormap - 1);

	msg_entity = ent;
	WriteByte (MSG_ALL, SVC_UPDATECOLORS);
	WriteByte (MSG_ALL, client);
	WriteByte (MSG_ALL, ((clientshirt * 16) + clientpants));
};
in proquake (which wont be viable on stock quake)

Code: Select all

float () get_top_color =
{
	local float tc;

	tc = floor((self.cl[CL_COLORS] / %1) / 16);

	return tc;
};
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Team shirt colors

Post by Cobalt »

Yes, you are right...its represents that number, I call it a slot number....but not sure if that is a good term for it. Thought it does something for the colors of the player, but cant confirm yet. In Darkplaces lets say your shirt is 4 (red) and you throw an ammo backpack via an impulse. If you set its .colormap to your colormap, the pack turns the color of your shirt (4).

They are also using this:

self.clientcolors = 12 * 16 + 4; // yellow (12) shirt and red (4) pants

...to I guess show the correct color in the scoreboard, which is likely internally identical to that writemessage code you posted.

I messed with my code today, and bitflagged out those floats like I intended, wrote a new bitflag check routine, and found some more illegal colors for the shirts. It was doing an endless loop until I saw I was not setting those team shirt floats to a non zero number, and when you check bitflags like that, the while-do loop was always seeing them as NOT or Zero! So I decided to check them for that first....then return a legal value and also set the float to a non zero so it would not fail the loop next time its picking a color for a client. Not sure if it can be done simpler or not, but so far seems to do the trick.


Code: Select all


float shirt1 = 1; // shirt color 0
float shirt2 = 2; // color 1
float shirt3 = 4;
float shirt4 = 8;
float shirt5 = 16;
float shirt6 = 32;
float shirt7 = 64;
float shirt8 = 128;
float shirt9 = 256;
float shirt10 = 512;
float shirt11 = 1024;
float shirt12 = 2048
float shirt13 = 4096;
float shirt14 = 8192;
float shirt15 = 16384;
float shirt16 = 32768; // color 15







float (float r) MatchBitflag =

{

if (!r)
return shirt1; 
if (r == 1)
return shirt2; 
if (r == 2)
return shirt3; 
if (r == 3)
return shirt4; 
if (r == 4)
return shirt5; 
if (r == 5)
return shirt6; 
if (r == 6)
return shirt7; 
if (r == 7)
return shirt8; 
if (r == 8)
return shirt9; 
if (r == 9)
return shirt10; 
if (r == 10)
return shirt11; 
if (r == 11)
return shirt12; 
if (r == 12)
return shirt13; 
if (r == 13)
return shirt14; 
if (r == 14)
return shirt15; 
if (r == 15)
return shirt16;  
};





float (float t, entity ent) TeamGetShirt =
{

local float x,v;


if ((t == TEAM_COLOR1))
{
if (!team1shirt)
{
 x = (rint (random () * 12));
 v = MatchBitflag (x + 1); // Illegal composite function
  team1shirt = team1shirt | (v);
return x;
}
do
			{
				x = (rint (random () * 15) + 1);
				if (x == 14 || x == 15)
				{
				if (random () < 0.5)
				x = 16;
				else
				x = (rint (random () * 13));
				}
				if (x - 1 < 0) // Illegal composite function
				x = 0;
				if (!team1shirt)
				 return (x - 1); // Illegal composite function
				v = MatchBitflag (x);

			} while ((team1shirt & v));
                      team1shirt = team1shirt | (v);
			 return (x - 1); // Illegal composite function

}

if ((t == TEAM_COLOR2))
{

if (!team2shirt)
{
x = (rint (random () * 10) + 5) ;
v = MatchBitflag (x + 1); // Illegal composite function
team2shirt = team2shirt | (v);
return x;
 }

do
			{

                            x = (rint (random () * 15) + 1);
				if (x == 4 || x == 5)
				{
				if (random () < 0.5)
				x = (rint (random () * 11) + 5);
				else
				x = (rint (random () * 2));
				}			
				if (x - 1 < 0) // Illegal composite function
				x = 0;
				
				
				v = MatchBitflag (x);
				
			} while ((team2shirt & v));
                      team2shirt = team2shirt | (v);
			 return (x - 1); // Illegal composite function

}



};






Also added some code in setchangeparms() and decodelevelparms() that floats those globals to scratch1 and scratch2 cvars so that they are known
between level changes. Next I need to set a clients bitflag free when they disconnect or go observer.

Also noticed that in Darkplaces, shirtcolor 15 appears as a bright fire orange color in the scoreboard, and the players shirt in the game looks light lime green. I thought maybe darkplaces added more colors..so am checking with LH on that one, strange.....


EDIT / UPDATE:

Found out this code would not work because it uses some ' composite functions ' that are illegal in QC. However most compilers out there wont detect them. I commented my bad code and updated this post today.


r00k wrote:I thought .colormap in stock quake was just the client slot number like when you type status online.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Team shirt colors

Post by Cobalt »

Ok, I edited my above post because I am pretty sure I used composite functions that would send attempted passed values into ' limbo' somewhere.
I have discovered that the smallest violation of this rule gives really unpredictable results that are impossible to trace logicly, because your passed values go absolutely nowhere to be found. I have commented those lines of code for anyones input on the matter. The compiler I am using is FrikQcc, and I acknowledge that other compilers may warn or disallow these coding practices, possibly.

Also seems I dont need to use " | " to merge the bitfield into the shirtcolor team floats...merely adding and subtracting them as their bitflag corresponding floats is in effect doing the same thing. The new code seems to be working alot better overall :
(we use the same global floats as previous code )

Code: Select all



loat (float t, entity ent) TeamGetShirt =
{

local float x,v,h;


if ((t == TEAM_COLOR1))
{
if (!team1shirt)
{

 x = (rint (random () * 12));
 h = x + 1;
 v = MatchBitflag (h);
  team1shirt = v;
return x;
}
do
			{
				x = (rint (random () * 15) + 1);
				if (x == 14 || x == 15)
				{
				if (random () < 0.5)
				x = 16;
				else
				x = (rint (random () * 12));
				}
				h = x - 1;
				if (h < 0)
				x = 0;
				
				 
				v = MatchBitflag (x);

			} while ((team1shirt & v));
			team1shirt = (team1shirt + v);
			 return (h);

}

if ((t == TEAM_COLOR2))
{

if (!team2shirt)
{
x = (rint (random () * 10) + 5) ;
h = x + 1;
v = MatchBitflag (h);
team2shirt = v;
return x;
 }

do
			{

                            x = (rint (random () * 15) + 1);
				if (x == 4 || x == 5)
				{
				if (random () < 0.5)
				x = (rint (random () * 11) + 5);
				else
				x = (rint (random () * 2));
				}			
				
				h = x - 1;
				if (h < 0)
				h = 0;
				
				v = MatchBitflag (x);
				
			} while ((team2shirt & v));
                      team2shirt = (team2shirt + v);
			 return (h);

}


// Called when player goes observer or disconnects
void () ReleaseShirtColor =

{
if (!self.clientcolors) return; // we are observer already , colors 0 0
bprint ("gonna free up your shirtcolor : ");
bprint (ftos(self.shirt_color));
bprint ("\n");
self.shirt_color = self.shirt_color + 1;
local float v;
v = MatchBitflag (self.shirt_color);

bprint (" >> which is matchshirt bitmap : ");
bprint (ftos(v));
bprint ("\n");
if (self.team == 14)
{
team2shirt = (team2shirt - v);
bprint ("NEW TEAM2SHIRT : ");
bprint (ftos(team2shirt));
bprint ("\n");
}
if (self.team == 5)
{
team1shirt = (team1shirt - v);
bprint ("New TEAM1SHIRT : ");
bprint (ftos(team1shirt));
bprint ("\n");
}

};




};



LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Re: Team shirt colors

Post by LordHavoc »

r00k: DP_SV_SETCOLOR extension is your friend, allowing both intercepting of color changes by clients and rejection and replacement of those, as well as just outright setting someone's color at any time - and you don't need to re-send all those svc_updatecolor messages when someone joins mid-game.

DP_SV_CLIENTCOLORS is fun too.
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Team shirt colors

Post by r00k »

Thanks LH, i'll check those out...
Post Reply