From 918833a7632038259522938a94ded27f415b7736 Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 16 Aug 2010 02:03:02 +0000 Subject: [PATCH] hexen2 infoplaque. splitscreen controls now on the menu. Fixed splitscreen panorama. Pause automatically when at the console/menus. Attempting to clean up replacement texture paths (internal textures are still an issue). Fixed a crash when playing oversized demos. gl_bloom/ffov should now work again without bugging out. H2 Demoness's staff should no longer generate errors when shooting with the tome of power. Some other related changes. Server should compile now. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3585 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cg.c | 2 +- engine/client/cl_ents.c | 17 ++- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 1 + engine/client/cl_parse.c | 75 ++++++++++- engine/client/cl_screen.c | 3 + engine/client/cl_tent.c | 51 ++++---- engine/client/image.c | 12 +- engine/client/m_items.c | 3 +- engine/client/m_options.c | 4 +- engine/client/m_single.c | 126 +++++++++++++++---- engine/client/menu.c | 86 +++++++++++-- engine/client/menu.h | 2 +- engine/client/net_master.c | 2 - engine/client/pr_menu.c | 2 +- engine/client/r_2d.c | 2 + engine/client/sbar.c | 46 +++++-- engine/client/view.c | 8 +- engine/common/bothdefs.h | 3 + engine/common/common.h | 2 + engine/common/fs.c | 236 ++++++++++++++++++++--------------- engine/common/net.h | 5 +- engine/common/net_wins.c | 2 +- engine/common/protocol.h | 3 +- engine/common/translate.c | 75 ++++++++++- engine/gl/gl_alias.c | 2 +- engine/gl/gl_backend.c | 9 ++ engine/gl/gl_rmain.c | 49 ++++---- engine/server/net_preparse.c | 1 + engine/server/pr_cmds.c | 98 ++++++++++----- engine/server/pr_q1qvm.c | 12 -- engine/server/server.h | 1 + engine/server/sv_init.c | 3 + engine/server/sv_main.c | 30 ++++- engine/server/sv_phys.c | 21 +++- engine/server/sv_send.c | 14 ++- engine/server/sv_user.c | 31 ++--- engine/server/svhl_phys.c | 2 +- 38 files changed, 753 insertions(+), 290 deletions(-) diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index ec1b4e41a..059066b88 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -879,7 +879,7 @@ static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, c case CG_KEY_GETKEY: { int ret[2]; - M_FindKeysForCommand (VM_POINTER(arg[0]), ret); + M_FindKeysForCommand (0, VM_POINTER(arg[0]), ret); return ret[0]; } break; diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 030ca5bd4..b8d6ba920 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1866,6 +1866,7 @@ void CL_LinkPacketEntities (void) cl_numvisedicts++; + ent->externalmodelview = 0; ent->forcedshader = NULL; ent->visframe = 0; @@ -2051,6 +2052,8 @@ void CL_LinkPacketEntities (void) else if (model->flags & EFH2_ACIDBALL) { rad = 120 - (rand() % 20); + dclr[0] = 0.1; + dclr[1] = 0.2; } else if (model->flags & EFH2_SPIT) { @@ -2750,8 +2753,11 @@ void CL_LinkPlayers (void) VectorCopy(state->origin, org); for (pnum = 0; pnum < cl.splitclients; pnum++) VectorCopy(cl.simorg[pnum], org); - org[2] -= model->mins[2]; - org[2] += 24; + if (model) + { + org[2] -= model->mins[2]; + org[2] += 24; + } radius += r_lightflicker.value?(rand()&31):0; CL_NewDlightRGB(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_ALLOW_FLASH; } @@ -2803,6 +2809,7 @@ void CL_LinkPlayers (void) angles[ROLL] = 0; angles[ROLL] = V_CalcRoll (angles, state->velocity)*4; + ent->externalmodelview = 0; // the player object gets added with flags | 2 for (pnum = 0; pnum < cl.splitclients; pnum++) { @@ -2819,9 +2826,11 @@ void CL_LinkPlayers (void) ent->origin[0] = cl.simorg[pnum][0]; ent->origin[1] = cl.simorg[pnum][1]; ent->origin[2] = cl.simorg[pnum][2]+cl.crouch[pnum]; + } + if (j == (cl.viewentity[pnum]?cl.viewentity[pnum]:cl.playernum[pnum])) + { ent->flags |= Q2RF_EXTERNALMODEL; - ent->externalmodelview = (1<externalmodelview |= (1<angles[i] = ((int)(cl.viewangles[pnum][i]*65536.0/360)&65535); - if (in_impulsespending[pnum]) + if (in_impulsespending[pnum] && !cl.paused) { in_nextimpulse[pnum]++; in_impulsespending[pnum]--; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index ea86bc047..f535fd4e4 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1004,6 +1004,7 @@ void CL_ClearState (void) CL_ClearParseState(); CL_ClearTEnts(); CL_ClearCustomTEnts(); + T_FreeInfoStrings(); SCR_ShowPic_Clear(); if (cl.playernum[0] == -1) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index b76fe6a4a..7285cccf8 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2139,8 +2139,6 @@ void CL_ParseServerData (void) if (!sv.state) #endif Wads_Flush(); - - T_FreeStrings(); } if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) @@ -2399,15 +2397,15 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. cls.protocol_nq = 0; cls.z_ext = 0; - if (protover == 250) + if (protover == NEHD_PROTOCOL_VERSION) Host_EndGame ("Nehahra demo net protocol is not supported\n"); - else if (protover == 666) + else if (protover == FITZ_PROTOCOL_VERSION) { //fitzquake 0.85 cls.protocol_nq = CPNQ_FITZ666; Con_DPrintf("FitzQuake 666 protocol\n"); } - else if (protover == 3502) + else if (protover == DP5_PROTOCOL_VERSION) { //darkplaces5 cls.protocol_nq = CPNQ_DP5; @@ -2438,6 +2436,10 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. Con_DPrintf("DP7 protocols\n"); } + else if (protover == H2_PROTOCOL_VERSION) + { + Host_EndGame ("\nUnable to connect to Hexen2 servers.\n"); + } else if (protover != NQ_PROTOCOL_VERSION) { Host_EndGame ("Server returned version %i, not %i\nYou will need to use a different client.", protover, NQ_PROTOCOL_VERSION); @@ -4692,7 +4694,7 @@ void CL_DumpPacket(void) for (i = 0; i < 16; i++) { if (pos >= net_message.cursize) - Con_Printf(" X "); + Con_Printf(" - "); else Con_Printf("%2x ", (unsigned char)packet[pos]); pos++; @@ -5490,6 +5492,65 @@ void CLNQ_ParseProQuakeMessage (char *s) } } +static enum { + CLNQPP_NONE, + CLNQPP_PINGS +} cl_nqparseprint; +qboolean CLNQ_ParseNQPrints(char *s) +{ + int i; + char *start = s; + if (cl_nqparseprint == CLNQPP_PINGS) + { + char *pingstart; + cl_nqparseprint = CLNQPP_NONE; + while(*s == ' ') + s++; + pingstart = s; + if (*s == '-') + s++; + if (*s >= '0' && *s <= '9') + { + while(*s >= '0' && *s <= '9') + s++; + if (*s == ' ' && s-start >= 4) + { + s++; + start = s; + s = strchr(s, '\n'); + if (!s) + return false; + *s = 0; + + for (i = 0; i < MAX_CLIENTS; i++) + { + if (!strcmp(start, cl.players[i].name)) + break; + } + if (i == MAX_CLIENTS) + { + + } + if (i != MAX_CLIENTS) + { + cl.players[i].ping = atoi(pingstart); + } + cl_nqparseprint = CLNQPP_PINGS; + return true; + } + } + + s = start; + } + + if (!strcmp(s, "Client ping times:\n")) + { + cl_nqparseprint = CLNQPP_PINGS; + return true; + } + + return false; +} void CLNQ_ParseServerMessage (void) { @@ -5572,6 +5633,8 @@ void CLNQ_ParseServerMessage (void) } else { + if (CLNQ_ParseNQPrints(s)) + break; #ifdef PLUGINS if (Plug_ServerMessage(s, PRINT_HIGH)) #endif diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 1208c8d09..14a306373 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1382,6 +1382,9 @@ void SCR_DrawPause (void) if (!cl.paused) return; + if (key_dest == key_menu) + return; + pic = Draw_SafeCachePic ("gfx/pause.lmp"); if (pic) { diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 55874308f..dded58390 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -170,19 +170,6 @@ typedef enum #define Q2SPLASH_BLOOD 6 #endif - - - // hexen 2 -#define TE_STREAM_CHAIN 25 -#define TE_STREAM_SUNSTAFF1 26 -#define TE_STREAM_SUNSTAFF2 27 -#define TE_STREAM_LIGHTNING 28 -#define TE_STREAM_COLORBEAM 29 -#define TE_STREAM_ICECHUNKS 30 -#define TE_STREAM_GAZE 31 -#define TE_STREAM_FAMINE 32 - - #define MAX_BEAMS 64 typedef struct { @@ -620,7 +607,7 @@ void CL_ParseStream (int type) flags-=tag; duration = (float)MSG_ReadByte()*0.05; skin = 0; - if(type == TE_STREAM_COLORBEAM) + if(type == TEH2_STREAM_COLORBEAM) { skin = MSG_ReadByte(); } @@ -649,13 +636,23 @@ void CL_ParseStream (int type) switch(type) { - case TE_STREAM_ICECHUNKS: + case TEH2_STREAM_LIGHTNING_SMALL: + b->model = Mod_ForName("models/stltng2.mdl", true); + b->flags |= 2; + b->particleeffect = P_FindParticleType("te_stream_lightning_small"); + break; + case TEH2_STREAM_LIGHTNING: + b->model = Mod_ForName("models/stlghtng.mdl", true); + b->flags |= 2; + b->particleeffect = P_FindParticleType("te_stream_lightning"); + break; + case TEH2_STREAM_ICECHUNKS: b->model = Mod_ForName("models/stice.mdl", true); b->flags |= 2; b->particleeffect = P_FindParticleType("te_stream_icechunks"); R_AddStain(end, -10, -10, 0, 20); break; - case TE_STREAM_SUNSTAFF1: + case TEH2_STREAM_SUNSTAFF1: b->model = Mod_ForName("models/stsunsf1.mdl", true); b->particleeffect = P_FindParticleType("te_stream_sunstaff1"); if (b->particleeffect < 0) @@ -669,11 +666,14 @@ void CL_ParseStream (int type) } } break; - case TE_STREAM_SUNSTAFF2: + case TEH2_STREAM_SUNSTAFF2: b->model = Mod_ForName("models/stsunsf1.mdl", true); b->particleeffect = P_FindParticleType("te_stream_sunstaff2"); R_AddStain(end, -10, -10, -10, 20); break; + default: + Con_Printf("Oh noes! type %i\n", type); + break; } } @@ -1142,14 +1142,15 @@ void CL_ParseTEnt (void) P_ParticleTrailIndex(pos, pos2, 208, 8, NULL); break; - case TE_STREAM_CHAIN: - case TE_STREAM_SUNSTAFF1: - case TE_STREAM_SUNSTAFF2: - case TE_STREAM_LIGHTNING: - case TE_STREAM_COLORBEAM: - case TE_STREAM_ICECHUNKS: - case TE_STREAM_GAZE: - case TE_STREAM_FAMINE: + case TEH2_STREAM_LIGHTNING_SMALL: + case TEH2_STREAM_CHAIN: + case TEH2_STREAM_SUNSTAFF1: + case TEH2_STREAM_SUNSTAFF2: + case TEH2_STREAM_LIGHTNING: + case TEH2_STREAM_COLORBEAM: + case TEH2_STREAM_ICECHUNKS: + case TEH2_STREAM_GAZE: + case TEH2_STREAM_FAMINE: CL_ParseStream (type); break; diff --git a/engine/client/image.c b/engine/client/image.c index 5433a6c20..5cd936026 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -2012,17 +2012,21 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) *data = '#'; } - tex = R_FindTexture(name); + snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); + tex = R_FindTexture(fname); if (TEXVALID(tex)) //don't bother if it already exists. return tex; if (subpath && *subpath) { - snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); - tex = R_FindTexture(fname); + tex = R_FindTexture(name); if (TEXVALID(tex)) //don't bother if it already exists. return tex; } + + tex = R_LoadCompressed(fname); + if (TEXVALID(tex)) + return tex; tex = R_LoadCompressed(name); if (TEXVALID(tex)) return tex; @@ -2067,7 +2071,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value) BoostGamma(data, image_width, image_height); TRACE(("dbg: Mod_LoadHiResTexture: %s loaded\n", name)); - if (i == 1) + if (tex_path[i].args >= 3) { //if it came from a special subpath (eg: map specific), upload it using the subpath prefix snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); tex = R_LoadTexture32 (fname, image_width, image_height, data, flags); diff --git a/engine/client/m_items.c b/engine/client/m_items.c index d915e8199..666cc3aed 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -540,9 +540,10 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) Draw_FunString(x, y, option->bind.caption); x += strlen(option->bind.caption)*8+28; { + extern cvar_t cl_forcesplitclient; l = strlen (option->bind.command); - M_FindKeysForCommand (option->bind.command, keys); + M_FindKeysForCommand (cl_forcesplitclient.ival, option->bind.command, keys); if (bindingactive && menu->selecteditem == option) { diff --git a/engine/client/m_options.c b/engine/client/m_options.c index f3f96fe69..100c0555a 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -64,7 +64,7 @@ qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_se //options menu. void M_Menu_Options_f (void) { - extern cvar_t cl_standardchat; + extern cvar_t cl_standardchat, cl_splitscreen; extern cvar_t cl_standardmsg, crosshair; #ifdef _WIN32 extern qboolean vid_isfullscreen; @@ -77,6 +77,7 @@ void M_Menu_Options_f (void) MC_AddConsoleCommand(menu, 16, y, " Customize controls", "menu_keys\n"); y+=8; MC_AddConsoleCommand(menu, 16, y, " Go to console", "toggleconsole\nplay misc/menu2.wav\n"); y+=8; MC_AddConsoleCommand(menu, 16, y, " Reset to defaults", "exec default.cfg\nplay misc/menu2.wav\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Save all settings", "cfg_save\n"); y+=8; MC_AddSlider(menu, 16, y, " Mouse Speed", &sensitivity, 1, 10, 0.5); y+=8; MC_AddSlider(menu, 16, y, " Crosshair", &crosshair, 0, 22, 1); y+=8; @@ -85,6 +86,7 @@ void M_Menu_Options_f (void) MC_AddCheckBox(menu, 16, y, " Invert Mouse", NULL,0)->func = M_Options_InvertMouse; y+=8; MC_AddCheckBox(menu, 16, y, " Lookspring", &lookspring,0); y+=8; MC_AddCheckBox(menu, 16, y, " Lookstrafe", &lookstrafe,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Splitscreen", &cl_splitscreen,0); y+=8; MC_AddCheckBox(menu, 16, y, " Use old status bar", &cl_sbar,0); y+=8; MC_AddCheckBox(menu, 16, y, " HUD on left side", &cl_hudswap,0); y+=8; MC_AddCheckBox(menu, 16, y, " Old-style chatting", &cl_standardchat,0);y+=8; diff --git a/engine/client/m_single.c b/engine/client/m_single.c index bbfc1da44..c68aa4958 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -165,40 +165,121 @@ void M_Menu_SinglePlayer_f (void) else if (mgt == MGT_HEXEN2) { //h2 int y; + int i; cvar_t *pc; qboolean havemp; - static char *classlist[] = { - "Random", - "Paladin", - "Crusader", - "Necromancer", - "Assasin", - NULL - }; static char *classlistmp[] = { "Paladin", "Crusader", "Necromancer", "Assasin", - "Demoness", - NULL - }; - static char *classvalues[] = { - "", - "1", - "2", - "3", - "4", - "5", - NULL + "Demoness" }; + menubutton_t *b; havemp = COM_FCheckExists("maps/keep1.bsp"); menu = M_CreateMenu(0); MC_AddPicture(menu, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); - MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title1.lmp"); - y = 64-8; + y = 64-20; + if (!strncmp(Cmd_Argv(1), "class", 5)) + { + int pnum; + extern cvar_t cl_splitscreen; + pnum = atoi(Cmd_Argv(1)+5); + if (!pnum) + pnum = 1; + + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title2.lmp"); + + if (cl_splitscreen.ival) + MC_AddBufferedText(menu, 80, (y+=8)+12, va("Player %i\n", pnum), false, true); + + for (i = 0; i < 4+havemp; i++) + { + b = MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, classlistmp[i], + va("p%i setinfo cl_playerclass %i; menu_single %s %s\n", + pnum, + i+1, + ((pnum+1 > cl_splitscreen.ival+1)?"skill":va("class%i",pnum+1)), + Cmd_Argv(2))); + if (!menu->selecteditem) + menu->selecteditem = (menuoption_t*)b; + } + } + else if (!strncmp(Cmd_Argv(1), "skill", 5)) + { + static char *skillnames[6][4] = + { + { + "Easy", + "Medium", + "Hard", + "Nightmare" + }, + { + "Apprentice", + "Squire", + "Adept", + "Lord" + }, + { + "Gallant", + "Holy Avenger", + "Divine Hero", + "Legend" + }, + { + "Sorcerer", + "Dark Servant", + "Warlock", + "Lich King" + }, + { + "Rogue", + "Cutthroat", + "Executioner", + "Widow Maker" + }, + { + "Larva", + "Spawn", + "Fiend", + "She Bitch" + } + }; + char **sn = skillnames[0]; + pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2"); + if (pc && (unsigned)pc->ival <= 5) + sn = skillnames[pc->ival]; + + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title5.lmp"); + for (i = 0; i < 4; i++) + { + b = MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, sn[i], va("skill %i; closemenu; disconnect; deathmatch 0; coop 0;wait;map %s\n", i, Cmd_Argv(2))); + if (!menu->selecteditem) + menu->selecteditem = (menuoption_t*)b; + } + } + else + { + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title1.lmp"); + if (havemp) + { + menu->selecteditem = (menuoption_t*) + MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "New Mission", "menu_single class keep1\n"); + MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Old Mission", "menu_single class demo1\n"); + } + else + { + menu->selecteditem = (menuoption_t*) + MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "New Game", "menu_single class demo1\n"); + } + MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Save Game", "menu_save\n"); + MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Load Game", "menu_load\n"); + } + + /* pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2"); if (pc) MC_AddCvarCombo (menu, 64, y+=8, "Player class", pc, havemp?(const char **)classlistmp:(const char **)classlist, (const char **)(classvalues+havemp)); @@ -220,6 +301,9 @@ void M_Menu_SinglePlayer_f (void) MC_AddConsoleCommand (menu, 64, y+=8, "Load Game", "menu_load\n"); MC_AddConsoleCommand (menu, 64, y+=8, "Save Game", "menu_save\n"); + */ + + menu->cursoritem = (menuoption_t *)MC_AddCursor(menu, 56, menu->selecteditem?menu->selecteditem->common.posy:0); return; } diff --git a/engine/client/menu.c b/engine/client/menu.c index dc4c913d0..f1ed14e3c 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -309,7 +309,7 @@ bindnames_t h2bindnames[] = {"+showinfo", "full inventory"}, {"+showdm", "info / frags "}, //{"toggle_dm", "toggle frags "}, -//{"+infoplaque", "objectives "}, //requires pulling info out of the mod... on the client. +{"+infoplaque", "objectives "}, //requires pulling info out of the mod... on the client. {"invleft", "inv move left "}, {"invright", "inv move right"}, {"impulse 100", "inv:torch "}, @@ -341,26 +341,58 @@ void M_Menu_Keys_f (void) int y; menu_t *menu; int mgt; + extern cvar_t cl_splitscreen, cl_forcesplitclient; key_dest = key_menu; m_state = m_complex; menu = M_CreateMenu(0); - - MC_AddCenterPicture(menu, 4, 24, "gfx/ttl_cstm.lmp"); - mgt = M_GameType(); #ifdef Q2CLIENT if (mgt == MGT_QUAKE2) //quake2 main menu. + { + y = 48; bindnames = q2bindnames; + } else #endif if (mgt == MGT_HEXEN2) + { + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title6.lmp"); + y = 64; bindnames = h2bindnames; + } else - bindnames = qwbindnames; + { + MC_AddCenterPicture(menu, 4, 24, "gfx/ttl_cstm.lmp"); + y = 48; + + bindnames = qwbindnames; + } + + if (cl_splitscreen.ival) + { + static char *texts[MAX_SPLITS+2] = + { + "Depends on device", + "Player 1", + "Player 2", + "Player 3", + "Player 4", + NULL + }; + static char *values[MAX_SPLITS+1] = + { + "0", + "1", + "2", + "3", + "4" + }; + MC_AddCvarCombo(menu, 16, y, "Force client", &cl_forcesplitclient, texts, values); + y+=8; + } - y = 48; while (bindnames->name) { MC_AddBind(menu, 16, y, bindnames->name, bindnames->command); @@ -370,15 +402,15 @@ void M_Menu_Keys_f (void) } } - -void M_FindKeysForCommand (char *command, int *twokeys) +int M_FindKeysForBind (char *command, int *keylist, int total) { int count; int j; int l; char *b; - twokeys[0] = twokeys[1] = -1; + for (count = 0; count < total; count++) + keylist[count] = -1; l = strlen(command); count = 0; @@ -389,12 +421,44 @@ void M_FindKeysForCommand (char *command, int *twokeys) continue; if (!strncmp (b, command, l) ) { - twokeys[count] = j; + keylist[count] = j; count++; - if (count == 2) + if (count == total) break; } } + return count; +} + +void M_FindKeysForCommand (int pnum, char *command, int *twokeys) +{ + char prefix[5]; + + if (*command == '+' || *command == '-') + { + prefix[0] = *command; + prefix[1] = 0; + if (pnum != 0) + { + prefix[1] = 'p'; + prefix[2] = '0'+pnum; + prefix[3] = ' '; + prefix[4] = 0; + } + command++; + } + else + { + prefix[0] = 0; + if (pnum != 0) + { + prefix[0] = 'p'; + prefix[1] = '0'+pnum; + prefix[2] = ' '; + prefix[3] = 0; + } + } + M_FindKeysForBind(va("%s%s", prefix, command), twokeys, 2); } void M_UnbindCommand (char *command) diff --git a/engine/client/menu.h b/engine/client/menu.h index 862b2d64a..b422eccdd 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -388,7 +388,7 @@ void M_PrintWhite (int cx, int cy, qbyte *str); void M_DrawScalePic (int x, int y, int w, int h, mpic_t *pic); -void M_FindKeysForCommand (char *command, int *twokeys); +void M_FindKeysForCommand (int pnum, char *command, int *twokeys); void M_UnbindCommand (char *command); qboolean MP_Init (void); diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 8429be9fd..f73258b82 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -848,8 +848,6 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) int NET_CheckPollSockets(void) { - #define MAX_UDP_PACKET 8192 // one more than msg + header - extern qbyte net_message_buffer[MAX_UDP_PACKET]; int sock; SOCKET usesocket; char adr[MAX_ADR_SIZE]; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 3a5fddf65..b201d2adb 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -221,7 +221,7 @@ void PF_cl_findkeysforcommand (progfuncs_t *prinst, struct globalvars_s *pr_glob int keynums[2]; char keyname[512]; - M_FindKeysForCommand(cmdname, keynums); + M_FindKeysForCommand(0, cmdname, keynums); keyname[0] = '\0'; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 8016fc404..84c919bc5 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -395,6 +395,7 @@ void R2D_PolyBlend (void) R2D_ImageColours (sw_blend[0], sw_blend[1], sw_blend[2], sw_blend[3]); R2D_ScalePic(0, 0, vid.width, vid.height, shader_polyblend); + R2D_ImageColours (1, 1, 1, 1); } //for lack of hardware gamma @@ -422,6 +423,7 @@ void R2D_BrightenScreen (void) R2D_ScalePic(0, 0, vid.width, vid.height, shader_brighten); f *= 0.5; } + R2D_ImageColours (1, 1, 1, 1); RSpeedEnd(RSPEED_PALETTEFLASHES); } diff --git a/engine/client/sbar.c b/engine/client/sbar.c index af2b9924e..27722ba31 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -80,6 +80,7 @@ cvar_t sbar_teamstatus = SCVAR("sbar_teamstatus", "1"); int sb_updates; // if >= vid.numpages, no update needed int sb_hexen2_cur_item;//hexen2 hud qboolean sb_hexen2_extra_info;//show the extra stuff +qboolean sb_hexen2_infoplaque; float sb_hexen2_item_time; qboolean sbar_parsingteamstatuses; //so we don't eat it if its not displayed @@ -688,16 +689,22 @@ void Sbar_Hexen2InvUse_f(void) { Cbuf_AddText(va("impulse %d\n", 100+sb_hexen2_cur_item), Cmd_ExecLevel); } - void Sbar_Hexen2ShowInfo_f(void) { sb_hexen2_extra_info = true; } - void Sbar_Hexen2DontShowInfo_f(void) { sb_hexen2_extra_info = false; } +void Sbar_Hexen2PInfoPlaque_f(void) +{ + sb_hexen2_infoplaque = true; +} +void Sbar_Hexen2MInfoPlaque_f(void) +{ + sb_hexen2_infoplaque = false; +} /* =============== @@ -913,6 +920,8 @@ void Sbar_Init (void) Cmd_AddCommand ("invuse", Sbar_Hexen2InvUse_f); Cmd_AddCommand ("+showinfo", Sbar_Hexen2ShowInfo_f); Cmd_AddCommand ("-showinfo", Sbar_Hexen2DontShowInfo_f); + Cmd_AddCommand ("+infoplaque", Sbar_Hexen2PInfoPlaque_f); + Cmd_AddCommand ("-infoplaque", Sbar_Hexen2MInfoPlaque_f); Cbuf_AddText("alias +crouch \"impulse 22\"\n", RESTRICT_LOCAL); Cbuf_AddText("alias -crouch \"impulse 22\"\n", RESTRICT_LOCAL); } @@ -1848,6 +1857,18 @@ void Sbar_Hexen2DrawExtra (int pnum) "Demoness" }; + if (sb_hexen2_infoplaque) + { + int i; + Con_Printf("Objectives:\n"); + for (i = 0; i < 64; i++) + { + if (cl.stats[pnum][STAT_H2_OBJECTIVE1 + i/32] & (1<<(i&31))) + Con_Printf("%s\n", T_GetInfoString(i)); + } + sb_hexen2_infoplaque = false; + } + if (!sb_hexen2_extra_info) { sbar_rect.y -= 46-SBAR_HEIGHT; @@ -2556,10 +2577,18 @@ void Sbar_DeathmatchOverlay (int start) skip = 8; // request new ping times every two second - if (realtime - cl.last_ping_request > 2 && cls.protocol == CP_QUAKEWORLD && cls.demoplayback != DPB_EZTV) + if (realtime - cl.last_ping_request > 2 && cls.demoplayback != DPB_EZTV) { - cl.last_ping_request = realtime; - CL_SendClientCommand(true, "pings"); + if (cls.protocol == CP_QUAKEWORLD) + { + cl.last_ping_request = realtime; + CL_SendClientCommand(true, "pings"); + } + else if (cls.protocol == CP_NETQUAKE) + { + cl.last_ping_request = realtime; + CL_SendClientCommand(true, "ping"); + } } if (start) @@ -2604,8 +2633,11 @@ void Sbar_DeathmatchOverlay (int start) //columns are listed here in priority order (if the screen is too narrow, later ones will be hidden) COLUMN_NAME COLUMN_PING - COLUMN_PL - COLUMN_TIME + if (cls.protocol == CP_QUAKEWORLD) + { + COLUMN_PL + COLUMN_TIME + } COLUMN_FRAGS if (cl.teamplay) { diff --git a/engine/client/view.c b/engine/client/view.c index a46da5933..182e666e2 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1139,7 +1139,7 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) case 2: //horizontal bands case 3: #ifdef GLQUAKE - if (qrenderer == QR_OPENGL && vid.pixelwidth > vid.pixelheight * 2) + if (qrenderer == QR_OPENGL && vid.pixelwidth > vid.pixelheight * 2 && ffov.value >= 0) { //over twice as wide as high, assume duel moniter, horizontal. vrect->width = vid.width/cl.splitclients; vrect->height = vid.height; @@ -1261,10 +1261,8 @@ void V_RenderPlayerViews(int plnum) CL_LinkViewModel (); Cam_SelfTrack(plnum); - { - R_RenderView (); - R_DrawNameTags(); - } + R_RenderView (); + R_DrawNameTags(); cl_numvisedicts = oldnuments; diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 7bd5637b7..8da808be1 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -536,6 +536,9 @@ STAT_H2_MAXMANA, STAT_H2_FLAGS, STAT_H2_PLAYERCLASS, +STAT_H2_OBJECTIVE1, +STAT_H2_OBJECTIVE2, + STAT_MOVEVARS_WALLFRICTION = 237, // DP diff --git a/engine/common/common.h b/engine/common/common.h index 485634377..f5d2d3031 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -434,6 +434,8 @@ int build_number( void ); void TL_InitLanguages(void); void T_FreeStrings(void); char *T_GetString(int num); +void T_FreeInfoStrings(void); +char *T_GetInfoString(int num); // // log.c diff --git a/engine/common/fs.c b/engine/common/fs.c index 7a35d8bf9..4b798c9fd 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1834,6 +1834,7 @@ const gamemode_info_t gamemode_info[] = { {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", NULL, {"baseq2", "fteq2"}, "Quake II"}, {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", NULL, {"baseq3", "fteq3"}, "Quake III Arena"}, {"FTE-Quake4", "q4", "-q4", "q4base/pak00.pk4", NULL, {"q4base", "fteq4"}, "Quake 4"}, + {"FTE-EnemyTerritory", "et", "-et", "etmain/pak0.pk3", NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"}, {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"}, @@ -2039,6 +2040,29 @@ void FS_ReloadPackFiles_f(void) #define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile. #endif #include +static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname) +{ + /* + Find where Valve's Steam distribution platform is installed. + Then take a look at that location for the relevent installed app. + */ + FILE *f; + DWORD resultlen; + HKEY key = NULL; + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + Q_strncatz(basepath, va("/SteamApps/common/%s", steamdir), basepathlen); + if (f = fopen(va("%s/%s", basepath, fname), "rb")) + { + fclose(f); + return true; + } + } + return false; +} qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen) { DWORD resultlen; @@ -2067,23 +2091,14 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base if (!strcmp(gamename, "q1")) { + FILE *f; + //try and find it via steam //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath //append SteamApps\common\quake //use it if we find winquake.exe there - FILE *f; - if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) - { - resultlen = basepathlen; - RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); - RegCloseKey(key); - Q_strncatz(basepath, "/SteamApps/common/quake", basepathlen); - if (f = fopen(va("%s/Winquake.exe", basepath), "rb")) - { - fclose(f); - return true; - } - } + if (Sys_SteamHasFile(basepath, basepathlen, "quake", "Winquake.exe")) + return true; //well, okay, so they don't have quake installed from steam. //quite a lot of people have it in c:\quake, as that's the default install location from the quake cd. @@ -2098,26 +2113,9 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base if (!strcmp(gamename, "q2")) { - //try and find it via steam - //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath - //append SteamApps\common\quake 2 - //use it if we find quake2.exe there FILE *f; DWORD resultlen; HKEY key = NULL; - if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) - { - resultlen = basepathlen; - RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); - RegCloseKey(key); - Q_strncatz(basepath, "/SteamApps/common/quake 2", basepathlen); - if (f = fopen(va("%s/quake2.exe", basepath), "rb")) - { - fclose(f); - return true; - } - } - //well, okay, so they don't have quake2 installed from steam. //look for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Quake2_exe\Path if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) @@ -2131,20 +2129,54 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base return true; } } + + if (Sys_SteamHasFile(basepath, basepathlen, "quake 2", "quake2.exe")) + return true; + } + + if (!strcmp(gamename, "et")) + { + FILE *f; + DWORD resultlen; + HKEY key = NULL; + //reads HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Wolfenstein - Enemy Territory + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Activision\\Wolfenstein - Enemy Territory", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + + if (f = fopen(va("%s/ET.exe", basepath), "rb")) + { + fclose(f); + return true; + } + return true; + } } if (!strcmp(gamename, "q3")) { + FILE *f; DWORD resultlen; HKEY key = NULL; + //reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) { resultlen = basepathlen; RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); RegCloseKey(key); - return true; + + if (f = fopen(va("%s/quake3.exe", basepath), "rb")) + { + fclose(f); + return true; + } } + + if (Sys_SteamHasFile(basepath, basepathlen, "quake 3 arena", "quake3.exe")) + return true; } if (!strcmp(gamename, "wop")) @@ -2179,9 +2211,9 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base if (!strcmp(gamename, "h2")) { - //try and find it via steam - //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath //append SteamApps\common\hexen 2 + if (Sys_SteamHasFile(basepath, basepathlen, "hexen 2", "h2.exe")) + return true; } #if !defined(NPQTV) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser @@ -2265,6 +2297,77 @@ void FS_Shutdown(void) } +void FS_StartupWithGame(int gamenum) +{ + int i; + + Cvar_Set(&com_gamename, gamemode_info[gamenum].protocolname); + +// +// start up with id1 by default +// + i = COM_CheckParm ("-basegame"); + if (i && i < com_argc-1) + { + do //use multiple -basegames + { + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), ~0); + if (*com_homedir) + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_homedir, com_argv[i+1]), ~0); + + i = COM_CheckNextParm ("-basegame", i); + } + while (i && i < com_argc-1); + } + else + { + for (i = 0; i < sizeof(gamemode_info[gamenum].dir)/sizeof(gamemode_info[gamenum].dir[0]); i++) + { + if (gamemode_info[gamenum].dir[i]) + { + FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_quakedir, gamemode_info[gamenum].dir[i]), ~0); + if (*com_homedir) + FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_homedir, gamemode_info[gamenum].dir[i]), ~0); + } + } + } + + i = COM_CheckParm ("-addbasegame"); + while (i && i < com_argc-1) //use multiple -addbasegames (this is so the basic dirs don't die) + { + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), ~0); + if (*com_homedir) + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_homedir, com_argv[i+1]), ~0); + + i = COM_CheckNextParm ("-addbasegame", i); + } + + // any set gamedirs will be freed up to here + com_base_searchpaths = com_searchpaths; + + //-game specifies the mod gamedir to use in NQ + i = COM_CheckParm ("-game"); //effectivly replace with +gamedir x (But overridable) + if (i && i < com_argc-1) + { + COM_Gamedir(com_argv[i+1]); + } + + //+gamedir specifies the mod gamedir to use in QW + //hack - we parse the commandline after the config so commandline always overrides + //but this means ktpro/server.cfg (for example) is not found + //so if they specify a gamedir on the commandline, let the default configs be loaded from that gamedir + //note that -game +gamedir will result in both being loaded. but hey, who cares + i = COM_CheckParm ("+gamedir"); //effectivly replace with +gamedir x (But overridable) + if (i && i < com_argc-1) + { + COM_Gamedir(com_argv[i+1]); + } + + + if (gamemode_info[gamenum].customexec) + Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL); +} + /* ================ COM_InitFilesystem @@ -2375,11 +2478,6 @@ void COM_InitFilesystem (void) } } - Cvar_Set(&com_gamename, gamemode_info[gamenum].protocolname); - - if (gamemode_info[gamenum].customexec) - Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL); - usehome = false; #ifdef _WIN32 @@ -2414,6 +2512,7 @@ void COM_InitFilesystem (void) //as a browser plugin, always use their home directory usehome = true; #else + /*would it not be better to just check to see if we have write permission to the basedir?*/ if (winver >= 0x6) // Windows Vista and above usehome = true; // always use home directory by default, as Vista+ mimics this behavior anyway else if (winver >= 0x5) // Windows 2000/XP/2003 @@ -2488,67 +2587,8 @@ void COM_InitFilesystem (void) if (*com_homedir) Con_Printf("Using home directory \"%s\"\n", com_homedir); -// -// start up with id1 by default -// - i = COM_CheckParm ("-basegame"); - if (i && i < com_argc-1) - { - do //use multiple -basegames - { - FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), ~0); - if (*com_homedir) - FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_homedir, com_argv[i+1]), ~0); - i = COM_CheckNextParm ("-basegame", i); - } - while (i && i < com_argc-1); - } - else - { - for (i = 0; i < sizeof(gamemode_info[gamenum].dir)/sizeof(gamemode_info[gamenum].dir[0]); i++) - { - if (gamemode_info[gamenum].dir[i]) - { - FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_quakedir, gamemode_info[gamenum].dir[i]), ~0); - if (*com_homedir) - FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_homedir, gamemode_info[gamenum].dir[i]), ~0); - } - } - } - - - i = COM_CheckParm ("-addbasegame"); - while (i && i < com_argc-1) //use multiple -addbasegames (this is so the basic dirs don't die) - { - FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), ~0); - if (*com_homedir) - FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_homedir, com_argv[i+1]), ~0); - - i = COM_CheckNextParm ("-addbasegame", i); - } - - - // any set gamedirs will be freed up to here - com_base_searchpaths = com_searchpaths; - - //-game specifies the mod gamedir to use in NQ - i = COM_CheckParm ("-game"); //effectivly replace with +gamedir x (But overridable) - if (i && i < com_argc-1) - { - COM_Gamedir(com_argv[i+1]); - } - - //+gamedir specifies the mod gamedir to use in QW - //hack - we parse the commandline after the config so commandline always overrides - //but this means ktpro/server.cfg (for example) is not found - //so if they specify a gamedir on the commandline, let the default configs be loaded from that gamedir - //note that -game +gamedir will result in both being loaded. but hey, who cares - i = COM_CheckParm ("+gamedir"); //effectivly replace with +gamedir x (But overridable) - if (i && i < com_argc-1) - { - COM_Gamedir(com_argv[i+1]); - } + FS_StartupWithGame(gamenum); } diff --git a/engine/common/net.h b/engine/common/net.h index 6c484dfea..9c4b04f35 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -65,7 +65,7 @@ extern netadr_t net_from; // address of who sent the packet extern sizebuf_t net_message; //#define MAX_UDP_PACKET (MAX_MSGLEN*2) // one more than msg + header #define MAX_UDP_PACKET 8192 // one more than msg + header -extern qbyte net_message_buffer[MAX_UDP_PACKET]; +extern qbyte net_message_buffer[MAX_OVERALLMSGLEN]; extern cvar_t hostname; @@ -228,6 +228,9 @@ void Huff_EmitByte(int ch, qbyte *buffer, int *count); //server->client protocol info #define NQ_PROTOCOL_VERSION 15 +#define H2_PROTOCOL_VERSION 19 +#define NEHD_PROTOCOL_VERSION 250 +#define FITZ_PROTOCOL_VERSION 666 #define DP5_PROTOCOL_VERSION 3502 #define DP6_PROTOCOL_VERSION 3503 #define DP7_PROTOCOL_VERSION 3504 diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index bf478952c..e1788b07a 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -31,7 +31,7 @@ sizebuf_t net_message; //#define MAX_UDP_PACKET (MAX_MSGLEN*2) // one more than msg + header #define MAX_UDP_PACKET 8192 // one more than msg + header -qbyte net_message_buffer[MAX_UDP_PACKET]; +qbyte net_message_buffer[MAX_OVERALLMSGLEN]; #ifdef _WIN32 WSADATA winsockdata; #endif diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 359febb15..52aef18ba 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -646,7 +646,8 @@ enum { TE_RAILTRAIL = 17, - // hexen 2 + // hexen 2 + TEH2_STREAM_LIGHTNING_SMALL = 24, TEH2_STREAM_CHAIN = 25, TEH2_STREAM_SUNSTAFF1 = 26, TEH2_STREAM_SUNSTAFF2 = 27, diff --git a/engine/common/translate.c b/engine/common/translate.c index 3af58e7f5..0f9ca4a47 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -757,12 +757,13 @@ void TL_InitLanguages(void) +#ifndef CLIENTONLY //this stuff is for hexen2 translation strings. //(hexen2 is uuuuggllyyyy...) -char *strings_list; -char **strings_table; -int strings_count; -qboolean strings_loaded; +static char *strings_list; +static char **strings_table; +static int strings_count; +static qboolean strings_loaded; void T_FreeStrings(void) { //on map change, following gamedir change if (strings_loaded) @@ -822,4 +823,70 @@ char *T_GetString(int num) return strings_table[num]; } +#endif +#ifndef SERVERONLY +static char *info_strings_list; +static char **info_strings_table; +static int info_strings_count; +static qboolean info_strings_loaded; +void T_FreeInfoStrings(void) +{ //on map change, following gamedir change + if (info_strings_loaded) + { + BZ_Free(info_strings_list); + BZ_Free(info_strings_table); + info_strings_count = 0; + info_strings_loaded = false; + } +} +void T_LoadInfoString(void) +{ + int i; + char *s, *s2; + //count new lines + info_strings_loaded = true; + info_strings_count = 0; + info_strings_list = FS_LoadMallocFile("infolist.txt"); + if (!info_strings_list) + return; + + for (s = info_strings_list; *s; s++) + { + if (*s == '\n') + info_strings_count++; + } + info_strings_table = BZ_Malloc(sizeof(char*)*info_strings_count); + + s = info_strings_list; + for (i = 0; i < info_strings_count; i++) + { + info_strings_table[i] = s; + s2 = strchr(s, '\n'); + if (!s2) + break; + + while (s < s2) + { + if (*s == '\r') + *s = '\0'; + else if (*s == '^' || *s == '@') //becomes new line + *s = '\n'; + s++; + } + s = s2+1; + *s2 = '\0'; + } +} +char *T_GetInfoString(int num) +{ + if (!info_strings_loaded) + { + T_LoadInfoString(); + } + if (num<0 || num >= info_strings_count) + return "BAD STRING"; + + return info_strings_table[num]; +} +#endif \ No newline at end of file diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index d85ec4227..f1291392a 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -846,7 +846,7 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int if ((e->drawflags & MLS_MASKIN) == MLS_ABSLIGHT) { shadelight[0] = shadelight[1] = shadelight[2] = e->abslight; - ambientlight[0] = ambientlight[1] = ambientlight[2] = 0; + ambientlight[0] = ambientlight[1] = ambientlight[2] = e->abslight; } //#define SHOWLIGHTDIR diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 60cb01038..64e8e34a3 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -664,6 +664,9 @@ static void RevertToKnownState(void) shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY); shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; + shaderstate.shaderbits &= ~(SBITS_BLEND_BITS); + qglDisable(GL_BLEND); + qglDepthFunc(GL_LEQUAL); qglDepthMask(GL_TRUE); @@ -2631,6 +2634,12 @@ static void BaseBrushTextures(entity_t *ent) for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) Surf_RenderAmbientLightmaps (s, shift, ent->abslight); } + else if (ent->drawflags & DRF_TRANSLUCENT) + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderAmbientLightmaps (s, shift, 255); + } else { //update lightmaps. diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 724e215e8..0f8f225a1 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1616,22 +1616,28 @@ qboolean R_RenderScene_Fish(void) vec3_t saveang; int rot45 = 0; -#pragma message("backend fixme") - Con_Printf("fisheye/panorama is not updated for the backend\n"); + vrect_t vrect; + vrect_t prect; + + SCR_VRectForPlayer(&vrect, r_refdef.currentplayernum); + prect.x = (vrect.x * vid.pixelwidth)/vid.width; + prect.width = (vrect.width * vid.pixelwidth)/vid.width; + prect.y = (vrect.y * vid.pixelheight)/vid.height; + prect.height = (vrect.height * vid.pixelheight)/vid.height; if (!scenepp_panorama_program) return false; if (gl_config.arb_texture_non_power_of_two) { - if (vid.pixelwidth < vid.pixelheight) - cmapsize = vid.pixelwidth; + if (prect.width < prect.height) + cmapsize = prect.width; else - cmapsize = vid.pixelheight; + cmapsize = prect.height; } else { - while (cmapsize > vid.pixelwidth || cmapsize > vid.pixelheight) + while (cmapsize > prect.width || cmapsize > prect.height) { cmapsize /= 2; } @@ -1684,8 +1690,6 @@ qboolean R_RenderScene_Fish(void) order[5] = 5; } - qglViewport (0, vid.pixelheight - cmapsize, cmapsize, cmapsize); - if (!TEXVALID(scenepp_fisheye_texture)) { scenepp_fisheye_texture = GL_AllocNewTexture(); @@ -1705,10 +1709,10 @@ qboolean R_RenderScene_Fish(void) qglDisable(GL_TEXTURE_CUBE_MAP_ARB); } - r_refdef.vrect.width = (cmapsize+0.99)*vid.width/vid.pixelwidth; - r_refdef.vrect.height = (cmapsize+0.99)*vid.height/vid.pixelheight; + r_refdef.vrect.width = cmapsize; + r_refdef.vrect.height = cmapsize; r_refdef.vrect.x = 0; - r_refdef.vrect.y = vid.height - r_refdef.vrect.height; + r_refdef.vrect.y = prect.y; ang[0][0] = -saveang[0]; ang[0][1] = -90; @@ -1738,13 +1742,13 @@ qboolean R_RenderScene_Fish(void) qglDisable(GL_TEXTURE_2D); qglEnable(GL_TEXTURE_CUBE_MAP_ARB); GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture); - qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + order[i], 0, 0, 0, 0, 0, cmapsize, cmapsize); + qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + order[i], 0, 0, 0, 0, vid.pixelheight - (prect.y + cmapsize), cmapsize, cmapsize); qglEnable(GL_TEXTURE_2D); qglDisable(GL_TEXTURE_CUBE_MAP_ARB); } //qglClear (GL_COLOR_BUFFER_BIT); - qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); + qglViewport (prect.x, vid.pixelheight - (prect.y+prect.height), prect.width, prect.height); qglDisable(GL_TEXTURE_2D); GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture); @@ -1766,7 +1770,7 @@ qboolean R_RenderScene_Fish(void) qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity (); - qglOrtho (0, vid.pixelwidth, 0, vid.pixelheight, -99999, 99999); + qglOrtho (0, vid.width, vid.height, 0, -99999, 99999); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity (); @@ -1776,14 +1780,14 @@ qboolean R_RenderScene_Fish(void) qglDisable (GL_ALPHA_TEST); qglDisable(GL_BLEND); qglBegin(GL_QUADS); - qglTexCoord2f(-0.5, -0.5); - qglVertex2f(0, 0); - qglTexCoord2f(0.5, -0.5); - qglVertex2f(vid.pixelwidth, 0); - qglTexCoord2f(0.5, 0.5); - qglVertex2f(vid.pixelwidth, vid.pixelheight); qglTexCoord2f(-0.5, 0.5); - qglVertex2f(0, vid.pixelheight); + qglVertex2f(0, 0); + qglTexCoord2f(0.5, 0.5); + qglVertex2f(vid.width, 0); + qglTexCoord2f(0.5, -0.5); + qglVertex2f(vid.width, vid.height); + qglTexCoord2f(-0.5, -0.5); + qglVertex2f(0, vid.height); qglEnd(); qglMatrixMode(GL_PROJECTION); @@ -1796,6 +1800,9 @@ qboolean R_RenderScene_Fish(void) GLSlang_UseProgram(0); + qglEnable (GL_DEPTH_TEST); + PPL_RevertToKnownState(); + return true; } #endif diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index f76a1da10..d7c23655e 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -992,6 +992,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) multicastpos=2; multicasttype=MULTICAST_PHS; break; + case TEH2_STREAM_LIGHTNING_SMALL: case TEH2_STREAM_CHAIN: case TEH2_STREAM_SUNSTAFF1: case TEH2_STREAM_SUNSTAFF2: diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 72e649d7a..4ca8eec88 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -93,6 +93,7 @@ cvar_t sql_defaultdb = SCVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND); evalc_t evalc_idealpitch, evalc_pitch_speed; int pr_teamfield; +unsigned int h2infoplaque[2]; /*hexen2 stat*/ void PR_ClearThreads(void); void PR_fclose_progs(progfuncs_t*); @@ -700,6 +701,9 @@ void PR_LoadGlabalStruct(void) SV_QCStatName(ev_float, "max_mana", STAT_H2_MAXMANA); SV_QCStatName(ev_float, "flags", STAT_H2_FLAGS); SV_QCStatName(ev_float, "playerclass", STAT_H2_PLAYERCLASS); + + SV_QCStatPtr(ev_integer, &h2infoplaque[0], STAT_H2_OBJECTIVE1); + SV_QCStatPtr(ev_integer, &h2infoplaque[1], STAT_H2_OBJECTIVE2); } } @@ -7141,86 +7145,116 @@ void PF_h2matchAngleToSlope(progfuncs_t *prinst, struct globalvars_s *pr_globals actor->v->angles[0] = dot*pitch; actor->v->angles[2] = (1-fabs(dot))*pitch*mod; } +void PF_h2updateinfoplaque(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int idx = G_FLOAT(OFS_PARM0); + int mode = G_FLOAT(OFS_PARM1); /*0=toggle, 1=force, 2=clear*/ + if (idx >= sizeof(h2infoplaque)*8) + return; + + if ((mode & 3) == 3) + /*idiot*/; + else if (mode & 1) + h2infoplaque[idx/32] |= 1<<(idx&31); + else if (mode & 2) + h2infoplaque[idx/32] &=~(1<<(idx&31)); + else + h2infoplaque[idx/32] ^= 1<<(idx&31); +} void PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) { switch((int)G_FLOAT(OFS_PARM0)) { - case 4: - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/whtsmk1.spr"), 0, 5, 20); + case 4: //white_smoke + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/whtsmk1.spr"), 0, 5, 1/G_FLOAT(OFS_PARM3)); break; - case 6: + case 6: //yellowspark SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/spark.spr"), 0, 10, 20); break; - case 7: + case 7: //sm_circle SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fcircle.spr"), 0, 6, 20); break; - case 9: + case 9: //sm_white_flash SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_white.spr"), 0, 3, 20); break; - case 11: + case 11: //yellowred_flash SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/yr_flash.spr"), 0, 21, 20); break; - case 13: + case 13: //sm_blue_flash SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bluflash.spr"), 0, 5, 20); break; - case 14: + case 14: //red_flash SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/redspt.spr"), 0, 5, 20); break; - case 15: + case 15: //sm_explosion SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_expld.spr"), 0, 12, 20); break; - case 16: + case 16: //lg_explosion SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bg_expld.spr"), 0, 12, 20); break; - case 17: + case 17: //floor_explosion SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fl_expld.spr"), 0, 20, 20); break; - case 24: + case 20: //green_smoke + //parm1 = vel + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/grnsmk1.spr"), 0, 8, 1/G_FLOAT(OFS_PARM3)); + break; + case 24: //redspark SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/rspark.spr"), 0, 10, 20); break; - case 25: + case 25: //greenspark SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gspark.spr"), 0, 10, 20); break; - case 26: - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/telesmk1.spr"), 0, 4, 20); + case 26: //telesmk1 + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/telesmk1.spr"), 0, 4, 1/G_FLOAT(OFS_PARM3)); break; - case 28: + case 28: //icehit SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/icehit.spr"), 0, 6, 20); break; - case 33: + case 33: //new_explosion SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gen_expl.spr"), 0, 14, 20); break; - case 34: + case 34: //magic_missile_explosion SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/mm_explod.spr"), 0, 50, 20); break; - case 42: + case 42: //flamestream SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/flamestr.spr"), 0, 12, 20); break; - case 45: + case 45: //bldrn_expl SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/xplsn_1.spr"), 0, 7, 20); break; - case 47: + case 47: //acid_hit SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/axplsn_2.spr"), 0, 14, 20); break; - case 48: + case 48: //firewall_small SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal1.spr"), 0, 18, 20); break; - case 49: + case 49: //firewall_medium SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal5.spr"), 0, 30, 20); break; - case 50: + case 50: //firewall_large SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal4.spr"), 0, 29, 20); break; - case 56: + case 54: //fboom + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fboom.spr"), 0, 14, 20); + break; + case 56: //bomb SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/pow.spr"), 0, 6, 20); break; - case 40: + case 46: + case 52: + case 53: + case 57: + break; + + + case 40: //boneshard // SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/boneshot.mdl"), 0, 50, 20); // break; - case 2: - case 55: + case 2: //fountain + case 55: //chunk Con_DPrintf("Start unsupported effect %i\n", (int)G_FLOAT(OFS_PARM0)); break; @@ -7248,6 +7282,10 @@ void PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals) { } +void PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} + void PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *s = T_GetString(G_FLOAT(OFS_PARM0)-1); @@ -9286,11 +9324,11 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"precache_sound3", PF_precache_sound, 0, 0, 96, 0}, {"precache_model3", PF_precache_model, 0, 0, 97, 0},//please don't use... {"matchangletoslope",PF_h2matchAngleToSlope,0, 0, 99, 0}, - + {"updateinfoplaque",PF_h2updateinfoplaque,0, 0, 100, 0}, {"precache_sound4", PF_precache_sound, 0, 0, 101, 0}, {"precache_model4", PF_precache_model, 0, 0, 102, 0}, {"precache_file4", PF_precache_file, 0, 0, 103, 0}, - {"dowhiteflash", PF_Fixme, 0, 0, 104, 0}, + {"dowhiteflash", PF_h2whiteflash, 0, 0, 104, 0}, {"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0}, {"stopsound", PF_h2StopSound, 0, 0, 106, 0}, diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 65629f1d1..e81094f9d 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -1224,18 +1224,6 @@ Con_DPrintf("PF_readcmd: %s\n%s", s, output); break; //nothing changed, ignore it. sv.paused = pause; sv.pausedstart = Sys_DoubleTime(); - - // send out notifications - for (i=0, cl = svs.clients ; istate) - continue; - if ((ISQWCLIENT(cl) || ISNQCLIENT(cl)) && !cl->controller) - { - ClientReliableWrite_Begin (cl, svc_setpause, 2); - ClientReliableWrite_Byte (cl, sv.paused); - } - } } break; diff --git a/engine/server/server.h b/engine/server/server.h index 32759d016..d45fe001e 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1012,6 +1012,7 @@ qboolean SV_ChallengePasses(int challenge); void SV_QCStatName(int type, char *name, int statnum); void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum); void SV_QCStatGlobal(int type, char *globalname, int statnum); +void SV_QCStatPtr(int type, void *ptr, int statnum); void SV_ClearQCStats(void); void SV_SendClientMessages (void); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index db88b3d84..2a9330efe 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1077,12 +1077,14 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us ent = EDICT_NUM(svprogfuncs, 0); ent->isfree = false; +#ifndef SERVERONLY /*force coop 1 if splitscreen and not deathmatch*/ { extern cvar_t cl_splitscreen; if (cl_splitscreen.value && !deathmatch.value && !coop.value) Cvar_Set(&coop, "1"); } +#endif /*only make one slot for single-player*/ if (!isDedicated && !deathmatch.value && !coop.value) sv.allocated_client_slots = 1; @@ -1454,6 +1456,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us SCR_ImageName(server); #endif + /*DP_BOTCLIENT bots should move over to the new map too*/ if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) { for (i = 0; i < sv.allocated_client_slots; i++) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f3f86952f..4c047a2e3 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -3321,6 +3321,23 @@ void SV_Impulse_f (void) svs.clients[i].state = cs_free; } +static void SV_PauseChanged(void) +{ + int i; + client_t *cl; + // send notification to all clients + for (i=0, cl = svs.clients ; istate) + continue; + if ((ISQWCLIENT(cl) || ISNQCLIENT(cl)) && !cl->controller) + { + ClientReliableWrite_Begin (cl, svc_setpause, 2); + ClientReliableWrite_Byte (cl, sv.paused!=0); + } + } +} + /* ================== SV_Frame @@ -3333,6 +3350,7 @@ void SV_Frame (void) static double start, end; float oldtime; qboolean isidle; + static int oldpaused; start = Sys_DoubleTime (); svs.stats.idle += start - end; @@ -3345,6 +3363,16 @@ void SV_Frame (void) if (!sv.gamespeed) sv.gamespeed = 1; +#ifndef SERVERONLY + sv.paused = (sv.paused & ~4) | ((!isDedicated && sv.allocated_client_slots == 1 && key_dest != key_game)?4:0); +#endif + + if (oldpaused != sv.paused) + { + SV_PauseChanged(); + oldpaused = sv.paused; + } + // decide the simulation time { oldtime = sv.time; @@ -3358,9 +3386,7 @@ void SV_Frame (void) sv.time = oldtime; //and keep time as it was. } -#ifndef SERVERONLY if (isDedicated) -#endif realtime += sv.time - oldtime; } diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 37bc869bd..032d5a9d1 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1180,12 +1180,23 @@ FIXME: is this true? static void SV_Physics_Step (edict_t *ent) { qboolean hitsound; + qboolean freefall; + int fl = ent->v->flags; - if (ent->v->velocity[2] >= (1.0 / 32.0) && ((int)ent->v->flags & FL_ONGROUND)) - ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; + if (ent->v->velocity[2] >= (1.0 / 32.0) && (fl & FL_ONGROUND)) + { + fl &= ~FL_ONGROUND; + ent->v->flags = fl; + } // frefall if not onground - if ( ! ((int)ent->v->flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) + if (fl & (FL_ONGROUND | FL_FLY)) + freefall = false; + else + freefall = true; + if (fl & FL_SWIM) + freefall = ent->v->waterlevel > 0; + if (freefall) { hitsound = ent->v->velocity[2] < movevars.gravity*-0.1; @@ -1858,12 +1869,12 @@ void SV_RunEntity (edict_t *ent) case MOVETYPE_FOLLOW: SV_Physics_Follow (ent); break; + case MOVETYPE_FLY: + case MOVETYPE_H2SWIM: case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: - case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: - case MOVETYPE_H2SWIM: SV_Physics_Toss (ent); break; case MOVETYPE_WALK: diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 4837086d6..cad452549 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -689,7 +689,9 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int // -1 is because pvs rows are 1 based, not 0 based like leafs if (mask != sv.pvs) { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, client->edict->v->origin)-1; + vec3_t pos; + VectorAdd(client->edict->v->origin, client->edict->v->view_ofs, pos); + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, pos)-1; if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) { // Con_Printf ("PVS supressed multicast\n"); @@ -1280,13 +1282,21 @@ void SV_QCStatGlobal(int type, char *globalname, int statnum) { eval_t *glob; + if (type < 0) + return; + glob = svprogfuncs->FindGlobal(svprogfuncs, globalname, PR_ANY); if (!glob) { Con_Printf("couldn't find named global for csqc stat (%s)\n", globalname); return; } - SV_QCStatEval(type, globalname, NULL, glob, statnum); + SV_QCStatEval(-type, globalname, NULL, glob, statnum); +} + +void SV_QCStatPtr(int type, void *ptr, int statnum) +{ + SV_QCStatEval(-type, "", NULL, ptr, statnum); } void SV_QCStatName(int type, char *name, int statnum) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 8d114e3c7..c227a7f55 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1423,9 +1423,9 @@ void SV_Spawn_f (void) // // force stats to be updated // - memset (host_client->statsi, 0, sizeof(host_client->statsi)); - memset (host_client->statsf, 0, sizeof(host_client->statsf)); - memset (host_client->statss, 0, sizeof(host_client->statss)); + memset (split->statsi, 0, sizeof(split->statsi)); + memset (split->statsf, 0, sizeof(split->statsf)); + memset (split->statss, 0, sizeof(split->statss)); } secret_total = pr_global_struct->total_secrets; @@ -1693,7 +1693,7 @@ void SV_Begin_f (void) if (!ISQ2CLIENT(host_client)) { ClientReliableWrite_Begin (host_client, svc_setpause, 2); - ClientReliableWrite_Byte (host_client, sv.paused); + ClientReliableWrite_Byte (host_client, sv.paused!=0); } SV_ClientTPrintf(host_client, PRINT_HIGH, STL_SERVERPAUSED); } @@ -2893,8 +2893,6 @@ SV_TogglePause */ qboolean SV_TogglePause (client_t *initiator) { - int i; - client_t *cl; int newv; newv = sv.paused^1; @@ -2906,18 +2904,6 @@ qboolean SV_TogglePause (client_t *initiator) sv.pausedstart = Sys_DoubleTime(); - // send notification to all clients - for (i=0, cl = svs.clients ; istate) - continue; - if (!ISQ2CLIENT(cl) && !cl->controller) - { - ClientReliableWrite_Begin (cl, svc_setpause, 2); - ClientReliableWrite_Byte (cl, sv.paused); - } - } - return true; } @@ -4299,9 +4285,9 @@ void SVNQ_Begin_f (void) if (!ISQ2CLIENT(host_client)) { ClientReliableWrite_Begin (host_client, svc_setpause, 2); - ClientReliableWrite_Byte (host_client, sv.paused); + ClientReliableWrite_Byte (host_client, sv.paused!=0); } - SV_ClientTPrintf(host_client, PRINT_HIGH, STL_SERVERPAUSED); + SV_ClientTPrintf(host_client, PRINT_HIGH, STL_SERVERPAUSED!=0); } if (sendangles) @@ -5778,6 +5764,11 @@ haveannothergo: SV_PostRunCmd(); } + else + { + if (newcmd.impulse)// && SV_FiltureImpulse(newcmd.impulse, host_client->trustlevel)) + sv_player->v->impulse = newcmd.impulse; + } cl->lastcmd = newcmd; cl->lastcmd.buttons = 0; // avoid multiple fires on lag diff --git a/engine/server/svhl_phys.c b/engine/server/svhl_phys.c index 3f97fcc31..29476c457 100644 --- a/engine/server/svhl_phys.c +++ b/engine/server/svhl_phys.c @@ -1024,7 +1024,7 @@ void SVHL_Physics_Toss (hledict_t *ent) if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE - && ent->v.movetype != MOVETYPE_SWIM) + && ent->v.movetype != MOVETYPE_H2SWIM) SVHL_AddGravity (ent, 1.0); // move angles