diff --git a/NQ/cl_input.c b/NQ/cl_input.c index ee38636..6ccb97e 100644 --- a/NQ/cl_input.c +++ b/NQ/cl_input.c @@ -137,13 +137,15 @@ void IN_MLookDown(void) { KeyDown(&in_mlook); + if (!((in_mlook.state & 1) ^ (int)m_freelook.value) && lookspring.value) + V_StartPitchDrift(); } void IN_MLookUp(void) { KeyUp(&in_mlook); - if (!(in_mlook.state & 1) && lookspring.value) + if (!((in_mlook.state & 1) ^ (int)m_freelook.value) && lookspring.value) V_StartPitchDrift(); } @@ -391,8 +393,8 @@ CL_KeyState(kbutton_t *key) //========================================================================== cvar_t cl_upspeed = { "cl_upspeed", "200" }; -cvar_t cl_forwardspeed = { "cl_forwardspeed", "200", true }; -cvar_t cl_backspeed = { "cl_backspeed", "200", true }; +cvar_t cl_forwardspeed = { "cl_forwardspeed", "200" }; +cvar_t cl_backspeed = { "cl_backspeed", "200" }; cvar_t cl_sidespeed = { "cl_sidespeed", "350" }; cvar_t cl_movespeedkey = { "cl_movespeedkey", "2.0" }; @@ -402,6 +404,8 @@ cvar_t cl_pitchspeed = { "cl_pitchspeed", "150" }; cvar_t cl_anglespeedkey = { "cl_anglespeedkey", "1.5" }; +cvar_t cl_run = { "cl_run", "0", true }; + /* ================ @@ -416,7 +420,7 @@ CL_AdjustAngles(void) float speed; float up, down; - if (in_speed.state & 1) + if ((in_speed.state & 1) ^ (int)cl_run.value) speed = host_frametime * cl_anglespeedkey.value; else speed = host_frametime; @@ -492,7 +496,7 @@ CL_BaseMove(usercmd_t *cmd) // // adjust for speed key // - if (in_speed.state & 1) { + if ((in_speed.state & 1) ^ (int)cl_run.value) { cmd->forwardmove *= cl_movespeedkey.value; cmd->sidemove *= cl_movespeedkey.value; cmd->upmove *= cl_movespeedkey.value; diff --git a/NQ/cl_main.c b/NQ/cl_main.c index 99bb5ec..8cba4f7 100644 --- a/NQ/cl_main.c +++ b/NQ/cl_main.c @@ -53,6 +53,8 @@ cvar_t m_yaw = { "m_yaw", "0.022", true }; cvar_t m_forward = { "m_forward", "1", true }; cvar_t m_side = { "m_side", "0.8", true }; +cvar_t m_freelook = { "m_freelook", "0", true }; + client_static_t cls; client_state_t cl; @@ -826,6 +828,7 @@ CL_Init(void) Cvar_RegisterVariable(&cl_yawspeed); Cvar_RegisterVariable(&cl_pitchspeed); Cvar_RegisterVariable(&cl_anglespeedkey); + Cvar_RegisterVariable(&cl_run); Cvar_RegisterVariable(&cl_shownet); Cvar_RegisterVariable(&cl_nolerp); Cvar_RegisterVariable(&lookspring); @@ -837,6 +840,8 @@ CL_Init(void) Cvar_RegisterVariable(&m_forward); Cvar_RegisterVariable(&m_side); + Cvar_RegisterVariable(&m_freelook); + Cmd_AddCommand("entities", CL_PrintEntities_f); Cmd_AddCommand("disconnect", CL_Disconnect_f); Cmd_AddCommand("record", CL_Record_f); diff --git a/NQ/client.h b/NQ/client.h index eb3f962..9438ef5 100644 --- a/NQ/client.h +++ b/NQ/client.h @@ -234,6 +234,8 @@ extern cvar_t cl_pitchspeed; extern cvar_t cl_anglespeedkey; +extern cvar_t cl_run; + extern cvar_t cl_autofire; extern cvar_t cl_shownet; @@ -249,6 +251,8 @@ extern cvar_t m_yaw; extern cvar_t m_forward; extern cvar_t m_side; +extern cvar_t m_freelook; + #define MAX_TEMP_ENTITIES 64 // lightning bolts, etc #define MAX_STATIC_ENTITIES 1024 // torches, etc diff --git a/NQ/host.c b/NQ/host.c index 0fd48ea..c6c3e06 100644 --- a/NQ/host.c +++ b/NQ/host.c @@ -284,10 +284,6 @@ Host_WriteConfiguration(void) Key_WriteBindings(f); Cvar_WriteVariables(f); - /* Save the mlook state (rarely used as an actual key binding) */ - if (in_mlook.state & 1) - fprintf(f, "+mlook\n"); - fclose(f); } } diff --git a/QW/client/cl_input.c b/QW/client/cl_input.c index 0f9625f..e0c22a1 100644 --- a/QW/client/cl_input.c +++ b/QW/client/cl_input.c @@ -135,13 +135,15 @@ static void IN_MLookDown(void) { KeyDown(&in_mlook); + if (!((in_mlook.state & 1) ^ (int)m_freelook.value) && lookspring.value) + V_StartPitchDrift(); } static void IN_MLookUp(void) { KeyUp(&in_mlook); - if (!(in_mlook.state & 1) && lookspring.value) + if (!((in_mlook.state & 1) ^ (int)m_freelook.value) && lookspring.value) V_StartPitchDrift(); } @@ -388,8 +390,8 @@ CL_KeyState(kbutton_t *key) //========================================================================== cvar_t cl_upspeed = { "cl_upspeed", "200" }; -cvar_t cl_forwardspeed = { "cl_forwardspeed", "200", true }; -cvar_t cl_backspeed = { "cl_backspeed", "200", true }; +cvar_t cl_forwardspeed = { "cl_forwardspeed", "200" }; +cvar_t cl_backspeed = { "cl_backspeed", "200" }; cvar_t cl_sidespeed = { "cl_sidespeed", "350" }; cvar_t cl_movespeedkey = { "cl_movespeedkey", "2.0" }; @@ -399,6 +401,8 @@ cvar_t cl_pitchspeed = { "cl_pitchspeed", "150" }; cvar_t cl_anglespeedkey = { "cl_anglespeedkey", "1.5" }; +cvar_t cl_run = { "cl_run", "0", true }; + /* ================ @@ -413,7 +417,7 @@ CL_AdjustAngles(void) float speed; float up, down; - if (in_speed.state & 1) + if ((in_speed.state & 1) ^ (int)cl_run.value) speed = host_frametime * cl_anglespeedkey.value; else speed = host_frametime; @@ -487,7 +491,7 @@ CL_BaseMove(usercmd_t *cmd) // // adjust for speed key // - if (in_speed.state & 1) { + if ((in_speed.state & 1) ^ (int)cl_run.value) { cmd->forwardmove *= cl_movespeedkey.value; cmd->sidemove *= cl_movespeedkey.value; cmd->upmove *= cl_movespeedkey.value; diff --git a/QW/client/cl_main.c b/QW/client/cl_main.c index 9bbfefe..4bfa4dc 100644 --- a/QW/client/cl_main.c +++ b/QW/client/cl_main.c @@ -88,6 +88,8 @@ cvar_t m_yaw = { "m_yaw", "0.022" }; cvar_t m_forward = { "m_forward", "1" }; cvar_t m_side = { "m_side", "0.8" }; +cvar_t m_freelook = { "m_freelook", "0", true }; + cvar_t entlatency = { "entlatency", "20" }; cvar_t cl_predict_players = { "cl_predict_players", "1" }; cvar_t cl_predict_players2 = { "cl_predict_players2", "1" }; @@ -1059,6 +1061,7 @@ CL_Init(void) Cvar_RegisterVariable(&cl_yawspeed); Cvar_RegisterVariable(&cl_pitchspeed); Cvar_RegisterVariable(&cl_anglespeedkey); + Cvar_RegisterVariable(&cl_run); Cvar_RegisterVariable(&cl_shownet); Cvar_RegisterVariable(&cl_sbar); Cvar_RegisterVariable(&cl_hudswap); @@ -1073,6 +1076,8 @@ CL_Init(void) Cvar_RegisterVariable(&m_forward); Cvar_RegisterVariable(&m_side); + Cvar_RegisterVariable(&m_freelook); + Cvar_RegisterVariable(&rcon_password); Cvar_RegisterVariable(&rcon_address); @@ -1240,10 +1245,6 @@ Host_WriteConfiguration(void) Key_WriteBindings(f); Cvar_WriteVariables(f); - /* Save the mlook state (rarely used as an actual key binding) */ - if (in_mlook.state & 1) - fprintf(f, "+mlook\n"); - fclose(f); } } diff --git a/QW/client/client.h b/QW/client/client.h index d724dc1..b526e09 100644 --- a/QW/client/client.h +++ b/QW/client/client.h @@ -307,6 +307,8 @@ extern cvar_t cl_pitchspeed; extern cvar_t cl_anglespeedkey; +extern cvar_t cl_run; + extern cvar_t cl_shownet; extern cvar_t cl_sbar; extern cvar_t cl_hudswap; @@ -321,6 +323,8 @@ extern cvar_t m_yaw; extern cvar_t m_forward; extern cvar_t m_side; +extern cvar_t m_freelook; + extern cvar_t name; extern cvar_t cl_predict_players; diff --git a/QW/cmds.txt b/QW/cmds.txt index 8f295c6..d8a3cb6 100644 --- a/QW/cmds.txt +++ b/QW/cmds.txt @@ -173,6 +173,7 @@ cl_movespeedkey cl_yawspeed cl_pitchspeed cl_anglespeedkey +cl_run cl_shownet cl_timeout cl_hightrack diff --git a/changelog.txt b/changelog.txt index 49e7b72..6b2f7ce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,7 +4,7 @@ Unreleased * SDL video/input/sound target, now default for MacOS instead of X11. * sndio sound target for OpenBSD (thanks Tony Spets/Jacob Meuser) * Support for BJP1/2/3 and FITZ(666) network/demo protocols -* Support for RMQ style BSP2 file format +* Support for Darkplaces and RMQ style BSP2/2PSB file formats * Work around buggy timers on some windows systems/drivers (thanks MH!) * Removed vid_win dependency on SciTech MGL (thanks MH!) * Netmasks can be used with qwsv's addip/removeip; e.g. "addip 192.168.0.0/24" @@ -12,6 +12,7 @@ Unreleased * Improved build system including new OSX, Win64, SDL targets * Lots more code sharing between NQ/QW * Use non-power-of-two OpenGL textures when extension is available +* New cvar "m_freelook" to replace need for manual editing "+mlook" in config 2009-07-05 TyrQuake v0.61 diff --git a/common/in_sdl.c b/common/in_sdl.c index f86f27f..dd14d2f 100644 --- a/common/in_sdl.c +++ b/common/in_sdl.c @@ -641,15 +641,15 @@ IN_MouseMove(usercmd_t *cmd) mouse_x *= sensitivity.value; mouse_y *= sensitivity.value; - if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) + if ((in_strafe.state & 1) || (lookstrafe.value && ((in_mlook.state & 1) ^ (int)m_freelook.value))) cmd->sidemove += m_side.value * mouse_x; else cl.viewangles[YAW] -= m_yaw.value * mouse_x; - if (in_mlook.state & 1) + if ((in_mlook.state & 1) ^ (int)m_freelook.value) if (mouse_x || mouse_y) V_StopPitchDrift(); - if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { + if (((in_mlook.state & 1) ^ (int)m_freelook.value) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80; diff --git a/common/in_win.c b/common/in_win.c index 629dd99..6f69dfd 100644 --- a/common/in_win.c +++ b/common/in_win.c @@ -657,16 +657,16 @@ IN_MouseMove(usercmd_t *cmd) mouse_y *= sensitivity.value; // add mouse X/Y movement to cmd - if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) + if ((in_strafe.state & 1) || (lookstrafe.value && ((in_mlook.state & 1) ^ (int)m_freelook.value))) cmd->sidemove += m_side.value * mouse_x; else cl.viewangles[YAW] -= m_yaw.value * mouse_x; - if (in_mlook.state & 1) + if ((in_mlook.state & 1) ^ (int)m_freelook.value) if (mouse_x || mouse_y) V_StopPitchDrift(); - if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { + if (((in_mlook.state & 1) ^ (int)m_freelook.value) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80; @@ -1015,7 +1015,7 @@ IN_JoyMove(usercmd_t *cmd) return; } - if (in_speed.state & 1) + if ((in_speed.state & 1) ^ (int)cl_run.value) speed = cl_movespeedkey.value; else speed = 1; @@ -1046,7 +1046,7 @@ IN_JoyMove(usercmd_t *cmd) switch (dwAxisMap[i]) { case AxisForward: - if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) { + if ((joy_advanced.value == 0.0) && ((in_mlook.state & 1) ^ (int)m_freelook.value)) { // user wants forward control to become look control if (fabs(fAxisValue) > joy_pitchthreshold.value) { // if mouse invert is on, invert the joystick pitch value @@ -1082,7 +1082,7 @@ IN_JoyMove(usercmd_t *cmd) case AxisTurn: if ((in_strafe.state & 1) - || (lookstrafe.value && (in_mlook.state & 1))) { + || (lookstrafe.value && ((in_mlook.state & 1) ^ (int)m_freelook.value)) { // user wants turn control to become side control if (fabs(fAxisValue) > joy_sidethreshold.value) { cmd->sidemove -= @@ -1107,7 +1107,7 @@ IN_JoyMove(usercmd_t *cmd) break; case AxisLook: - if (in_mlook.state & 1) { + if ((in_mlook.state & 1) ^ (int)m_freelook.value) { if (fabs(fAxisValue) > joy_pitchthreshold.value) { // pitch movement detected and pitch movement desired by user if (dwControlMap[i] == JOY_ABSOLUTE_AXIS) { diff --git a/common/in_x11.c b/common/in_x11.c index eb79cd0..d7721f5 100644 --- a/common/in_x11.c +++ b/common/in_x11.c @@ -292,16 +292,16 @@ IN_MouseMove(usercmd_t *cmd) mouse_y *= sensitivity.value; /* add mouse X/Y movement to cmd */ - if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) + if ((in_strafe.state & 1) || (lookstrafe.value && ((in_mlook.state & 1) ^ (int)m_freelook.value))) cmd->sidemove += m_side.value * mouse_x; else cl.viewangles[YAW] -= m_yaw.value * mouse_x; - if (in_mlook.state & 1) + if ((in_mlook.state & 1) ^ (int)m_freelook.value) if (mouse_x || mouse_y) V_StopPitchDrift (); - if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { + if (((in_mlook.state & 1) ^ (int)m_freelook.value) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80; diff --git a/common/menu.c b/common/menu.c index e48fdfb..10498d1 100644 --- a/common/menu.c +++ b/common/menu.c @@ -416,6 +416,7 @@ typedef enum { M_OPTIONS_CURSOR_SOUNDVOLUME, M_OPTIONS_CURSOR_ALWAYSRUN, M_OPTIONS_CURSOR_MOUSEINVERT, + M_OPTIONS_CURSOR_MOUSELOOK, M_OPTIONS_CURSOR_LOOKSPRING, M_OPTIONS_CURSOR_LOOKSTRAFE, #ifdef QW_HACK @@ -475,17 +476,14 @@ M_AdjustSliders(int dir) Cvar_SetValue("volume", volume.value); break; case M_OPTIONS_CURSOR_ALWAYSRUN: - if (cl_forwardspeed.value > 200) { - Cvar_SetValue("cl_forwardspeed", 200); - Cvar_SetValue("cl_backspeed", 200); - } else { - Cvar_SetValue("cl_forwardspeed", 400); - Cvar_SetValue("cl_backspeed", 400); - } + Cvar_SetValue("cl_run", !cl_run.value); break; case M_OPTIONS_CURSOR_MOUSEINVERT: Cvar_SetValue("m_pitch", -m_pitch.value); break; + case M_OPTIONS_CURSOR_MOUSELOOK: + Cvar_SetValue("m_freelook", !m_freelook.value); + break; case M_OPTIONS_CURSOR_LOOKSPRING: Cvar_SetValue("lookspring", !lookspring.value); break; @@ -566,11 +564,14 @@ M_Options_Draw(void) M_DrawSlider(220, height, slider); M_Print(16, height += 8, " Always Run"); - M_DrawCheckbox(220, height, cl_forwardspeed.value > 200); + M_DrawCheckbox(220, height, cl_run.value); M_Print(16, height += 8, " Invert Mouse"); M_DrawCheckbox(220, height, m_pitch.value < 0); + M_Print(16, height += 8, " Mouse Look"); + M_DrawCheckbox(220, height, m_freelook.value); + M_Print(16, height += 8, " Lookspring"); M_DrawCheckbox(220, height, lookspring.value); diff --git a/common/model.c b/common/model.c index 9715a00..dfe6342 100644 --- a/common/model.c +++ b/common/model.c @@ -647,6 +647,28 @@ Mod_LoadTextures(brushmodel_t *brushmodel, dheader_t *header) } } +/* + * Mod_LoadBytes + * - Common code for loading lighting, visibility and entities + */ +static void * +Mod_LoadBytes(brushmodel_t *brushmodel, dheader_t *header, int lumpnum) +{ + const model_t *model = &brushmodel->model; + const lump_t *headerlump = &header->lumps[lumpnum]; + const byte *in; + byte *out; + + if (!headerlump->filelen) + return NULL; + + in = (byte *)header + headerlump->fileofs; + out = Mod_AllocName(headerlump->filelen, model->name); + memcpy(out, in, headerlump->filelen); + + return out; +} + /* ================= Mod_LoadLighting @@ -655,17 +677,7 @@ Mod_LoadLighting static void Mod_LoadLighting(brushmodel_t *brushmodel, dheader_t *header) { - const model_t *model = &brushmodel->model; - const lump_t *headerlump = &header->lumps[LUMP_LIGHTING]; - const byte *lightdata; - - if (!headerlump->filelen) { - brushmodel->lightdata = NULL; - return; - } - lightdata = (byte *)header + headerlump->fileofs; - brushmodel->lightdata = Mod_AllocName(headerlump->filelen, model->name); - memcpy(brushmodel->lightdata, lightdata, headerlump->filelen); + brushmodel->lightdata = Mod_LoadBytes(brushmodel, header, LUMP_LIGHTING); } @@ -677,17 +689,7 @@ Mod_LoadVisibility static void Mod_LoadVisibility(brushmodel_t *brushmodel, dheader_t *header) { - const model_t *model = &brushmodel->model; - const lump_t *headerlump = &header->lumps[LUMP_VISIBILITY]; - const byte *visdata; - - if (!headerlump->filelen) { - brushmodel->visdata = NULL; - return; - } - visdata = (byte *)header + headerlump->fileofs; - brushmodel->visdata = Mod_AllocName(headerlump->filelen, model->name); - memcpy(brushmodel->visdata, visdata, headerlump->filelen); + brushmodel->visdata = Mod_LoadBytes(brushmodel, header, LUMP_VISIBILITY); } @@ -699,17 +701,7 @@ Mod_LoadEntities static void Mod_LoadEntities(brushmodel_t *brushmodel, dheader_t *header) { - const model_t *model = &brushmodel->model; - const lump_t *headerlump = &header->lumps[LUMP_ENTITIES]; - const byte *entities; - - if (!headerlump->filelen) { - brushmodel->entities = NULL; - return; - } - entities = (byte *)header + headerlump->fileofs; - brushmodel->entities = Mod_AllocName(headerlump->filelen, model->name); - memcpy(brushmodel->entities, entities, headerlump->filelen); + brushmodel->entities = Mod_LoadBytes(brushmodel, header, LUMP_ENTITIES); } @@ -799,7 +791,7 @@ Mod_LoadEdges_BSP29(brushmodel_t *brushmodel, dheader_t *header) if (headerlump->filelen % sizeof(*in)) SV_Error("%s: funny lump size in %s", __func__, model->name); count = headerlump->filelen / sizeof(*in); - out = Mod_AllocName((count + 1) * sizeof(*out), model->name); + out = Mod_AllocName(count * sizeof(*out), model->name); brushmodel->edges = out; brushmodel->numedges = count; @@ -823,7 +815,7 @@ Mod_LoadEdges_BSP2(brushmodel_t *brushmodel, dheader_t *header) if (headerlump->filelen % sizeof(*in)) SV_Error("%s: funny lump size in %s", __func__, model->name); count = headerlump->filelen / sizeof(*in); - out = Mod_AllocName((count + 1) * sizeof(*out), model->name); + out = Mod_AllocName(count * sizeof(*out), model->name); brushmodel->edges = out; brushmodel->numedges = count; @@ -1128,7 +1120,7 @@ Mod_SetParent(mnode_t *node, mnode_t *parent) /* ================= Mod_LoadNodes - => Two versions for the different BSP file formats + => Three versions for the different BSP file formats ================= */ static void @@ -1170,15 +1162,15 @@ Mod_LoadNodes_BSP29(brushmodel_t *brushmodel, dheader_t *header) } static void -Mod_LoadNodes_BSP2(brushmodel_t *brushmodel, dheader_t *header) +Mod_LoadNodes_BSP2rmq(brushmodel_t *brushmodel, dheader_t *header) { const model_t *model = &brushmodel->model; const lump_t *headerlump = &header->lumps[LUMP_NODES]; - const bsp2_dnode_t *in; + const bsp2rmq_dnode_t *in; mnode_t *out; int i, j, count; - in = (bsp2_dnode_t *)((byte *)header + headerlump->fileofs); + in = (bsp2rmq_dnode_t *)((byte *)header + headerlump->fileofs); if (headerlump->filelen % sizeof(*in)) SV_Error("%s: funny lump size in %s", __func__, model->name); count = headerlump->filelen / sizeof(*in); @@ -1207,10 +1199,77 @@ Mod_LoadNodes_BSP2(brushmodel_t *brushmodel, dheader_t *header) Mod_SetParent(brushmodel->nodes, NULL); } +static void +Mod_LoadNodes_BSP2(brushmodel_t *brushmodel, dheader_t *header) +{ + const model_t *model = &brushmodel->model; + const lump_t *headerlump = &header->lumps[LUMP_NODES]; + const bsp2_dnode_t *in; + mnode_t *out; + int i, j, count; + + in = (bsp2_dnode_t *)((byte *)header + headerlump->fileofs); + if (headerlump->filelen % sizeof(*in)) + SV_Error("%s: funny lump size in %s", __func__, model->name); + count = headerlump->filelen / sizeof(*in); + out = Mod_AllocName(count * sizeof(*out), model->name); + + brushmodel->nodes = out; + brushmodel->numnodes = count; + + for (i = 0; i < count; i++, in++, out++) { + out->plane = brushmodel->planes + LittleLong(in->planenum); + out->firstsurface = (uint32_t)LittleLong(in->firstface); + out->numsurfaces = (uint32_t)LittleLong(in->numfaces); + for (j = 0; j < 3; j++) { + out->mins[j] = LittleFloat(in->mins[j]); + out->maxs[j] = LittleFloat(in->maxs[j]); + } + for (j = 0; j < 2; j++) { + const int nodenum = LittleLong(in->children[j]); + if (nodenum >= 0) + out->children[j] = brushmodel->nodes + nodenum; + else + out->children[j] = (mnode_t *)(brushmodel->leafs - nodenum - 1); + } + } + + Mod_SetParent(brushmodel->nodes, NULL); +} + +static void +Mod_SetLeafFlags(const model_t *model, mleaf_t *leaf) +{ +#ifdef GLQUAKE + int i; + + // FIXME - gl underwater warp + // this warping is ugly, these ifdefs are ugly - get rid of it all? + if (leaf->contents != CONTENTS_EMPTY) { + for (i = 0; i < leaf->nummarksurfaces; i++) + leaf->firstmarksurface[i]->flags |= SURF_UNDERWATER; + } + +#ifdef QW_HACK + { + char mapmodel[MAX_QPATH]; + snprintf(mapmodel, sizeof(mapmodel), "maps/%s.bsp", + Info_ValueForKey(cl.serverinfo, "map")); + if (strcmp(mapmodel, model->name)) { +#endif + for (i = 0; i < leaf->nummarksurfaces; i++) + leaf->firstmarksurface[i]->flags |= SURF_DONTWARP; +#ifdef QW_HACK + } + } +#endif +#endif +} + /* ================= Mod_LoadLeafs - => Two versions for the different BSP file formats + => Three versions for the different BSP file formats ================= */ static void @@ -1251,28 +1310,49 @@ Mod_LoadLeafs_BSP29(brushmodel_t *brushmodel, dheader_t *header) for (j = 0; j < 4; j++) out->ambient_sound_level[j] = in->ambient_level[j]; -#ifdef GLQUAKE - // FIXME - gl underwater warp - // this warping is ugly, these ifdefs are ugly - get rid of it all? - if (out->contents != CONTENTS_EMPTY) { - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_UNDERWATER; - } + Mod_SetLeafFlags(model, out); + } +} -#ifdef QW_HACK - { - char mapmodel[MAX_QPATH]; - snprintf(mapmodel, sizeof(mapmodel), "maps/%s.bsp", - Info_ValueForKey(cl.serverinfo, "map")); - if (strcmp(mapmodel, model->name)) { -#endif - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_DONTWARP; -#ifdef QW_HACK - } +static void +Mod_LoadLeafs_BSP2rmq(brushmodel_t *brushmodel, dheader_t *header) +{ + const model_t *model = &brushmodel->model; + const lump_t *headerlump = &header->lumps[LUMP_LEAFS]; + const bsp2rmq_dleaf_t *in; + mleaf_t *out; + int i, j, count, visofs; + + in = (bsp2rmq_dleaf_t *)((byte *)header + headerlump->fileofs); + if (headerlump->filelen % sizeof(*in)) + SV_Error("%s: funny lump size in %s", __func__, model->name); + count = headerlump->filelen / sizeof(*in); + out = Mod_AllocName(count * sizeof(*out), model->name); + + brushmodel->leafs = out; + brushmodel->numleafs = count; + + for (i = 0; i < count; i++, in++, out++) { + out->efrags = NULL; + out->contents = LittleLong(in->contents); + out->firstmarksurface = brushmodel->marksurfaces + + (uint32_t)LittleLong(in->firstmarksurface); + out->nummarksurfaces = (uint32_t)LittleLong(in->nummarksurfaces); + + visofs = LittleLong(in->visofs); + if (visofs == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = brushmodel->visdata + visofs; + + for (j = 0; j < 3; j++) { + out->mins[j] = LittleShort(in->mins[j]); + out->maxs[j] = LittleShort(in->maxs[j]); } -#endif -#endif + for (j = 0; j < 4; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + + Mod_SetLeafFlags(model, out); } } @@ -1308,34 +1388,13 @@ Mod_LoadLeafs_BSP2(brushmodel_t *brushmodel, dheader_t *header) out->compressed_vis = brushmodel->visdata + visofs; for (j = 0; j < 3; j++) { - out->mins[j] = LittleShort(in->mins[j]); - out->maxs[j] = LittleShort(in->maxs[j]); + out->mins[j] = LittleFloat(in->mins[j]); + out->maxs[j] = LittleFloat(in->maxs[j]); } for (j = 0; j < 4; j++) out->ambient_sound_level[j] = in->ambient_level[j]; -#ifdef GLQUAKE - // FIXME - gl underwater warp - // this warping is ugly, these ifdefs are ugly - get rid of it all? - if (out->contents != CONTENTS_EMPTY) { - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_UNDERWATER; - } - -#ifdef QW_HACK - { - char mapmodel[MAX_QPATH]; - snprintf(mapmodel, sizeof(mapmodel), "maps/%s.bsp", - Info_ValueForKey(cl.serverinfo, "map")); - if (strcmp(mapmodel, model->name)) { -#endif - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_DONTWARP; -#ifdef QW_HACK - } - } -#endif -#endif + Mod_SetLeafFlags(model, out); } } @@ -1650,6 +1709,38 @@ Mod_SetupSubmodels(brushmodel_t *world) } } +static const char * +BSPVersionString(int32_t version) +{ + static char buffers[2][20]; + static int index; + char *buffer; + + switch (version) { + case BSP2RMQVERSION: + return "BSP2rmq"; + case BSP2VERSION: + return "BSP2"; + default: + buffer = buffers[1 & ++index]; + snprintf(buffer, sizeof(buffers[0]), "%d", version); + return buffer; + } +} + +static qboolean +BSPVersionSupported(int32_t version) +{ + switch (version) { + case BSPVERSION: + case BSP2VERSION: + case BSP2RMQVERSION: + return true; + default: + return false; + } +} + /* ================= Mod_LoadBrushModel @@ -1671,10 +1762,9 @@ Mod_LoadBrushModel(brushmodel_t *brushmodel, void *buffer, size_t size) header->lumps[i].filelen = LittleLong(header->lumps[i].filelen); } - if (header->version != BSPVERSION && header->version != BSP2VERSION) - SV_Error("%s: %s has wrong version number (%i should be %i or %i)", - __func__, model->name, header->version, - BSPVERSION, BSP2VERSION); + if (!BSPVersionSupported(header->version)) + SV_Error("%s: %s has unsupported version %s", + __func__, model->name, BSPVersionString(header->version)); /* * Check the lump extents @@ -1753,8 +1843,13 @@ Mod_LoadBrushModel(brushmodel_t *brushmodel, void *buffer, size_t size) Mod_LoadNodes_BSP29(brushmodel, header); Mod_LoadClipnodes_BSP29(brushmodel, header); } else { - Mod_LoadLeafs_BSP2(brushmodel, header); - Mod_LoadNodes_BSP2(brushmodel, header); + if (header->version == BSP2RMQVERSION) { + Mod_LoadLeafs_BSP2rmq(brushmodel, header); + Mod_LoadNodes_BSP2rmq(brushmodel, header); + } else { + Mod_LoadLeafs_BSP2(brushmodel, header); + Mod_LoadNodes_BSP2(brushmodel, header); + } Mod_LoadClipnodes_BSP2(brushmodel, header); } Mod_LoadEntities(brushmodel, header); diff --git a/include/bspfile.h b/include/bspfile.h index 230084c..608b11f 100644 --- a/include/bspfile.h +++ b/include/bspfile.h @@ -58,8 +58,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //============================================================================= -#define BSPVERSION 29 -#define BSP2VERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') +#define BSPVERSION 29 +#define BSP2RMQVERSION (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') +#define BSP2VERSION ('B' | ('S' << 8) | ('P' << 16) | ('2' << 24)) typedef struct { int32_t fileofs; @@ -163,6 +164,15 @@ typedef struct { int16_t maxs[3]; uint32_t firstface; uint32_t numfaces; // counting both sides +} bsp2rmq_dnode_t; + +typedef struct { + int32_t planenum; + int32_t children[2]; // negative numbers are -(leafs+1), not nodes + float mins[3]; // for sphere culling + float maxs[3]; + uint32_t firstface; + uint32_t numfaces; // counting both sides } bsp2_dnode_t; /* @@ -266,6 +276,19 @@ typedef struct { uint32_t firstmarksurface; uint32_t nummarksurfaces; + uint8_t ambient_level[NUM_AMBIENTS]; +} bsp2rmq_dleaf_t; + +typedef struct { + int32_t contents; + int32_t visofs; // -1 = no visibility info + + float mins[3]; // for frustum culling + float maxs[3]; + + uint32_t firstmarksurface; + uint32_t nummarksurfaces; + uint8_t ambient_level[NUM_AMBIENTS]; } bsp2_dleaf_t; diff --git a/man/tyrquake.6 b/man/tyrquake.6 index 7f3028b..31a1d03 100644 --- a/man/tyrquake.6 +++ b/man/tyrquake.6 @@ -187,7 +187,38 @@ to use this (and it probably doesn't even work anymore!) .SH "CONSOLE COMMANDS" -.IP "\fBcd\fP" +.IP "\fBcd\fP [command] [arguments]" +Passes commands to the CD audio subsystem. Sub-commands are listed below. +.RS +.IP "\fBon\fP" +Enable the CD audio subsystem. +.IP "\fBoff\fP" +Disable the CD audio subsystem. +.IP "\fBplay n\fP" +Play CD audio track \fIn\fP. +.IP "\fBloop n\fP" +Play CD audio track \fIn\fP in a loop. +.IP "\fBstop\fP" +Stop playing CD audio. +.IP "\fBpause\fP" +Pause CD audio playback. +.IP "\fBresume\fP" +Resume playing CD audio (if currently paused). +.IP "\fBeject\fP" +Eject the CD media. +.IP "\fBclose\fP" +Request the CD tray to close. +.IP "\fBremap x y\fP" +Given two track numbers \fIx\fP and \fIy\fP, remap a CD track number such that +a request to play track \fIx\fP will result in real track \fIy\fP being +played. Remappings can be reset with the \fIcd reset\fP command. +.IP "\fBreset\fP" +Stop playing audio, remove any CD track remappings and re-read the CD table of +contents. +.IP "\fBinfo\fP" +Displays number of tracks on the currently loaded CD, which track is currently +playing or paused (if any) and the current CD audio volume. +.RE .IP "\fBstuffcmds\fP" .IP "\fBexec\fP" .IP "\fBecho\fP" @@ -262,6 +293,10 @@ every memory block in the zone is printed. .IP "\fB+jump, \-jump\fP" .IP "\fB+klook, \-klook\fP" .IP "\fB+mlook, \-mlook\fP" +When the mlook key is depressed, mouse movement controls the view +orientation instead of direction of movement. If cvar "m_freelook" is +1, then the reverse is true, with mouse look enabled by default and +the mlook key activates mouse movement instead. .IP "\fBimpulse\fP" .IP "\fBentities\fP" .IP "\fBdisconnect\fP" @@ -374,6 +409,8 @@ listip.cfg which can later be restored with 'exec listip.cfg'. .SH "CONSOLE VARIABLES" .IP "\fBbgmvolume\fP" +Set volume level for background music. Valid values are between 0 (off) and 1 +(full volume). Default 1. .IP "\fBregistered\fP" .IP "\fBcmdline\fP" .IP "\fBcon_notifytime\fP" @@ -544,6 +581,7 @@ to their defaults after reloading the engine. Default 1. .IP "\fBcl_yawspeed\fP" .IP "\fBcl_pitchspeed\fP" .IP "\fBcl_anglespeedkey\fP" +.IP "\fBcl_run\fP" .IP "\fBcl_shownet\fP" .IP "\fBcl_nolerp\fP" .IP "\fBlookspring\fP" @@ -553,6 +591,10 @@ to their defaults after reloading the engine. Default 1. .IP "\fBm_yaw\fP" .IP "\fBm_forward\fP" .IP "\fBm_side\fP" +.IP "\fBm_freelook\fP" +If 1, view orientation is controlled by mouse and the "mouse look" key +(+mlook) has the inverse effect of temporarily disabling free look +mode while depressed. .IP "\fBhost_speeds\fP" .IP "\fBsys_ticrate\fP" .IP "\fBserverprofile\fP"