From d0661cdc47886b2c9fbe1803024f92f0e5b5e219 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 28 Feb 2006 00:46:04 +0000 Subject: [PATCH] An alternate server browser, accessable via menu_servers2. Needs tweeks. A good base for killing off the origional browser. Mouse driven. Needs keyboard input to actually connect still. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2035 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_master.h | 5 +- engine/client/client.h | 1 + engine/client/m_items.c | 58 ++++- engine/client/m_master.c | 419 ++++++++++++++++++++++++++++++++++- engine/client/m_options.c | 4 +- engine/client/menu.c | 3 + engine/client/menu.h | 9 +- engine/client/merged.h | 1 + engine/client/net_master.c | 50 +++-- engine/ftequake/ftequake.dsp | 9 +- engine/gl/gl_alias.c | 11 +- engine/gl/gl_rlight.c | 4 +- engine/gl/gl_rmain.c | 2 +- 13 files changed, 530 insertions(+), 46 deletions(-) diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index d991a66be..e4226b37b 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -40,6 +40,9 @@ typedef enum{ SLKEY_MAXPLAYERS, SLKEY_GAMEDIR, + SLKEY_FREEPLAYERS, + SLKEY_BASEGAME, + SLKEY_TOOMANY, SLKEY_CUSTOM } hostcachekey_t; @@ -90,7 +93,7 @@ typedef struct serverinfo_s { short tl; short fl; char gamedir[8+1]; - char map[8+1]; + char map[16]; float refreshtime; diff --git a/engine/client/client.h b/engine/client/client.h index 5bebf1417..7621ed53b 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -748,6 +748,7 @@ void CL_TimeDemo_f (void); extern int packet_latency[NET_TIMINGS]; int CL_CalcNet (void); void CL_ParseServerMessage (void); +void CL_DumpPacket(void); void CLNQ_ParseServerMessage (void); #ifdef Q2CLIENT void CLQ2_ParseServerMessage (void); diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 610ab4826..c0f6001d1 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -173,6 +173,11 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) Draw_TransPic (xpos+option->common.posx, ypos+option->common.posy, p); break; + + case mt_strechpic: + p = Draw_SafeCachePic(option->picture.picturename); + if (p) Draw_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width, option->common.height, p); + break; case mt_childwindow: MenuDrawItems(xpos+option->common.posx, ypos+option->common.posy, ((menu_t *)option->custom.data)->options, (menu_t *)option->custom.data); break; @@ -216,7 +221,7 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) int y = ypos+option->common.posy; qboolean on; if (option->check.func) - on = option->check.func(option, CHK_CHECKED); + on = option->check.func(&option->check, menu, CHK_CHECKED); else if (!option->check.var) on = option->check.value; else if (option->check.bits) //bits is a bitmask for use with cvars (users can be clumsy, so bittage of 0 uses non-zero as true, but sets only bit 1) @@ -340,7 +345,8 @@ void MenuDraw(menu_t *menu) { if (menu->event) menu->event(menu); - menu->xpos = ((vid.width - 320)>>1); + if (!menu->dontexpand) + menu->xpos = ((vid.width - 320)>>1); MenuDrawItems(menu->xpos, menu->ypos, menu->options, menu); } @@ -429,6 +435,29 @@ menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, char *picname) return n; } +menupicture_t *MC_AddStrechPicture(menu_t *menu, int x, int y, int width, int height, char *picname) +{ + menupicture_t *n; + if (!qrenderer) + return NULL; + + Draw_SafeCachePic(picname); + + n = Z_Malloc(sizeof(menupicture_t) + strlen(picname)+1); + n->common.type = mt_strechpic; + n->common.iszone = true; + n->common.posx = x; + n->common.posy = y; + n->common.width = width; + n->common.height = height; + n->picturename = (char *)(n+1); + strcpy(n->picturename, picname); + + n->common.next = menu->options; + menu->options = (menuoption_t *)n; + return n; +} + menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, char *picname) { int x; @@ -568,6 +597,25 @@ menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t menu->options = (menuoption_t *)n; return n; } +menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits) +{ + menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); + n->common.type = mt_checkbox; + n->common.iszone = true; + n->common.posx = x; + n->common.posy = y; + n->common.height = 8; + n->common.width = (strlen(text)+7)*8; + n->text = (char *)(n+1); + strcpy((char *)(n+1), text); + n->func = func; + n->bits = bits; + + n->common.next = menu->options; + menu->options = (menuoption_t *)n; + return n; +} + menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t *var, float min, float max) { menuslider_t *n = Z_Malloc(sizeof(menuslider_t)+strlen(text)+1); @@ -774,12 +822,12 @@ void MC_Slider_Key(menuslider_t *option, int key) S_LocalSound ("misc/menu2.wav"); } -void MC_CheckBox_Key(menucheck_t *option, int key) +void MC_CheckBox_Key(menucheck_t *option, menu_t *menu, int key) { if (key != K_ENTER && key != K_LEFTARROW && key != K_RIGHTARROW && key != K_MOUSE1) return; if (option->func) - option->func((union menuoption_s *)option, CHK_TOGGLE); + option->func(option, menu, CHK_TOGGLE); else if (!option->var) option->value = !option->value; else @@ -1164,7 +1212,7 @@ void M_Complex_Key(int key) MC_Slider_Key(¤tmenu->selecteditem->slider, key); break; case mt_checkbox: - MC_CheckBox_Key(¤tmenu->selecteditem->check, key); + MC_CheckBox_Key(¤tmenu->selecteditem->check, currentmenu, key); break; case mt_button: case mt_buttonbigfont: diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 44c0e7c6a..3cbe05fcd 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -3,18 +3,6 @@ #ifdef CL_MASTER #include "cl_master.h" -enum { -SLISTTYPE_SERVERS, -SLISTTYPE_FAVORITES, -SLISTTYPE_SOURCES, -SLISTTYPE_OPTIONS //must be last -} slist_option; - -int slist_numoptions; -int slist_firstoption; - -int slist_type; - //filtering cvar_t sb_hideempty = SCVARF("sb_hideempty", "0", CVAR_ARCHIVE); cvar_t sb_hidenotempty = SCVARF("sb_hidenotempty", "0", CVAR_ARCHIVE); @@ -71,6 +59,19 @@ void M_Serverlist_Init(void) Cvar_Register(&slist_cacheinfo, grp); } +enum { + SLISTTYPE_SERVERS, + SLISTTYPE_FAVORITES, + SLISTTYPE_SOURCES, + SLISTTYPE_OPTIONS //must be last +} slist_option; + +int slist_numoptions; +int slist_firstoption; + +int slist_type; + + static void NM_DrawColouredCharacter (int cx, int line, unsigned int num) { @@ -871,4 +872,398 @@ void M_SListKey(int key) return; } } + + + + + + + + + + + + + +typedef struct { + int visibleslots; + int scrollpos; + int selectedpos; + + int numslots; + qboolean stillpolling; + qbyte filter[8]; + + qboolean sliderpressed; + + menupicture_t *mappic; +} serverlist_t; + +void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) +{ + x = ths->common.width/8; + if (sb_showtimelimit.value) {x-=4; Draw_FunStringLen(x+8, y, "tl", 3); } + if (sb_showfraglimit.value) {x-=4; Draw_FunStringLen(x+8, y, "fl", 3); } + if (sb_showplayers.value) {Draw_FunStringLen((x-5)*8, y, "plyrs", 5); x-=6;} + if (sb_showmap.value) {Draw_FunStringLen((x-8)*8, y, "map", 8); x-=9;} + if (sb_showgamedir.value) {Draw_FunStringLen((x-8)*8, y, "gamedir", 8); x-=9;} + if (sb_showping.value) {Draw_FunStringLen((x-3)*8, y, "png", 3); x-=4;} + if (sb_showaddress.value) {Draw_FunStringLen((x-21)*8, y, "address", 21); x-=22;} + Draw_FunStringLen(0, y, "name", x); +} + +qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key) +{ + int x; + extern int mousecursor_x, mousecursor_y; + int mx = mousecursor_x/8; + int sortkey; + + if (key != K_MOUSE1) + return false; + + do { + x = ths->common.width/8; + if (mx > x) return false; //out of bounds + if (sb_showtimelimit.value) {x-=4;if (mx > x) {sortkey = SLKEY_NAME; break;}} + if (sb_showfraglimit.value) {x-=4;if (mx > x) {sortkey = SLKEY_NAME; break;}} + if (sb_showplayers.value) {x-=6;if (mx > x) {sortkey = SLKEY_NUMPLAYERS; break;}} + if (sb_showmap.value) {x-=9;if (mx > x) {sortkey = SLKEY_MAP; break;}} + if (sb_showgamedir.value) {x-=9;if (mx > x) {sortkey = SLKEY_GAMEDIR; break;}} + if (sb_showping.value) {x-=4;if (mx > x) {sortkey = SLKEY_PING; break;}} + if (sb_showaddress.value) {x-=22;if (mx > x) {sortkey = SLKEY_ADDRESS; break;}} + sortkey = SLKEY_NAME;break; + } while (0); + + Master_SetSortField(sortkey, Master_GetSortField()!=sortkey||!Master_GetSortDescending()); + return true; +} + + +void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) +{ + extern int mousecursor_x, mousecursor_y; + serverlist_t *info = (serverlist_t*)(menu + 1); + serverinfo_t *si; + int thisone = (int)ths->data + info->scrollpos; + si = Master_SortedServer(thisone); + if (si) + { + x = ths->common.width; + if (thisone == info->selectedpos) + Draw_Fill(0, y, ths->common.width, 8, 63-24); + else if (thisone == info->scrollpos + (mousecursor_y-16)/8 && mousecursor_x < x) + Draw_Fill(0, y, ths->common.width, 8, (int)(sin(realtime*4.4)*4)+12+16); + else if (thisone & 1) + Draw_Fill(0, y, ths->common.width, 8, 1); + else + Draw_Fill(0, y, ths->common.width, 8, 2); + + x /= 8; + + if (sb_showtimelimit.value) {Draw_FunStringLen((x-3)*8, y, va("%i", si->tl), 3); x-=4;} + if (sb_showfraglimit.value) {Draw_FunStringLen((x-3)*8, y, va("%i", si->fl), 3); x-=4;} + if (sb_showplayers.value) {Draw_FunStringLen((x-5)*8, y, va("%2i/%2i", si->players, si->maxplayers), 5); x-=6;} + if (sb_showmap.value) {Draw_FunStringLen((x-8)*8, y, si->map, 8); x-=9;} + if (sb_showgamedir.value) {Draw_FunStringLen((x-8)*8, y, si->gamedir, 8); x-=9;} + if (sb_showping.value) {Draw_FunStringLen((x-3)*8, y, va("%i", si->ping), 3); x-=4;} + if (sb_showaddress.value) {Draw_FunStringLen((x-21)*8, y, NET_AdrToString(si->adr), 21); x-=22;} + Draw_FunStringLen(0, y, si->name, x); + } +} +qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) +{ + extern int mousecursor_x, mousecursor_y; + serverlist_t *info = (serverlist_t*)(menu + 1); + serverinfo_t *server; + if (key == K_MOUSE1) + { + info->selectedpos = info->scrollpos + (mousecursor_y-16)/8; + { + serverinfo_t *server; + server = Master_SortedServer(info->selectedpos); + if (server) + { + _snprintf(info->mappic->picturename, 32, "levelshots/%s", server->map); + } + else + { + _snprintf(info->mappic->picturename, 32, "levelshots/nomap"); + } + } + } + if (key == K_ENTER || key == 's' || key == 'j') + { + server = Master_SortedServer((int)ths->data + info->scrollpos); + if (server) + { + if (key == 's') + Cbuf_AddText("spectator 1\n", RESTRICT_LOCAL); + else if (key == 'j') + Cbuf_AddText("spectator 0\n", RESTRICT_LOCAL); + + if (server->special & SS_NETQUAKE) + Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(server->adr)), RESTRICT_LOCAL); + else + Cbuf_AddText(va("connect %s\n", NET_AdrToString(server->adr)), RESTRICT_LOCAL); + } + return true; + } + return false; +} +void SL_PreDraw (menu_t *menu) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + NET_CheckPollSockets(); + + CL_QueryServers(); + + info->numslots = Master_NumSorted(); +} +qboolean SL_Key (int key, menu_t *menu) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + + if (key == K_HOME) + { + info->scrollpos = 0; + info->selectedpos = 0; + return true; + } + if (key == K_END) + { + info->selectedpos = info->numslots-1; + info->scrollpos = info->selectedpos - (vid.height-16-7)/8; + return true; + } + if (key == K_PGDN) + info->selectedpos += 10; + else if (key == K_PGUP) + info->selectedpos -= 10; + else if (key == K_DOWNARROW) + info->selectedpos += 1; + else if (key == K_UPARROW) + info->selectedpos -= 1; + else if (key == K_MWHEELUP) + info->selectedpos -= 3; + else if (key == K_MWHEELDOWN) + info->selectedpos += 3; + else + return false; + + { + serverinfo_t *server; + server = Master_SortedServer(info->selectedpos); + if (server) + { + _snprintf(info->mappic->picturename, 32, "levelshots/%s", server->map); + } + else + { + _snprintf(info->mappic->picturename, 32, "levelshots/nomap"); + } + } + + if (info->selectedpos < 0) + info->selectedpos = 0; + if (info->selectedpos > info->numslots-1) + info->selectedpos = info->numslots-1; + if (info->scrollpos < info->selectedpos - info->visibleslots) + info->scrollpos = info->selectedpos - info->visibleslots; + if (info->selectedpos < info->scrollpos) + info->scrollpos = info->selectedpos; + + return true; +} + +void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + Draw_Fill(x, y, ths->common.width, ths->common.height, 54); + + y += ((info->scrollpos) / ((float)info->numslots - info->visibleslots)) * (ths->common.height-8); + + Draw_Fill(x, y, 8, 8, 45); + + if (info->sliderpressed) + { + extern qboolean keydown[K_MAX]; + if (keydown[K_MOUSE1]) + { + extern int mousecursor_x, mousecursor_y; + float my; + serverlist_t *info = (serverlist_t*)(menu + 1); + + my = mousecursor_y; + my -= ths->common.posy; + my /= ths->common.height; + my *= (info->numslots-info->visibleslots); + + if (my > info->numslots-info->visibleslots-1) + my = info->numslots-info->visibleslots-1; + if (my < 0) + my = 0; + + info->scrollpos = my; + } + else + info->sliderpressed = false; + } +} +qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) +{ + if (key == K_MOUSE1) + { + extern int mousecursor_x, mousecursor_y; + float my; + serverlist_t *info = (serverlist_t*)(menu + 1); + + my = mousecursor_y; + my -= ths->common.posy; + my /= ths->common.height; + my *= (info->numslots-info->visibleslots); + + if (my > info->numslots-info->visibleslots-1) + my = info->numslots-info->visibleslots-1; + if (my < 0) + my = 0; + + info->scrollpos = my; + info->sliderpressed = true; + return true; + } + return false; +} + +void CalcFilters(menu_t *menu) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + + Master_ClearMasks(); + + Master_SetMaskInteger(false, SLKEY_PING, 0, SLIST_TEST_LESS); + if (info->filter[1]) Master_SetMaskInteger(true, SLKEY_BASEGAME, SS_NETQUAKE|SS_DARKPLACES, SLIST_TEST_CONTAINS); + if (info->filter[2]) Master_SetMaskInteger(true, SLKEY_BASEGAME, SS_NETQUAKE|SS_DARKPLACES|SS_QUAKE2|SS_QUAKE3, SLIST_TEST_NOTCONTAIN); + if (info->filter[3]) Master_SetMaskInteger(true, SLKEY_BASEGAME, SS_QUAKE2, SLIST_TEST_CONTAINS); + if (info->filter[4]) Master_SetMaskInteger(true, SLKEY_BASEGAME, SS_QUAKE3, SLIST_TEST_CONTAINS); + + if (info->filter[6]) Master_SetMaskInteger(false, SLKEY_NUMPLAYERS, 0, SLIST_TEST_NOTEQUAL); + if (info->filter[7]) Master_SetMaskInteger(false, SLKEY_FREEPLAYERS, 0, SLIST_TEST_NOTEQUAL); +} + +qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + switch(set) + { + case CHK_CHECKED: + return info->filter[option->bits]; + case CHK_TOGGLE: + if (option->bits>0) + info->filter[option->bits] ^= 1; + + CalcFilters(menu); + + return true; + } + + return true; +} + +void SL_Remove (menu_t *menu) +{ + serverlist_t *info = (serverlist_t*)(menu + 1); + + Cvar_Set(&sb_hidenetquake, info->filter[1]?"0":"1"); + Cvar_Set(&sb_hidequakeworld, info->filter[2]?"0":"1"); + Cvar_Set(&sb_hidequake2, info->filter[3]?"0":"1"); + Cvar_Set(&sb_hidequake3, info->filter[4]?"0":"1"); + + Cvar_Set(&sb_hideempty, info->filter[6]?"1":"0"); + Cvar_Set(&sb_hidefull, info->filter[7]?"1":"0"); +} + +void M_Menu_ServerList2_f(void) +{ + int i, y; + menu_t *menu; + menucustom_t *cust; + serverlist_t *info; + + key_dest = key_menu; + m_state = m_complex; + + MasterInfo_Begin(); + + menu = M_CreateMenu(sizeof(serverlist_t)); + menu->event = SL_PreDraw; + menu->key = SL_Key; + menu->remove = SL_Remove; + + info = (serverlist_t*)(menu + 1); + + y = 8; + cust = MC_AddCustom(menu, 0, y, 0); + cust->draw = SL_TitlesDraw; + cust->key = SL_TitlesKey; + cust->common.height = 8; + cust->common.width = vid.width-8; + + info->visibleslots = (vid.height-16 - 64); + + cust = MC_AddCustom(menu, vid.width-8, 16, NULL); + cust->draw = SL_SliderDraw; + cust->key = SL_SliderKey; + cust->common.height = info->visibleslots; + cust->common.width = 8; + + info->visibleslots = (info->visibleslots-7)/8; + for (i = 0, y = 16; i <= info->visibleslots; y +=8, i++) + { + cust = MC_AddCustom(menu, 0, y, (void*)i); + cust->draw = SL_ServerDraw; + cust->key = SL_ServerKey; + cust->common.height = 8; + cust->common.width = vid.width-8; + } + menu->dontexpand = true; + + MC_AddCheckBox(menu, 0, vid.height - 64+8*1, "Ping ", &sb_showping, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*2, "Address ", &sb_showaddress, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*3, "Map ", &sb_showmap, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*4, "Gamedir ", &sb_showgamedir, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*5, "Players ", &sb_showplayers, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*6, "Fraglimit", &sb_showfraglimit, 1); + MC_AddCheckBox(menu, 0, vid.height - 64+8*7, "Timelimit", &sb_showtimelimit, 1); + + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*1, "List NQ ", SL_ReFilter, 1); + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*2, "List QW ", SL_ReFilter, 2); + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*3, "List Q2 ", SL_ReFilter, 3); + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*4, "List Q3 ", SL_ReFilter, 4); + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*6, "Hide Empty", SL_ReFilter, 6); + MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*7, "Hide Full ", SL_ReFilter, 7); + + info->filter[1] = !sb_hidenetquake.value; + info->filter[2] = !sb_hidequakeworld.value; + info->filter[3] = !sb_hidequake2.value; + info->filter[4] = !sb_hidequake3.value; + info->filter[6] = !!sb_hideempty.value; + info->filter[7] = !!sb_hidefull.value; + + info->mappic = (menupicture_t *)MC_AddStrechPicture(menu, vid.width - 64, vid.height - 64, 64, 64, "012345678901234567890123456789012"); + + CalcFilters(menu); + + Master_SetSortField(SLKEY_PING, true); +} + + + + + + + + + + #endif diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 622ea43b0..67c6882b1 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -4,7 +4,7 @@ #include "winquake.h" //these are awkward/strange -qboolean M_Options_AlwaysRun (union menuoption_s *option, chk_set_t set) +qboolean M_Options_AlwaysRun (menucheck_t *option, struct menu_s *menu, chk_set_t set) { if (set == CHK_CHECKED) return cl_forwardspeed.value > 200; @@ -21,7 +21,7 @@ qboolean M_Options_AlwaysRun (union menuoption_s *option, chk_set_t set) return true; } } -qboolean M_Options_InvertMouse (union menuoption_s *option, chk_set_t set) +qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_set_t set) { if (set == CHK_CHECKED) return m_pitch.value < 0; diff --git a/engine/client/menu.c b/engine/client/menu.c index 8641a1321..cc9510c9f 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -804,6 +804,7 @@ void M_Menu_Quit_f (void) //============================================================================= /* Menu Subsystem */ +void M_Menu_ServerList2_f(void); void M_Menu_MediaFiles_f (void); void M_Menu_FPS_f (void); @@ -838,6 +839,8 @@ void M_Init_Internal (void) Cmd_AddRemCommand ("menu_mediafiles", M_Menu_MediaFiles_f); #ifdef CL_MASTER + Cmd_AddRemCommand ("menu_servers2", M_Menu_ServerList2_f); + Cmd_AddRemCommand ("menu_servers", M_Menu_ServerList_f); Cmd_AddRemCommand ("menu_slist", M_Menu_ServerList_f); #endif diff --git a/engine/client/menu.h b/engine/client/menu.h index d3a841e6a..24e8b5dee 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -116,7 +116,7 @@ struct menu_s; typedef enum {m_none, m_complex, m_help, m_keys, m_slist, m_media, m_plugin, m_menu_dat} m_state_t; extern m_state_t m_state; -typedef enum {mt_childwindow, mt_button, mt_buttonbigfont, mt_box, mt_colouredbox, mt_line, mt_edit, mt_text, mt_slider, mt_combo, mt_bind, mt_checkbox, mt_picture, mt_menudot, mt_custom} menutype_t; +typedef enum {mt_childwindow, mt_button, mt_buttonbigfont, mt_box, mt_colouredbox, mt_line, mt_edit, mt_text, mt_slider, mt_combo, mt_bind, mt_checkbox, mt_picture, mt_strechpic, mt_menudot, mt_custom} menutype_t; typedef struct { //must be first of each structure type. menutype_t type; @@ -158,13 +158,13 @@ typedef struct { } menuslider_t; typedef enum {CHK_CHECKED, CHK_TOGGLE} chk_set_t; -typedef struct { +typedef struct menucheck_s { menucommon_t common; const char *text; cvar_t *var; int bits; float value; - qboolean (*func) (union menuoption_s *option, chk_set_t set); + qboolean (*func) (struct menucheck_s *option, struct menu_s *menu, chk_set_t set); } menucheck_t; typedef struct { @@ -227,6 +227,7 @@ typedef struct menu_s { int ypos; int width; int height; + qboolean dontexpand; int numoptions; qboolean iszone; @@ -254,10 +255,12 @@ menutext_t *MC_AddWhiteText(menu_t *menu, int x, int y, const char *text, qboole menubind_t *MC_AddBind(menu_t *menu, int x, int y, const char *caption, char *command); menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height); menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, char *picname); +menupicture_t *MC_AddStrechPicture(menu_t *menu, int x, int y, int width, int height, char *picname); menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, char *picname); menupicture_t *MC_AddCursor(menu_t *menu, int x, int y); menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t *var, float min, float max); menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t *var, int cvarbitmask); +menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits); menubutton_t *MC_AddConsoleCommand(menu_t *menu, int x, int y, const char *text, const char *command); menubutton_t *MC_AddCommand(menu_t *menu, int x, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int)); menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const char **text, int initialvalue); diff --git a/engine/client/merged.h b/engine/client/merged.h index bc967bd13..fffc91ce1 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -106,6 +106,7 @@ extern int FNC(Mod_SkinForName) (struct model_s *model, char *name); #undef FNC void Draw_FunString(int x, int y, unsigned char *str); +void Draw_FunStringLen(int x, int y, unsigned char *str, int len); #ifdef SERVERONLY diff --git a/engine/client/net_master.c b/engine/client/net_master.c index eeb30014b..4e7ff1aa7 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -153,7 +153,7 @@ qboolean Master_CompareInteger(int a, int b, slist_test_t rule) switch(rule) { case SLIST_TEST_CONTAINS: - return a&b; + return !!(a&b); case SLIST_TEST_NOTCONTAIN: return !(a&b); case SLIST_TEST_LESSEQUAL: @@ -205,6 +205,10 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b) return Master_CompareInteger(a->players, b->players, SLIST_TEST_LESS); case SLKEY_MAXPLAYERS: return Master_CompareInteger(a->maxplayers, b->maxplayers, SLIST_TEST_LESS); + case SLKEY_FREEPLAYERS: + return Master_CompareInteger(a->maxplayers - a->players, b->maxplayers - b->players, SLIST_TEST_LESS); + case SLKEY_BASEGAME: + return Master_CompareInteger(a->special, b->special, SLIST_TEST_LESS); case SLKEY_MAP: return Master_CompareString(a->map, b->map, SLIST_TEST_LESS); case SLKEY_GAMEDIR: @@ -218,43 +222,53 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b) qboolean Master_PassesMasks(serverinfo_t *a) { int i; + qboolean val, res; //always filter out dead unresponsive servers. if (!a->ping) return false; + val = 1; + for (i = 0; i < numvisrules; i++) { switch(visrules[i].fieldindex) { case SLKEY_PING: - if (!Master_CompareInteger(a->ping, visrules[i].operandi, visrules[i].compareop)) - return false; + res = Master_CompareInteger(a->ping, visrules[i].operandi, visrules[i].compareop); break; case SLKEY_NUMPLAYERS: - if (!Master_CompareInteger(a->players, visrules[i].operandi, visrules[i].compareop)) - return false; + res = Master_CompareInteger(a->players, visrules[i].operandi, visrules[i].compareop); break; case SLKEY_MAXPLAYERS: - if (!Master_CompareInteger(a->maxplayers, visrules[i].operandi, visrules[i].compareop)) - return false; + res = Master_CompareInteger(a->maxplayers, visrules[i].operandi, visrules[i].compareop); + break; + case SLKEY_FREEPLAYERS: + res = Master_CompareInteger(a->maxplayers-a->players, visrules[i].operandi, visrules[i].compareop); break; case SLKEY_MAP: - if (!Master_CompareString(a->map, visrules[i].operands, visrules[i].compareop)) - return false; + res = Master_CompareString(a->map, visrules[i].operands, visrules[i].compareop); break; case SLKEY_NAME: - if (!Master_CompareString(a->name, visrules[i].operands, visrules[i].compareop)) - return false; + res = Master_CompareString(a->name, visrules[i].operands, visrules[i].compareop); break; case SLKEY_GAMEDIR: - if (!Master_CompareString(a->gamedir, visrules[i].operands, visrules[i].compareop)) - return false; + res = Master_CompareString(a->gamedir, visrules[i].operands, visrules[i].compareop); break; + + case SLKEY_BASEGAME: + res = Master_CompareInteger(a->special, visrules[i].operandi, visrules[i].compareop); + break; + default: + continue; } + if (visrules[i].or) + val |= res; + else + val &= res; } - return true; + return val; } void Master_ClearMasks(void) @@ -408,6 +422,10 @@ float Master_ReadKeyFloat(serverinfo_t *server, int keynum) return server->players; case SLKEY_MAXPLAYERS: return server->maxplayers; + case SLKEY_FREEPLAYERS: + return server->maxplayers - server->players; + case SLKEY_BASEGAME: + return server->special; default: return atof(Master_ReadKeyString(server, keynum)); @@ -463,8 +481,12 @@ int Master_KeyForName(char *keyname) return SLKEY_MAXPLAYERS; else if (!strcmp(keyname, "numplayers")) return SLKEY_NUMPLAYERS; + else if (!strcmp(keyname, "freeplayers")) + return SLKEY_FREEPLAYERS; else if (!strcmp(keyname, "gamedir") || !strcmp(keyname, "game") || !strcmp(keyname, "*gamedir") || !strcmp(keyname, "mod")) return SLKEY_GAMEDIR; + else if (!strcmp(keyname, "special")) + return SLKEY_BASEGAME; else if (slist_customkeys == SLIST_MAXKEYS) return SLKEY_TOOMANY; diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 4b9ea930b..6c00ab8f4 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -165,6 +165,7 @@ LINK32=link.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client\gltod3d\sdk7\include" /I "..\client\gltod3d\D3DFrame" /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /I "..\client" /D "NQPROT" /D "_DEBUG" /D "GLQUAKE" /D "SERVERDLL" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /YX /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c # ADD CPP /nologo /G5 /W3 /Gi /GX /ZI /Od /I "..\client" /I "../libs/dxsdk7/include" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE" /D "SWQUAKE" /D "USE_D3D" /Fr /Fp".\MDebug/qwcl.pch" /Yu"quakedef.h" /FD /c +# SUBTRACT CPP /WX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" @@ -9284,8 +9285,8 @@ SOURCE=..\client\winquake.rc !IF "$(CFG)" == "ftequake - Win32 Release" -# ADD BASE RSC /l 0x809 /i "\Projects\fteqw\engine\client" /i "\ftetgcvs\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" -# ADD RSC /l 0x809 /i "\Projects\fteqw\engine\client" /i "\ftetgcvs\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" /d "MINIMAL" +# ADD BASE RSC /l 0x809 /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" +# ADD RSC /l 0x809 /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" /d "MINIMAL" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug" @@ -9354,6 +9355,10 @@ SOURCE=..\nqnet\net_dgrm.h SOURCE=..\common\protocol.h # End Source File +# Begin Source File + +SOURCE=..\client\quakedef.h +# End Source File # End Group # Begin Group "Resource Files" diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 0cf5779f3..ea5340c7c 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -2001,7 +2001,7 @@ void R_DrawGAliasModel (entity_t *e) skin = GL_ChooseSkin(inf, clmodel->name, surfnum, e); - if (!skin || (skin->base == NULL + if (!skin || ((void*)skin->base == NULL #ifdef Q3SHADERS && skin->shader == NULL #endif @@ -3524,12 +3524,15 @@ static void Q2_LoadSkins(char *skins) galias->numskins = LittleLong(pq2inmodel->num_skins); #ifndef SERVERONLY - while (galias->numskins) + outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); + outskin += galias->numskins - 1; + if (galias->numskins) { + texnums = (galiastexnum_t*)((char *)outskin +outskin->ofstexnums); if (texnums->base) - break; + return; if (texnums->shader) - break; + return; galias->numskins--; } diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index a7ce0512e..fe409933f 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -380,8 +380,8 @@ void GLR_PushDlights (void) if (!r_dynamic.value || !cl.worldmodel) return; -// if (!cl.worldmodel->nodes) -// return; + if (!cl.worldmodel->nodes) + return; currentmodel = cl.worldmodel; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index a70fb520a..f9cb8b535 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1616,7 +1616,7 @@ void R_RenderScene (void) { qboolean GLR_DoomWorld(void); - if (!cl.worldmodel) + if (!cl.worldmodel || !cl.worldmodel->nodes) r_refdef.flags |= Q2RDF_NOWORLDMODEL; GLR_SetupFrame ();