r3780 - in trunk/data/qcsrc: client common server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Jul 6 18:12:00 EDT 2008


Author: blub0
Date: 2008-07-06 18:11:59 -0400 (Sun, 06 Jul 2008)
New Revision: 3780

Modified:
   trunk/data/qcsrc/client/Defs.qc
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/View.qc
   trunk/data/qcsrc/client/csqc_builtins.qc
   trunk/data/qcsrc/client/main.qh
   trunk/data/qcsrc/client/ons.qc
   trunk/data/qcsrc/client/sbar.qc
   trunk/data/qcsrc/common/constants.qh
   trunk/data/qcsrc/server/cl_client.qc
   trunk/data/qcsrc/server/clientcommands.qc
   trunk/data/qcsrc/server/ctf.qc
   trunk/data/qcsrc/server/defs.qh
   trunk/data/qcsrc/server/ent_cs.qc
   trunk/data/qcsrc/server/g_damage.qc
   trunk/data/qcsrc/server/g_world.qc
   trunk/data/qcsrc/server/teamplay.qc
Log:
Added the capture-counter and changed the CTF scoreboard to display the caps.
Gameplay changes:
cvar g_ctf_win_mode:
2 to play as usual, with just a fraglimit
1 use the teamfrags if the team-captures are equal
0 use overtime
cvar capturelimit - does it need explanation?
g_ctf_flagscore_kill - frags to get when killing the carrier (default 6)
g_ctf_flagpenalty_drop - frags to lose when dropping the flag (default 0)


Modified: trunk/data/qcsrc/client/Defs.qc
===================================================================
--- trunk/data/qcsrc/client/Defs.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/Defs.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -169,3 +169,4 @@
 .float enttype; // entity type sent from server
 .float sv_entnum; // entity number sent from server
 float vid_conwidth, vid_conheight;
+float caps_team1, caps_team2;

Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/Main.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -20,8 +20,6 @@
 
 void CSQC_Init(void)
 {
-	float i;
-
 	drawfont = 0;
 	menu_visible = FALSE;
 	menu_show = menu_show_error;
@@ -39,9 +37,23 @@
 
 	gps_start = world;
 
+	postinit = false;
+}
+
+void PostInit(void)
+{
+	float i;
+	entity pl;
+
+	print(strcat("PostInit\n    maxclients = ", ftos(maxclients), "\n"));
 	databuf = buf_create();
 	for(i = 0; i < maxclients; ++i)
+	{
 		bufstr_set(databuf, DATABUF_PING + i, "N/A");
+		bufstr_set(databuf, DATABUF_CAPTURES + i, "0");
+	}
+
+	postinit = true;
 }
 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
 void CSQC_Shutdown(void)
@@ -95,34 +107,44 @@
 
 // --------------------------------------------------------------------------
 // BEGIN OPTIONAL CSQC FUNCTIONS
-
-void ReadPings()
+void ReadONS()
 {
-	float plnum, ping;
-	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
-	{
-		ping = ReadShort();
-		bufstr_set(databuf, DATABUF_PING + plnum-1, ftos(ping));
-	}
-}
+	entity gps;
+	using_gps = true;
 
-void ReadONS(float bIsNewEntity)
-{
-	using_gps = true;
-			
 	self.origin_x = ReadCoord();
 	self.origin_y = ReadCoord();
 	self.angles_y = ReadCoord();
 	self.origin_z = self.angles_x = self.angles_z = 0;
 
-	if(bIsNewEntity)
+	for(gps = gps_start; gps; gps = gps.chain)
 	{
-		//print(strcat("Adding entity: ", ftos(self.sv_entnum), "\n"));
+		if(gps == self)
+			break;
+	}
+	if(!gps)
+	{
 		self.chain = gps_start;
 		gps_start = self;
 	}
 }
 
+void RemoveONS()
+{
+	if(gps_start == self)
+		gps_start = self.chain;
+	else
+	{
+		local entity ent;
+		ent = gps_start;
+			
+		while(ent.chain != self && ent.chain != world)
+			ent = ent.chain;
+		if(ent.chain == self)
+			ent.chain = self.chain;
+	}
+}
+
 // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
 // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
 void(float bIsNewEntity) CSQC_Ent_Update =
