diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index ab64f945e..3657f7e2d 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -83,7 +83,7 @@ void CL_StopPlayback (void) if (cls.timedemo) CL_FinishTimeDemo (); - TP_ExecTrigger("f_demoend"); + TP_ExecTrigger("f_demoend", true); } /* @@ -1684,7 +1684,7 @@ void CL_PlayDemoStream(vfsfile_t *file, struct dl_download *dl, char *filename, Con_Printf("Buffering for %g seconds\n", bufferdelay); cls.netchan.last_received=demtime; - TP_ExecTrigger ("f_demostart"); + TP_ExecTrigger ("f_demostart", true); } vfsfile_t *CL_OpenFileInZipOrSys(char *name, qboolean usesystempath) @@ -1813,7 +1813,7 @@ void CL_PlayDemo(char *demoname, qboolean usesystempath) Con_Printf ("ERROR: couldn't open \"%s\".\n", demoname); cls.demonum = -1; // stop demo loop - TP_ExecTrigger ("f_demoend"); + TP_ExecTrigger ("f_demoend", true); return; } Q_strncpyz (lastdemoname, demoname, sizeof(lastdemoname)); @@ -2435,7 +2435,7 @@ void CL_FinishTimeDemo (void) cls.td_startframe = 0; - TP_ExecTrigger ("f_timedemoend"); + TP_ExecTrigger ("f_timedemoend", true); vw = Cvar_FindVar("vid_wait"); Cvar_Set(vw, vw->string); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 2c53c23c6..f1f9b833f 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -87,7 +87,7 @@ cvar_t cl_serveraddress = CVARD("cl_serveraddress", "none", "The address of the cvar_t qtvcl_forceversion1 = CVAR("qtvcl_forceversion1", "0"); cvar_t qtvcl_eztvextensions = CVAR("qtvcl_eztvextensions", "0"); -cvar_t cl_demospeed = CVARAF("cl_demospeed", "1", "demo_setspeed", 0); +cvar_t cl_demospeed = CVARF("cl_demospeed", "1", 0); cvar_t cl_demoreel = CVARFD("cl_demoreel", "0", CVAR_SAVE, "When enabled, the engine will begin playing a demo loop on startup."); cvar_t cl_loopbackprotocol = CVARD("cl_loopbackprotocol", "qw", "Which protocol to use for single-player/the internal client. Should be one of: qw, qwid, nqid, nq, fitz, dp6, dp7. If empty, will use qw protocols for qw mods, and nq protocols for nq mods."); @@ -331,7 +331,11 @@ void CL_MakeActive(char *gamename) Mod_Purge(MP_MAPCHANGED); - TP_ExecTrigger("f_spawn"); + TP_ExecTrigger("f_begin", true); + if (cls.demoplayback) + TP_ExecTrigger("f_spawndemo", true); + else + TP_ExecTrigger("f_spawn", false); } /* ================== @@ -353,7 +357,7 @@ void CL_Quit_f (void) } } - TP_ExecTrigger("f_quit"); + TP_ExecTrigger("f_quit", true); Cbuf_Execute(); /* #ifndef CLIENTONLY @@ -3507,6 +3511,18 @@ void CL_Status_f(void) Con_Printf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit. } +void CL_Demo_SetSpeed_f(void) +{ + char *s = Cmd_Argv(1); + if (s) + { + float f = atof(s)/100; + Cvar_SetValue(&cl_demospeed, f); + } + else + Con_Printf("demo playback speed %g%%\n", cl_demospeed.value * 100); +} + void CL_Skygroup_f(void); /* ================= @@ -3566,6 +3582,7 @@ void CL_Init (void) Cvar_Register (&cl_servername, cl_controlgroup); Cvar_Register (&cl_serveraddress, cl_controlgroup); Cvar_Register (&cl_demospeed, "Demo playback"); + Cmd_AddCommand("demo_setspeed", CL_Demo_SetSpeed_f); Cvar_Register (&cl_upspeed, cl_inputgroup); Cvar_Register (&cl_forwardspeed, cl_inputgroup); Cvar_Register (&cl_backspeed, cl_inputgroup); @@ -4927,7 +4944,7 @@ void CL_StartCinematicOrMenu(void) Con_ClearNotify(); - TP_ExecTrigger("f_startup"); + TP_ExecTrigger("f_startup", true); Cbuf_Execute (); if (com_installer) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index eba64b4f3..38df2b524 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3504,7 +3504,7 @@ void CLNQ_ParseClientdata (void) if (bits & SU_VIEWHEIGHT) CL_SetStatInt(0, STAT_VIEWHEIGHT, MSG_ReadChar ()); - else// if (CPNQ_IS_DP || cls.protocol_nq == CPNQ_DP5) + else if (!CPNQ_IS_DP || cls.protocol_nq <= CPNQ_DP5) CL_SetStatInt(0, STAT_VIEWHEIGHT, DEFAULT_VIEWHEIGHT); if (bits & SU_IDEALPITCH) @@ -3560,7 +3560,7 @@ void CLNQ_ParseClientdata (void) CL_SetStatInt(0, STAT_ACTIVEWEAPON, (unsigned short)MSG_ReadShort()); } - else if (CPNQ_IS_DP) + else if (CPNQ_IS_DP && cls.protocol_nq > CPNQ_DP5) { /*nothing in dp6+*/ } @@ -3621,7 +3621,7 @@ void CLNQ_ParseClientdata (void) { if (bits & DPSU_VIEWZOOM) { - if (cls.protocol_nq) + if (cls.protocol_nq >= CPNQ_DP5) i = (unsigned short) MSG_ReadShort(); else i = MSG_ReadByte(); @@ -4646,7 +4646,7 @@ void CL_UpdateUserinfo (void) char *qz; qz = Info_ValueForKey(player->userinfo, "Qizmo"); if (*qz) - TP_ExecTrigger("f_qizmoconnect"); + TP_ExecTrigger("f_qizmoconnect", false); } } @@ -4723,9 +4723,9 @@ static void CL_SetStat_Internal (int pnum, int stat, int ivalue, float fvalue) if (cl.playerview[pnum].stats[stat] != ivalue) { if (ivalue == 0) - TP_ExecTrigger ("f_reloadstart"); + TP_ExecTrigger ("f_reloadstart", false); else if (cl.playerview[pnum].stats[stat] == 0) - TP_ExecTrigger ("f_reloadend"); + TP_ExecTrigger ("f_reloadend", false); } } @@ -5988,7 +5988,7 @@ void CLQW_ParseServerMessage (void) //vanilla QW has no timing info in the client and depends upon the client for all timing. //using the demo's timing for interpolation prevents unneccesary drift, and solves issues with demo seeking and other such things. - if (cls.demoplayback && !(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) + if (cls.demoplayback == DPB_QUAKEWORLD && !(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) { extern float demtime; if (cl.gametime != demtime) @@ -6314,7 +6314,11 @@ void CLQW_ParseServerMessage (void) case svc_intermission: if (!cl.intermission) - TP_ExecTrigger ("f_mapend"); + { + TP_ExecTrigger ("f_mapend", false); + if (cl.spectator) + TP_ExecTrigger ("f_specmapend", true); + } cl.intermission = 1; cl.completed_time = cl.gametime; for (i=0 ; i<3 ; i++) @@ -7162,7 +7166,7 @@ void CLNQ_ParseServerMessage (void) case svc_intermission: if (!cl.intermission) - TP_ExecTrigger ("f_mapend"); + TP_ExecTrigger ("f_mapend", false); cl.intermission = 1; cl.completed_time = cl.gametime; break; diff --git a/engine/client/client.h b/engine/client/client.h index 3aa96d9b2..6f6648dad 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1309,7 +1309,7 @@ qboolean TP_CheckSoundTrigger (char *str); int TP_CountPlayers (void); char* TP_EnemyName (void); char* TP_EnemyTeam (void); -void TP_ExecTrigger (char *s); +void TP_ExecTrigger (char *s, qboolean indemos); qboolean TP_FilterMessage (char *s); void TP_Init(void); char* TP_LocationName (vec3_t location); @@ -1481,7 +1481,7 @@ int Stats_GetTKills(int playernum); int Stats_GetDeaths(int playernum); int Stats_GetTouches(int playernum); int Stats_GetCaptures(int playernum); -qboolean Stats_HaveFlags(void); +qboolean Stats_HaveFlags(int mode); qboolean Stats_HaveKills(void); void VARGS Stats_Message(char *msg, ...) LIKEPRINTF(1); int qm_strcmp(char *s1, char *s2); diff --git a/engine/client/fragstats.c b/engine/client/fragstats.c index 008e5d378..7697d2f68 100644 --- a/engine/client/fragstats.c +++ b/engine/client/fragstats.c @@ -68,7 +68,7 @@ typedef struct { stat kills; //times they killed (including by you) stat teamkills; //times they killed a team member. stat teamdeaths; //times they died to a team member. - stat suisides; //times they were stupid. + stat suicides; //times they were stupid. } clienttotals[MAX_CLIENTS]; qboolean readcaps; @@ -100,9 +100,17 @@ int Stats_GetCaptures(int playernum) return fragstats.clienttotals[playernum].caps; } -qboolean Stats_HaveFlags(void) +qboolean Stats_HaveFlags(int showtype) { - return fragstats.readcaps; + int i; + for (i = 0; i < cl.allocated_client_slots; i++) + { + if (fragstats.clienttotals[i].caps || + fragstats.clienttotals[i].drops || + fragstats.clienttotals[i].grabs) + return fragstats.readcaps; + } + return false; } qboolean Stats_HaveKills(void) { @@ -303,7 +311,7 @@ void Stats_Evaluate(fragfilemsgtypes_t mt, int wid, int p1, int p2) fragstats.weapontotals[wid].suicides++; fragstats.weapontotals[wid].kills++; - fragstats.clienttotals[p1].suisides++; + fragstats.clienttotals[p1].suicides++; fragstats.clienttotals[p1].deaths++; fragstats.totalsuicides++; fragstats.totaldeaths++; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 05de7347e..065e398ef 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -304,7 +304,7 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) } } } -static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key) +static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) { package_t *p, *p2; p = c->dptr; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 725c1fab1..534ccd7c5 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -1806,7 +1806,7 @@ void M_Complex_Key(int key, int unicode) if (currentmenu->selecteditem && currentmenu->selecteditem->common.type == mt_custom && (key == K_DOWNARROW || key == K_UPARROW || key == K_TAB)) if (currentmenu->selecteditem->custom.key) - if (currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key)) + if (currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key, unicode)) return; if (currentmenu->selecteditem && currentmenu->selecteditem->common.type == mt_bind) @@ -1912,7 +1912,7 @@ void M_Complex_Key(int key, int unicode) break; case mt_custom: if (currentmenu->selecteditem->custom.key) - currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key); + currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key, unicode); break; case mt_edit: MC_EditBox_Key(¤tmenu->selecteditem->edit, key, unicode); diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 9e09b4f8e..b2d7455fd 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -2,32 +2,40 @@ #if defined(CL_MASTER) && !defined(NOBUILTINMENUS) #include "cl_master.h" +#include "shader.h" //filtering -static cvar_t sb_hideempty = SCVARF("sb_hideempty", "0", CVAR_ARCHIVE); -static cvar_t sb_hidenotempty = SCVARF("sb_hidenotempty", "0", CVAR_ARCHIVE); -static cvar_t sb_hidefull = SCVARF("sb_hidefull", "0", CVAR_ARCHIVE); -static cvar_t sb_hidedead = SCVARF("sb_hidedead", "1", CVAR_ARCHIVE); -static cvar_t sb_hidenetquake = SCVARF("sb_hidenetquake", "0", CVAR_ARCHIVE); -static cvar_t sb_hidequakeworld = SCVARF("sb_hidequakeworld","0", CVAR_ARCHIVE); -static cvar_t sb_hideproxies = SCVARF("sb_hideproxies", "0", CVAR_ARCHIVE); +static cvar_t sb_sortcolumn = CVARF("sb_sortcolumn", "0", CVAR_ARCHIVE); +static cvar_t sb_filtertext = CVARF("sb_filtertext", "", CVAR_ARCHIVE); +static cvar_t sb_hideempty = CVARF("sb_hideempty", "0", CVAR_ARCHIVE); +static cvar_t sb_hidenotempty = CVARF("sb_hidenotempty", "0", CVAR_ARCHIVE); +static cvar_t sb_hidefull = CVARF("sb_hidefull", "0", CVAR_ARCHIVE); +static cvar_t sb_hidedead = CVARF("sb_hidedead", "1", CVAR_ARCHIVE); +static cvar_t sb_hidenetquake = CVARF("sb_hidenetquake", "0", CVAR_ARCHIVE); +static cvar_t sb_hidequakeworld = CVARF("sb_hidequakeworld","0", CVAR_ARCHIVE); +static cvar_t sb_hideproxies = CVARF("sb_hideproxies", "0", CVAR_ARCHIVE); -static cvar_t sb_showping = SCVARF("sb_showping", "1", CVAR_ARCHIVE); -static cvar_t sb_showaddress = SCVARF("sb_showaddress", "0", CVAR_ARCHIVE); -static cvar_t sb_showmap = SCVARF("sb_showmap", "0", CVAR_ARCHIVE); -static cvar_t sb_showgamedir = SCVARF("sb_showgamedir", "0", CVAR_ARCHIVE); -static cvar_t sb_showplayers = SCVARF("sb_showplayers", "1", CVAR_ARCHIVE); -static cvar_t sb_showfraglimit = SCVARF("sb_showfraglimit","0", CVAR_ARCHIVE); -static cvar_t sb_showtimelimit = SCVARF("sb_showtimelimit","0", CVAR_ARCHIVE); +static cvar_t sb_showping = CVARF("sb_showping", "1", CVAR_ARCHIVE); +static cvar_t sb_showaddress = CVARF("sb_showaddress", "0", CVAR_ARCHIVE); +static cvar_t sb_showmap = CVARF("sb_showmap", "0", CVAR_ARCHIVE); +static cvar_t sb_showgamedir = CVARF("sb_showgamedir", "0", CVAR_ARCHIVE); +static cvar_t sb_showplayers = CVARF("sb_showplayers", "1", CVAR_ARCHIVE); +static cvar_t sb_showfraglimit = CVARF("sb_showfraglimit", "0", CVAR_ARCHIVE); +static cvar_t sb_showtimelimit = CVARF("sb_showtimelimit", "0", CVAR_ARCHIVE); + +static cvar_t sb_alpha = CVARF("sb_alpha", "0.3", CVAR_ARCHIVE); extern cvar_t slist_writeserverstxt; extern cvar_t slist_cacheinfo; +static void CalcFilters(menu_t *menu); + void M_Serverlist_Init(void) { char *grp = "Server Browser Vars"; + Cvar_Register(&sb_alpha, grp); Cvar_Register(&sb_hideempty, grp); Cvar_Register(&sb_hidenotempty, grp); Cvar_Register(&sb_hidefull, grp); @@ -35,6 +43,8 @@ void M_Serverlist_Init(void) Cvar_Register(&sb_hidenetquake, grp); Cvar_Register(&sb_hidequakeworld, grp); Cvar_Register(&sb_hideproxies, grp); + Cvar_Register(&sb_filtertext, grp); + Cvar_Register(&sb_sortcolumn, grp); Cvar_Register(&sb_showping, grp); Cvar_Register(&sb_showaddress, grp); @@ -52,10 +62,12 @@ typedef struct { int visibleslots; int scrollpos; int selectedpos; + int filtermodcount; int numslots; qboolean stillpolling; qbyte filter[8]; + menuedit_t *filtertext; char refreshtext[64]; @@ -111,11 +123,13 @@ static void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) SL_DrawColumnTitle(NULL, y, x, mx, "hostname ", (sf==SLKEY_NAME), clr, &filldraw); } -static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key) +static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) { int x; int mx = mousecursor_x/8; int sortkey; + qboolean descending; + char sortchar = 0; if (key != K_MOUSE1) return false; @@ -123,30 +137,35 @@ static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key) 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_TIMELIMIT; break;}} - if (sb_showfraglimit.value) {x-=4;if (mx > x) {sortkey = SLKEY_FRAGLIMIT; 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; + if (sb_showtimelimit.value) {x-=4;if (mx > x) {sortkey = SLKEY_TIMELIMIT; sortchar='t'; break;}} + if (sb_showfraglimit.value) {x-=4;if (mx > x) {sortkey = SLKEY_FRAGLIMIT; sortchar='f'; break;}} + if (sb_showplayers.value) {x-=6;if (mx > x) {sortkey = SLKEY_NUMPLAYERS; sortchar='p'; break;}} + if (sb_showmap.value) {x-=9;if (mx > x) {sortkey = SLKEY_MAP; sortchar='m'; break;}} + if (sb_showgamedir.value) {x-=9;if (mx > x) {sortkey = SLKEY_GAMEDIR; sortchar='g'; break;}} + if (sb_showping.value) {x-=4;if (mx > x) {sortkey = SLKEY_PING; sortchar='l'; break;}} + if (sb_showaddress.value) {x-=22;if (mx > x) {sortkey = SLKEY_ADDRESS; sortchar='a'; break;}} + sortkey = SLKEY_NAME; sortchar='n'; break; } while (0); - if (sortkey == SLKEY_ADDRESS) - return true; +// if (sortkey == SLKEY_ADDRESS) +// return true; switch(sortkey) { case SLKEY_NUMPLAYERS: //favour descending order (low first) - Master_SetSortField(sortkey, Master_GetSortField()!=sortkey||!Master_GetSortDescending()); + descending = Master_GetSortField()!=sortkey||!Master_GetSortDescending(); break; default: //favour ascending order (low first) - Master_SetSortField(sortkey, Master_GetSortField()==sortkey&&!Master_GetSortDescending()); + descending = Master_GetSortField()==sortkey&&!Master_GetSortDescending(); break; } + if (descending) + Cvar_Set(&sb_sortcolumn, va("-%c", sortchar)); + else + Cvar_Set(&sb_sortcolumn, va("+%c", sortchar)); + Master_SetSortField(sortkey, descending); return true; } @@ -237,6 +256,9 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) servertypes_t stype; char adr[MAX_ADR_SIZE]; + if (sb_filtertext.modified != info->filtermodcount) + CalcFilters(menu); + si = Master_SortedServer(thisone); if (si) { @@ -251,16 +273,16 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) 1.0); } else if (thisone == info->scrollpos + (int)(mousecursor_y-16)/8 && mousecursor_x < x) - R2D_ImageColours((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, 1.0); + R2D_ImageColours((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, sb_alpha.value); else if (selectedserver.inuse && NET_CompareAdr(&si->adr, &selectedserver.adr)) - R2D_ImageColours(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, 1.0); + R2D_ImageColours(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, sb_alpha.value); else { R2D_ImageColours( serverbackcolor[(int)stype * 2 + (thisone & 1)][0], serverbackcolor[(int)stype * 2 + (thisone & 1)][1], serverbackcolor[(int)stype * 2 + (thisone & 1)][2], - 1.0); + sb_alpha.value); } R2D_FillBlock(0, y, ths->common.width, 8); @@ -274,7 +296,8 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) Draw_FunStringWidth(0, y, si->name, x, false, false); } } -static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) +void MC_EditBox_Key(menuedit_t *edit, int key, unsigned int unicode); +static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) { static int lastclick; int curtime; @@ -282,6 +305,8 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) serverlist_t *info = (serverlist_t*)(menu + 1); serverinfo_t *server; char adr[MAX_ADR_SIZE]; + extern qboolean keydown[]; + qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL]; if (key == K_MOUSE1) { @@ -315,7 +340,7 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) return true; } - if (key == 'f') + else if (ctrl && key == 'f') { server = Master_SortedServer(info->selectedpos); if (server) @@ -324,7 +349,7 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) } } - if (key == K_ENTER || key == K_KP_ENTER || key == K_KP_ENTER || key == 's' || key == 'j' || key == K_SPACE) + else if (key == K_ENTER || key == K_KP_ENTER || key == K_KP_ENTER || (ctrl && (key == 's' || key == 'j')) || key == K_SPACE) { server = Master_SortedServer(info->selectedpos); if (server) @@ -346,6 +371,11 @@ joinserver: } return true; } + else + { + MC_EditBox_Key(info->filtertext, key, unicode); + return true; + } return false; } static void SL_PreDraw (menu_t *menu) @@ -446,7 +476,7 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) mpic_t *pic; pic = R2D_SafeCachePic("scrollbars/slidebg.tga"); - if (pic) + if (pic && R_GetShaderSizes(pic, NULL, NULL, false)>0) { R2D_ScalePic(x + ths->common.width - 8, y+8, 8, ths->common.height-16, pic); @@ -504,7 +534,7 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) info->sliderpressed = false; } } -static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) +static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) { if (key == K_MOUSE1) { @@ -537,6 +567,7 @@ static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) static void CalcFilters(menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); + info->filtermodcount = sb_filtertext.modified; Master_ClearMasks(); @@ -554,6 +585,8 @@ static void CalcFilters(menu_t *menu) if (info->filter[5]) Master_SetMaskInteger(false, SLKEY_FLAGS, SS_FAVORITE, 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); + + if (*sb_filtertext.string) Master_SetMaskString(false, SLKEY_NAME, sb_filtertext.string, SLIST_TEST_CONTAINS); } static qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) @@ -606,6 +639,9 @@ void M_Menu_ServerList2_f(void) menu_t *menu; menucustom_t *cust; serverlist_t *info; + qboolean descending; + int sortkey; + char *sc; if (!qrenderer) { @@ -642,6 +678,8 @@ void M_Menu_ServerList2_f(void) for (i = 0, y = 16; i <= info->visibleslots; y +=8, i++) { cust = MC_AddCustom(menu, 0, y, NULL, i); + if (i==0) + menu->selecteditem = (menuoption_t*)&cust->common; cust->draw = SL_ServerDraw; cust->key = SL_ServerKey; cust->common.height = 8; @@ -681,6 +719,8 @@ void M_Menu_ServerList2_f(void) } #endif MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*3, "Hide Proxies", SL_ReFilter, 3); + info->filtertext = + MC_AddEditCvar (menu, 128, 200, vid.height - 64+8*4, "Filter", sb_filtertext.name, true); MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*5, "Only Favs ", SL_ReFilter, 5); MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*6, "Hide Empty", SL_ReFilter, 6); MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*7, "Hide Full ", SL_ReFilter, 7); @@ -697,7 +737,29 @@ void M_Menu_ServerList2_f(void) CalcFilters(menu); - Master_SetSortField(SLKEY_PING, false); + descending = false; + + sc = sb_sortcolumn.string; + if (*sc == '-') + descending = true; + else if (*sc == '+') + descending = false; + else + sc--; + sc++; + switch(*sc) + { + case 't': sortkey = SLKEY_TIMELIMIT; break; + case 'f': sortkey = SLKEY_FRAGLIMIT; break; + case 'p': sortkey = SLKEY_NUMPLAYERS; break; + case 'm': sortkey = SLKEY_MAP; break; + case 'g': sortkey = SLKEY_GAMEDIR; break; + case 'l': sortkey = SLKEY_PING; break; + case 'a': sortkey = SLKEY_ADDRESS; break; + case 'n': sortkey = SLKEY_NAME; break; + default: sortkey = SLKEY_PING; break; + } + Master_SetSortField(sortkey, descending); MasterInfo_Refresh(); } diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index faddf119b..126c24315 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -308,7 +308,7 @@ void q2skin_destroy(q2skinsearch_t *s) BZ_Free(s); } -qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, int key) +qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, int key, unsigned int unicode) { setupmenu_t *info = menu->data; q2skinsearch_t *s = Z_Malloc(sizeof(*s)); diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 04c2757a5..bdc407863 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -2769,7 +2769,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ break; } } -static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int key) +static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) { modelview_t *mods = c->dptr; @@ -2884,7 +2884,7 @@ static void Mods_Draw(int x, int y, struct menucustom_s *c, struct menu_s *m) Draw_FunString(x, y, mods->manifests[i]->formalname); } } -static qboolean Mods_Key(struct menucustom_s *c, struct menu_s *m, int key) +static qboolean Mods_Key(struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) { modmenu_t *mods = c->dptr; int i; diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 52c2aed0b..db040d387 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -513,7 +513,7 @@ static void M_DemoDraw(int x, int y, menucustom_t *control, menu_t *menu) } } static void ShowDemoMenu (menu_t *menu, const char *path); -static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key) +static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned int unicode) { demomenu_t *info = menu->data; int i; diff --git a/engine/client/menu.h b/engine/client/menu.h index 49d4097f3..9a788a73b 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -213,7 +213,7 @@ typedef struct menucustom_s { void *dptr; int dint; void (*draw) (int x, int y, struct menucustom_s *, struct menu_s *); - qboolean (*key) (struct menucustom_s *, struct menu_s *, int key); + qboolean (*key) (struct menucustom_s *, struct menu_s *, int key, unsigned int unicode); } menucustom_t; typedef struct { diff --git a/engine/client/net_master.c b/engine/client/net_master.c index ec049dcc5..1e3fb1b4b 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -706,25 +706,25 @@ qboolean Master_CompareString(const char *a, const char *b, slist_test_t rule) switch(rule) { case SLIST_TEST_STARTSWITH: - return strnicmp(a, b, strlen(b))==0; + return Q_strncasecmp(a, b, strlen(b))==0; case SLIST_TEST_NOTSTARTSWITH: - return strnicmp(a, b, strlen(b))!=0; + return Q_strncasecmp(a, b, strlen(b))!=0; case SLIST_TEST_CONTAINS: - return !!strstr(a, b); + return !!Q_strcasestr(a, b); case SLIST_TEST_NOTCONTAIN: - return !strstr(a, b); + return !Q_strcasestr(a, b); case SLIST_TEST_LESSEQUAL: - return stricmp(a, b)<=0; + return Q_strcasecmp(a, b)<=0; case SLIST_TEST_LESS: - return stricmp(a, b)<0; + return Q_strcasecmp(a, b)<0; case SLIST_TEST_EQUAL: - return stricmp(a, b)==0; + return Q_strcasecmp(a, b)==0; case SLIST_TEST_GREATER: - return stricmp(a, b)>0; + return Q_strcasecmp(a, b)>0; case SLIST_TEST_GREATEREQUAL: - return stricmp(a, b)>=0; + return Q_strcasecmp(a, b)>=0; case SLIST_TEST_NOTEQUAL: - return stricmp(a, b)!=0; + return Q_strcasecmp(a, b)!=0; } return false; } @@ -734,6 +734,28 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b) switch(sortfield) { case SLKEY_ADDRESS: + if (a->adr.type != b->adr.type) + return a->adr.type < b->adr.type; + if (a->adr.type == NA_IP) + { + int i; + for (i = 0; i < 4; i++) + { + if (a->adr.address.ip[i] != b->adr.address.ip[i]) + return a->adr.address.ip[i] < b->adr.address.ip[i]; + } + } + if (a->adr.type == NA_IPV6) + { + int i; + for (i = 0; i < 16; i++) + { + if (a->adr.address.ip6[i] != b->adr.address.ip6[i]) + return a->adr.address.ip6[i] < b->adr.address.ip6[i]; + } + } + return false; + break; case SLKEY_BASEGAME: return Master_CompareInteger(a->special&SS_PROTOCOLMASK, b->special&SS_PROTOCOLMASK, SLIST_TEST_LESS); @@ -1266,8 +1288,8 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b { netadr_t adrs[MAX_MASTER_ADDRESSES]; char token[1024]; - int found = 0; - qboolean first = true; + int found = 0, j, i; +// qboolean first = true; char *str; master_t *work = data; //resolve all the addresses @@ -1277,9 +1299,11 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b str = COM_ParseOut(str, token, sizeof(token)); if (*token) found += NET_StringToAdr2(token, 0, &adrs[found], MAX_MASTER_ADDRESSES-found); - if (first && found) - break; //if we found one by name, don't try any fallback ip addresses. - first = false; + //we don't do this logic because windows doesn't look up ipv6 names if it only has teredo + //this means an ipv4+teredo client cannot see ivp6-only servers. and that sucks. +// if (first && found) +// break; //if we found one by name, don't try any fallback ip addresses. +// first = false; } //add the main ip address @@ -1287,18 +1311,28 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b COM_AddWork(0, CLMaster_AddMaster_Worker_Resolved, NULL, work, a, b); //add dupes too (eg: ipv4+ipv6) - while(found --> 1) + for (i = 1; i < found; i++) { - master_t *alt = Z_Malloc(sizeof(master_t)+strlen(work->name)+1+strlen(work->address)+1); - alt->address = work->name + strlen(work->name)+1; - alt->mastertype = work->mastertype; - alt->protocoltype = work->protocoltype; - strcpy(alt->name, work->name); - strcpy(alt->address, work->address); - alt->sends = 1; - alt->nosave = true; - alt->adr = adrs[found]; - COM_AddWork(0, CLMaster_AddMaster_Worker_Resolved, NULL, alt, a, b); + master_t *alt; + //don't add the same ip twice, because that's silly + for (j = 0; j < i; j++) + { + if (NET_CompareAdr(&adrs[j], &adrs[i])) + break; + } + if (j == i) + { //not already added, hurrah + master_t *alt = Z_Malloc(sizeof(master_t)+strlen(work->name)+1+strlen(work->address)+1); + alt->address = work->name + strlen(work->name)+1; + alt->mastertype = work->mastertype; + alt->protocoltype = work->protocoltype; + strcpy(alt->name, work->name); + strcpy(alt->address, work->address); + alt->sends = 1; + alt->nosave = true; + alt->adr = adrs[i]; + COM_AddWork(0, CLMaster_AddMaster_Worker_Resolved, NULL, alt, a, b); + } } } diff --git a/engine/client/p_script.c b/engine/client/p_script.c index cf846f07e..aba66bd5a 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -6008,14 +6008,14 @@ static void PScript_DrawParticleTypes (void) P_RunParticleEffectType(p->org, p->vel, 1, type->emit); // make sure stain effect runs - if (type->stainonimpact && r_bloodstains.ival) + if (type->stainonimpact && r_bloodstains.value) { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { Surf_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[1]*-10), - 30*p->rgba[3]*type->stainonimpact); + 30*p->rgba[3]*type->stainonimpact*r_bloodstains.value); } } @@ -6235,11 +6235,11 @@ static void PScript_DrawParticleTypes (void) { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { - if (type->stainonimpact && r_bloodstains.ival) + if (type->stainonimpact && r_bloodstains.value) Surf_AddStain(stop, p->rgba[1]*-10+p->rgba[2]*-10, p->rgba[0]*-10+p->rgba[2]*-10, p->rgba[0]*-10+p->rgba[1]*-10, - 30*p->rgba[3]); + 30*p->rgba[3]*r_bloodstains.value); if (part_type + type->cliptype == type) { //bounce @@ -6269,7 +6269,7 @@ static void PScript_DrawParticleTypes (void) } } } - else if (type->stainonimpact && r_bloodstains.ival) + else if (type->stainonimpact && r_bloodstains.value) { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { @@ -6277,12 +6277,12 @@ static void PScript_DrawParticleTypes (void) Surf_AddStain(stop, (p->rgba[0]*-1), (p->rgba[1]*-1), (p->rgba[2]*-1), - p->scale*-type->stainonimpact); + p->scale*-type->stainonimpact*r_bloodstains.value); else Surf_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[1]*-10), - 30*p->rgba[3]*type->stainonimpact); + 30*p->rgba[3]*type->stainonimpact*r_bloodstains.value); p->die = -1; continue; } diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 02df3ee0b..14e2434c7 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -29,8 +29,11 @@ extern cvar_t *hud_tracking_show; cvar_t scr_scoreboard_drawtitle = SCVAR("scr_scoreboard_drawtitle", "1"); cvar_t scr_scoreboard_forcecolors = SCVAR("scr_scoreboard_forcecolors", "0"); //damn americans cvar_t scr_scoreboard_newstyle = SCVAR("scr_scoreboard_newstyle", "1"); // New scoreboard style ported from Electro, by Molgrum -cvar_t scr_scoreboard_showfrags = SCVAR("scr_scoreboard_showfrags", "0"); +cvar_t scr_scoreboard_showfrags = CVARD("scr_scoreboard_showfrags", "0", "Display kills+deaths+teamkills, as determined by fragfile.dat-based conprint parsing. These may be inaccurate if you join mid-game."); +cvar_t scr_scoreboard_showflags = CVARD("scr_scoreboard_showflags", "2", "Display flag caps+touches on the scoreboard, where our fragfile.dat supports them.\n0: off\n1: on\n2: on only if someone appears to have interacted with a flag."); +cvar_t scr_scoreboard_fillalpha = CVAR("scr_scoreboard_fillalpha", "0.7"); cvar_t scr_scoreboard_teamscores = SCVAR("scr_scoreboard_teamscores", "1"); +cvar_t scr_scoreboard_teamsort = SCVAR("scr_scoreboard_teamsort", "1"); cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1"); cvar_t sbar_teamstatus = SCVAR("sbar_teamstatus", "1"); @@ -1047,7 +1050,10 @@ void Sbar_Init (void) Cvar_Register(&scr_scoreboard_forcecolors, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_newstyle, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_showfrags, "Scoreboard settings"); + Cvar_Register(&scr_scoreboard_showflags, "Scoreboard settings"); + Cvar_Register(&scr_scoreboard_fillalpha, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_teamscores, "Scoreboard settings"); + Cvar_Register(&scr_scoreboard_teamsort, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_titleseperator, "Scoreboard settings"); Cvar_Register(&sbar_teamstatus, "Status bar settings"); @@ -1186,16 +1192,16 @@ void Sbar_FillPC (float x, float y, float w, float h, unsigned int pcolour) R2D_FillBlock (x, y, w, h); } } -static void Sbar_FillPCDark (float x, float y, float w, float h, unsigned int pcolour) +static void Sbar_FillPCDark (float x, float y, float w, float h, unsigned int pcolour, float alpha) { if (pcolour >= 16) { - R2D_ImageColours (((pcolour&0xff0000)>>16)/1024.0f, ((pcolour&0xff00)>>8)/1024.0f, (pcolour&0xff)/1024.0f, 1.0); + R2D_ImageColours (((pcolour&0xff0000)>>16)/1024.0f, ((pcolour&0xff00)>>8)/1024.0f, (pcolour&0xff)/1024.0f, alpha); R2D_FillBlock (x, y, w, h); } else { - R2D_ImagePaletteColour(Sbar_ColorForMap(pcolour)-1, 1.0); + R2D_ImagePaletteColour(Sbar_ColorForMap(pcolour)-1, alpha); R2D_FillBlock (x, y, w, h); } } @@ -1362,12 +1368,12 @@ void Sbar_PQ_Team_Reset(void) Sbar_SortFrags =============== */ -void Sbar_SortFrags (qboolean includespec, qboolean teamsort) +void Sbar_SortFrags (qboolean includespec, qboolean doteamsort) { int i, j, k; if (!cl.teamplay) - teamsort = false; + doteamsort = false; // sort by frags scoreboardlines = 0; @@ -1384,31 +1390,26 @@ void Sbar_SortFrags (qboolean includespec, qboolean teamsort) } for (i=0 ; i t2) - { - k = fragsort[j]; - fragsort[j] = fragsort[j+1]; - fragsort[j+1] = k; - } + k = fragsort[i]; + fragsort[i] = fragsort[j]; + fragsort[j] = k; } } } @@ -2917,6 +2918,9 @@ void Sbar_TeamOverlay (void) int pw,ph; playerview_t *pv = r_refdef.playerview; + int rank_width = 320-32*2; + int startx; + if (!pv) pv = &cl.playerview[0]; @@ -2942,6 +2946,20 @@ void Sbar_TeamOverlay (void) x = l = (vid.width - 320)/2 + 36; + startx = x; + + if (scr_scoreboard_newstyle.ival) + { + y += 8; + // Electro's scoreboard eyecandy: Draw top border + R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value); + R2D_FillBlock(startx - 3, y - 1, rank_width - 1, 1); + + // Electro's scoreboard eyecandy: Draw the title row background + R2D_ImagePaletteColour (1, scr_scoreboard_fillalpha.value); + R2D_FillBlock(startx - 2, y, rank_width - 3, 9); + } + #define COLUMN(title, cwidth, code) Draw_FunString(x, y, title), x+=cwidth + 8; ALL_TEAM_COLUMNS // if (rank_width+(cwidth)+8 <= vid.width) {showcolumns |= (1<0) {buf[c++] = '^'; buf[c++] = 'U'; buf[c++] = 'e'; buf[c++] = '0'; buf[c++] = '1'; buf[c] = (c==5?'d':(!t?'f':'e')); c++;} buf[c] = 0; Draw_FunString(x, y, buf); x += cwidth + 8;} - ALL_TEAM_COLUMNS -// Draw_FunString(x, y, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f"); - y += 8; + ALL_TEAM_COLUMNS +// Draw_FunString(x, y, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f"); + y += 8; #undef COLUMN + } // sort the teams Sbar_SortTeams(pv); @@ -2970,6 +3004,26 @@ void Sbar_TeamOverlay (void) k = teamsort[i]; tm = teams + k; + if (scr_scoreboard_newstyle.ival) + { + // Electro's scoreboard eyecandy: Render the main background transparencies behind players row + // TODO: Alpha values on the background + int background_color; + + if (!(strcmp("red", tm->team))) + background_color = 4; // forced red + else if (!(strcmp("blue", tm->team))) + background_color = 13; // forced blue + else + background_color = tm->bottomcolour; + + Sbar_FillPCDark (startx - 2, y, rank_width - 3, 8, background_color, scr_scoreboard_fillalpha.value); + + R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value); + R2D_FillBlock (startx - 3, y, 1, 8); // Electro - Border - Left + R2D_FillBlock (startx - 3 + rank_width - 2, y, 1, 8); // Electro - Border - Right + } + // draw pings plow = tm->plow; if (plow < 0 || plow > 999) @@ -3014,7 +3068,14 @@ void Sbar_TeamOverlay (void) #endif y += 8; } - y += 8; + + if (scr_scoreboard_newstyle.ival) + { + R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value); + R2D_FillBlock (startx - 3, y, rank_width - 1, 1); // Electro - Border - Bottom + } + else + y += 8; Sbar_DeathmatchOverlay(y); } @@ -3176,7 +3237,7 @@ void Sbar_DeathmatchOverlay (int start) } // scores - Sbar_SortFrags(true, true); + Sbar_SortFrags(true, scr_scoreboard_teamsort.ival); // draw the text if (start) @@ -3210,11 +3271,11 @@ void Sbar_DeathmatchOverlay (int start) { COLUMN_TEAMNAME } - if (cl.teamplay && Stats_HaveFlags()) + if (scr_scoreboard_showflags.ival && cl.teamplay && Stats_HaveFlags(scr_scoreboard_showflags.ival&1)) { COLUMN_CAPS } - if (scr_scoreboard_showfrags.value && Stats_HaveKills()) + if (scr_scoreboard_showfrags.ival && Stats_HaveKills()) { COLUMN_KILLS COLUMN_DEATHS @@ -3223,7 +3284,7 @@ void Sbar_DeathmatchOverlay (int start) COLUMN_TKILLS } } - if (cl.teamplay && Stats_HaveFlags()) + if (scr_scoreboard_showflags.ival && cl.teamplay && Stats_HaveFlags(scr_scoreboard_showflags.ival&1)) { COLUMN_TOUCHES } @@ -3235,11 +3296,11 @@ void Sbar_DeathmatchOverlay (int start) if (scr_scoreboard_newstyle.ival) { // Electro's scoreboard eyecandy: Draw top border - R2D_ImagePaletteColour (0, 1.0); + R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value); R2D_FillBlock(startx - 3, y - 1, rank_width - 1, 1); // Electro's scoreboard eyecandy: Draw the title row background - R2D_ImagePaletteColour (1, 1.0); + R2D_ImagePaletteColour (1, scr_scoreboard_fillalpha.value); R2D_FillBlock(startx - 2, y, rank_width - 3, 9); } @@ -3271,7 +3332,7 @@ if (showcolumns & (1< 0) @@ -3234,9 +3238,9 @@ void TP_StatChanged (int stat, int value) { if (cl.teamfortress && (cl.playerview[SP].stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2)) && Cmd_AliasExist("f_flagdeath", RESTRICT_LOCAL)) - TP_ExecTrigger ("f_flagdeath"); + TP_ExecTrigger ("f_flagdeath", false); else - TP_ExecTrigger ("f_death"); + TP_ExecTrigger ("f_death", false); } } vars.health = value; @@ -3265,7 +3269,7 @@ void TP_StatChanged (int stat, int value) else if (stat == STAT_ACTIVEWEAPON) { if (cl.playerview[SP].stats[STAT_ACTIVEWEAPON] != vars.activeweapon) - TP_ExecTrigger ("f_weaponchange"); + TP_ExecTrigger ("f_weaponchange", false); vars.activeweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON]; } diff --git a/engine/common/fs.c b/engine/common/fs.c index 7db0fd0fb..ffef6b628 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1532,6 +1532,7 @@ vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesi COM_CreatePath(sysname); return VFSOS_Open(sysname, "wbp"); } + FS_NativePath(fname, FS_GAMEONLY, sysname, sysnamesize); return NULL; } @@ -3011,9 +3012,9 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) } else { - FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_gamepath, dir), reloadflags, SPF_EXPLICIT); + FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_gamepath, dir), reloadflags, SPF_EXPLICIT|(com_homepathenabled?0:SPF_WRITABLE)); if (com_homepathenabled) - FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_homepath, dir), reloadflags, SPF_EXPLICIT); + FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_homepath, dir), reloadflags, SPF_EXPLICIT|SPF_WRITABLE); } } } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 00da309a2..c188dca0d 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -75,7 +75,7 @@ int UDP6_OpenSocket (int port, qboolean bcast); #ifdef USEIPX void IPX_CloseSocket (int socket); #endif -cvar_t net_hybriddualstack = CVAR("net_hybriddualstack", "1"); +cvar_t net_hybriddualstack = CVARD("net_hybriddualstack", "1", "Uses hybrid ipv4+ipv6 sockets where possible. Not supported on xp or below."); cvar_t net_fakeloss = CVARFD("net_fakeloss", "0", CVAR_CHEAT, "Simulates packetloss in both receiving and sending, on a scale from 0 to 1."); cvar_t net_enabled = CVARD("net_enabled", "1", "If 0, disables all network access, including name resolution and socket creation. Does not affect loopback/internal connections."); @@ -421,6 +421,34 @@ qboolean NET_AddressSmellsFunny(netadr_t *a) } } +static void NET_AdrToStringDoResolve(void *ctx, void *data, size_t a, size_t b) +{ + netadr_t *n = data; + struct sockaddr_qstorage s; + int ssz; + char *adrstring = Z_Malloc(NI_MAXHOST); + if (n->type == NA_LOOPBACK) + NET_BaseAdrToString(adrstring, NI_MAXHOST, n); + else + { + ssz = NetadrToSockadr(n, &s); + if (getnameinfo((struct sockaddr *)&s, ssz, adrstring, NI_MAXHOST, NULL, 0, NI_NUMERICSERV|NI_DGRAM)) + { + NET_BaseAdrToString(adrstring, NI_MAXHOST, n); + } + } + COM_AddWork(0, *(void**)(n+1), ctx, adrstring, a, b); + Z_Free(n); +} + +void NET_AdrToStringResolve (netadr_t *adr, void (*resolved)(void *ctx, void *data, size_t a, size_t b), void *ctx, size_t a, size_t b) +{ + netadr_t *n = Z_Malloc(sizeof(*n) + sizeof(void*)); + *n = *adr; + *(void**)(n+1) = resolved; + COM_AddWork(2, NET_AdrToStringDoResolve, ctx, n, a, b); +} + char *NET_AdrToString (char *s, int len, netadr_t *a) { char *rs = s; @@ -5724,7 +5752,7 @@ void QDECL SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_IPV6, true); } -cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "", SV_PortIPv6_Callback); +cvar_t sv_port_ipv6 = CVARCD("sv_port_ipv6", "", SV_PortIPv6_Callback, "Port to use for incoming ipv6 udp connections. Due to hybrid sockets this might not be needed. You can specify an ipv4 address:port for a second ipv4 port if you want."); #endif #ifdef USEIPX void QDECL SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) diff --git a/engine/droid/configs/touch.cfg b/engine/droid/configs/touch.cfg index 514428143..4cbd20b43 100644 --- a/engine/droid/configs/touch.cfg +++ b/engine/droid/configs/touch.cfg @@ -11,4 +11,3 @@ showpic gfx/touch_jump.png jump 160 -56 bm 32 32 +jump showpic gfx/touch_turnleft.png turnleft 0 -56 bm 32 32 +left showpic gfx/touch_turnright.png turnright 192 -56 bm 32 32 +right - diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 4407d0b41..016112ef5 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -353,6 +353,8 @@ typedef struct QCC_type_s char *aname; struct accessor_s *accessors; + + struct QCC_type_s *ptrto; //this points to a type that is a pointer back to this type. yeah, weird. } QCC_type_t; int typecmp(QCC_type_t *a, QCC_type_t *b); int typecmp_lax(QCC_type_t *a, QCC_type_t *b); diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index f36a1e36e..78442d5ac 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -4263,7 +4263,11 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto) { QCC_type_t *ptype, *e; - ptype = QCC_PR_NewType("ptr", ev_pointer, false); + char name[128]; + if (pointsto->ptrto) + return pointsto->ptrto; + QC_snprintfz(name, sizeof(name), "%s*", pointsto->name); + ptype = QCC_PR_NewType(name, ev_pointer, false); ptype->aux_type = pointsto; e = QCC_PR_FindType (ptype); if (e == ptype) @@ -4273,6 +4277,7 @@ QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto) e->name = qccHunkAlloc(strlen(name)+1); strcpy(e->name, name); } + pointsto->ptrto = e; return e; } QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto) diff --git a/engine/qclib/qccguistuff.c b/engine/qclib/qccguistuff.c index e8c5773b2..465d65ed0 100644 --- a/engine/qclib/qccguistuff.c +++ b/engine/qclib/qccguistuff.c @@ -367,7 +367,7 @@ void GUI_ParseCommandLine(char *args) l = 0; if (qt) args++; - while (*args != ' ' && *args) + while ((*args != ' ' || qt) && *args) { if (qt && *args == '\"') { diff --git a/engine/server/server.h b/engine/server/server.h index 67db8445a..b47e4cecf 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -633,6 +633,7 @@ typedef struct client_s int realip_status; int realip_num; int realip_ping; + char *reversedns; unsigned int plimitwarned; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 4b76d03a4..3fc96d411 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -1762,6 +1762,8 @@ static void SV_Status_f (void) else s = "ParmZombie"; } + else if (cl->reversedns) + s = cl->reversedns; else if (cl->state == cs_zombie && cl->netchan.remote_address.type == NA_INVALID) s = "none"; else if (cl->protocol == SCP_BAD) @@ -1802,6 +1804,8 @@ static void SV_Status_f (void) else s = "ParmZombie"; } + else if (cl->reversedns) + s = cl->reversedns; else if (cl->state == cs_zombie && cl->netchan.remote_address.type == NA_INVALID) s = "none"; else if (cl->protocol == SCP_BAD) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index eed7c2cab..aee8308f0 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1863,6 +1863,21 @@ void SV_ClientProtocolExtensionsChanged(client_t *client) } +//void NET_AdrToStringResolve (netadr_t *adr, void (*resolved)(void *ctx, void *data, size_t a, size_t b), void *ctx, size_t a, size_t b); +void SV_UserDNSResolved(void *ctx, void *data, size_t idx, size_t uid) +{ + if (idx < svs.allocated_client_slots) + { + if (svs.clients[idx].userid == uid) + { + Z_Free(svs.clients[idx].reversedns); + svs.clients[idx].reversedns = data; + return; + } + } + Con_DPrintf("stale dns lookup result: %s\n", data); + Z_Free(data); +} /* ================== @@ -2542,6 +2557,8 @@ client_t *SVC_DirectConnect(void) temp.team = newcl->team; *newcl = temp; +// NET_AdrToStringResolve(&adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid); + newcl->challenge = challenge; newcl->zquake_extensions = atoi(Info_ValueForKey(newcl->userinfo, "*z_ext")); if (*Info_ValueForKey(newcl->userinfo, "*fuhquake")) //fuhquake doesn't claim to support z_ext but does look at our z_ext serverinfo key.