r3761 - in trunk/data: gfx maps qcsrc/client qcsrc/common qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Jul 2 15:06:22 EDT 2008


Author: blub0
Date: 2008-07-02 15:06:22 -0400 (Wed, 02 Jul 2008)
New Revision: 3761

Added:
   trunk/data/gfx/ons-frame-team.tga
   trunk/data/gfx/ons-frame.tga
   trunk/data/gfx/ons-reborn_mini.tga
   trunk/data/maps/ons-reborn.info
   trunk/data/qcsrc/client/ctf.qc
   trunk/data/qcsrc/client/main.qh
   trunk/data/qcsrc/client/ons.qc
   trunk/data/qcsrc/server/ent_cs.qc
Modified:
   trunk/data/qcsrc/client/Defs.qc
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/View.qc
   trunk/data/qcsrc/client/progs.src
   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/extensions.qh
   trunk/data/qcsrc/server/progs.src
   trunk/data/qcsrc/server/teamplay.qc
Log:
Committed my CSQC stuff, let's see:
ent_cs.qc contains "info-entities" which are attached to players.
   This is because using .SendEntity directly on players will force csqc
   to also handle client prediction, which is evil.
And then there's ONS Minimap code, and the images for ons-reborn



Added: trunk/data/gfx/ons-frame-team.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/ons-frame-team.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/gfx/ons-frame.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/ons-frame.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/gfx/ons-reborn_mini.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/ons-reborn_mini.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/maps/ons-reborn.info
===================================================================
--- trunk/data/maps/ons-reborn.info	                        (rev 0)
+++ trunk/data/maps/ons-reborn.info	2008-07-02 19:06:22 UTC (rev 3761)
@@ -0,0 +1,8 @@
+// This file is necessary if world.mins/maxs is wrong.
+// It happens when q3map2 fucks up, or you put entities far outside the map,
+// like ons-reborn the trains.
+// Every unrecognized line in this file will be printed to the console
+// unless it begins with double slashes
+// This is a sample file =)
+mins -8224.0 -8224.0 -96.0
+maxs 8224.0 8224.0 6496.0

Modified: trunk/data/qcsrc/client/Defs.qc
===================================================================
--- trunk/data/qcsrc/client/Defs.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/client/Defs.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -168,4 +168,4 @@
 // Basic variables
 .float enttype; // entity type sent from server
 .float sv_entnum; // entity number sent from server
-float vid_conwidth, vid_conheight;
\ No newline at end of file
+float vid_conwidth, vid_conheight;

Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/client/Main.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -1,22 +1,45 @@
 // --------------------------------------------------------------------------
 // BEGIN REQUIRED CSQC FUNCTIONS
+//include "main.qh"
 
+
+void() menu_show_error =
+{
+	drawstring('0 200', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0);
+};
+
 // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
 // Useful for precaching things
+
+void() menu_sub_null =
+{
+};
+
 void CSQC_Init(void)
-{
+{	
+	menu_visible = FALSE;
+	menu_show = menu_show_error;
+	menu_action = menu_sub_null;
+	//ctf_temp_1 = "";
+	localcmd("alias order \"cmd order $*\"");
+	//registercmd("ctf_menu");
+	registercmd("ons_map");
+	//registercmd("menu_action");
+
+	gametype = 0;
+
+	gps_start = world;
 }
 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
 void CSQC_Shutdown(void)
 {
 }
+
 // CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function
 // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
 float CSQC_ConsoleCommand(string strMessage)
 {
 	local float nReturn;
-	local string s;
-	local vector v;
 		nReturn = FALSE;
 		
 	// Tokenize String
@@ -24,15 +47,17 @@
 	
 	// Acquire Command
 	local string strCmd;
-		strCmd = argv(0);
+	strCmd = argv(0);
 
-	/*
-	if (strCmd == "+forward")
-	{
-		// blah
+	/*if(strCmd == "ctf_menu") {
+		ctf_menu_show();
 		nReturn = TRUE;
+		} else*/
+	if(strCmd == "ons_map") {
+		Cmd_ons_map();
+		nReturn = TRUE;
 	}
-	*/
+	
 	return nReturn;
 }
 // CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
@@ -44,7 +69,10 @@
 float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
 {
 	local float bSkipKey;
-		bSkipKey = false;
+	bSkipKey = false;
+	if(menu_visible)
+		if(menu_action(bInputType, nPrimary, nSecondary))
+			return TRUE;
 	return bSkipKey;
 }
 
@@ -59,8 +87,8 @@
 void(float bIsNewEntity) CSQC_Ent_Update =
 {
 	self.enttype = ReadByte();
-	/*
-	if (self.enttype == ENT_CLIENT)
+
+	/*if (self.enttype == ENT_CLIENT)
 	{
 		setmodelindex(self, ReadShort());
 		self.origin_x = ReadCoord();
@@ -69,29 +97,131 @@
 		self.angles_x = ReadCoord();
 		self.angles_y = ReadCoord();
 		self.angles_z = ReadCoord();
-		self.sv_entnum = ReadShort();
+		self.velocity_x = ReadCoord();
+		self.velocity_y = ReadCoord();
+		self.velocity_z = ReadCoord();
+		pmove_org = self.origin;
+		pmove_vel = self.velocity;
+		self.avelocity_x = ReadCoord();
+		self.avelocity_y = ReadCoord();
+		self.avelocity_z = ReadCoord();
+		self.movetype = ReadShort();
+		self.frame = ReadShort();
+		self.flags = ReadShort();
+		self.colormap = ReadShort();
 		setorigin(self, self.origin); // relink
 		if (bIsNewEntity)
 		{
 			setsize(self, '0 0 0', '0 0 0');
 			self.drawmask = MASK_NORMAL;
-			self.think = Client_Think;
-			self.nextthink = time;
+			//self.think = Client_Think;
+			//self.nextthink = time;
 		}
+		self.ctf_state = ReadByte();
+		}*/
+	if(self.enttype == ENT_CLIENT_ENTCS)
+	{
+		self.sv_entnum = ReadByte();
+		self.origin_x = ReadCoord();
+		self.origin_y = ReadCoord();
+		self.angles_y = ReadCoord();
+		self.origin_z = self.angles_x = self.angles_z = 0;
+
+		if(bIsNewEntity)
+		{
+			//print(strcat("Adding entity: ", ftos(self.sv_entnum), "\n"));
+			self.chain = gps_start;
+			gps_start = self;
+		}
 	}
 	else
 		error("unknown entity type in CSQC_Ent_Update\n");
-	*/
+	
 };
 // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed.  Essentially call remove(self) as well.
 void CSQC_Ent_Remove()
 {
+	if(self.enttype == ENT_CLIENT_ENTCS)
+	{
+		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;
+		}
+	}
 	remove(self);
 }