@@ -137,7 +159,8 @@
 		{
 			switch(msg)
 			{
-			case ENTCS_MSG_ONS: ReadONS(bIsNewEntity); break;
+			case ENTCS_MSG_ONS_GPS: ReadONS(); break;
+			case ENTCS_MSG_ONS_REMOVE: RemoveONS(); break;
 			default:
 				error("unknown ENTCS_MSG type\n");
 			}
@@ -250,6 +273,37 @@
 {
 	cprint(strMessage);
 }
+
+void ReadInit()
+{
+	maxclients = ReadByte();
+}
+
+void ReadPings()
+{
+	float plnum, ping;
+	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
+	{
+		ping = ReadShort();
+		bufstr_set(databuf, DATABUF_PING + plnum-1, ftos(ping));
+	}
+}
+
+void ReadCaptures()
+{
+	float plnum, caps;
+	entity pl;
+	caps_team1 = ReadByte();
+	caps_team2 = ReadByte();
+	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
+	{
+		caps = ReadByte();
+		//print(strcat("Cap update: ", ftos(plnum), " has ", ftos(caps), " caps\n"));
+		//print(strcat("Index: ", ftos(DATABUF_CAPTURES + plnum-1), " -- I AM: ", ftos(player_localentnum), "\n"));
+		bufstr_set(databuf, DATABUF_CAPTURES + plnum-1, ftos(caps));
+	}
+}
+
 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
@@ -263,18 +317,26 @@
 		
 	switch(nTEID)
 	{
+		case TE_CSQC_INIT:
+			ReadInit();
+			bHandled = true;
+			break;
 		case TE_CSQC_PING:
 			ReadPings();
 			bHandled = true;
 			break;
-		//case TE_GUNSHOT:
-		//	Do something cool with TE_GUNSHOT!
-		//	break;
+		case TE_CSQC_CAPTURES:
+			ReadCaptures();
+			bHandled = true;
+			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;
 			break;
 	}
+	
+	if(!postinit)
+		PostInit();
 		
 	return bHandled;
 }

Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/View.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -14,8 +14,12 @@
 
 void CSQC_kh_hud(void);
 void CSQC_ctf_hud(void);
