r3819 - in trunk/data: . qcsrc/client qcsrc/common qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sun Jul 13 13:42:30 EDT 2008
Author: blub0
Date: 2008-07-13 13:42:30 -0400 (Sun, 13 Jul 2008)
New Revision: 3819
Added:
trunk/data/qcsrc/client/mapvoting.qc
Modified:
trunk/data/Makefile
trunk/data/defaultNexuiz.cfg
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/miscfunctions.qc
trunk/data/qcsrc/client/progs.src
trunk/data/qcsrc/client/sbar.qc
trunk/data/qcsrc/client/sortlist.qc
trunk/data/qcsrc/client/teamplay.qc
trunk/data/qcsrc/common/constants.qh
trunk/data/qcsrc/server/cl_client.qc
trunk/data/qcsrc/server/clientcommands.qc
trunk/data/qcsrc/server/g_world.qc
Log:
map previews when voting, g_maplist_textonly for old style
new sorting in the scoreboard
-Fparms in Makefile for future FTE version check
Modified: trunk/data/Makefile
===================================================================
--- trunk/data/Makefile 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/Makefile 2008-07-13 17:42:30 UTC (rev 3819)
@@ -3,6 +3,18 @@
PK3NAME ?= `date +../data%Y%m%d.pk3`
ZIP ?= 7za a -tzip -mx=9
+# -Fparm: define PARM0, RETURN, etc. for use in asm{}
+# This will make it possible to make a non-FTE asm{} block
+# checking if the client's engine supports -TFTE.
+# At some point CSQC should use -TFTE too, and then, for at least
+# some time, it would be useful to have a well-formatted error message
+# followed by localcmd("disconnect") if the client doesn't support -TFTE
+# instead of letting him guess what the huge QCVM error message means...
+QCFLAGS_CSQC ?= -Fparm
+
+# to be enabled when possible
+# QCFLAGS_SVQC ?= -TFTE
+
all: qc
.PHONY: qc
@@ -19,10 +31,10 @@
rm -f progs.dat menu.dat csprogs.dat
csprogs.dat: qcsrc/client/*.* qcsrc/common/*.*
- ( cd qcsrc/client; $(FTEQCC) )
+ ( cd qcsrc/client; $(FTEQCC) $(QCFLAGS_CSQC) )
progs.dat: qcsrc/server/*.* qcsrc/common/*.*
- ( cd qcsrc/server; $(FTEQCC) )
+ ( cd qcsrc/server; $(FTEQCC) $(QCFLAGS_SVQC) )
menu.dat: qcsrc/menu/*.* qcsrc/menu/*/*.* qcsrc/common/*.*
( cd qcsrc/menu; $(FTEQCC) )
Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/defaultNexuiz.cfg 2008-07-13 17:42:30 UTC (rev 3819)
@@ -811,6 +811,7 @@
seta g_maplist_votable_suggestions_override_mostrecent 0
seta g_maplist_votable_nodetail 0 // nodetail only shows total count instead of all vote counts per map, so votes don't influence others that much
seta g_maplist_votable_abstain 0 // when 1, you can abstain from your vote
+seta g_maplist_textonly 0 // use old style centerprint
alias suggestmap "cmd suggestmap $1"
set g_chat_flood_spl 0 // seconds between lines to not count as flooding
@@ -1053,5 +1054,3 @@
alias sbar_font "loadfont user1 $*; sbar_columns_set"
sbar_font gfx/vera-sans
-// supporting stringwidth
-seta csqc_flags 1
Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/Main.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -15,11 +15,34 @@
};
// let's make this a general data buffer...
-float databuf;
float using_gps;
+float __engine_check;
+
+void testpassedyay() {
+ asm {
+ RETURN 0;
+ }
+}
+
void CSQC_Init(void)
{
+#if 0
+ asm {
+ STORE_F "DP_SV_WRITEPICTURE" PARM0;
+ CALL1 checkextension;
+ STORE_F RETURN __engine_check;
+ IF __engine_check 6;
+ STORE_F "^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n" PARM0;
+ CALL1 print;
+ STORE_F "\ndisconnect\n" PARM0;
+ CALL1 localcmd;
+ DONE;
+ }
+#else
+ __engine_check = true;
+#endif
+
float i;
CSQC_CheckEngine();
drawfont = 0;
@@ -47,8 +70,20 @@
sbar_title[i] = strzone("(null)");
postinit = false;
+
+ Sbar_Init();
}
+// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
+void CSQC_Shutdown(void)
+{
+ asm {
+ IF __engine_check 2;
+ RETURN 0;
+ }
+ buf_del(databuf);
+}
+
void PostInit(void)
{
float i;
@@ -67,11 +102,6 @@
postinit = true;
}
-// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
-void CSQC_Shutdown(void)
-{
- buf_del(databuf);
-}
// 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.
@@ -104,6 +134,21 @@
return false;
}
+
+float GameCommand(string msg)
+{
+ float argc;
+ argc = tokenize(msg);
+ string cmd;
+ cmd = argv(0);
+ if(cmd == "mv_download") {
+ Cmd_MapVote_MapDownload(argc);
+ return true;
+ }
+
+ return false;
+}
+
// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
// All keys are in ascii.
@@ -219,7 +264,6 @@
local float file;
local vector mi_min, mi_max;
- draw_enginesbar = true;
gametype = cvar("gametype");
if(gametype == GAME_ONSLAUGHT) {
if(!strcasecmp(substring(mapname, 0, 5), "maps/"))
@@ -248,7 +292,7 @@
}
}
} else {
- print(strcat("^1Error: ^7Mapinfo file '", mapinfo, "' missing! Minimap will be screwed.\n"));
+ print(strcat("Map has no .info file (", mapinfo, ").\n"));
}
fclose(file);
@@ -268,7 +312,6 @@
} else if(gametype == GAME_KEYHUNT) {
precache_pic("gfx/sb_key_carrying");
precache_pic("gfx/sb_key_carrying_outline");
- draw_enginesbar = false;
}
}
// 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.
@@ -293,7 +336,8 @@
}
void CSQC_CheckRevision();
-void ReadInit()
+
+void Net_ReadInit()
{
csqc_revision = ReadShort();
maxclients = ReadByte();
@@ -301,7 +345,7 @@
CSQC_CheckRevision();
}
-void ReadPings()
+void Net_ReadPings()
{
float plnum, ping;
for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
@@ -311,7 +355,7 @@
}
}
-void ReadCaptures()
+void Net_ReadCaptures()
{
float plnum, caps, mode;
mode = ReadByte();
@@ -324,7 +368,7 @@
}
}
-void ReadDatabuf(float ofs)
+void Net_ReadDatabuf(float ofs)
{
float plnum, data;
for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
@@ -334,6 +378,26 @@
}
}
+void Net_ReadPicture()
+{
+ string img;
+ if(csqc_flags & CSQC_FLAG_READPICTURE)
+ {
+ img = ReadPicture();
+ print(strcat("Got Picture: ", img, "\n"));
+ } else {
+ img = ReadString();
+ print(strcat("^3Warning: ^7Couldn't download ", img, ". This is probably because your engine build is outdated.\n"));
+ float psize, i;
+ psize = ReadShort();
+ // Can I be sure that ReadShort is 2 bytes and ReadLong is 4 bytes?
+ // Because then this could be optimized to first get all 4-byte-groups,
+ // then the remaining 2, then the remaining 1
+ for(i = 0; i < psize; ++i)
+ ReadByte();
+ }
+}
+
// 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.
@@ -344,29 +408,39 @@
// Acquire TE ID
local float nTEID;
nTEID = ReadByte();
-
+
+ // NOTE: Could just do return instead of break...
switch(nTEID)
{
case TE_CSQC_INIT:
- ReadInit();
+ Net_ReadInit();
bHandled = true;
break;
case TE_CSQC_PING:
- ReadPings();
+ Net_ReadPings();
bHandled = true;
break;
case TE_CSQC_CAPTURES:
- ReadCaptures();
+ Net_ReadCaptures();
bHandled = true;
break;
case TE_CSQC_RETURNS:
- ReadDatabuf(DATABUF_RETURNS);
+ Net_ReadDatabuf(DATABUF_RETURNS);
bHandled = true;
break;
case TE_CSQC_DEATHS:
- ReadDatabuf(DATABUF_DEATHS);
+ Net_ReadDatabuf(DATABUF_DEATHS);
bHandled = true;
break;
+ case TE_CSQC_PICTURE:
+ Net_ReadPicture();
+ bHandled = true;
+ break;
+ case TE_CSQC_MAPVOTE:
+ Net_Mapvote();
+ bHandled = true;
+ break;
+
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
bHandled = false;
@@ -382,7 +456,8 @@
// COMMIT-TODO: Update if necessare, before committing
float csqc_svn_map[CSQC_REVISION] =
{
- 3795,
+ 3812, // 3795,
+ 3815
};
// COMMIT-TODO: Update if necessare, before committing
Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/View.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,15 +1,5 @@
//include "main.qh"
-float sbar_alpha_fg;
-float last_weapon;
-float activeweapon;
-float weapontime;
-float sbar_hudselector;
-float teamplay;
-float myteam;
-
-float numteams; // NOTE: This is changed in Sbar_SortFrags, so use it only AFTER that
-
void CSQC_common_hud(void);
void CSQC_kh_hud(void);
Modified: trunk/data/qcsrc/client/csqc_builtins.qc
===================================================================
--- trunk/data/qcsrc/client/csqc_builtins.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/csqc_builtins.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -98,7 +98,6 @@
void drawresetcliparea(void) = #325;
float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #326;
float stringwidth_engine(string text, float handleColors) = #327;
-float stringwidth(string text, float handleColors);
float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328;
@@ -260,4 +259,6 @@
float(string str, string sub, float startoffs) strstrofs = #221;
//float(string str, string sub) strstrofs = #221;
entity(float num) edict_num = #459;
+string(void) ReadPicture = #501;
+string(string filename) whichpack = #503;
float(entity ent) num_for_edict = #512;
Modified: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/main.qh 2008-07-13 17:42:30 UTC (rev 3819)
@@ -11,11 +11,10 @@
void() menu_show_error;
void() menu_sub_null;
-void() menu_show;
float menu_visible;
+var void() menu_show;
+var float(float bInputType, float nPrimary, float nSecondary) menu_action;
-float(float bInputType, float nPrimary, float nSecondary) menu_action;
-
// --------------------------------------------------------------------------
// CTF
@@ -86,4 +85,4 @@
float sbar_font;
float csqc_flags;
-#define CSQC_FLAG_STRINGWIDTH 1
+#define CSQC_FLAG_READPICTURE 1
Added: trunk/data/qcsrc/client/mapvoting.qc
===================================================================
--- trunk/data/qcsrc/client/mapvoting.qc (rev 0)
+++ trunk/data/qcsrc/client/mapvoting.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -0,0 +1,276 @@
+float mv_num_maps;
+
+string mv_maps[MAPVOTE_COUNT];
+string mv_pics[MAPVOTE_COUNT];
+string mv_pk3[MAPVOTE_COUNT];
+float mv_preview[MAPVOTE_COUNT];
+float mv_votes[MAPVOTE_COUNT];
+entity mv_pk3list;
+float mv_abstain;
+float mv_ownvote;
+float mv_detail;
+
+void MapVote_DrawMapItem(vector pos, float isize, string map, string pic, float count, float id)
+{
+ vector img_size;
+ //img_size_x = img_size_y = isize;
+ img_size_y = isize;
+ img_size_x = isize / 0.75; // 4:3 x can be stretched easily, height is defined in isize
+
+ drawpic(pos, pic, img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ // half size for the impulse number
+ img_size_x = img_size_y = isize*0.5;
+ pos_y += img_size_y*0.5;
+
+ if(id == mv_ownvote)
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 0', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ // half again for the mapname
+ img_size = img_size * 0.5; // *= broken???
+ pos_y += img_size_y*0.5;
+ pos_x += isize/0.75 + 10;
+
+ if(mv_detail)
+ drawstring(pos, strcat(ftos(count), " : ", map), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos, map, img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+}
+
+void MapVote_DrawMapNotAvailable(vector pos, float isize, string map, float count, float id)
+{
+ vector img_size, a, b;
+ img_size_y = isize;
+ img_size_x = isize / 0.75;
+
+ a_x = img_size_x; // for the lines
+ b_y = img_size_y;
+ drawfill(pos, img_size, '.5 .5 .5', .7, DRAWFLAG_NORMAL);
+ drawline(2, pos, pos + a, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawline(2, pos, pos + b, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawline(2, pos + img_size, pos + a, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawline(2, pos + img_size, pos + b, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ img_size_x = img_size_y = isize*0.5;
+ pos_y += img_size_y*0.5;
+
+ if(id == mv_ownvote)
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 0', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ img_size = img_size * 0.5; // *= broken???
+ pos_y += img_size_y*0.5;
+ pos_x += isize/0.75 + 10;
+
+ if(mv_detail)
+ drawstring(pos, strcat(ftos(count), " : ", map), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos, map, img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+}
+
+void MapVote_DrawAbstain(vector pos, float isize, float count, float id)
+{
+ vector img_size;
+ img_size_y = isize;
+ img_size_x = isize / 0.75;
+
+ img_size_x = img_size_y = isize*0.5;
+ pos_y += img_size_y*0.5;
+
+ if(id == mv_ownvote)
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 0', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos - '40 0', strcat(ftos(id+1), ")"), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ img_size = img_size * 0.5; // *= broken???
+ pos_y += img_size_y*0.5;
+ pos_x += isize/0.75 + 10;
+
+ if(mv_detail)
+ drawstring(pos, strcat(ftos(count), " : Don't care"), img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+ else
+ drawstring(pos, "Don't care", img_size, '1 1 1', 1, DRAWFLAG_NORMAL);
+}
+
+void MapVote_Draw()
+{
+ string map;
+ float i, tmp;
+ vector pos;
+ vector center;
+ float isize;
+
+ center_x = (vid_conwidth - 1)/2;
+ xmin = vid_conwidth*0.2;
+ xmax = vid_conwidth - xmin;
+ ymin = 24;
+ i = cvar("con_chatpos"); //*cvar("con_chatsize");
+ if(i < 0)
+ ymax = vid_conheight + (i - cvar("con_chat")) * cvar("con_chatsize");
+ if(i >= 0 || ymax < (vid_conheight*0.5))
+ ymax = vid_conheight - ymin;
+
+ drawfont = sbar_font;
+ sbar_fontsize = stov(cvar_string("sbar_fontsize"));
+ if(sbar_fontsize_x == 0)
+ sbar_fontsize = '8 8 0';
+ if(sbar_fontsize_y == 0)
+ sbar_fontsize_y = sbar_fontsize_x;
+
+ pos_y = ymin;
+ pos_z = 0;
+ pos_x = center_x - stringwidth("Vote for a map", false) * 0.5 * 24;
+ drawstring(pos, "Vote for a map", '24 24', '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ pos_x = xmin;
+ pos_y += 32;
+ isize = (ymax - ymin - mv_num_maps*10) / mv_num_maps;
+ isize = min(isize, 64);
+ for(i = 0; i < (mv_num_maps - mv_abstain); ++i) // - mv_abstain safe? make sure it's 0 or 1
+ {
+ tmp = mv_votes[i]; // FTEQCC bug: too many array accesses in the function call screw it up
+ if(tmp < 0)
+ continue;
+ map = mv_maps[i];
+ if(mv_preview[i])
+ MapVote_DrawMapItem(pos, isize, map, mv_pics[i], tmp, i);
+ else
+ MapVote_DrawMapNotAvailable(pos, isize, map, tmp, i);
+ pos_y += isize + 10;
+ }
+ if(mv_abstain && i < mv_num_maps) {
+ tmp = mv_votes[i];
+ MapVote_DrawAbstain(pos, isize, tmp, i);
+ }
+}
+
+void Cmd_MapVote_MapDownload(float argc)
+{
+ float id;
+ entity pak;
+
+ if(argc != 2 || !mv_pk3list)
+ {
+ print("mv_mapdownload: ^3You're not supposed to use this command on your own!\n");
+ return;
+ }
+
+ id = stof(argv(1));
+ for(pak = mv_pk3list; pak; pak = pak.chain)
+ if(pak.sv_entnum == id)
+ break;
+
+ if(!pak || pak.sv_entnum != id) {
+ print("^1Error:^7 Couldn't find pak index.\n");
+ return;
+ }
+
+ //print(strcat("^3Adding: ", ftos(id), " - ", pak.message, " - "));
+
+ if(PreviewExists(pak.message))
+ {
+ mv_preview[id] = true;
+ //print("^2Found...\n");
+ return;
+ } else if(csqc_flags & CSQC_FLAG_READPICTURE) {
+ print("Requesting preview...\n");
+ localcmd(strcat("\ncmd mv_getpic ", ftos(id), "\n"));
+ } else {
+ print("^3Missing map preview - Update to a newer build to be able to see them.\n");
+ }
+}
+
+void MapVote_CheckPK3(string pic, string pk3, float id)
+{
+ entity pak;
+ pak = spawn();
+ pak.netname = pk3;
+ pak.message = pic;
+ pak.sv_entnum = id;
+
+ pak.chain = mv_pk3list;
+ mv_pk3list = pak;
+
+ localcmd(strcat("\ncurl --pak ", pk3, "; wait; cl_cmd mv_download ", ftos(id), "\n"));
+}
+
+void MapVote_CheckPic(string pic, string pk3, float id)
+{
+ if(PreviewExists(pic))
+ {
+ //print(strcat("^2Exists... ", pic, "\n"));
+ mv_preview[id] = true;
+ return;
+ }
+ MapVote_CheckPK3(pic, pk3, id);
+}
+
+void MapVote_Init()
+{
+ float i;
+ string map, pk3;
+
+ mv_num_maps = min(MAPVOTE_COUNT, ReadByte());
+ mv_abstain = ReadByte();
+ if(mv_abstain)
+ mv_abstain = 1; // must be 1
+ mv_detail = ReadByte();
+ mv_ownvote = -1;
+
+ // Assume mv_pk3list is NULL, there should only be 1 mapvote per round
+ mv_pk3list = NULL; // I'm still paranoid!
+
+ for(i = 0; i < mv_num_maps; ++i)
+ {
+ mv_votes[i] = 0;
+ map = strzone(ReadString());
+ pk3 = strzone(ReadString());
+ mv_maps[i] = map;
+ mv_pk3[i] = pk3;
+ map = strzone(strcat("maps/", map));
+ mv_pics[i] = map;
+
+ mv_preview[i] = false;
+
+ //print(strcat("RECV: ", map, " in ", pk3, "\n"));
+ MapVote_CheckPic(map, pk3, i);
+ }
+}
+
+void MapVote_Update()
+{
+ float i, e;
+ for(i = 0; i < mv_num_maps; ++i)
+ {
+ e = ReadByte();
+ mv_votes[i] = ReadByte();
+ if(!e)
+ mv_votes[i] = -1;
+ }
+}
+
+void Net_Mapvote()
+{
+ float type;
+ type = ReadByte();
+ switch(type)
+ {
+ case MAPVOTE_NET_INIT:
+ MapVote_Init();
+ break;
+ case MAPVOTE_NET_UPDATE:
+ MapVote_Update();
+ break;
+ case MAPVOTE_NET_OWNVOTE:
+ mv_ownvote = ReadByte()-1;
+ break;
+ case MAPVOTE_NET_PIC:
+ type = ReadByte();
+ mv_preview[type] = true;
+ //print(strcat("MAPVOTE_NET_PIC: ^2", ftos(type), "\n"));
+ break;
+ }
+}
Modified: trunk/data/qcsrc/client/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/client/miscfunctions.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/miscfunctions.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,3 +1,6 @@
+float databuf;
+var float(string text, float handleColors) stringwidth;
+
float stringwidth_oldfont(string text, float handleColors)
{
float i, len, ch, width;
@@ -23,14 +26,18 @@
void CSQC_CheckEngine()
{
- float i, tmp;
+ /*
registercvar("csqc_flags", "0");
csqc_flags = cvar("csqc_flags");
+ */
- if(csqc_flags & CSQC_FLAG_STRINGWIDTH)
+ csqc_flags = 0;
+
+ if(checkextension("DP_SV_WRITEPICTURE"))
{
stringwidth = stringwidth_engine;
sbar_font = FONT_USER+1;
+ csqc_flags |= CSQC_FLAG_READPICTURE;
} else {
stringwidth = stringwidth_oldfont;
sbar_font = FONT_DEFAULT;
@@ -39,7 +46,42 @@
vector Sbar_GetFontsize()
{
- if(csqc_flags & CSQC_FLAG_STRINGWIDTH)
+ if(csqc_flags & CSQC_FLAG_READPICTURE)
return stov(cvar_string("sbar_fontsize"));
return '8 8' ;
}
+
+float PreviewExists(string name)
+{
+ float f;
+ string file;
+ file = strcat(name, ".tga");
+ f = fopen(file, FILE_READ);
+ if(f >= 0)
+ {
+ fclose(f);
+ return true;
+ }
+ file = strcat(name, ".png");
+ f = fopen(file, FILE_READ);
+ if(f >= 0)
+ {
+ fclose(f);
+ return true;
+ }
+ file = strcat(name, ".jpg");
+ f = fopen(file, FILE_READ);
+ if(f >= 0)
+ {
+ fclose(f);
+ return true;
+ }
+ file = strcat(name, ".pcx");
+ f = fopen(file, FILE_READ);
+ if(f >= 0)
+ {
+ fclose(f);
+ return true;
+ }
+ return false;
+}
Modified: trunk/data/qcsrc/client/progs.src
===================================================================
--- trunk/data/qcsrc/client/progs.src 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/progs.src 2008-07-13 17:42:30 UTC (rev 3819)
@@ -14,6 +14,9 @@
ons.qc
ctf.qc
+sbar.qc
+mapvoting.qc
+
Main.qc
View.qc
-sbar.qc
+
Modified: trunk/data/qcsrc/client/sbar.qc
===================================================================
--- trunk/data/qcsrc/client/sbar.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/sbar.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,8 +1,14 @@
+float last_weapon;
+float activeweapon;
+float weapontime;
+
float sb_lines; // still don't know what to do with that NOTE: check dp's sbar.c to see what that should be
vector sbar;
vector sbar_fontsize;
+float sbar_alpha_fg;
+float sbar_hudselector;
entity sortedPlayers;
entity sortedTeams;
@@ -12,13 +18,22 @@
.float sb_player;
.float sb_caps;
+entity team1, team2, team3, team4, teamspec;
+
+void CSQC_kh_hud();
+void CSQC_ctf_hud();
+void MapVote_Draw();
void Sbar_FinaleOverlay()
{
- vector pos;
+ /*vector pos;
pos_x = (vid_conwidth - 1)/2;
pos_y = 16;
- pos_z = 0;
- drawpic(pos, "gfx/finale", '0 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);
+ pos_z = 0;*/
+
+ //drawpic(pos, "gfx/finale", '0 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);
+
+ //drawstring(pos, "END", sbar_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+ MapVote_Draw();
}
void Sbar_DrawWeapon(float nr, float fade, float active)
@@ -151,94 +166,269 @@
return (l.sb_player > r.sb_player);
}
+void Sbar_Init()
+{
+ entity tm;
+ sortedPlayers = Sort_New(Sbar_PlayerCmp);
+ sortedTeams = Sort_New(Sbar_TeamCmp);
+ team1 = Sort_Next(sortedTeams);
+ team1.sb_team = COLOR_TEAM1;
+ team2 = Sort_Next(sortedTeams);
+ team2.sb_team = COLOR_TEAM2;
+ team3 = Sort_Next(sortedTeams);
+ team3.sb_team = COLOR_TEAM3;
+ team4 = Sort_Next(sortedTeams);
+ team4.sb_team = COLOR_TEAM4;
+ teamspec = Sort_Next(sortedTeams);
+ teamspec.sb_team = COLOR_SPECTATOR;
+}
+
+void Sbar_UpdatePosFrags(entity player)
+{
+ other = player.sort_prev;
+ while(other != sortedPlayers && player.sb_frags > other.sb_frags)
+ {
+ SORT_SWAP(other, player);
+ other = player.sort_prev;
+ }
+
+ other = player.sort_next;
+ while(other && player.sb_frags < other.sb_frags)
+ {
+ SORT_SWAP(player, other);
+ other = player.sort_next;
+ }
+}
+void Sbar_UpdatePosFragsCTF(entity player)
+{
+ other = player.sort_prev;
+ while(other != sortedPlayers && player.sb_frags > other.sb_frags && player.sb_caps == other.sb_caps)
+ {
+ SORT_SWAP(other, player);
+ other = player.sort_prev;
+ }
+
+ other = player.sort_next;
+ while(other && player.sb_frags < other.sb_frags && player.sb_caps == other.sb_caps)
+ {
+ SORT_SWAP(player, other);
+ other = player.sort_next;
+ }
+}
+void Sbar_UpdatePosCaps(entity player)
+{
+ other = player.sort_prev;
+ while(other != sortedPlayers && player.sb_caps > other.sb_caps)
+ {
+ SORT_SWAP(other, player);
+ other = player.sort_prev;
+ }
+ other = player.sort_next;
+ while(other && player.sb_caps < other.sb_caps)
+ {
+ SORT_SWAP(player, other);
+ other = player.sort_next;
+ }
+ // let it update the frags now too, so if we have more frags then the next guy with the same caps
+ // we beat his ass :)
+ player.sb_frags -= 1;
+}
+
+void Sbar_UpdatePosTeam(entity player)
+{
+ player.sb_caps -= 1; // team change needs a full update
+ other = player.sort_prev;
+ while(other != sortedPlayers && player.sb_team > other.sb_team)
+ {
+ SORT_SWAP(other, player);
+ other = player.sort_prev;
+ }
+
+ other = player.sort_next;
+ while(other && player.sb_team < other.sb_team)
+ {
+ SORT_SWAP(player, other);
+ other = player.sort_next;
+ }
+}
+
+void Sbar_UpdatePlayer(entity player)
+{
+ float i;
+
+ if(player.sb_frags == -666)
+ i = COLOR_SPECTATOR;
+ else
+ i = GetPlayerColor(player.sb_player);
+
+ if(player.sb_team != i)
+ {
+ player.sb_team = i;
+ Sbar_UpdatePosTeam(player);
+ }
+
+ if(gametype == GAME_CTF)
+ {
+ i = stof(bufstr_get(databuf, DATABUF_CAPTURES + player.sb_player));
+ if(player.sb_caps != i)
+ {
+ player.sb_caps = i;
+ Sbar_UpdatePosCaps(player);
+ }
+ i = stof(getplayerkey(player.sb_player, "frags"));
+ if(player.sb_frags != i)
+ {
+ player.sb_frags = i;
+ Sbar_UpdatePosFragsCTF(player);
+ }
+ } else {
+ i = stof(getplayerkey(player.sb_player, "frags"));
+ if(player.sb_frags != i)
+ {
+ player.sb_frags = i;
+ Sbar_UpdatePosFrags(player);
+ }
+ }
+}
+
+void Sbar_UpdateTeamPosCaps(entity tm)
+{
+ other = tm.sort_prev;
+ while(other != sortedTeams && tm.sb_caps > other.sb_caps)
+ {
+ SORT_SWAP(other, tm);
+ other = tm.sort_prev;
+ }
+
+ other = tm.sort_next;
+ while(other && tm.sb_caps < tm.sb_caps)
+ {
+ SORT_SWAP(tm, other);
+ other = tm.sort_next;
+ }
+}
+void Sbar_UpdateTeamPosFrags(entity tm)
+{
+ other = tm.sort_prev;
+ while(other != sortedTeams && tm.sb_caps == other.sb_caps && tm.sb_frags > other.sb_frags)
+ {
+ SORT_SWAP(other, tm);
+ other = tm.sort_prev;
+ }
+
+ other = tm.sort_next;
+ while(other && tm.sb_caps == tm.sb_caps && tm.sb_frags < other.sb_frags)
+ {
+ SORT_SWAP(tm, other);
+ other = tm.sort_next;
+ }
+}
+
void Sbar_SortFrags()
{
float i;
entity tmp;
- entity t1, t2, t3, t4, ts;
+ float t1f, t2f, t3f, t4f;
- Sort_Remove(sortedPlayers);
- sortedPlayers = Sort_New(Sbar_PlayerCmp);
+ Sort_Reset(sortedPlayers);
numteams = 0;
if(teamplay)
{
- Sort_Remove(sortedTeams);
-
- t1 = spawn();
- t2 = spawn();
- t3 = spawn();
- t4 = spawn();
- ts = spawn();
-
- t1.sb_team = COLOR_TEAM1;
- t2.sb_team = COLOR_TEAM2;
- t3.sb_team = COLOR_TEAM3;
- t4.sb_team = COLOR_TEAM4;
- ts.sb_team = COLOR_SPECTATOR;
+ Sort_Reset(sortedTeams);
+ tmp = Sort_Next(sortedTeams);
- 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);
+ team1.sb_player = 0;
+ team2.sb_player = 0;
+ team3.sb_player = 0;
+ team4.sb_player = 0;
+ teamspec.sb_player = 0;
+ t1f = team1.sb_frags;
+ t2f = team2.sb_frags;
+ t3f = team3.sb_frags;
+ t4f = team4.sb_frags;
+
+ team1.sb_frags = 0;
+ team2.sb_frags = 0;
+ team3.sb_frags = 0;
+ team4.sb_frags = 0;
+
for(i = 0; i < maxclients; ++i)
{
if(strlen(getplayerkey(i, "name")) <= 0)
continue;
-
- tmp = spawn();
+
+ Sort_Reset(sortedPlayers);
+
+ tmp = NULL;
+ while(Sort_HasNext(sortedPlayers))
+ {
+ tmp = Sort_Next(sortedPlayers);
+ if(tmp.sb_player == i)
+ break;
+ }
+ if(!tmp || tmp.sb_player != i)
+ tmp = Sort_Next(sortedPlayers);
+
tmp.sb_player = i;
- tmp.sb_frags = stof(getplayerkey(i, "frags"));
- tmp.sb_caps = stof(bufstr_get(databuf, DATABUF_CAPTURES + tmp.sb_player));
+ tmp.frame = time;
+ Sbar_UpdatePlayer(tmp);
- if(tmp.sb_frags == -666)
- tmp.sb_team = COLOR_SPECTATOR;
- else
- tmp.sb_team = GetPlayerColor(i);
-
switch(tmp.sb_team)
{
- case COLOR_TEAM1: t1.sb_frags += tmp.sb_frags; t1.sb_player++; break;
- case COLOR_TEAM2: t2.sb_frags += tmp.sb_frags; t2.sb_player++; break;
- case COLOR_TEAM3: t3.sb_frags += tmp.sb_frags; t3.sb_player++; break;
- case COLOR_TEAM4: t4.sb_frags += tmp.sb_frags; t4.sb_player++; break;
- case COLOR_SPECTATOR: ts.sb_frags += tmp.sb_frags; ts.sb_player++; break;
+ case COLOR_TEAM1: team1.sb_frags += tmp.sb_frags; team1.sb_player++; break;
+ case COLOR_TEAM2: team2.sb_frags += tmp.sb_frags; team2.sb_player++; break;
+ case COLOR_TEAM3: team3.sb_frags += tmp.sb_frags; team3.sb_player++; break;
+ case COLOR_TEAM4: team4.sb_frags += tmp.sb_frags; team4.sb_player++; break;
+ case COLOR_SPECTATOR: teamspec.sb_frags += tmp.sb_frags; teamspec.sb_player++; break;
}
if(i == player_localentnum-1)
myteam = tmp.sb_team;
+ }
+ if(team1.sb_player) ++numteams;
+ if(team2.sb_player) ++numteams;
+ if(team3.sb_player) ++numteams;
+ if(team4.sb_player) ++numteams;
- Sort_Add(sortedPlayers, tmp);
+ if(team1.sb_caps != caps_team1)
+ {
+ team1.sb_caps = caps_team1;
+ Sbar_UpdateTeamPosCaps(team1);
}
- if(t1.sb_player) ++numteams;
- if(t2.sb_player) ++numteams;
- if(t3.sb_player) ++numteams;
- if(t4.sb_player) ++numteams;
-
- Sort_Add(sortedTeams, t1);
- Sort_Add(sortedTeams, t2);
- Sort_Add(sortedTeams, t3);
- Sort_Add(sortedTeams, t4);
- Sort_Add(sortedTeams, ts);
-
+ if(team2.sb_caps != caps_team2)
+ {
+ team2.sb_caps = caps_team2;
+ Sbar_UpdateTeamPosCaps(team2);
+ }
+ if(team1.sb_frags != t1f) Sbar_UpdateTeamPosFrags(team1);
+ if(team2.sb_frags != t2f) Sbar_UpdateTeamPosFrags(team2);
+ if(team3.sb_frags != t3f) Sbar_UpdateTeamPosFrags(team3);
+ if(team4.sb_frags != t4f) Sbar_UpdateTeamPosFrags(team4);
} else {
for(i = 0; i < maxclients; ++i)
{
if(strlen(getplayerkey(i, "name")) <= 0)
continue;
- tmp = spawn();
+ Sort_Reset(sortedPlayers);
+ tmp = NULL;
+ while(Sort_HasNext(sortedPlayers))
+ {
+ tmp = Sort_Next(sortedPlayers);
+ if(tmp.sb_player == i)
+ break;
+ }
+ if(!tmp || tmp.sb_player != i)
+ tmp = Sort_Next(sortedPlayers);
+
tmp.sb_player = i;
- tmp.sb_frags = stof(getplayerkey(i, "frags"));
- if(tmp.sb_frags == -666)
- tmp.sb_team = COLOR_SPECTATOR;
- else
- tmp.sb_team = COLOR_TEAM1;
- Sort_Add(sortedPlayers, tmp);
+ tmp.frame = time;
+ Sbar_UpdatePlayer(tmp);
}
}
+ Sort_RemoveOld(sortedPlayers);
}
void Cmd_Sbar_Help(float argc)
@@ -367,7 +557,8 @@
return str;
}
}
-
+#define SBAR_DEFAULT_MASK 0
+#define SBAR_MASK_SPECTATORS 1
float Sbar_IsFieldMasked(float field, float mask)
{
if(mask&1) // spectator
@@ -425,7 +616,7 @@
void Sbar_PrintScoreboardItem(vector pos, entity pl, float is_self, float mask)
{
vector tmp;
- string str, tempstr;
+ string str;
float i, field, len;
// Layout:
@@ -517,7 +708,6 @@
entity pl, tm;
float specs, i;
float center_x;
- string str;
sbar_fontsize = Sbar_GetFontsize();
if(sbar_fontsize_x == 0)
@@ -557,7 +747,7 @@
for(i = 0; i < sbar_num_fields; ++i)
{
- if(Sbar_IsFieldMasked(sbar_field[i]))
+ if(Sbar_IsFieldMasked(sbar_field[i], SBAR_DEFAULT_MASK))
continue;
if(sbar_field[i] == SBF_SEPARATOR)
break;
@@ -571,7 +761,7 @@
tmp_y = tmp_z = 0;
for(i = sbar_num_fields-1; i > 0; --i)
{
- if(Sbar_IsFieldMasked(sbar_field[i]))
+ if(Sbar_IsFieldMasked(sbar_field[i], SBAR_DEFAULT_MASK))
continue;
if(sbar_field[i] == SBF_SEPARATOR)
break;
@@ -639,7 +829,7 @@
{
if(pl.sb_team != tm.sb_team)
continue;
- Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
+ Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), SBAR_DEFAULT_MASK);
pos_y += 1.25 * sbar_fontsize_y;
tmp_y -= 1.25 * sbar_fontsize_y;
}
@@ -654,7 +844,7 @@
if(pl.sb_team != COLOR_SPECTATOR)
continue;
//drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
- Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
+ Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), SBAR_MASK_SPECTATORS);
pos += '0 1.25 0' * sbar_fontsize_y;
++specs;
}
@@ -667,11 +857,10 @@
{
if(pl.sb_team == COLOR_SPECTATOR)
continue;
- Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
+ Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), SBAR_DEFAULT_MASK);
pos_y += 1.25 * sbar_fontsize_y;
tmp_y -= 1.25 * sbar_fontsize_y;
}
- pos_y += tmp_y + 1.5 * sbar_fontsize_y;
// rgb := tempvector :)
rgb = pos + '0 1.5 0' * sbar_fontsize_y;
@@ -682,7 +871,7 @@
if(pl.sb_team != COLOR_SPECTATOR)
continue;
//drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
- Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
+ Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), SBAR_MASK_SPECTATORS);
pos += '0 1.25 0' * sbar_fontsize_y;
++specs;
}
Modified: trunk/data/qcsrc/client/sortlist.qc
===================================================================
--- trunk/data/qcsrc/client/sortlist.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/sortlist.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,5 +1,3 @@
-
-
.float(entity,entity) sort_cmp;
.entity sort_next, sort_prev;
@@ -9,6 +7,7 @@
sort = spawn();
sort.sort_cmp = cmp;
sort.sort_next = NULL;
+ sort.chain = sort;
return sort;
}
@@ -29,8 +28,10 @@
entity next, parent;
parent = sort;
next = sort.sort_next;
- while(next && sort.sort_cmp(next, ent))
+ while(next)
{
+ if(!sort.sort_cmp(next, ent))
+ break;
parent = next;
next = next.sort_next;
}
@@ -41,6 +42,45 @@
next.sort_prev = ent;
}
+void Sort_Reset(entity sort)
+{
+ sort.chain = sort;
+}
+
+float Sort_HasNext(entity sort)
+{
+ return (sort.chain.sort_next != NULL);
+}
+
+entity Sort_Next(entity sort)
+{
+ entity next;
+ next = sort.chain.sort_next;
+ if(!next) {
+ next = spawn();
+ sort.chain.sort_next = next;
+ next.sort_prev = sort.chain;
+ next.sort_next = NULL;
+ }
+ sort.chain = next;
+ return next;
+}
+
+void Sort_Finish(entity sort)
+{
+ entity next;
+ next = sort.chain;
+ if(!next)
+ return;
+
+ while(next.sort_next)
+ {
+ sort = next.sort_next;
+ next.sort_next = sort.sort_next;
+ remove(sort);
+ }
+}
+
entity Sort_Get(entity sort, float i)
{
for(; sort.sort_next && i > 0; --i)
@@ -48,16 +88,31 @@
return sort;
}
-void Sort_DoSort(entity sort)
+#define SORT_SWAP(a,b) \
+ b.sort_prev = a.sort_prev; \
+ a.sort_next = b.sort_next; \
+ if(b.sort_next) b.sort_next.sort_prev = a; \
+ a.sort_prev.sort_next = b; \
+ a.sort_prev = b; \
+ b.sort_next = a
+
+void Sort_Erase(entity ent)
{
- entity newsort, next, tmp;
- newsort = Sort_New(sort.sort_cmp);
- next = sort.sort_next;
- while(next)
+ ent.sort_prev.sort_next = ent.sort_next;
+ if(ent.sort_next)
+ ent.sort_next.sort_prev = ent.sort_prev;
+ remove(ent);
+}
+
+void Sort_RemoveOld(entity sort)
+{
+ entity tmp;
+ for(tmp = sort.sort_next; tmp; tmp = tmp.sort_next)
{
- tmp = next.sort_next;
- Sort_Add(newsort, next);
- next = tmp;
+ if(tmp.frame < time)
+ {
+ tmp = tmp.sort_prev;
+ Sort_Erase(tmp.sort_next);
+ }
}
- sort.sort_next = newsort.sort_next;
}
Modified: trunk/data/qcsrc/client/teamplay.qc
===================================================================
--- trunk/data/qcsrc/client/teamplay.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/client/teamplay.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,3 +1,6 @@
+float numteams; // NOTE: This is changed in Sbar_SortFrags, so use it only AFTER that
+float teamplay;
+float myteam;
float TeamByColor(float color)
{
Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/common/constants.qh 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1,5 +1,7 @@
// COMMIT-TODO: Update if necessary before committing
-#define CSQC_REVISION 1
+// Revision 1: additional statistics sent (flag caps, returns, deaths)
+// Revision 2: Mapvote preview pictures
+#define CSQC_REVISION 2
// probably put these in common/
// so server/ and client/ can be synced better
@@ -163,18 +165,24 @@
const float ENTCS_MSG_ONS_GPS = 1;
const float ENTCS_MSG_ONS_REMOVE = 2;
-const float TE_CSQC_START = 100;
const float TE_CSQC_INIT = 100;
const float TE_CSQC_PING = 101;
const float TE_CSQC_CAPTURES = 102;
const float TE_CSQC_RETURNS = 103;
const float TE_CSQC_DEATHS = 104;
+const float TE_CSQC_PICTURE = 105;
+const float TE_CSQC_MAPVOTE = 106;
-const float TE_CSQC_END = 105;
-
const float STAT_KH_KEYS = 32;
const float STAT_CTF_STATE = 33;
const float CTF_STATE_ATTACK = 1;
const float CTF_STATE_DEFEND = 2;
const float CTF_STATE_COMMANDER = 3;
+// moved that here so the client knows the max.
+// # of maps, I'll use arrays for them :P
+#define MAPVOTE_COUNT 10
+const float MAPVOTE_NET_INIT = 0;
+const float MAPVOTE_NET_UPDATE = 1;
+const float MAPVOTE_NET_PIC = 2;
+const float MAPVOTE_NET_OWNVOTE = 3;
Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/server/cl_client.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1147,6 +1147,11 @@
ctf_UpdateCaptures(MSG_ONE);
ctf_UpdateReturns(MSG_ONE);
net_UpdateDeaths(MSG_ONE);
+ if(mapvote_initialized && !cvar("g_maplist_textonly"))
+ {
+ MapVote_SendData(MSG_ONE);
+ MapVote_UpdateData(MSG_ONE);
+ }
}
}
Modified: trunk/data/qcsrc/server/clientcommands.qc
===================================================================
--- trunk/data/qcsrc/server/clientcommands.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/server/clientcommands.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -172,6 +172,8 @@
if(GameCommand_Vote(s, self)) {
return;
+ } else if(GameCommand_MapVote(argv(0))) {
+ return;
} else if(argv(0) == "autoswitch") {
// be backwards compatible with older clients (enabled)
self.autoswitch = ("0" != argv(1));
Modified: trunk/data/qcsrc/server/g_world.qc
===================================================================
--- trunk/data/qcsrc/server/g_world.qc 2008-07-13 16:39:55 UTC (rev 3818)
+++ trunk/data/qcsrc/server/g_world.qc 2008-07-13 17:42:30 UTC (rev 3819)
@@ -1921,7 +1921,6 @@
float mapvote_timeout;
string mapvote_message;
-#define MAPVOTE_COUNT 10
float mapvote_count;
float mapvote_count_real;
string mapvote_maps[MAPVOTE_COUNT];
@@ -2006,6 +2005,7 @@
mapvote_count += 1;
}
+void MapVote_SendData(float target);
void MapVote_Init()
{
float i;
@@ -2053,7 +2053,87 @@
if(mapvote_count_real < 3 || mapvote_keeptwotime <= time)
mapvote_keeptwotime = 0;
mapvote_message = "Choose a map and press its key!";
+
+ if(!cvar("g_maplist_textonly"))
+ MapVote_SendData(MSG_BROADCAST);
}
+
+void MapVote_SendPicture(float id)
+{
+ msg_entity = self;
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_PICTURE);
+ WritePicture(MSG_ONE, strcat("maps/", mapvote_maps[id]), 1024);
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_MAPVOTE);
+ WriteByte(MSG_ONE, MAPVOTE_NET_PIC);
+ WriteByte(MSG_ONE, id);
+}
+
+float GameCommand_MapVote(string cmd)
+{
+ if(!intermission_running)
+ return FALSE;
+ if(!cvar("g_maplist_textonly"))
+ {
+ if(cmd == "mv_getpic")
+ {
+ MapVote_SendPicture(stof(argv(1)));
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void MapVote_SendData(float targ)
+{
+ string mapfile;
+ float i, o, c;
+ WriteByte(targ, SVC_TEMPENTITY);
+ WriteByte(targ, TE_CSQC_MAPVOTE);
+ WriteByte(targ, MAPVOTE_NET_INIT);
+ WriteByte(targ, mapvote_count);
+ WriteByte(targ, mapvote_abstain);
+ WriteByte(targ, mapvote_detail);
+ for(i = 0; i < mapvote_count; ++i)
+ {
+ WriteString(targ, mapvote_maps[i]);
+ mapfile = strcat("maps/", mapvote_maps[i], ".bsp");
+ localcmd(strcat("\ncurl --pak ", whichpack(mapfile), "\n"));
+ mapfile = whichpack(mapfile);
+ for(o = strstr(mapfile, "/", 0)+1; o > 0; o = strstr(mapfile, "/", 0)+1)
+ mapfile = substring(mapfile, o, 999);
+ for(o = strstr(mapfile, "\\", 0)+1; o > 0; o = strstr(mapfile, "\\", 0)+1)
+ mapfile = substring(mapfile, o, 999);
+ WriteString(targ, mapfile);
+ }
+}
+
+void MapVote_UpdateData(float targ)
+{
+ float i;
+ WriteByte(targ, SVC_TEMPENTITY);
+ WriteByte(targ, TE_CSQC_MAPVOTE);
+ WriteByte(targ, MAPVOTE_NET_UPDATE);
+ for(i = 0; i < mapvote_count; ++i)
+ {
+ if(strlen(mapvote_maps[i]) <= 0)
+ WriteByte(targ, 0);
+ else
+ WriteByte(targ, 1);
+ WriteByte(targ, mapvote_votes[i]);
+ }
+}
+void MapVote_TellVote(float targ, float vote)
+{
+ float i;
+ WriteByte(targ, SVC_TEMPENTITY);
+ WriteByte(targ, TE_CSQC_MAPVOTE);
+ WriteByte(targ, MAPVOTE_NET_OWNVOTE);
+ WriteByte(targ, vote);
+}
+
float MapVote_Finished(float mappos)
{
string result;
@@ -2111,6 +2191,13 @@
mapvote_votes[i] = mapvote_votes[i] + 1;
}
}
+
+ if(!cvar("g_maplist_textonly"))
+ {
+ MapVote_UpdateData(MSG_BROADCAST);
+ FOR_EACH_REALCLIENT(msg_entity)
+ MapVote_TellVote(MSG_ONE, msg_entity.mapvote);
+ }
}
float MapVote_CheckRules_2()
@@ -2231,51 +2318,54 @@
MapVote_CheckRules_1(); // just count
- FOR_EACH_REALCLIENT(other)
+ if(cvar("g_maplist_textonly"))
{
- // display voting screen
- msgstr = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
- msgstr = substring(msgstr, 0, strlen(msgstr) - mapvote_count);
- if(mapvote_abstain)
- msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
- msgstr = strcat(msgstr, mapvote_message);
- msgstr = strcat(msgstr, "\n\n");
- for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps[i] == "")
- msgstr = strcat(msgstr, "\n");
- else
- {
- tmp = mapvote_maps[i];
- tmp = strpad(mapvote_maxlen, tmp);
- tmp = strcat(ftos(mod(i + 1, 10)), ": ", tmp);
- if(mapvote_detail)
- {
- tmp = strcat(tmp, " ^2(", ftos(mapvote_votes[i]), " vote");
- if(mapvote_votes[i] != 1)
- tmp = strcat(tmp, "s");
- tmp = strcat(tmp, ")");
- tmp = strpad(mapvote_maxlen + 15, tmp);
- }
- if(mapvote_abstain)
- if(i == mapvote_count - 1)
- msgstr = strcat(msgstr, "\n");
- if(other.mapvote == i + 1)
- msgstr = strcat(msgstr, "^3> ", tmp, "\n");
+ FOR_EACH_REALCLIENT(other)
+ {
+ // display voting screen
+ msgstr = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
+ msgstr = substring(msgstr, 0, strlen(msgstr) - mapvote_count);
+ if(mapvote_abstain)
+ msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
+ msgstr = strcat(msgstr, mapvote_message);
+ msgstr = strcat(msgstr, "\n\n");
+ for(i = 0; i < mapvote_count; ++i)
+ if(mapvote_maps[i] == "")
+ msgstr = strcat(msgstr, "\n");
else
- msgstr = strcat(msgstr, "^7 ", tmp, "\n");
- }
+ {
+ tmp = mapvote_maps[i];
+ tmp = strpad(mapvote_maxlen, tmp);
+ tmp = strcat(ftos(mod(i + 1, 10)), ": ", tmp);
+ if(mapvote_detail)
+ {
+ tmp = strcat(tmp, " ^2(", ftos(mapvote_votes[i]), " vote");
+ if(mapvote_votes[i] != 1)
+ tmp = strcat(tmp, "s");
+ tmp = strcat(tmp, ")");
+ tmp = strpad(mapvote_maxlen + 15, tmp);
+ }
+ if(mapvote_abstain)
+ if(i == mapvote_count - 1)
+ msgstr = strcat(msgstr, "\n");
+ if(other.mapvote == i + 1)
+ msgstr = strcat(msgstr, "^3> ", tmp, "\n");
+ else
+ msgstr = strcat(msgstr, "^7 ", tmp, "\n");
+ }
- msgstr = strcat(msgstr, "\n\n^2", ftos(totalvotes), " vote");
- if(totalvotes != 1)
- msgstr = strcat(msgstr, "s");
- msgstr = strcat(msgstr, " cast");
- i = ceil(mapvote_timeout - time);
- msgstr = strcat(msgstr, "\n", ftos(i), " second");
- if(i != 1)
- msgstr = strcat(msgstr, "s");
- msgstr = strcat(msgstr, " left");
+ msgstr = strcat(msgstr, "\n\n^2", ftos(totalvotes), " vote");
+ if(totalvotes != 1)
+ msgstr = strcat(msgstr, "s");
+ msgstr = strcat(msgstr, " cast");
+ i = ceil(mapvote_timeout - time);
+ msgstr = strcat(msgstr, "\n", ftos(i), " second");
+ if(i != 1)
+ msgstr = strcat(msgstr, "s");
+ msgstr = strcat(msgstr, " left");
- centerprint_atprio(other, CENTERPRIO_MAPVOTE, msgstr);
+ centerprint_atprio(other, CENTERPRIO_MAPVOTE, msgstr);
+ }
}
}
void MapVote_Start()
More information about the nexuiz-commits
mailing list