+
+void Gamemode_Init()
+{
+	local string mapinfo, infoline;
+	local float len;
+	local float file;
+	local vector mi_min, mi_max;
+	
+	gametype = cvar("gametype");
+	if(gametype == GAME_ONSLAUGHT) {
+		if(!strcasecmp(substring(mapname, 0, 5), "maps/"))
+			minimapname = substring(mapname, 5, 999);
+		else
+			minimapname = mapname;
+		len = strlen(minimapname);
+		if(!strcasecmp(substring(minimapname, len-4, 4), ".bsp"))
+			minimapname = substring(minimapname, 0, len-4);
+		
+		mapinfo = strcat("maps/", minimapname, ".info");
+		minimapname = strzone(strcat("gfx/", minimapname, "_mini.tga"));
+
+		mi_min = world.mins;
+		mi_max = world.maxs;
+		
+		file = fopen(mapinfo, FILE_READ);
+		if(file >= 0) {
+			while((infoline = fgets(file))) {
+				if(!strncasecmp(infoline, "mins", 4)) {
+					mi_min = stov(substring(infoline, 5, 999));
+				} else if(!strncasecmp(infoline, "maxs", 4)) {
+					mi_max = stov(substring(infoline, 5, 999));
+				} else if(strncasecmp(infoline, "//", 2)) { // don't print comment-style lines
+					print(strcat("mapinfo: ", infoline, "\n"));
+				}
+			}
+		} else {
+			print(strcat("^1Error: ^7Mapinfo file '", mapinfo, "' missing! Minimap will be screwed.\n"));
+		}
+		fclose(file);
+
+		print(strcat("Mins: ", vtos(mi_min), "    Maxs: ", vtos(mi_max), "\n"));
+		
+		mi_center = (mi_min + mi_max) * 0.5;
+		mi_scale = mi_max - mi_min;
+		
+		
+		print(strcat("Using ", minimapname, " as minimap.\n"));
+		precache_pic(minimapname);
+		precache_pic("gfx/ons-cp-neutral.tga");
+		precache_pic("gfx/ons-cp-red.tga");
+		precache_pic("gfx/ons-cp-blue.tga");
+		precache_pic("gfx/ons-frame.tga");
+		precache_pic("gfx/ons-frame-team.tga");
+	}
+}
 // CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided.  To execute standard behavior, simply execute localcmd with the string.
 void CSQC_Parse_StuffCmd(string strMessage)
-{	
+{
 	localcmd(strMessage);
+	// watch for gametype changes!
+	if(gametype != cvar("gametype"))
+	{
+		Gamemode_Init();
+	}
 }
 // CSQC_Parse_Print : Provides the print string in the first parameter that the server provided.  To execute standard behavior, simply execute print with the string.
 void CSQC_Parse_Print(string strMessage)
@@ -126,4 +256,4 @@
 	}
 		
 	return bHandled;