+void PostInit(void);
 void CSQC_UpdateView(void)
 {
+	if(!postinit)
+		PostInit();
+	
 	sbar_alpha_fg = cvar("sbar_alpha_fg" );
 	sbar_hudselector = cvar("sbar_hudselector");
 	activeweapon = getstati(STAT_ACTIVEWEAPON);

Modified: trunk/data/qcsrc/client/csqc_builtins.qc
===================================================================
--- trunk/data/qcsrc/client/csqc_builtins.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/csqc_builtins.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -257,3 +257,4 @@
 float(string str, string sub, float startoffs)		strstrofs = #221;
 //float(string str, string sub) 	    		strstrofs = #221;
 entity(float num)   	   				edict_num = #459;
+float(entity ent)					num_for_edict = #512;

Modified: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/main.qh	2008-07-06 22:11:59 UTC (rev 3780)
@@ -2,7 +2,8 @@
 // MENU Functionality
 
 #define DATABUF_PING 0
-#define DATABUF_SAMPLE (1*maxclients)
+#define DATABUF_CAPTURES (1*maxclients)
+#define DATABUF_NEXT (2*maxclients)
 
 void() menu_show_error;
 void() menu_sub_null;
@@ -32,7 +33,7 @@
 // General stuff
 
 float drawfont;
-
+float postinit;
 float gametype;
 entity gps_start;
 

Modified: trunk/data/qcsrc/client/ons.qc
===================================================================
--- trunk/data/qcsrc/client/ons.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/ons.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -39,20 +39,13 @@
 		local float color;
 		local vector coord, rgb;
 
-		color = stof(getplayerkey(player_localentnum-1, "colors")) & 15;
+		color = GetPlayerColor(player_localentnum-1);
+		rgb = GetTeamRGB(color);
 
 		coord = mapcoords(pmove_org);
 			
 		drawpic('272 50', minimapname, '256 256', '1 1 1', 1, 0);
 		drawpic('257 35', "gfx/ons-frame.tga", '286 286', '1 1 1', 1, 0);
-		if(color == COLOR_TEAM_RED)
-		{
-			rgb = '1 0 0';
-		} else if(color == COLOR_TEAM_BLUE) {
-			rgb = '0 0 1';
-		} else {
-			rgb = '1 1 1';
-		}
 		drawpic('257 35', "gfx/ons-frame-team.tga", '286 286', rgb, 1, 0);
 
 		drawplayer(coord, input_angles, '1 1 1');

Modified: trunk/data/qcsrc/client/sbar.qc
===================================================================
--- trunk/data/qcsrc/client/sbar.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/client/sbar.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -9,6 +9,7 @@
 .float sb_frags;
 .float sb_team;
 .float sb_player;
+.float sb_caps;
 
 void Sbar_FinaleOverlay()
 {
@@ -115,10 +116,17 @@
 {
 	if(teamplay)
 	{
-		if(l.sb_team < r.sb_team)
+		if(l.sb_team > r.sb_team)
 			return true;
 		else if(l.sb_team > r.sb_team)
 			return false;
+		if(gametype == GAME_CTF)
+		{
+			if(l.sb_caps > r.sb_caps)
+				return true;
+			else if(l.sb_caps < r.sb_caps)
+				return false;
+		}
 	}
 	if(l.sb_frags > r.sb_frags)
 		return true;
@@ -128,6 +136,13 @@
 }
 float Sbar_TeamCmp(entity l, entity r)
 {
+	if(gametype == GAME_CTF)
+	{
+		if(l.sb_caps > r.sb_caps)
+			return true;
+		else if(l.sb_caps < r.sb_caps)
+			return false;
+	}
 	if(l.sb_frags > r.sb_frags)
 		return true;
 	else if(l.sb_frags < r.sb_frags)
@@ -163,6 +178,8 @@
 
 		t1.sb_player = t2.sb_player = t3.sb_player = t4.sb_player = ts.sb_player = 0;
 		t1.sb_frags = t2.sb_frags = t3.sb_frags = t4.sb_frags = 0;
+		t1.sb_caps = caps_team1;
+		t2.sb_caps = caps_team2;
 		sortedTeams = Sort_New(Sbar_TeamCmp);
 		
 		for(i = 0; i < maxclients; ++i)
@@ -173,6 +190,8 @@
 			tmp = spawn();
 			tmp.sb_player = i;
 			tmp.sb_frags = stof(getplayerkey(i, "frags"));
+			tmp.sb_caps = stof(bufstr_get(databuf, DATABUF_CAPTURES + tmp.sb_player));
+			
 			if(tmp.sb_frags == -666)
 				tmp.sb_team = COLOR_SPECTATOR;
 			else
@@ -220,11 +239,12 @@
 		}
 	}
 }