-}
\ No newline at end of file
+}

Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/client/View.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -1,4 +1,5 @@
-// CSQC_UpdateView - Called every rendered frame on the client.  Useful for HUD drawing operations.
+//include "main.qh"
+
 void CSQC_UpdateView(void)
 {
 	// ALWAYS Clear Current Scene First
@@ -24,19 +25,47 @@
 	*/
 
 	// Update the camera
-	/*
-	UpdateCamera();
+	//UpdateCamera();
+	/*self.origin_z += getstati(STAT_VIEWHEIGHT);
 	R_SetView(VF_ORIGIN, self.origin);
-	R_SetView(VF_ANGLES, self.angles);
-	*/
-
+	self.origin_z -= getstati(STAT_VIEWHEIGHT);
+	R_SetView(VF_ANGLES, input_angles);*/
+	
 	// Setup Entities to be Rendered (include all base types; normal, engine and viewmodels)
 	R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
+
+	/* Sample for 3D polygon rendering, do it before R_RenderScene!
+	   R_BeginPolygon("gfx/ctf_ic_atk.tga", 0);
+	   R_PolygonVertex('-5000 -5000 5200', '0 0', '1 1 1', 1);
+	   R_PolygonVertex(' 5000 -5000 5200', '1 0', '1 1 1', 1);
+	   R_PolygonVertex(' 5000  5000 -5200', '1 1', '1 1 1', 1);
+	   R_PolygonVertex('-5000  5000 -5200', '0 1', '1 1 1', 1);
+	   R_EndPolygon();
+	*/
 	
 	// Render the Scene
 	R_RenderScene();
 
 	// Draw the mouse cursor
 	// NOTE: drawpic must happen after R_RenderScene for some reason
-	//drawpic(mousepos, "gfx/cursor.tga", '11 14 0', '1 1 1', 1, 0);
-}
\ No newline at end of file
+	//drawpic(getmousepos(), "gfx/cursor.tga", '11 14 0', '1 1 1', 1, 0);
+	//drawstring('50 50', ftos(game), '10 10 0', '1 1 1', 1, 0);
+	//self = edict_num(player_localnum);
+	//drawstring('0 0', vtos(pmove_org), '8 8 0', '1 1 1', 1, 0);
+	//drawstring('0 8', strcat("ORG: ", vtos(self.origin), " state: ", ftos(self.ctf_state), " HP: ", ftos(self.health)), '8 8 0', '1 1 1', 1, 0);
+	// as long as the ctf part isn't in, this is useless
+	if(menu_visible)
+		menu_show();
+	
+	/*if(gametype == GAME_CTF)
+	{
+		ctf_view();
+	} else */
+	if(gametype == GAME_ONSLAUGHT)
+	{
+		//drawstring('0 0', minimapname, '8 8 0', '1 1 1', 1, 0);
+		drawsetcliparea(0,0,800,600);
+		ons_view();
+		drawresetcliparea();
+	}
+}

Added: trunk/data/qcsrc/client/ctf.qc
===================================================================
--- trunk/data/qcsrc/client/ctf.qc	                        (rev 0)
+++ trunk/data/qcsrc/client/ctf.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -0,0 +1,222 @@
+//include "main.qh"
+// NOTE: This file contains lots of debugging stuff
+// it is not really used... can be seen as another sample...
+
+string STR_PLAYER = "player";
+#define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; )
+
+string ctf_temp_1;
+float order_page;
+
+void() menu_close =
+{
+	menu_visible = false;
+	menu_show = menu_show_error;
+	menu_action = menu_sub_null;
+	
+	/*if(ctf_temp_1)
+	  strunzone(ctf_temp_1);*/
+	
+	localcmd("\nin_bindmap 0 0;");
+};
+
+void() order_menu_render =
+{
+	local vector ps, po;
+	local float i, p, n;
+	local string frags, color;
+	ps = '0 200';
+	po = '0 8';
+
+	color = getplayerkey(player_localentnum-1, "topcolor");
+	
+	if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) {
+		drawstring(ps, "\x1D\x1E\x1E\x1E\x1E Order Menu \x1E\x1E\x1E\x1E\x1F", '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawstring(ps, strcat("Order: ", ctf_temp_1), '8 8 0', '1 1 0', 1, 0); ps += po;
+		//drawstring(ps, strcat("N1 = ", ftos(player_localnum), " - N2 = ", ftos(player_localentnum)), '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawcolorcodedstring(ps, "1) ^3previous page", '8 8 0', 1, 0); ps += po;
+		drawcolorcodedstring(ps, "2) ^3next page", '8 8 0', 1, 0); ps += po;
+		//drawcolorcodedstring(ps, strcat("Clients to go: ", ftos(maxclients)), '8 8 0', 1, 0); ps += po;
+		for((n = 2), (p = i = 0); i < maxclients && n > 0; ++i) {
+			frags = getplayerkey(i, "frags");
+			/*print(strcat(ftos(i), "/", ftos(p), "/", ftos(n), "/", getplayerkey(i, "viewentity"), "\n"));
+			print(strcat(" - name: ", getplayerkey(i, "name"), " - frags: ", frags, "\n"));
+			print(strcat(" - color: ", getplayerkey(i, "topcolor"), " - ", color, "\n"));*/
+			if(!frags || (i+1) == player_localentnum)
+				continue;
+			if(frags == "-666" || getplayerkey(i, "topcolor") != color)
+				continue;
+			++p;
+			if(p > (8*order_page))
+			{
+				// only render current page
+				++n;
+				if(n == 10)
+					n = 0;
+				drawcolorcodedstring(ps, strcat(ftos(n), ") ", getplayerkey(i, "name"), " : ", ftos(getstatf(STAT_CTF_STATE))), '8 8 0', 1, 0); ps += po;
+			}
+		}
+		//drawstring(ps, strcat("LocalEntNum = ", ftos(player_localnum)), '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawstring(ps, "ESC) Exit Menu", '8 8 0', '1 1 0', 1, 0); ps += po;
+	} else {
+		menu_close();
+	}
+};
+
+float(float bInputType, float nPrimary, float nSecondary) order_menu_action =
+{
+	local string arg;
+	local float p, i, n, chose;
+	local string frags, color;
+	if(bInputType != 0) // key down wanted
+		return FALSE;
+	
+	arg = chr2str(nSecondary);
+	chose = stof(chr2str(nPrimary));
+	//str2chr
+	if(arg == "1") {
+		color = getplayerkey(player_localentnum-1, "topcolor");
+		++order_page;
+		for(p = i = 0; i < maxclients; ++i) {
+			frags = getplayerkey(i, "frags");
+			if(!frags || (i+1) == player_localentnum)
+				continue;
+			if(frags == "-666" || getplayerkey(i, "topcolor") != color)
+				continue;
+			++p;
+		}
+		if(p <= (8*order_page)) // no ppl on page
+			order_page = 0;
+	} else if(arg == "2") {
+		color = getplayerkey(player_localentnum-1, "topcolor");
+		--order_page;
+		if(order_page < 0) {
+			for(p = i = 0; i < maxclients; ++i) {
+				frags = getplayerkey(i, "frags");
+				if(!frags || (i+1) == player_localentnum)
+					continue;
+				if(frags == "-666" || getplayerkey(i, "topcolor") != color)
+					continue;
+				++p;
+			}
+			order_page = floor(p/8);
+		}
+	} else if(chose >= 3 && chose <= 9 || arg == "0") { // the 10 needs extra checking, assuming that stof(astring) returns 0
+		if(chose == 0)
+			chose = 10;
+		n = 2;
+		color = getplayerkey(player_localentnum-1, "topcolor");
+		for(p = i = 0; i < maxclients && n > 0; ++i) {
+			frags = getplayerkey(i, "frags");
+			if(!frags || (i+1) == player_localentnum)
+				continue;
+			if(frags == "-666" || getplayerkey(i, "topcolor") != color)
+				continue;
+			++p;
+			if(p > (8*order_page))
+			{
+				// only render current page
+				++n;
+				if(n == chose) {
+					n = 0;
+					break;
+				}
+			}
+		}
+		if(n == 0) {
+			//print(strcat("Issuing order to: ", ftos(i+1), "\n"));
+			//print(strcat("cmd order #", ftos(i+1), " ", ctf_temp_1, ";\n"));
+			localcmd(strcat("\ncmd order #", ftos(i+1), " ", ctf_temp_1, ";"));
+		} else {
+			print(strcat("Couldn't find player ", ftos(chose), "\n"));
+		}
+		return TRUE;
+	} else if(nSecondary == K_ESCAPE) {
+		strunzone(ctf_temp_1);
+		menu_close();
+	} else {
+		//print(strcat("Menu action ", arg, " does not exist.\n"));
+		return FALSE;
+	}
+	return TRUE;
+};
+
+void() order_menu_show =
+{
+	order_page = 0;
+	menu_show = order_menu_render;
+	menu_action = order_menu_action;
+};
+
+
+void() ctf_menu_render =
+{
+	local vector ps, po;
+	ps = '0 200';
+	po = '0 8';
+	
+	if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) {
+		drawstring(ps, "\x1D\x1E\x1E\x1E\x1E Command Menu \x1E\x1E\x1E\x1E\x1F", '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawstring(ps, "Issue orders:", '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawstring(ps, " 1) Attack ", '8 8 0', '1 1 0', 1, 0);
+		drawstring(ps + '80 0', " \x0F", '8 8 0', '1 1 1', 1, 0); ps += po;
+		drawstring(ps, " 2) Defend \x0E", '8 8 0', '1 1 0', 1, 0); ps += po;
+		ps += po;
+		drawstring(ps, "3) Resign from command.", '8 8 0', '1 1 0', 1, 0); ps += po;
+		drawstring(ps, "ESC) Exit Menu", '8 8 0', '1 1 0', 1, 0); ps += po;
+	} else {
+		menu_close();
+	}
+};
+
+float(float bInputType, float nPrimary, float nSecondary) ctf_menu_action =
+{
+	local string arg;
+	if(bInputType != 0) // key down wanted
+		return FALSE;
+	
+	arg = chr2str(nSecondary);
+
+	if(arg == "1") {
+		ctf_temp_1 = strzone("attack");
+		order_menu_show();
+	} else if(arg == "2") {
+		ctf_temp_1 = strzone("defend");
+		order_menu_show();
+	} else if(arg == "3") {
+		localcmd("\ncmd order resign;");
+		menu_close();
+	} else if(nSecondary == K_ESCAPE) {
+		menu_close();
+	} else {
+		//print(strcat("Menu action ", arg, " does not exist.\n"));
+		return FALSE;
+	}
+	return TRUE;
+};
+
+void() ctf_menu_show =
+{
+	if(getstati(STAT_CTF_STATE) < 0)
+		return;
+	menu_show = ctf_menu_render;
+	menu_action = ctf_menu_action;
+	menu_visible = TRUE;
+	//menu_default_binds();
+};
+
+void() ctf_view =
+{
+	local float stat;
+	stat = getstati(STAT_CTF_STATE);
+	if(stat == CTF_STATE_ATTACK) {
+		drawpic('0 0', "gfx/ctf_ic_atk.tga", '64 64 0', '1 1 1', 1, 0);
+	} else if(stat == CTF_STATE_DEFEND) {
+		drawpic('0 0', "gfx/ctf_ic_def.tga", '64 64 0', '1 1 1', 1, 0);
+	} else if(stat == CTF_STATE_COMMANDER) {
+		drawstring('0 0', "You're commander!", '8 8 0', '1 1 1', 1, 0);
+	} else if(stat < 0) {
+	} else {
+		drawstring('0 0', "Awaiting orders...", '8 8 0', '1 1 1', 0.5, 0);
+	}
+};