-
+float xmin, xmax, ymin, ymax;
 void Sbar_PrintScoreboardItem(vector pos, entity pl, float is_self, float mask)
 {
 	vector tmp;
 	string str;
+	entity player;
 	
 	tmp_y = tmp_z = 0;
 	pos_x += 56;
@@ -233,8 +253,15 @@
 	tmp_x = 4*8 - strlen(str) * 8 - 56;
 	drawstring(pos + tmp, str, '8 8 0', '0.8 0.8 0.8', 0.8, 0);
 
-	if(!(mask & 1))
+	if(!(mask & 1)) // not a spectator:
 	{
+		if(gametype == GAME_CTF)
+		{
+			str = bufstr_get(databuf, DATABUF_CAPTURES + pl.sb_player);
+			tmp_x = xmax - strlen(str)*8 - pos_x;
+			drawstring(pos + tmp, str, '8 8 0', '1 1 1', 1, 0);
+		}
+	
 		str = ftos(pl.sb_frags);
 		tmp_x = 4*8 - strlen(str) * 8;
 		drawstring(pos + tmp, str, '8 8 0', '1 1 1', 1, 0);
@@ -266,10 +293,11 @@
 void Sbar_DrawScoreboard()
 {
 	// Assume: frags are already sorted
-	float xmin, xmax, ymin, ymax, plcount;
+	//float xmin, xmax, ymin, ymax, plcount;
+	float plcount;
 	vector pos, teammin, teammax, rgb;
 	entity pl, tm;
-	float specs;
+	float specs, minoffset;
 	specs = false;
 
 	xmin = vid_conwidth / 4;
@@ -282,7 +310,7 @@
 
 	teammin = teammax = '0 0 0';
 	teammin_x = xmin - 2;
-	teammax_x = xmax - 2;
+	teammax_x = xmax + 2;
 
 	pos_x = 0.5 * (xmin + xmax) - (24*5);
 	drawfont = FONT_USER+0;
@@ -294,29 +322,39 @@
 	drawstring(pos, "ping", '8 8 0', '1 1 1', 1, 0);
 	drawstring(pos + '48 0 0', "frags", '8 8 0', '1 1 1', 1, 0);
 	drawstring(pos + '104 0 0', "name", '8 8 0', '1 1 1', 1, 0);
+	if(gametype == GAME_CTF)
+	{
+		pos_x = xmax - 4*8;
+		drawstring(pos, "caps", '8 8 0', '1 1 1', 1, 0);
+		pos_x = xmin;
+	}
+	
 	pos_y += 16;
 	
 	if(teamplay)
 	{
-		/*teampos_z = 0;
-		teampos_y = pos_y - 40;
-		teampos_x = (vid_conwidth * 0.5) - (numteams*6*12);*/
 		for(tm = sortedTeams.sort_next; tm; tm = tm.sort_next)
 		{
+			minoffset = pos_y + 24;
 			if(!tm.sb_player || tm.sb_team == COLOR_SPECTATOR) // no players in it?
 				continue;
 
-			//Sbar_DrawXNum(teampos-sbar, tm.sb_frags, -4, 24, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
-			//teampos_x += 6*24;
-			Sbar_DrawXNum(pos-'106 0 0'-sbar, tm.sb_frags, 4, 24, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
+			rgb = GetTeamRGB(tm.sb_team);
+			if(gametype == GAME_CTF)
+			{
+				minoffset = pos_y + 24 + 12;
+				if(tm.sb_team == COLOR_TEAM1)
+					Sbar_DrawXNum(pos-'106 0 0'-sbar, caps_team1, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
+				else if(tm.sb_team == COLOR_TEAM2)
+					Sbar_DrawXNum(pos-'106 0 0'-sbar, caps_team2, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
+				Sbar_DrawXNum(pos-'44 -24 0'-sbar, tm.sb_frags, 4, 10, rgb, 1, DRAWFLAG_NORMAL);
+			} else
+				Sbar_DrawXNum(pos-'106 0 0'-sbar, tm.sb_frags, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
 
 			teammin_y = pos_y - 2;
 			teammax_y = pos_y + 2 + 10 * (tm.sb_player);
-			rgb = GetTeamRGB(tm.sb_team);
 			drawfill(teammin, teammax - teammin, rgb, 0.2, DRAWFLAG_NORMAL);
-			/*Sbar_PrintScoreboardTeamItem(pos, tm, rgb, GetTeamName(tm.sb_team));
-			pos_y += 12;*/
-			//for(i = 0; i < maxclients; ++i)
+			
 			plcount = 0;
 			for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
 			{
@@ -326,9 +364,10 @@
 				pos_y += 10;
 				++plcount;
 			}
+
 			pos_y += 12;
-			if(plcount < 2)
-				pos_y += 12;
+			if(pos_y < minoffset)
+				pos_y = minoffset;
 		}
 
 		// rgb := tempvector :)

Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/common/constants.qh	2008-07-06 22:11:59 UTC (rev 3780)
@@ -147,16 +147,20 @@
 const float K_MOUSE16		=	529;
 
 const float ENTCS_MSG_END = 0;
-const float ENTCS_MSG_ONS = 1;
+const float ENTCS_MSG_ONS_GPS = 1;
+const float ENTCS_MSG_ONS_REMOVE = 2;
 
 const float TE_CSQC_START = 100;
-const float TE_CSQC_PING = 100;
+const float TE_CSQC_INIT = 100;
+const float TE_CSQC_PING = 101;
+const float TE_CSQC_CAPTURES = 102;
 
-const float TE_CSQC_END = 100;
+const float TE_CSQC_END = 101;
 
 const float STAT_KH_KEYS = 32;
+const float STAT_CTF_CAPTURES = 33;
 
-const float STAT_CTF_STATE = 33;
+const float STAT_CTF_STATE = 34;
 const float CTF_STATE_ATTACK = 1;
 const float CTF_STATE_DEFEND = 2;
 const float CTF_STATE_COMMANDER = 3;

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/cl_client.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -348,6 +348,7 @@
 putting a client as observer in the server
 =============
 */
+void ctf_UpdateCaptures();
 void PutObserverInServer (void)
 {
 	entity	spot;
@@ -372,6 +373,11 @@
 	WaypointSprite_PlayerDead();
 
 	DistributeFragsAmongTeam(self, self.team, 1);
+	if(g_ctf)
+	{
+		self.captures = 0;
+		ctf_UpdateCaptures();
+	}
 
 	if(self.frags <= 0 && self.frags > -666 && g_lms && self.killcount != -666)
 		bprint ("^4", self.netname, "^4 has no more lives left\n");
@@ -699,6 +705,23 @@
 
 /*
 =============
+SendCSQCInfo
+
+Send whatever CSQC needs NOW and cannot wait for SendServerInfo to happen...
+=============
+*/
+void SendCSQCInfo(void)
+{
+	if(clienttype(self) != CLIENTTYPE_REAL)
+		return;
+	msg_entity = self;
+	WriteByte(MSG_ONE, SVC_TEMPENTITY);
+	WriteByte(MSG_ONE, TE_CSQC_INIT);
+	WriteByte(MSG_ONE, maxclients-1);
+}
+
+/*
+=============
 SetNewParms
 =============
 */
@@ -745,6 +768,11 @@
 
 void ClientKill_Now_TeamChange()
 {
+	if(g_ctf)
+	{
+		self.captures = 0;
+		ctf_UpdateCaptures();
+	}
 	if(self.killindicator_teamchange == -1)
 	{
 		self.team = -1;
@@ -941,6 +969,7 @@
 //void ctf_clientconnect();
 string ColoredTeamName(float t);
 void DecodeLevelParms (void);
+void ctf_SendCaptures(entity);
 //void dom_player_join_team(entity pl);
 void ClientConnect (void)
 {
@@ -1094,6 +1123,9 @@
 
 	self.jointime = time;
 	self.allowedTimeouts = cvar("sv_timeout_number");
+
+	SendCSQCInfo();
+	ctf_SendCaptures(self);
 }
 
 /*
@@ -1146,6 +1178,11 @@
 		DropFlag(self.flagcarried);
 
 	DistributeFragsAmongTeam(self, self.team, 1);
+	if(g_ctf)
+	{
+		self.captures = 0;
+		ctf_UpdateCaptures();
+	}
 
 	save = self.flags;
 	self.flags = self.flags - (self.flags & FL_CLIENT);

Modified: trunk/data/qcsrc/server/clientcommands.qc
===================================================================
--- trunk/data/qcsrc/server/clientcommands.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/clientcommands.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -214,6 +214,8 @@
 			kh_Key_DropAll(self, TRUE);
 			WaypointSprite_PlayerDead();
 			DistributeFragsAmongTeam(self, self.team, 1.0);
+			self.captures = 0;
+			ctf_UpdateCaptures();
 			self.classname = "observer";
 			if(blockSpectators)
 				sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
@@ -226,6 +228,8 @@
 			if(isJoinAllowed()) {
 				self.classname = "player";
 				self.frags = 0;
+				self.captures = 0;
+				ctf_UpdateCaptures();
 				bprint ("^4", self.netname, "^4 is playing now\n");
 				PutClientInServer();
 			}

Modified: trunk/data/qcsrc/server/ctf.qc
===================================================================
--- trunk/data/qcsrc/server/ctf.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/ctf.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -4,7 +4,6 @@
 
 .float next_take_time;			// the next time a player can pick up a flag (time + blah)
 								/// I used this, in part, to fix the looping score bug. - avirox
-
 //float FLAGSCORE_PICKUP        =  1;
 //float FLAGSCORE_RETURN        =  5; // returned by owner team
 //float FLAGSCORE_RETURNROGUE   = 10; // returned by rogue team
@@ -130,6 +129,12 @@
 		return;
 	}
 	bprint(p.netname, "^7 lost the ", e.netname, "\n");
+
+	if(cvar("g_ctf_flagpenalty_drop"))
+		UpdateFrags(p, -cvar("g_ctf_flagpenalty_drop"));
+	
+	//if(e.enemy && e.enemy != e)
+	//UpdateFrags(e.enemy, cvar("g_ctf_flagscore_kill"));
 	WaypointSprite_DetachCarrier(p);
 	LogCTF("dropped", p.team, p.flagcarried);
 
@@ -225,6 +230,39 @@
 	}
 };
 
+void ctf_SendCaptures(entity player)
+{
+	entity p;
+	if(clienttype(player) != CLIENTTYPE_REAL)
+		return;
+	msg_entity = player;
+	WriteByte(MSG_ONE, SVC_TEMPENTITY);
+	WriteByte(MSG_ONE, TE_CSQC_CAPTURES);
+	WriteByte(MSG_ONE, caps_team1);
+	WriteByte(MSG_ONE, caps_team2);
+	FOR_EACH_CLIENT(p)
+	{
+		WriteByte(MSG_ONE, num_for_edict(p));
+		WriteByte(MSG_ONE, p.captures);
+	}
+	WriteByte(MSG_ONE, 0);
+}
+
+void ctf_UpdateCaptures()
+{
+	entity p;
+	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+	WriteByte(MSG_BROADCAST, TE_CSQC_CAPTURES);
+	WriteByte(MSG_BROADCAST, caps_team1);
+	WriteByte(MSG_BROADCAST, caps_team2);
+	FOR_EACH_REALCLIENT(p)
+	{
+		WriteByte(MSG_BROADCAST, num_for_edict(p));
+		WriteByte(MSG_BROADCAST, p.captures);
+	}
+	WriteByte(MSG_BROADCAST, 0);
+}
+
 void FlagTouch()
 {
 	if(gameover) return;
@@ -278,6 +316,16 @@
 			bprint(other.netname, "^7 captured the ", other.flagcarried.netname, " in ", s, ", failing to break ", strcat(h0, " record of ", s0, " seconds\n"));
 		}
 
+		other.captures++;
+		if(other.team == COLOR_TEAM1)
+			caps_team1++;
+		else if(other.team == COLOR_TEAM2)
+			caps_team2++;
+		else
+			print("Unknown team captured the flag!\n");
+		ctf_UpdateCaptures();
+		// FIXME: When counting captures, should the score be updated?
+
 		LogCTF("capture", other.flagcarried.team, other);
 		// give credit to the individual player
 		UpdateFrags(other, cvar("g_ctf_flagscore_capture"));
@@ -665,6 +713,13 @@
 {
 	local entity e;
 
+	caps_team1 = caps_team2 = 0;
+	registercvar("capturelimit", "8");
+	registercvar("g_ctf_win_mode", "0");
+	//registercvar("g_overtime", "1");
+	registercvar("g_ctf_flagscore_kill", "6");
+	registercvar("g_ctf_flagpenalty_drop", "0");
+	//addstat(STAT_CTF_CAPTURES, AS_INT, captures);
 	//addstat(STAT_CTF_STATE, AS_FLOAT_TRUNCATED, ctf_state);
 	e = spawn();
 	e.think = ctf_delayedinit;

Modified: trunk/data/qcsrc/server/defs.qh
===================================================================
--- trunk/data/qcsrc/server/defs.qh	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/defs.qh	2008-07-06 22:11:59 UTC (rev 3780)
@@ -436,3 +436,6 @@
 float sv_maxidle_spectatorsareidle;
 
 float next_pingtime;
+
+.float captures;
+float caps_team1, caps_team2;

Modified: trunk/data/qcsrc/server/ent_cs.qc
===================================================================
--- trunk/data/qcsrc/server/ent_cs.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/ent_cs.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -37,11 +37,13 @@
 
 void entcs_ons(entity to)
 {
-	if(to == self.owner || self.team != to.team)
+	if(to == self.owner || self.team != to.team ||
+	   self.owner.classname == "observer" || to.classname == "observer")
+	{
+		WriteByte(MSG_ENTITY, ENTCS_MSG_ONS_REMOVE);
 		return;
-	if(self.owner.classname == "observer" || to.classname == "observer")
-		return;
-	WriteByte(MSG_ENTITY, ENTCS_MSG_ONS);
+	}
+	WriteByte(MSG_ENTITY, ENTCS_MSG_ONS_GPS);
 	WriteCoord(MSG_ENTITY, self.owner.origin_x);
 	WriteCoord(MSG_ENTITY, self.owner.origin_y);
 	WriteCoord(MSG_ENTITY, self.owner.angles_y);
@@ -76,7 +78,7 @@
 		entcs_common_self();
 	}
 	
-	if(game == GAME_ONSLAUGHT)
+	if(g_onslaught)
 		entcs_ons(to);
 	
 	WriteByte(MSG_ENTITY, ENTCS_MSG_END);
@@ -94,7 +96,7 @@
 		self.nextthink = time + 10; // update pings every 10 seconds
 };
 
-void attach_entcs()
+entity attach_entcs()
 {
 	local float num;
 	local entity ent;
@@ -116,6 +118,7 @@
 	setsize(ent, '0 0 0', '0 0 0');
 		
 	ent.SendEntity = entcs_send;
+	return ent;
 };
 
 void detach_entcs()

Modified: trunk/data/qcsrc/server/g_damage.qc
===================================================================
--- trunk/data/qcsrc/server/g_damage.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/g_damage.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -318,8 +318,10 @@
 					else
 						bprint ("^1",s, "^1 was fragged by ", a, "\n");
 				}
-
-				GiveFrags(attacker, targ, 1);
+				if(g_ctf && targ.flagcarried)
+					GiveFrags(attacker, targ, cvar("g_ctf_flagscore_kill"));
+				else
+					GiveFrags(attacker, targ, 1);
 				if (targ.killcount > 2) {
 					if(sv_gentle)
 						bprint ("^1",s,"'s ^1", ftos(targ.killcount), " scoring spree was ended by ", a, "\n");

Modified: trunk/data/qcsrc/server/g_world.qc
===================================================================
--- trunk/data/qcsrc/server/g_world.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/g_world.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -1484,7 +1484,7 @@
 			AddWinners(team, COLOR_TEAM4);
 	}
 
-	if(!g_runematch && !g_domination)
+	if(!g_runematch && !g_domination && !g_ctf)
 		if(tdm_max_score != tdm_old_score)
 		{
 			if(tdm_max_score == fraglimit - 1)
@@ -1558,6 +1558,23 @@
 	return WinningConditionBase_Teamplay(fraglimit);
 }
 
+float WinningCondition_CTF(float capturelimit, float fraglimit)
+{
+	if(cvar("g_ctf_win_mode") == 2)
+		return WinningCondition_MaxTeamSum(fraglimit);
+	
+	team1_score = caps_team1;
+	team2_score = caps_team2;
+	team3_score = team4_score = 0;
+
+	if(team1_score == team2_score && cvar("g_ctf_win_mode"))
+	{
+		return WinningCondition_MaxTeamSum(0);
+	}
+
+	return WinningConditionBase_Teamplay(capturelimit);
+}
+
 void print_to(entity e, string s)
 {
 	if(e)
@@ -1758,6 +1775,7 @@
 	local float status;
 	local float timelimit;
 	local float fraglimit;
+	local float capturelimit;
 
 	VoteThink();
 	MapVote_Think();
@@ -1786,6 +1804,7 @@
 
 	timelimit = cvar("timelimit") * 60;
 	fraglimit = cvar("fraglimit");
+	capturelimit = cvar("capturelimit");
 
 	if(checkrules_overtimeend)
 	{
@@ -1831,6 +1850,10 @@
 	{
 		status = WinningCondition_Onslaught();
 	}
+	else if(g_ctf)
+	{
+		status = WinningCondition_CTF(capturelimit, fraglimit);
+	}
 	else
 	{
 		if(teams_matter)

Modified: trunk/data/qcsrc/server/teamplay.qc
===================================================================
--- trunk/data/qcsrc/server/teamplay.qc	2008-07-06 12:17:47 UTC (rev 3779)
+++ trunk/data/qcsrc/server/teamplay.qc	2008-07-06 22:11:59 UTC (rev 3780)
@@ -25,6 +25,10 @@
 
 void TeamchangeFrags(entity e)
 {
+	if(g_ctf)
+	{
+		e.captures = 0;
+	}
 	if(e.classname == "player")
 	{
 		// reduce frags during a team change




More information about the nexuiz-commits mailing list