Added: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh	                        (rev 0)
+++ trunk/data/qcsrc/client/main.qh	2008-07-02 19:06:22 UTC (rev 3761)
@@ -0,0 +1,51 @@
+// --------------------------------------------------------------------------
+// MENU Functionality
+
+void() menu_show_error;
+void() menu_sub_null;
+
+void() menu_show; // ptr
+float menu_visible;
+
+float(float bInputType, float nPrimary, float nSecondary) menu_action;
+
+// --------------------------------------------------------------------------
+// CTF
+
+void() ctf_menu_show;
+string ctf_temp_1;
+
+
+// --------------------------------------------------------------------------
+// Onslaught
+
+// Map coordinate base calculations need these
+/*vector mi_redicon;
+vector mi_blueicon;
+vector mi_redbase;
+vector mi_bluebase;
+vector mi_scale;*/
+//vector mi_min;
+//vector mi_max;
+vector mi_center;
+vector mi_scale;
+// Minimap
+string minimapname;
+float ons_showmap;
+
+// --------------------------------------------------------------------------
+// General stuff
+
+float gametype;
+entity gps_start;
+
+// Defs
+.float ctf_state;
+.float health;
+
+// Constants
+const float COLOR_TEAM_RED = 64;
+const float COLOR_TEAM_BLUE = 208;
+
+const float COLOR_TEAM1 = 64;
+const float COLOR_TEAM2 = 208;

Added: trunk/data/qcsrc/client/ons.qc
===================================================================
--- trunk/data/qcsrc/client/ons.qc	                        (rev 0)
+++ trunk/data/qcsrc/client/ons.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -0,0 +1,74 @@
+void() Cmd_ons_map =
+{
+	ons_showmap = !ons_showmap;
+};
+
+vector(vector coord) mapCoords =
+{
+	local vector ret;
+	ret = coord; // put that up to ret's definition and it's '0 0 0' ... stupid fteqcc
+	ret -= mi_center;
+	ret_x = ret_x * 256.0 / mi_scale_x;
+	ret_y = -ret_y * 256.0 / mi_scale_y;
+	ret_z = 0;
+	ret = ret + '400 178';
+	return ret;
+};
+
+void(vector coord, vector pangles, vector rgb) drawplayer =
+{
+	makevectors(pangles);
+	v_forward_z = 0;
+	v_forward = normalize(v_forward);
+	v_forward_y *= -1.0;
+	v_right_x = -v_forward_y;
+	v_right_y = v_forward_x;
+	// Ryling on !tex[0] => texture_white
+	// beware of the order, it has to be clockwise!
+	R_BeginPolygon("", 0);
+	R_PolygonVertex(coord+v_forward*2, '0 0', rgb, 1);
+	R_PolygonVertex(coord+v_right*3-v_forward*2, '0 1', rgb, 1);
+	R_PolygonVertex(coord-v_forward, '1 0', rgb, 1);
+	R_PolygonVertex(coord-v_right*3-v_forward*2, '1 1', rgb, 1);
+	R_EndPolygon();
+};
+
+void() ons_view =
+{
+	if(ons_showmap) {
+		local float color;
+		local vector coord, dir, rgb;
+
+		color = stof(getplayerkey(player_localentnum-1, "topcolor"));
+
+		/*dir = pmove_org - mi_redbase;
+
+		dir_x *= mi_scale_x;
+		dir_y *= -mi_scale_y;
+			
+		coord = '272 50' + mi_redicon + dir*mi_scale_z;
+		  coord_z = 0;*/
+		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');
+
+		local entity tm;
+		for(tm = gps_start; tm != world; tm = tm.chain)
+		{
+			//print(strcat("GPS: ", ftos(tm.sv_entnum), " - ", vtos(tm.origin), "\n"));
+			drawplayer(mapCoords(tm.origin), tm.angles, rgb);
+		}
+	}
+};

Modified: trunk/data/qcsrc/client/progs.src
===================================================================
--- trunk/data/qcsrc/client/progs.src	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/client/progs.src	2008-07-02 19:06:22 UTC (rev 3761)
@@ -2,7 +2,12 @@
 
 Defs.qc
 csqc_constants.qc
+../common/constants.qh
 csqc_builtins.qc
 
+main.qh
+ons.qc
+ctf.qc
+
 Main.qc
-View.qc
\ No newline at end of file
+View.qc

Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/common/constants.qh	2008-07-02 19:06:22 UTC (rev 3761)
@@ -25,7 +25,7 @@
 
 const float ENT_CLIENT = 0;
 const float ENT_CLIENT_DEAD = 1;
-const float ENT_CLIENT_GPS = 2;
+const float ENT_CLIENT_ENTCS = 2;
 
 ///////////////////////////
 // key constants

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/cl_client.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -520,6 +520,7 @@
 Called when a client spawns in the server
 =============
 */
+//void() ctf_playerchanged;
 void PutClientInServer (void)
 {
 	if(clienttype(self) == CLIENTTYPE_BOT)
@@ -691,6 +692,9 @@
 	} else if(self.classname == "observer") {
 		PutObserverInServer ();
 	}
+
+	//if(g_ctf)
+	//	ctf_playerchanged();
 }
 
 /*
@@ -934,6 +938,7 @@
 Called when a client connects to the server
 =============
 */
+//void ctf_clientconnect();
 string ColoredTeamName(float t);
 void DecodeLevelParms (void);
 //void dom_player_join_team(entity pl);
@@ -1071,7 +1076,14 @@
 		self.classname = "observer";
 		Spawnqueue_Insert(self);
 	}
+	/*else if(g_ctf)
+	{
+		ctf_clientconnect();
+	}*/
 
+	if(entcs_start)
+		attach_entcs();
+
 	bot_relinkplayerlist();
 
 	self.spectatortime = time;
@@ -1094,9 +1106,14 @@
 void(entity e) DropFlag;
 .entity chatbubbleentity;
 .entity teambubbleentity;
+//void() ctf_clientdisconnect;
 void ClientDisconnect (void)
 {
 	float save;
+
+	if(entcs_start)
+		detach_entcs();
+	
 	if(cvar("sv_eventlog"))
 		GameLogEcho(strcat(":part:", ftos(self.playerid)), FALSE);
 	bprint ("^4",self.netname);
@@ -1145,6 +1162,11 @@
 		Spawnqueue_Unmark(self);
 		Spawnqueue_Remove(self);
 	}
+	/*if(g_ctf)
+	{
+		ctf_clientdisconnect();
+	}
+	*/
 
 	if(self.netname_previous)
 		strunzone(self.netname_previous);

Modified: trunk/data/qcsrc/server/clientcommands.qc
===================================================================
--- trunk/data/qcsrc/server/clientcommands.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/clientcommands.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -137,6 +137,33 @@
 	strunzone(msgstr);
 }
 
+entity GetPlayer(string name)
+{
+	float num;
+	entity e;
+	string ns;
+
+	if(substring(name, 0, 1) == "#") {
+		num = stof(substring(name, 1, 999));
+		if(num >= 1 && num <= maxclients) {
+			for((e = world); num > 0; --num, (e = nextent(e)))
+				;
+			//if(clienttype(e) == CLIENTTYPE_REAL)
+			if(e.classname == "player")
+				return e;
+		}
+	} else {
+		ns = strdecolorize(name);
+		FOR_EACH_REALPLAYER(e) {
+			if(!strcasecmp(strdecolorize(e.netname), ns)) {
+				return e;
+			}
+		}
+	}
+	return world;
+}
+
+//float ctf_clientcommand();
 void SV_ParseClientCommand(string s) {
 	local string cmd;
 	local float i;
@@ -304,6 +331,8 @@
 			evaluateResumeGame();
 		}
 	} else {
+		//if(ctf_clientcommand())
+		//	return;
 		cmd = argv(0);
 		/* checks not needed any more since DP has separated clientcommands and regular commands
 		if(cmd != "status")

Modified: trunk/data/qcsrc/server/ctf.qc
===================================================================
--- trunk/data/qcsrc/server/ctf.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/ctf.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -26,6 +26,8 @@
 
 float   flagcaptimerecord;
 .float  flagpickuptime;
+//.float  iscommander;
+//.float  ctf_state;
 
 void() FlagThink;
 void() FlagTouch;
@@ -662,6 +664,8 @@
 void ctf_init()
 {
 	local entity e;
+
+	//addstat(STAT_CTF_STATE, AS_FLOAT_TRUNCATED, ctf_state);
 	e = spawn();
 	e.think = ctf_delayedinit;
 	e.nextthink = time + 0.1;
@@ -726,3 +730,142 @@
 		}
 	}
 };
+/*
+entity(float cteam) ctf_team_has_commander =
+{
+	entity pl;
+	if(cteam != COLOR_TEAM1 || cteam != COLOR_TEAM2)
+		return world;
+	
+	FOR_EACH_REALPLAYER(pl) {
+		if(pl.team == cteam && pl.iscommander) {
+			return pl;
+		}
+	}
+	return world;
+};
+
+void(entity e, float st) ctf_setstate =
+{
+	e.ctf_state = st;
+	e.version ++;
+};
+
+void(float cteam) ctf_new_commander =
+{
+	entity pl, plmax;
+	
+	plmax = world;
+	FOR_EACH_REALPLAYER(pl) {
+		if(pl.team == cteam) {
+			if(pl.iscommander) { // don't reassign if alreay there
+				return;
+			}
+			if(plmax == world || plmax.frags < pl.frags)
+				plmax = pl;
+		}
+	}
+	if(plmax == world) {
+		bprint(strcat(ColoredTeamName(cteam), " Team has no Commander!\n"));
+		return;
+	}
+
+	plmax.iscommander = TRUE;
+	ctf_setstate(plmax, 3);
+	sprint(plmax, "^3You're the commander now!\n");
+	centerprint(plmax, "^3You're the commander now!\n");
+};
+
+void() ctf_clientconnect =
+{
+	self.iscommander = FALSE;
+	
+	if(!self.team || self.classname != "player") {
+		ctf_setstate(self, -1);
+	} else
+		ctf_setstate(self, 0);
+
+	self.team_saved = self.team;
+	
+	if(self.team != 0 && self.classname == "player" && !ctf_team_has_commander(self.team)) {
+		ctf_new_commander(self.team);
+	}
+};
+
+void() ctf_playerchanged =
+{
+	if(!self.team || self.classname != "player") {
+		ctf_setstate(self, -1);
+	} else if(self.ctf_state < 0 && self.classname == "player") {
+		ctf_setstate(self, 0);
+	}
+
+	if(self.iscommander &&
+	   (self.classname != "player" || self.team != self.team_saved)
+		)
+	{
+		self.iscommander = FALSE;
+		if(self.classname == "player")
+			ctf_setstate(self, 0);
+		else
+			ctf_setstate(self, -1);
+		ctf_new_commander(self.team_saved);
+	}
+	
+	self.team_saved = self.team;
+	
+	ctf_new_commander(self.team);
+};
+
+void() ctf_clientdisconnect =
+{
+	if(self.iscommander)
+	{
+		ctf_new_commander(self.team);
+	}
+};
+
+entity GetPlayer(string);
+float() ctf_clientcommand =
+{
+	entity e;
+	if(argv(0) == "order") {
+		if(!g_ctf) {
+			sprint(self, "This command is not supported in this gamemode.\n");
+			return TRUE;
+		}
+		if(!self.iscommander) {
+			sprint(self, "^1You are not the commander!\n");
+			return TRUE;
+		}
+		if(argv(2) == "") {
+			sprint(self, "Usage: order #player status   - (playernumber as in status)\n");
+			return TRUE;
+		}
+		e = GetPlayer(argv(1));
+		if(e == world) {
+			sprint(self, "Invalid player.\nUsage: order #player status   - (playernumber as in status)\n");
+			return TRUE;
+		}
+		if(e.team != self.team) {
+			sprint(self, "^3You can only give orders to your own team!\n");
+			return TRUE;
+		}
+		if(argv(2) == "attack") {
+			sprint(self, strcat("Ordering ", e.netname, " to attack!\n"));
+			sprint(e, "^1Attack!\n");
+			centerprint(e, "^7You've been ordered to^9\n^1Attack!\n");
+			ctf_setstate(e, 1);
+		} else if(argv(2) == "defend") {
+			sprint(self, strcat("Ordering ", e.netname, " to defend!\n"));
+			sprint(e, "^Defend!\n");
+			centerprint(e, "^7You've been ordered to^9\n^2Defend!\n");
+			ctf_setstate(e, 2);
+		} else {
+			sprint(self, "^7Invalid command, use ^3attack^7, or ^3defend^7.\n");
+		}
+		return TRUE;
+	}
+	return FALSE;
+};
+*/

Added: trunk/data/qcsrc/server/ent_cs.qc
===================================================================
--- trunk/data/qcsrc/server/ent_cs.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/ent_cs.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -0,0 +1,98 @@
+/**
+ * The point of these entities is to avoid the problems
+ * with clientprediction.
+ * If you add SendEntity to players, the engine will not
+ * do any prediction anymore, and you'd have to write the whole
+ * prediction code in CSQC, you want that? :P
+ * Data can depend on gamemode. For now, it serves as GPS entities
+ * in onslaught... YAY ;)
+ */
+
+// Beware: do not redefine those in other files
+// and NO, you cannot use ".version", which already exists (at least
+// it did when I added this) But you have to use .Version
+// Capital V
+
+.float(entity to) SendEntity;
+.float Version;
+
+entity entcs_start;
+
+void() entcs_init =
+{
+	print("Initializing ClientSide information entities\n");
+	entcs_start = spawn();
+	entcs_start.solid = SOLID_NOT;
+	entcs_start.chain = world;
+};
+
+entity(float num) get_entcs_ent =
+{
+	entity entcs;
+	entcs = spawn();
+	entcs.chain = entcs_start.chain;
+	entcs_start.chain = entcs;
+	return entcs;
+};
+
+
+float(entity to) entcs_send =
+{
+	if(to == self.owner || self.team != to.team)
+		return FALSE;
+	if(self.owner.classname == "observer" || to.classname == "observer")
+		return FALSE;
+	
+	WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
+	WriteByte(MSG_ENTITY, self.health); // serves as entitynumber
+	WriteCoord(MSG_ENTITY, self.owner.origin_x);
+	WriteCoord(MSG_ENTITY, self.owner.origin_y);
+	WriteCoord(MSG_ENTITY, self.owner.angles_y);
+	// write health maybe?
+	return TRUE;
+};
+
+void() entcs_think =
+{
+	self.team = self.owner.team;
+	self.Version++;
+	setorigin(self, self.owner.origin);
+	self.nextthink = time + 0.1;
+};
+
+void() attach_entcs =
+{
+	local float num;
+	local entity ent;
+
+	print("Attaching ENTCS entity\n");
+
+	num = num_for_edict(self);
+	ent = get_entcs_ent(num);
+
+	ent.classname = "entcs_sender";
+	ent.health = num;
+	setorigin(ent, self.origin);
+	ent.owner = self;
+	ent.think = entcs_think;
+	ent.nextthink = time;
+	ent.effects = EF_NODEPTHTEST | EF_LOWPRECISION;
+	ent.model = "entcs_sender";
+	ent.modelindex = 1;
+	setsize(ent, '0 0 0', '0 0 0');
+		
+	ent.SendEntity = entcs_send;
+};
+
+void() detach_entcs =
+{
+	local float num;
+	local entity ent;
+	num = num_for_edict(self);
+	for(ent = entcs_start; ent.chain.owner != self && ent.chain != world; ent = ent.chain);
+	if(ent.chain != world && ent.chain.owner == self)
+	{
+		remove(ent.chain);
+		ent.chain = ent.chain.chain;
+	}
+};

Modified: trunk/data/qcsrc/server/extensions.qh
===================================================================
--- trunk/data/qcsrc/server/extensions.qh	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/extensions.qh	2008-07-02 19:06:22 UTC (rev 3761)
@@ -1707,3 +1707,8 @@
 //Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities.
 //Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A).
 //Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix.
+
+
+//EXT_CSQC
+// #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
+void(float index, float type, ...) addstat = #232;

Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/progs.src	2008-07-02 19:06:22 UTC (rev 3761)
@@ -75,6 +75,8 @@
 //g_tetris.qc
 cl_impulse.qc
 
+ent_cs.qc
+
 cl_player.qc
 cl_client.qc
 t_plats.qc

Modified: trunk/data/qcsrc/server/teamplay.qc
===================================================================
--- trunk/data/qcsrc/server/teamplay.qc	2008-07-02 13:45:59 UTC (rev 3760)
+++ trunk/data/qcsrc/server/teamplay.qc	2008-07-02 19:06:22 UTC (rev 3761)
@@ -75,6 +75,7 @@
 void ctf_init();
 void runematch_init();
 void tdm_init();
+void entcs_init();
 
 void LogTeamchange(entity pl)
 {
@@ -325,6 +326,8 @@
 		tdm_init();
 	else if (game == GAME_KEYHUNT)//cvar("g_keyhunt"))
 		kh_init();
+	else if (game == GAME_ONSLAUGHT)
+		entcs_init();
 }
 
 string GetClientVersionMessage(float v) {
@@ -925,7 +928,7 @@
 	return smallest;
 }
 
-
+//void() ctf_playerchanged;
 void SV_ChangeTeam(float _color)
 {
 	float scolor, dcolor, steam, dteam, dbotcount, scount, dcount;
@@ -1054,6 +1057,7 @@
 		if(self.deadflag == DEAD_NO)
 			Damage(self, self, self, 100000, DEATH_TEAMCHANGE, self.origin, '0 0 0');
 	}
+	//ctf_playerchanged();
 }
 
 void ShufflePlayerOutOfTeam (float source_team)




More information about the nexuiz-commits mailing list