From ea5c476ced52d2dd88d28665a4372981bf3961cf Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 10 Oct 2004 06:32:29 +0000 Subject: [PATCH] I need to commit more often... git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@316 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cam.c | 2 + engine/client/cl_ents.c | 65 +++++++- engine/client/cl_main.c | 5 + engine/client/cl_parse.c | 17 +- engine/client/cl_screen.c | 61 ++++++- engine/client/cl_tent.c | 17 +- engine/client/client.h | 4 +- engine/client/console.c | 13 +- engine/client/image.c | 27 ++- engine/client/net_master.c | 4 +- engine/client/renderer.c | 71 ++++++-- engine/client/view.c | 4 + engine/client/zqtp.c | 111 +++++++++++++ engine/common/bothdefs.h | 3 + engine/common/cvar.c | 4 +- engine/common/cvar.h | 4 +- engine/common/mathlib.c | 180 ++++++++++++++++++++ engine/common/plugin.c | 308 ++++++++++++++++++++++++++++++++--- engine/common/protocol.h | 3 + engine/common/qvm.c | 2 +- engine/common/vm.h | 1 + engine/common/zone.c | 54 +++++- engine/ftequake/ftequake.dsp | 2 +- engine/gl/gl_alias.c | 1 + engine/gl/gl_draw.c | 209 ++++++++++++++++++------ engine/gl/gl_rmisc.c | 12 +- engine/gl/gl_screen.c | 3 + engine/gl/gl_vidcommon.c | 8 + engine/gl/gl_warp.c | 38 ++++- engine/gl/glquake.h | 3 + engine/server/pr_cmds.c | 170 +++++++++++++------ engine/server/progdefs.h | 10 +- engine/server/progs.h | 3 + engine/server/sv_ents.c | 143 ++++++++++------ engine/server/sv_main.c | 1 + engine/server/sv_phys.c | 72 +++++++- engine/server/sv_send.c | 5 +- engine/server/sv_user.c | 24 ++- engine/sw/d_edge.c | 24 ++- engine/sw/sw_draw.c | 116 ++++++------- 40 files changed, 1493 insertions(+), 311 deletions(-) diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 8124e0d0a..1cd9091d0 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -105,6 +105,8 @@ qboolean Cam_DrawViewModel(int pnum) // returns true if we should draw this player, we don't if we are chase camming qboolean Cam_DrawPlayer(int pnum, int playernum) { + if (playernum == cl.playernum[pnum]) + return false; if (cl.spectator && autocam[pnum] && locked[pnum] && cl_chasecam.value && spec_track[pnum] == playernum) return false; diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index a54fc7c77..398c39278 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -780,6 +780,49 @@ entity_state_t *CL_FindPacketEntity(int num) } #endif +void CL_RotateAroundTag(entity_t *ent, int num) +{ + entity_state_t *ps; + float *org=NULL, *ang=NULL; + + ps = CL_FindPacketEntity(cl.lerpents[num].tagent); + if (ps) + { + org = ps->origin; + ang = ps->angles; + } + else + { + extern int parsecountmod; + if (cl.lerpents[num].tagent <= MAX_CLIENTS && cl.lerpents[num].tagent > 0) + { + if (cl.lerpents[num].tagent-1 == cl.playernum[0]) + { + org = cl.simorg[0]; + ang = cl.simangles[0]; + } + else + { + org = cl.frames[parsecountmod].playerstate[cl.lerpents[num].tagent-1].origin; + ang = cl.frames[parsecountmod].playerstate[cl.lerpents[num].tagent-1].viewangles; + } + } + } + + if (org) + VectorAdd(ent->origin, org, ent->origin); + if (ang) + { + if (ps) + ent->angles[0]+=ang[0]; + else + ent->angles[0]+=-ang[0]/3; + ent->angles[1]+=ang[1]; + ent->angles[2]+=ang[2]; + } + + ent->keynum = cl.lerpents[num].tagent; +} /* =============== CL_LinkPacketEntities @@ -1002,6 +1045,11 @@ void CL_LinkPacketEntities (void) } } + if (cl.lerpents[s1->number].tagent) + { //ent is attached to a tag, rotate this ent accordingly. + CL_RotateAroundTag(ent, s1->number); + } + // add automatic particle trails if (!model || (!(model->flags&~EF_ROTATE) && model->particletrail<0)) continue; @@ -1299,7 +1347,7 @@ void CL_ParsePlayerinfo (void) state->hullnum = 1; state->scale = 1; - state->trans = 100; + state->trans = 1; state->fatness = 0; state->pm_type = PM_NORMAL; @@ -1383,7 +1431,7 @@ void CL_ParsePlayerinfo (void) state->hullnum = 1; state->scale = 1; - state->trans = 100; + state->trans = 1; state->fatness = 0; if (cls.z_ext & Z_EXT_PM_TYPE) @@ -1396,7 +1444,7 @@ void CL_ParsePlayerinfo (void) #endif #ifdef PEXT_TRANS if (flags & PF_TRANS_Z && cls.fteprotocolextensions & PEXT_TRANS) - state->trans = (float)MSG_ReadByte() / 2.55; + state->trans = (float)MSG_ReadByte() / 255; #endif #ifdef PEXT_FATNESS if (flags & PF_FATNESS_Z && cls.fteprotocolextensions & PEXT_FATNESS) @@ -1458,7 +1506,7 @@ void CL_ParsePlayerinfo (void) #endif #ifdef PEXT_TRANS if (flags & PF_TRANS_NOZ && cls.fteprotocolextensions & PEXT_TRANS) - state->trans = (float)MSG_ReadByte() / 2.55; + state->trans = (float)MSG_ReadByte() / 255; #endif #ifdef PEXT_FATNESS if (flags & PF_FATNESS_NOZ && cls.fteprotocolextensions & PEXT_FATNESS) @@ -1559,6 +1607,15 @@ void CL_AddVWeapModel(entity_t *player, int model) newent->frame = player->frame; } +void CL_ParseAttachment(void) +{ + int e = (unsigned short)MSG_ReadShort(); + int o = (unsigned short)MSG_ReadShort(); + int i = (unsigned short)MSG_ReadShort(); + cl.lerpents[e].tagent = o; + cl.lerpents[e].tagindex = i; +} + /* ============= CL_LinkPlayers diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index cb4626e41..b2f1b758a 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -153,7 +153,11 @@ qbyte *host_colormap; cvar_t host_speeds = {"host_speeds","0"}; // set for running times cvar_t show_fps = {"show_fps","0"}; // set for running times +#ifdef CRAZYDEBUGGING +cvar_t developer = {"developer","1"}; +#else cvar_t developer = {"developer","0"}; +#endif int fps_count; @@ -316,6 +320,7 @@ void CL_SendConnectPacket ( fteprotextsupported |= PEXT_256PACKETENTITIES; // fteprotextsupported |= PEXT_64PLAYERS; fteprotextsupported |= PEXT_SHOWPIC; + fteprotextsupported |= PEXT_SETATTACHMENT; fteprotextsupported &= ftepext; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index fc7c3029d..39d01c911 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -519,6 +519,8 @@ to start a download from the server. */ qboolean CL_CheckOrDownloadFile (char *filename, int nodelay) { + downloadlist_t *failed; + if (strstr (filename, "..")) { Con_TPrintf (TL_NORELATIVEPATHS); @@ -541,18 +543,17 @@ qboolean CL_CheckOrDownloadFile (char *filename, int nodelay) if (cl.faileddownloads) { - downloadlist_t *failed; for (failed = cl.faileddownloads; failed; failed = failed->next) //yeah, so it failed... Ignore it. { if (!strcmp(failed->name, filename)) return true; } + } - for (failed = cl.downloadlist; failed; failed = failed->next) //It's already on our list. Ignore it. - { - if (!strcmp(failed->name, filename)) - return true; - } + for (failed = cl.downloadlist; failed; failed = failed->next) //It's already on our list. Ignore it. + { + if (!strcmp(failed->name, filename)) + return true; } if ((!requiredownloads.value && !nodelay) || nodelay==-1) @@ -3677,6 +3678,10 @@ void CL_ParseServerMessage (void) case svc_updatepic: SCR_ShowPic_Update(); break; + + case svc_setattachment: + CL_ParseAttachment(); + break; } } } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 72d7f2ade..3f452e382 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -387,6 +387,7 @@ static void SP_RecalcXY ( float *xx, float *yy, int origin ) } void SCR_ShowPics_Draw(void) { + downloadlist_t *failed; float x, y; showpic_t *sp; qpic_t *p; @@ -395,9 +396,18 @@ void SCR_ShowPics_Draw(void) x = sp->x; y = sp->y; SP_RecalcXY(&x, &y, sp->zone); - p = Draw_SafeCachePic(sp->picname); if (!*sp->picname) continue; + + for (failed = cl.faileddownloads; failed; failed = failed->next) + { //don't try displaying ones that we know to have failed. + if (!strcmp(failed->name, sp->picname)) + break; + } + if (failed) + continue; + + p = Draw_SafeCachePic(sp->picname); if (!p) continue; Draw_Pic(x, y, p); @@ -675,6 +685,49 @@ void SCR_CalcRefdef (void) scr_vrect = r_refdef.vrect; } +void SCR_CrosshairPosition(int pnum, int *x, int *y) +{ + extern cvar_t cl_crossx, cl_crossy, crosshaircorrect; + + vrect_t rect; + SCR_VRectForPlayer(&rect, pnum); + + if (cl.worldmodel && crosshaircorrect.value) + { + trace_t tr; + vec3_t end; + vec3_t start; + vec3_t right, up, fwds; + + AngleVectors(cl.viewangles[pnum], fwds, right, up); + VectorMA(cl.simorg[pnum], 100000, fwds, end); + + memset(&tr, 0, sizeof(tr)); + tr.fraction = 1; + cl.worldmodel->hulls->funcs.RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, cl.simorg[pnum], end, &tr); + if (tr.fraction == 1) + { + *x = rect.x + rect.width/2 + cl_crossx.value; + *y = rect.y + rect.height/2 + cl_crossy.value; + return; + } + else + { + VectorCopy(cl.simorg[pnum], start); + start[2] -= cl.viewheight[pnum]/4; + ML_Project(tr.endpos, end, cl.viewangles[pnum], start, (float)rect.width/rect.height); + *x = rect.x+rect.width*end[0]; + *y = rect.y+rect.height*end[1]; + return; + } + } + else + { + *x = rect.x + rect.width/2 + cl_crossx.value; + *y = rect.y + rect.height/2 + cl_crossy.value; + return; + } +} /* ================= @@ -817,6 +870,12 @@ void SCR_DrawFPS (void) sprintf(st, "%3.1f FPS", lastfps); x = vid.width - strlen(st) * 8 - 8; y = vid.height - sb_lines - 8; +// Draw_TileClear(x, y, strlen(st) * 8, 8); + Draw_String(x, y, st); + + sprintf(st, "%3.1f UPS", Length(cl.simvel[0])); + x = vid.width - strlen(st) * 8 - 8; + y = vid.height - sb_lines - 16; // Draw_TileClear(x, y, strlen(st) * 8, 8); Draw_String(x, y, st); } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 05812470a..41041b7ca 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -169,6 +169,7 @@ sfx_t *cl_sfx_ric3; sfx_t *cl_sfx_r_exp3; cvar_t cl_expsprite = {"cl_expsprite", "0"}; +cvar_t cl_truelightning = {"cl_truelightning", "0", NULL, CVAR_SEMICHEAT}; /* ================= @@ -186,6 +187,7 @@ void CL_InitTEnts (void) cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); Cvar_Register (&cl_expsprite, "Temporary entity control"); + Cvar_Register (&cl_truelightning, "Temporary entity control"); } #ifdef Q2CLIENT @@ -1667,6 +1669,8 @@ void CL_UpdateBeams (void) float yaw, pitch; float forward, offset; + extern cvar_t cl_truelightning; + // update lightning for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { @@ -1683,12 +1687,13 @@ void CL_UpdateBeams (void) //rotate the end point to face in the view direction. This gives a smoother shafting. turning looks great. - VectorSubtract (b->end, b->start, dist); - d = VectorNormalize(dist); - AngleVectors (cl.simangles[0], b->end, dist, org); - VectorMA(b->start, d, b->end, b->end); - -// b->start[2] -= cl.viewheight; // adjust for view height? + if (cl_truelightning.value) + { + VectorSubtract (b->end, b->start, dist); + d = VectorNormalize(dist); + AngleVectors (cl.simangles[0], b->end, dist, org); + VectorMA(b->start, d, b->end, b->end); + } } else if (b->flags & STREAM_ATTACHED) { diff --git a/engine/client/client.h b/engine/client/client.h index 46d5818f4..4c8a45070 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -356,8 +356,10 @@ typedef struct { float lerprate; //inverse rate... vec3_t origin; vec3_t angles; - int frame; trailstate_t trailstate; //when to next throw out a trail + unsigned short frame; + unsigned short tagent; + unsigned short tagindex; } lerpents_t; // // the client_state_t structure is wiped completely at every diff --git a/engine/client/console.c b/engine/client/console.c index 423e0892d..3e75f3b0e 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -445,6 +445,11 @@ void Con_Init (void) { con_debuglog = COM_CheckParm("-condebug"); +#ifdef CRAZYDEBUGGING + con_debuglog = true; + TRACE(("dbg: Con_Init: con_debuglog forced\n")); +#endif + con = &con_main; con->linewidth = -1; Con_CheckResize (); @@ -1037,7 +1042,7 @@ void Con_DrawConsole (int lines, qboolean noback) int row; unsigned char dlbar[1024]; char *progresstext; - int progresspercent; + float progresspercent; #ifdef RUNTIMELIGHTING extern model_t *lightmodel; @@ -1110,7 +1115,7 @@ void Con_DrawConsole (int lines, qboolean noback) if (relitsurface < lightmodel->numsurfaces) { progresstext = "light"; - progresspercent = (relitsurface*100) / lightmodel->numsurfaces; + progresspercent = (relitsurface*100.0f) / lightmodel->numsurfaces; } } #endif @@ -1140,7 +1145,7 @@ void Con_DrawConsole (int lines, qboolean noback) if (progresspercent == 0) n = 0; else - n = y * (float)progresspercent / 100; + n = y * progresspercent / 100; x = i; for (j = 0; j < y; j++) @@ -1153,7 +1158,7 @@ void Con_DrawConsole (int lines, qboolean noback) dlbar[i++] = '\x82'; dlbar[i] = 0; - sprintf(dlbar + strlen(dlbar), " %02d%%", progresspercent); + sprintf(dlbar + strlen(dlbar), " %02d%%", (int)progresspercent); // draw it y = con->vislines-22 + 8; diff --git a/engine/client/image.c b/engine/client/image.c index a33e6604d..10bf44e33 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -1481,22 +1481,39 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height) { qbyte *data; if ((data = ReadTargaFile(buf, len, width, height, false))) + { + TRACE(("dbg: Read32BitImageFile: tga\n")); return data; + } #ifdef AVAIL_PNGLIB if ((buf[0] == 137 && buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G') && (data = ReadPNGFile(buf, com_filesize, width, height))) + { + TRACE(("dbg: Read32BitImageFile: png\n")); return data; + } #endif #ifdef AVAIL_JPEGLIB //jpeg jfif only. if ((buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && buf[3] == 0xe0) && (data = ReadJPEGFile(buf, com_filesize, width, height))) + { + TRACE(("dbg: Read32BitImageFile: jpeg\n")); return data; + } #endif - if ((data = ReadPCXFile(buf, com_filesize, width, height))) + if ((data = ReadPCXFile(buf, com_filesize, width, height))) + { + TRACE(("dbg: Read32BitImageFile: pcx\n")); return data; + } if ((buf[0] == 'B' && buf[1] == 'M') && (data = ReadBMPFile(buf, com_filesize, width, height))) + { + TRACE(("dbg: Read32BitImageFile: bitmap\n")); return data; + } + + TRACE(("dbg: Read32BitImageFile: life sucks\n")); return NULL; } @@ -1573,12 +1590,14 @@ int Mod_LoadHiResTexture(char *name, qboolean mipmap, qboolean alpha, qboolean c } else _snprintf(fname, sizeof(fname)-1, path[i], nicename, extensions[e]); + TRACE(("dbg: Mod_LoadHiResTexture: trying %s\n", fname)); if ((buf = COM_LoadFile (fname, 5))) { if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height))) { if (colouradjust) BoostGamma(data, image_width, image_height); + TRACE(("dbg: Mod_LoadHiResTexture: %s loaded\n", name)); len = GL_LoadTexture32 (name, image_width, image_height, (unsigned*)data, mipmap, alpha); BZ_Free(data); @@ -1631,6 +1650,8 @@ int Mod_LoadBumpmapTexture(char *name) int i, e; + TRACE(("dbg: Mod_LoadBumpmapTexture: texture %s\n", name)); + COM_StripExtension(name, nicename); if ((len = GL_FindTexture(name))!=-1) //don't bother if it already exists. @@ -1662,10 +1683,14 @@ int Mod_LoadBumpmapTexture(char *name) } else _snprintf(fname, sizeof(fname)-1, path[i], nicename, extensions[e]); + + TRACE(("dbg: Mod_LoadBumpmapTexture: opening %s\n", fname)); + if ((buf = COM_LoadFile (fname, 5))) { if ((data = ReadTargaFile(buf, com_filesize, &image_width, &image_height, 2))) //Only load a greyscale image. { + TRACE(("dbg: Mod_LoadBumpmapTexture: tga %s loaded\n", name)); len = GL_LoadTexture8Bump(name, image_width, image_height, data, true); BZ_Free(data); } diff --git a/engine/client/net_master.c b/engine/client/net_master.c index e3a0fcf41..51726581a 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -788,8 +788,8 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) info->special |= SS_FTESERVER; else if (!strncmp("FTE", Info_ValueForKey(msg, "*version"), 3)) info->special |= SS_FTESERVER; - - + + if (servertype == MT_SINGLEQ2) info->special |= SS_QUAKE2; else if (servertype == MT_SINGLENQ) diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 39ea24891..42ac1ada6 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -75,6 +75,7 @@ cvar_t r_numedges = {"r_numedges", "0"}; cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; cvar_t d_smooth = {"d_smooth", "0"}; +cvar_t gl_skyboxdist = {"gl_skyboxdist", "2300"}; extern cvar_t r_dodgytgafiles; @@ -214,6 +215,8 @@ void R_BulletenForce_f (void); rendererstate_t currentrendererstate; cvar_t gl_skyboxname = {"r_skybox", ""}; +cvar_t r_fastsky = {"r_fastsky", "0"}; +cvar_t r_fastskycolour = {"r_fastskycolour", "0"}; #if defined(RGLQUAKE) cvar_t gl_ztrick = {"gl_ztrick","1"}; @@ -302,6 +305,8 @@ void GLRenderer_Init(void) Cvar_Register (&gl_ati_truform, GRAPHICALNICETIES); Cvar_Register (&gl_ati_truform_type, GRAPHICALNICETIES); Cvar_Register (&gl_ati_truform_tesselation, GRAPHICALNICETIES); + + Cvar_Register (&gl_skyboxdist, GLRENDEREROPTIONS); } #endif #if defined(SWQUAKE) @@ -490,6 +495,9 @@ void Renderer_Init(void) Cvar_Register (&r_nolerp, GRAPHICALNICETIES); Cvar_Register (&r_nolightdir, GRAPHICALNICETIES); + Cvar_Register (&r_fastsky, GRAPHICALNICETIES); + Cvar_Register (&r_fastskycolour, GRAPHICALNICETIES); + //bulletens Cvar_Register(&bul_nowater, BULLETENVARS); Cvar_Register(&bul_rippleamount, BULLETENVARS); @@ -1023,12 +1031,19 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) return false; if (R_DeInit) + { + TRACE(("dbg: R_ApplyRenderer: R_DeInit\n")); R_DeInit(); - - SCR_DeInit(); + } if (VID_DeInit) + { + TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n")); VID_DeInit(); + } + + TRACE(("dbg: R_ApplyRenderer: SCR_DeInit\n")); + SCR_DeInit(); IN_Shutdown(); @@ -1048,6 +1063,8 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) Hunk_FreeToLowMark(host_hunklevel); //is this a good idea? + TRACE(("dbg: R_ApplyRenderer: old renderer closed\n")); + gl_skyboxname.modified = true; if (qrenderer) //graphics stuff only when not dedicated @@ -1112,28 +1129,38 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) if (vid.fullbright < 2) vid.fullbright = 0; //transparent colour doesn't count. - +TRACE(("dbg: R_ApplyRenderer: Palette loaded\n")); if (!VID_Init(newr, host_basepal)) + { + R_SetRenderer(QR_NONE); return false; + } +TRACE(("dbg: R_ApplyRenderer: vid applied\n")); #ifdef RGLQUAKE if (qrenderer == QR_OPENGL) GLV_UpdatePalette(); #endif +TRACE(("dbg: R_ApplyRenderer: done palette\n")); + v_oldgammavalue = -1; //force the gamma to be reset W_LoadWadFile("gfx.wad"); +TRACE(("dbg: R_ApplyRenderer: wad loaded\n")); Draw_Init(); +TRACE(("dbg: R_ApplyRenderer: draw inited\n")); R_Init(); +TRACE(("dbg: R_ApplyRenderer: renderer inited\n")); SCR_Init(); - +TRACE(("dbg: R_ApplyRenderer: screen inited\n")); Sbar_Flush(); IN_Init(); } else { +TRACE(("dbg: R_ApplyRenderer: isDedicated = true\n")); isDedicated = true; if (cls.state) { @@ -1145,16 +1172,19 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) Sys_InitTerminal(); Con_PrintToSys(); } - +TRACE(("dbg: R_ApplyRenderer: initing mods\n")); Mod_Init(); - +TRACE(("dbg: R_ApplyRenderer: initing bulletein boards\n")); WipeBulletenTextures(); // host_hunklevel = Hunk_LowMark(); if (R_PreNewMap) if (cl.worldmodel) + { + TRACE(("dbg: R_ApplyRenderer: R_PreNewMap (how handy)\n")); R_PreNewMap(); + } if (sv.worldmodel) { @@ -1163,11 +1193,14 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) q2edict_t *q2ent; #endif +TRACE(("dbg: R_ApplyRenderer: reloading server map\n")); sv.worldmodel = Mod_ForName (sv.modelname, false); +TRACE(("dbg: R_ApplyRenderer: loaded\n")); if (sv.worldmodel->needload) { SV_Error("Bsp went missing on render restart\n"); } +TRACE(("dbg: R_ApplyRenderer: doing that funky phs thang\n")); SV_CalcPHS (); for (i = 0; i < MAX_MODELS; i++) @@ -1177,7 +1210,7 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) else sv.models[i] = NULL; } - +TRACE(("dbg: R_ApplyRenderer: clearing world\n")); SV_ClearWorld (); if (svprogfuncs) @@ -1220,7 +1253,9 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) } #endif } + Plug_ResChanged(); +TRACE(("dbg: R_ApplyRenderer: starting on client state\n")); if (cl.worldmodel) { int staticmodelindex[MAX_STATIC_ENTITIES]; @@ -1235,13 +1270,14 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) cl.worldmodel = NULL; cl_numvisedicts=0; - +TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n")); for (i=1 ; ineedload) { CL_Disconnect (); @@ -1268,9 +1304,11 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) return true; } +TRACE(("dbg: R_ApplyRenderer: checking any wad textures\n")); Mod_NowLoadExternal(); +TRACE(("dbg: R_ApplyRenderer: R_NewMap\n")); R_NewMap(); - +TRACE(("dbg: R_ApplyRenderer: efrags\n")); for (i = 0; i < cl.num_statics; i++) //make the static entities reappear. { cl_static_entities[i].model = cl.model_precache[staticmodelindex[i]]; @@ -1317,6 +1355,8 @@ void R_RestartRenderer_f (void) rendererstate_t newr; memset(&newr, 0, sizeof(newr)); +TRACE(("dbg: R_RestartRenderer_f\n")); + Media_CaptureDemoEnd(); Cvar_ApplyLatches(CVAR_RENDERERLATCH); @@ -1386,20 +1426,31 @@ void R_RestartRenderer_f (void) #error "no default renderer" #endif + TRACE(("dbg: R_RestartRenderer_f renderer %i\n", newr.renderer)); + memcpy(&oldr, ¤trendererstate, sizeof(rendererstate_t)); if (!R_ApplyRenderer(&newr)) { + TRACE(("dbg: R_RestartRenderer_f failed\n")); if (R_ApplyRenderer(&oldr)) + { + TRACE(("dbg: R_RestartRenderer_f old restored\n")); Con_Printf("^1Video mode switch failed. Old mode restored.\n"); //go back to the old mode, the new one failed. + } else { newr.renderer = QR_NONE; if (R_ApplyRenderer(&newr)) + { + TRACE(("dbg: R_RestartRenderer_f going to dedicated\n")); Con_Printf("^1Video mode switch failed. Old mode wasn't supported either. Console forced.\nChange vid_mode to a compatable mode, and then use the setrenderer command.\n"); + } else Sys_Error("Couldn't fall back to previous renderer\n"); } } + + TRACE(("dbg: R_RestartRenderer_f success\n")); } void R_SetRenderer_f (void) diff --git a/engine/client/view.c b/engine/client/view.c index 54c78a50c..f164d518a 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -74,9 +74,11 @@ cvar_t v_idlescale = {"v_idlescale", "0", NULL}; cvar_t crosshair = {"crosshair", "0", NULL, CVAR_ARCHIVE}; cvar_t crosshaircolor = {"crosshaircolor", "79", NULL, CVAR_ARCHIVE}; +cvar_t crosshairsize = {"crosshairsize", "8", NULL, CVAR_ARCHIVE}; cvar_t cl_crossx = {"cl_crossx", "0", NULL, CVAR_ARCHIVE}; cvar_t cl_crossy = {"cl_crossy", "0", NULL, CVAR_ARCHIVE}; +cvar_t crosshaircorrect = {"crosshaircorrect", "0", NULL, CVAR_SEMICHEAT}; cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100"}; @@ -1440,6 +1442,8 @@ void V_Init (void) Cvar_Register (&crosshaircolor, VIEWVARS); Cvar_Register (&crosshair, VIEWVARS); + Cvar_Register (&crosshairsize, VIEWVARS); + Cvar_Register (&crosshaircorrect, VIEWVARS); Cvar_Register (&cl_crossx, VIEWVARS); Cvar_Register (&cl_crossy, VIEWVARS); Cvar_Register (&gl_cshiftpercent, VIEWVARS); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index b9a0fac9e..b5bbb9726 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -700,6 +700,99 @@ static char *Macro_TF_Skin (void) } + +//Spike: added these: +static char *Macro_ConnectionType (void) +{ + if (!cls.state) + return "disconnected"; + if (cl.spectator) + return "spectator"; + return "connected"; +} + +static char *Macro_demoplayback (void) +{ + switch (cls.demoplayback) + { + case DPB_NONE: + return "0"; + case DPB_QUAKEWORLD: + return "qwdplayback"; + case DPB_MVD: + return "mvdplayback"; + case DPB_NETQUAKE: + return "demplayback"; + case DPB_QUAKE2: + return "dm2playback"; + + //gcc will warn if we add annother playback and forget here, otherwise I'd use a default. + } + return "1"; //unknown. +} +/* +$droploc +Tells location of the dropped flag. +Note: This will tell only if you have dropped the flag (CTF/TF). + +$droptime +Tells how many seconds gone of dropped flag. + +$ledpoint +This reports the type of the pointed object as a LED according to the +following rules: +If teammate then green. +If enemy then red. +If powerup then yellow. +if item then blue. + +$ledstatus +This checks your current status (health, armor and best weapon) and +reports a LED according to the following rules: +if all of the above is ok then green. +if there is one thing low then yellow. +if there are two or over things low then red. + +$matchname +you can use to get the name of the match +manually (echo $matchname). +Example: a matchname might be +"[clan]quaker - [4on4_myclan_vs_someclan] - [dm3]" or whatever. + +$matchstatus +("disconnected", "standby" or "normal"). This can be +used for detecting prewar/prematch on ktpro/oztf servers. + +$matchtype +duel,2on2,4on4,ffa,etc... + +$mp3info +Evaluates to "author - title". +Examples: +if you bind space "say listening to $mp3info" +then hitting space will say something like +"listening to disturbed - rise". +bind x "if disturbed isin $mp3info then say dde music is cool" + +$need +What you need. +Note: you have to set this with tp_need* variables. + +$point +Name of object you are looking at. + +$pointatloc +Name of object and location of object you are looking at. + +$pointloc +Location of object you are looking at. + +$triggermatch +$triggermatch is the last chat message that exec'd a msg_trigger. + +*/ +//Spike: added end. + static void TP_InitMacros(void) { Cmd_AddMacro("qt", Macro_Quote); @@ -727,6 +820,24 @@ static void TP_InitMacros(void) Cmd_AddMacro("took", Macro_Took); Cmd_AddMacro("tf_skin", Macro_TF_Skin); + //ones added by Spike, for fuhquake compatability + Cmd_AddMacro("connectiontype", Macro_ConnectionType); + Cmd_AddMacro("demoplayback", Macro_demoplayback); +/* +$droploc +$droptime +$ledpoint +$ledstatus +$matchname +$matchstatus +$matchtype +$mp3info +$need +$point +$pointatloc +$pointloc +$triggermatch +*/ } #define MAX_MACRO_STRING 1024 diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 8da752b25..32fe83f7a 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -100,6 +100,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define IN_XFLIP //allow input to be flipped horizontally. #define TEXTEDITOR + #define PLUGINS + // #define VOICECHAT //experimental //these things were moved to plugins. @@ -153,6 +155,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef EMAILCLIENT #undef TEXTEDITOR #undef RUNTIMELIGHTING + #undef PLUGINS //we don't have any server side stuff. #endif #ifdef CLIENTONLY //remove optional server componants that make no sence on a client only build. #undef Q2SERVER diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 55f3489cd..746c82430 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -326,7 +326,7 @@ void Cvar_ApplyLatches(int latchflag) cvar_t *var; int mask = ~0; - if (latchflag == CVAR_SERVEROVERRIDE) + if (latchflag == CVAR_SERVEROVERRIDE) //these ones are cleared mask = ~CVAR_SERVEROVERRIDE; for (grp=cvar_groups ; grp ; grp=grp->next) @@ -483,6 +483,8 @@ void Cvar_LockFromServer(cvar_t *var, char *str) { char *oldlatch; + Con_DPrintf("Server taking control of cvar %s\n", var->name); + var->flags |= CVAR_SERVEROVERRIDE; oldlatch = var->latched_string; diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 1fd4d0904..f1261333d 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -90,8 +90,8 @@ typedef struct cvar_group_s #define CVAR_POINTER 32 // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. #define CVAR_NOTFROMSERVER 64 #define CVAR_USERCREATED 128 //write a 'set' or 'seta' in front of the var name. -#define CVAR_CHEAT 256 //latch from 0 unless cheats are enabled. -#define CVAR_SEMICHEAT 512 //if strict ruleset, force to 0. +#define CVAR_CHEAT 256 //latch to the default, unless cheats are enabled. +#define CVAR_SEMICHEAT 512 //if strict ruleset, force to 0/blank. #define CVAR_RENDERERLATCH 1024 #define CVAR_SERVEROVERRIDE 2048 // diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 69ff19b4f..e27e752db 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -713,3 +713,183 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) } } #endif + +//This function is GL stylie (use as 2nd arg to ML_MultMatrix4). +float *ML_RotationMatrix(float a, float x, float y, float z) +{ + static float ret[16]; + float c = cos(a* M_PI / 180.0); + float s = sin(a* M_PI / 180.0); + + ret[0] = x*x*(1-c)+c; + ret[4] = x*y*(1-c)-z*s; + ret[8] = x*z*(1-c)+y*s; + ret[12] = 0; + + ret[1] = y*x*(1-c)+z*s; + ret[5] = y*y*(1-c)+c; + ret[9] = y*z*(1-c)-x*s; + ret[13] = 0; + + ret[2] = x*z*(1-c)-y*s; + ret[6] = y*z*(1-c)+x*s; + ret[10] = z*z*(1-c)+c; + ret[14] = 0; + + ret[3] = 0; + ret[7] = 0; + ret[11] = 0; + ret[15] = 1; + return ret; +} + +//This function is GL stylie (use as 2nd arg to ML_MultMatrix4). +float *ML_TranslationMatrix(float x, float y, float z) +{ + static float ret[16]; + ret[0] = 1; + ret[4] = 0; + ret[8] = 0; + ret[12] = x; + + ret[1] = 0; + ret[5] = 1; + ret[9] = 0; + ret[13] = y; + + ret[2] = 0; + ret[6] = 0; + ret[10] = 1; + ret[14] = z; + + ret[3] = 0; + ret[7] = 0; + ret[11] = 0; + ret[15] = 1; + return ret; +} + +//be aware that this generates two sorts of matricies depending on order of a+b +void ML_MultMatrix4(float *a, float *b, float *out) +{ + out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3]; + out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3]; + out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3]; + out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3]; + + out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7]; + out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7]; + out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7]; + out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7]; + + out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11]; + out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11]; + out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11]; + out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11]; + + out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15]; + out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15]; + out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15]; + out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]; +} + +//transform 4d vector by a 4d matrix. +void ML_MatrixTransform4 (float *matrix, float *vector, float *product) +{ + product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]*vector[3]; + product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]*vector[3]; + product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14]*vector[3]; + product[3] = matrix[3]*vector[0] + matrix[7]*vector[1] + matrix[11]*vector[2] + matrix[15]*vector[3]; +} + +//returns fractions of screen. +//uses GL style rotations and translations and stuff. +void ML_Project (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy) +{ + float modelview[16]; + float proj[16]; + + { + float tempmat[16]; + //load identity. + memset(modelview, 0, sizeof(modelview)); +#if FULLYGL + modelview[0] = 1; + modelview[5] = 1; + modelview[10] = 1; + modelview[15] = 1; + + ML_MultMatrix4(modelview, ML_RotationMatrix(-90, 1, 0, 0), tempmat); // put Z going up + ML_MultMatrix4(tempmat, ML_RotationMatrix(90, 0, 0, 1), modelview); // put Z going up +#else + //use the lame wierd and crazy identity matrix.. + modelview[2] = -1; + modelview[4] = -1; + modelview[9] = 1; + modelview[15] = 1; +#endif + //figure out the current modelview matrix + + //I would if some of these, but then I'd still need a couple of copys + ML_MultMatrix4(modelview, ML_RotationMatrix(-viewangles[2], 1, 0, 0), tempmat); // put Z going up + ML_MultMatrix4(tempmat, ML_RotationMatrix(-viewangles[0], 0, 1, 0), modelview); // put Z going up + ML_MultMatrix4(modelview, ML_RotationMatrix(-viewangles[1], 0, 0, 1), tempmat); // put Z going up + + ML_MultMatrix4(tempmat, ML_TranslationMatrix(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up + + } + + { + float xmin, xmax, ymin, ymax; + float nudge = 1; + + //proj + ymax = 4 * tan( fovy * M_PI / 360.0 ); + ymin = -ymax; + + xmin = ymin * wdivh; + xmax = ymax * wdivh; + + proj[0] = (2*4) / (xmax - xmin); + proj[4] = 0; + proj[8] = (xmax + xmin) / (xmax - xmin); + proj[12] = 0; + + proj[1] = 0; + proj[5] = (2*4) / (ymax - ymin); + proj[9] = (ymax + ymin) / (ymax - ymin); + proj[13] = 0; + + proj[2] = 0; + proj[6] = 0; + proj[10] = -1 * nudge; + proj[14] = -2*4 * nudge; + + proj[3] = 0; + proj[7] = 0; + proj[11] = -1; + proj[15] = 0; + } + + + //we've got our two matricies now. + + { + float v[4], tempv[4]; + v[0] = in[0]; + v[1] = in[1]; + v[2] = in[2]; + v[3] = 1; + + ML_MatrixTransform4(modelview, v, tempv); + ML_MatrixTransform4(proj, tempv, v); + + v[0] /= v[3]; + v[1] /= v[3]; + v[2] /= v[3]; + + out[0] = (1+v[0])/2; + out[1] = (1+v[1])/2; + out[2] = (1+v[2])/2; + } +} diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 978b8a2c6..ad3c25344 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -6,12 +6,16 @@ #ifdef PLUGINS +#include "glquake.h" + typedef struct plugin_s { char *name; vm_t *vm; int tick; int executestring; int menufunction; + int sbarlevel[3]; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all. + int reschange; struct plugin_s *next; } plugin_t; @@ -169,6 +173,9 @@ plugin_t *Plug_Load(char *file) argarray = (int)"Plug_GetEngineFunction"; VM_Call(newplug->vm, 0, Plug_FindBuiltin(NULL, ~0, &argarray)); + + if (newplug->reschange) + VM_Call(newplug->vm, newplug->reschange, vid.width, vid.height); } else { @@ -209,11 +216,79 @@ int Plug_ExportToEngine(void *offset, unsigned int mask, const long *arg) currentplug->executestring = arg[1]; else if (!strcmp(name, "MenuEvent")) currentplug->menufunction = arg[1]; + else if (!strcmp(name, "UpdateVideo")) + currentplug->reschange = arg[1]; else return 0; return 1; } -//void(char *buffer, int buffersize) + +typedef struct { + //Make SURE that the engine has resolved all cvar pointers into globals before this happens. + plugin_t *plugin; + cvar_t *var; +} plugincvararray_t; +int plugincvararraylen; +plugincvararray_t *plugincvararray; +//qhandle_t Cvar_Register (char *name, char *defaultval, int flags, char *grouphint); +int Plug_Cvar_Register(void *offset, unsigned int mask, const long *arg) +{ + char *name = VM_POINTER(arg[0]); + char *defaultvalue = VM_POINTER(arg[1]); + unsigned int flags = VM_LONG(arg[2]); + char *groupname = VM_POINTER(arg[3]); + cvar_t *var; + int i; + + var = Cvar_Get(name, defaultvalue, flags&1, groupname); + + for (i = 0; i < plugincvararraylen; i++) + { + if (!plugincvararray[i].var) + { //hmm... a gap... + plugincvararray[i].plugin = currentplug; + plugincvararray[i].var = var; + return i; + } + } + + plugincvararray = BZ_Realloc(plugincvararray, (plugincvararraylen+1)*sizeof(plugincvararray_t)); + plugincvararray[plugincvararraylen].plugin = currentplug; + plugincvararray[plugincvararraylen].var = var; + plugincvararraylen++; + return plugincvararraylen-1; +} +//int Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. +int Plug_Cvar_Update(void *offset, unsigned int mask, const long *arg) +{ + int handle; + int modcount; + char *stringv; //255 bytes long. + float *floatv; + cvar_t *var; + handle = VM_LONG(arg[0]); + if (handle < 0 || handle >= plugincvararraylen) + return 0; + if (plugincvararray[handle].plugin != currentplug) + return 0; //I'm not letting you know what annother plugin has registered. + + if (VM_OOB(arg[2], 256) || VM_OOB(arg[3], 4)) //Oi, plugin - you screwed up + return 0; + + modcount = VM_LONG(arg[1]); + stringv = VM_POINTER(arg[2]); + floatv = VM_POINTER(arg[3]); + + var = plugincvararray[handle].var; + + + strcpy(stringv, var->string); + *floatv = var->value; + + return var->modified; +} + +//void Cmd_Args(char *buffer, int buffersize) int Plug_Cmd_Args(void *offset, unsigned int mask, const long *arg) { char *buffer = (char*)VM_POINTER(arg[0]); @@ -224,7 +299,7 @@ int Plug_Cmd_Args(void *offset, unsigned int mask, const long *arg) strcpy(buffer, args); return 1; } -//void(int num, char *buffer, int buffersize) +//void Cmd_Argv(int num, char *buffer, int buffersize) int Plug_Cmd_Argv(void *offset, unsigned int mask, const long *arg) { char *buffer = (char*)VM_POINTER(arg[1]); @@ -235,7 +310,7 @@ int Plug_Cmd_Argv(void *offset, unsigned int mask, const long *arg) strcpy(buffer, args); return 1; } -//int(void) +//int Cmd_Argc(void) int Plug_Cmd_Argc(void *offset, unsigned int mask, const long *arg) { return Cmd_Argc(); @@ -245,39 +320,221 @@ int Plug_Menu_Control(void *offset, unsigned int mask, const long *arg) { switch(VM_LONG(arg[0])) { - case 0: //weather it's us or not. - return currentplug == menuplug && m_state == m_plugin; - case 1: //weather a menu is active - return key_dest == key_menu; - case 2: //give us menu control + case 0: //take away all menus + case 1: + if (menuplug) + { + plugin_t *oldplug = currentplug; + currentplug = menuplug; + Plug_Menu_Event(3, 0); + menuplug = NULL; + currentplug = oldplug; + key_dest = key_game; + } + if (VM_LONG(arg[0]) != 1) + return 1; + //give us menu control menuplug = currentplug; key_dest = key_menu; + m_state = m_plugin; return 1; + case 2: //weather it's us or not. + return currentplug == menuplug && m_state == m_plugin; + case 3: //weather a menu is active + return key_dest == key_menu; default: return 0; } } +int Plug_Draw_Character(void *offset, unsigned int mask, const long *arg) +{ + Draw_Character(arg[0], arg[1], (unsigned int)arg[2]); + return 0; +} + +int Plug_Draw_Fill(void *offset, unsigned int mask, const long *arg) +{ + return 0; +} + +//hrm.... FIXME! +int Plug_Draw_ColourP(void *offset, unsigned int mask, const long *arg) +{ + extern unsigned char vid_curpal[256*3]; + qbyte *pal = vid_curpal + VM_LONG(arg[0])*3; + + if (arg[0]<0 || arg[0]>255) + return false; + + switch(qrenderer) + { + case QR_OPENGL: + glColor3f(pal[0]/255.0f, pal[1]/255.0f, pal[2]/255.0f); + break; + case QR_SOFTWARE: + SWDraw_ImageColours(pal[0]/255.0f, pal[1]/255.0f, pal[2]/255.0f, 1); + break; + default: + return 0; + } + return 1; +} + +int Plug_Draw_Colour3f(void *offset, unsigned int mask, const long *arg) +{ + switch(qrenderer) + { + case QR_OPENGL: + glColor3f(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2])); + break; + case QR_SOFTWARE: + SWDraw_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), 1); + break; + default: + return 0; + } + return 1; +} +int Plug_Draw_Colour4f(void *offset, unsigned int mask, const long *arg) +{ + switch(qrenderer) + { + case QR_OPENGL: + glColor4f(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3])); + break; + case QR_SOFTWARE: + SWDraw_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3])); + break; + default: + return 0; + } + return 1; +} + +int Plug_Key_GetKeyCode(void *offset, unsigned int mask, const long *arg) +{ + int modifier; + return Key_StringToKeynum(VM_POINTER(arg[0]), &modifier); +} + +//void Cvar_SetString (char *name, char *value); +int Plug_Cvar_SetString(void *offset, unsigned int mask, const long *arg) +{ + char *name = VM_POINTER(arg[0]), + *value = VM_POINTER(arg[1]); + cvar_t *var = Cvar_Get(name, value, 0, "Plugin vars"); + if (var) + { + Cvar_Set(var, value); + return 1; + } + + return 0; +} + +//void Cvar_SetFloat (char *name, float value); +int Plug_Cvar_SetFloat(void *offset, unsigned int mask, const long *arg) +{ + char *name = VM_POINTER(arg[0]); + float value = VM_FLOAT(arg[1]); + cvar_t *var = Cvar_Get(name, "", 0, "Plugin vars"); //"" because I'm lazy + if (var) + { + Cvar_SetValue(var, value); + return 1; + } + + return 0; +} + +//void Cvar_GetFloat (char *name); +int Plug_Cvar_GetFloat(void *offset, unsigned int mask, const long *arg) +{ + char *name = VM_POINTER(arg[0]); + float value = VM_FLOAT(arg[1]); + int ret; + cvar_t *var = Cvar_Get(name, "", 0, "Plugin vars"); + if (var) + { + VM_FLOAT(ret) = var->value; + } + else + VM_FLOAT(ret) = 0; + return ret; +} + +//qboolean Cvar_GetString (char *name, char *retstring, int sizeofretstring); +int Plug_Cvar_GetString(void *offset, unsigned int mask, const long *arg) +{ + char *name, *ret; + int retsize; + cvar_t *var; + if (VM_OOB(arg[1], arg[2])) + { + return false; + } + + name = VM_POINTER(arg[0]); + ret = VM_POINTER(arg[1]); + retsize = VM_LONG(arg[2]); + + + var = Cvar_Get(name, "", 0, "Plugin vars"); + if (strlen(var->name)+1 > retsize) + return false; + + strcpy(ret, var->string); + + return true; +} + +//void Cmd_AddText (char *text, qboolean insert); //abort the entire engine. +int Plug_Cmd_AddText(void *offset, unsigned int mask, const long *arg) +{ + if (VM_LONG(arg[1])) + Cbuf_InsertText(VM_POINTER(arg[0]), RESTRICT_LOCAL); + else + Cbuf_AddText(VM_POINTER(arg[0]), RESTRICT_LOCAL); + + return 1; +} + void Plug_Init(void) { - Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_FindBuiltin, 0);//plugin wishes to find a builtin number. - Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. - Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. - Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); - Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy. + Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_FindBuiltin, 0);//plugin wishes to find a builtin number. + Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. + Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. + Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); + Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy. - Plug_RegisterBuiltin("Cmd_Args", Plug_Cmd_Args, 0); - Plug_RegisterBuiltin("Cmd_Argc", Plug_Cmd_Argc, 0); - Plug_RegisterBuiltin("Cmd_Argv", Plug_Cmd_Argv, 0); + Plug_RegisterBuiltin("Cmd_Args", Plug_Cmd_Args, 0); + Plug_RegisterBuiltin("Cmd_Argc", Plug_Cmd_Argc, 0); + Plug_RegisterBuiltin("Cmd_Argv", Plug_Cmd_Argv, 0); + Plug_RegisterBuiltin("Cmd_AddText", Plug_Cmd_AddText, 0); - Plug_RegisterBuiltin("Menu_Control", Plug_Menu_Control, 0); + Plug_RegisterBuiltin("Menu_Control", Plug_Menu_Control, 0); + + Plug_RegisterBuiltin("Cvar_Register", Plug_Cvar_Register, 0); + Plug_RegisterBuiltin("Cvar_SetString", Plug_Cvar_SetString, 0); + Plug_RegisterBuiltin("Cvar_SetFloat", Plug_Cvar_SetFloat, 0); + Plug_RegisterBuiltin("Cvar_GetString", Plug_Cvar_GetString, 0); + Plug_RegisterBuiltin("Cvar_GetFloat", Plug_Cvar_GetFloat, 0); + + Plug_RegisterBuiltin("Draw_Character", Plug_Draw_Character, 0); + Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, 0); + Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, 0); + Plug_RegisterBuiltin("Draw_Colour3f", Plug_Draw_Colour3f, 0); + Plug_RegisterBuiltin("Draw_Colour4f", Plug_Draw_Colour4f, 0); + + Plug_RegisterBuiltin("Key_GetKeyCode", Plug_Key_GetKeyCode, 0); #ifdef _WIN32 - COM_EnumerateFiles("plugins/*x86.dll", Plug_Emumerated, "x86.dll"); + COM_EnumerateFiles("plugins/*x86.dll", Plug_Emumerated, "x86.dll"); #elif defined(__linux__) - COM_EnumerateFiles("plugins/*x86.so", Plug_Emumerated, "x86.so"); + COM_EnumerateFiles("plugins/*x86.so", Plug_Emumerated, "x86.so"); #endif - COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); + COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); } void Plug_Tick(void) @@ -293,6 +550,17 @@ void Plug_Tick(void) } } +void Plug_ResChanged(void) +{ + plugin_t *oldplug = currentplug; + for (currentplug = plugs; currentplug; currentplug = currentplug->next) + { + if (currentplug->reschange) + VM_Call(currentplug->vm, currentplug->reschange, vid.width, vid.height); + } + currentplug = oldplug; +} + qboolean Plugin_ExecuteString(void) { plugin_t *plug; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index de5690c7e..fcd9d6389 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -54,6 +54,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PEXT_256PACKETENTITIES 0x01000000 //Client can recieve 256 packet entities. //#define PEXT_64PLAYERS 0x02000000 //Client is able to cope with 64 players. Wow. #define PEXT_SHOWPIC 0x04000000 +#define PEXT_SETATTACHMENT 0x08000000 //md3 tags (needs networking, they need to lerp). @@ -224,6 +225,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_movepic 71 #define svc_updatepic 72 +#define svc_setattachment 73 + #define svc_invalid 256 diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 2006f6236..a6de1bca5 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -573,7 +573,7 @@ static void inline QVM_Return(qvm_t *vm, long size) if(vm->bp>vm->len_ds+vm->len_ss/2) Sys_Error("VM run time error: freed too much stack\n"); - if(fp[1]>vm->len_cs) + if(fp[1]>vm->len_cs*2) if (vm->cs+fp[1]) //this being false causes the program to quit. Sys_Error("VM run time error: program returned to hyperspace\n"); if(fp[1]<0) diff --git a/engine/common/vm.h b/engine/common/vm.h index 768db5be2..9bf1bda60 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -19,6 +19,7 @@ typedef struct vm_s vm_t; #define VM_LONG(x) (*(long*)&(x)) #define VM_FLOAT(x) (*(float*)&(x)) #define VM_POINTER(x) ((x)?(void*)((char *)offset+((x)%mask)):NULL) +#define VM_OOB(p,l) (p + l >= mask || VM_POINTER(p) < offset) // ------------------------- * interface * ------------------------- void VM_PrintInfo(vm_t *vm); diff --git a/engine/common/zone.c b/engine/common/zone.c index ae463772a..b40de1d81 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -34,7 +34,7 @@ void Cache_FreeLow (int new_low_hunk); void Cache_FreeHigh (int new_high_hunk); #ifdef _DEBUG -#define MEMDEBUG 8192 //Debugging adds sentinels (the number is the size - I have the ram) +//#define MEMDEBUG 8192 //Debugging adds sentinels (the number is the size - I have the ram) #endif #ifndef MEMDEBUG @@ -331,11 +331,11 @@ void Zone_Print_f(void) int allocated = 0; int blocks = 0; int futurehide = false; - int i; int minsize = 0; - qbyte *sent; zone_t *zone; #if MEMDEBUG > 0 + int i; + qbyte *sent; qboolean testsent = false; if (*Cmd_Argv(1) == 't') { @@ -736,8 +736,24 @@ void Hunk_Check (void) { if (h->sentinal != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < 16 || h->size + (qbyte *)h - hunk_base > hunk_size) + if (h->size < 16+MEMDEBUG*2 || h->size + (qbyte *)h - hunk_base > hunk_size) Sys_Error ("Hunk_Check: bad size"); +#if MEMDEBUG > 0 + { + qbyte *present; + qbyte *postsent; + int i; + present = (qbyte *)(h+1); + postsent = (qbyte *)h + h->size-MEMDEBUG; + for (i = 0; i < MEMDEBUG; i++) + { + if (present[i] != sentinalkey) + *(int*)0 = -3; + if (postsent[i] != sentinalkey) + *(int*)0 = -3; + } + } +#endif h = (hunk_t *)((qbyte *)h+h->size); } } @@ -797,7 +813,22 @@ void Hunk_Print (qboolean all) Sys_Error ("Hunk_Check: trahsed sentinal"); if (h->size < 16 || h->size + (qbyte *)h - hunk_base > hunk_size) Sys_Error ("Hunk_Check: bad size"); - +#if MEMDEBUG > 0 + { + qbyte *present; + qbyte *postsent; + int i; + present = (qbyte *)(h+1); + postsent = (qbyte *)h + h->size-MEMDEBUG; + for (i = 0; i < MEMDEBUG; i++) + { + if (present[i] != sentinalkey) + *(int*)0 = -3; + if (postsent[i] != sentinalkey) + *(int*)0 = -3; + } + } +#endif next = (hunk_t *)((qbyte *)h+h->size); count++; totalblocks++; @@ -846,7 +877,7 @@ void *Hunk_AllocName (int size, char *name) if (size < 0) Sys_Error ("Hunk_Alloc: bad size: %i", size); - size = sizeof(hunk_t) + ((size+15)&~15); + size = sizeof(hunk_t) + MEMDEBUG*2 + ((size+15)&~15); #ifndef _WIN32 if (hunk_size - hunk_low_used - hunk_high_used < size) @@ -857,7 +888,7 @@ void *Hunk_AllocName (int size, char *name) Sys_Error ("Not enough RAM allocated. Try starting using \"-mem 16\" on the QuakeWorld command line."); #endif #endif - + h = (hunk_t *)(hunk_base + hunk_low_used); #ifdef _WIN32 @@ -874,13 +905,18 @@ void *Hunk_AllocName (int size, char *name) Cache_FreeLow (hunk_low_used); - memset (h, 0, size); + memset (h, 0, size-MEMDEBUG); + +#if MEMDEBUG>0 + memset ((h+1), sentinalkey, MEMDEBUG); + memset ((qbyte *)h+size-MEMDEBUG, sentinalkey, MEMDEBUG); +#endif h->size = size; h->sentinal = HUNK_SENTINAL; Q_strncpyz (h->name, COM_SkipPath(name), sizeof(h->name)); - return (void *)(h+1); + return (void *)((char *)(h+1)+MEMDEBUG); } /* diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 440bc2f49..e020f45f7 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -87,7 +87,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib ws32_2.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../../fteqw.exe" /pdbtype:sept +# ADD LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../../fteqw.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 0a81b4086..44e6d537d 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1925,6 +1925,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) // move the complete, relocatable alias model to the cache // hunkend = Hunk_LowMark (); + Hunk_Alloc(0); hunktotal = hunkend - hunkstart; Cache_Alloc (&mod->cache, hunktotal, loadname); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 7b6904039..5f39497d5 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -47,7 +47,7 @@ extern qbyte gammatable[256]; unsigned char *d_15to8table; qboolean inited15to8; -extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor; +extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor, crosshairsize; static int filmtexture; @@ -641,6 +641,8 @@ void GLDraw_ReInit (void) int maxtexsize; gltexture_t *glt; + + TRACE(("dbg: GLDraw_ReInit: Closing old\n")); while(gltextures) { glt = gltextures; @@ -661,6 +663,7 @@ void GLDraw_ReInit (void) currenttexture=0; glmenu_numcachepics=0; // GL_FlushSkinCache(); + TRACE(("dbg: GLDraw_ReInit: GL_GAliasFlushSkinCache\n")); GL_GAliasFlushSkinCache(); memset(scrap_allocated, 0, sizeof(scrap_allocated)); @@ -680,7 +683,7 @@ void GLDraw_ReInit (void) //required to hold the image after scaling has occured sizeofuploadmemorybuffer = maxtexsize*maxtexsize*4; - +TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); uploadmemorybuffer = BZ_Realloc(uploadmemorybuffer, sizeofuploadmemorybuffer); uploadmemorybufferintermediate = BZ_Realloc(uploadmemorybufferintermediate, sizeofuploadmemorybufferintermediate); @@ -697,6 +700,7 @@ void GLDraw_ReInit (void) } // now turn them into textures + TRACE(("dbg: GLDraw_ReInit: looking for conchars\n")); if (!(char_texture=Mod_LoadReplacementTexture("gfx/conchars.lmp", false, true))) //no high res { if (!draw_chars) //or low res. @@ -756,13 +760,28 @@ void GLDraw_ReInit (void) } default_char_texture=char_texture; + TRACE(("dbg: GLDraw_ReInit: loaded charset\n")); + gl_font.modified = true; gl_smoothfont.modified = 1; + TRACE(("dbg: GLDraw_ReInit: GL_BeginRendering\n")); GL_BeginRendering (&glx, &gly, &glwidth, &glheight); - SCR_DrawLoading (); + TRACE(("dbg: GLDraw_ReInit: SCR_DrawLoading\n")); + + GL_Set2D(); + + glClear(GL_COLOR_BUFFER_BIT); + { + qpic_t *pic = Draw_SafeCachePic ("loading"); + if (pic) + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); + } + + TRACE(("dbg: GLDraw_ReInit: GL_EndRendering\n")); GL_EndRendering (); //now emit the conchars picture as if from a wad. @@ -777,6 +796,7 @@ void GLDraw_ReInit (void) gl->th = 1; glmenu_numcachepics++; + TRACE(("dbg: GLDraw_ReInit: W_SafeGetLumpName\n")); tinyfont = W_SafeGetLumpName ("tinyfont"); if (tinyfont) { @@ -794,6 +814,7 @@ void GLDraw_ReInit (void) gl->th = 1; glmenu_numcachepics++; } + TRACE(("dbg: GLDraw_ReInit: gfx/menu/bigfont\n")); bigfont = (qpic_t *)COM_LoadMallocFile ("gfx/menu/bigfont.lmp"); if (bigfont) { @@ -815,6 +836,7 @@ void GLDraw_ReInit (void) } + TRACE(("dbg: GLDraw_ReInit: gfx/conchars2.lmp\n")); if (!(char_tex2=Mod_LoadReplacementTexture("gfx/conchars2.lmp", false, true))) { if (!draw_chars) @@ -829,12 +851,14 @@ void GLDraw_ReInit (void) start = Hunk_LowMark (); conback = default_conback; + TRACE(("dbg: GLDraw_ReInit: COM_FDepthFile(\"gfx/conback.lmp\", false)\n")); if (COM_FDepthFile("gfx/conback.lmp", false) <= COM_FDepthFile("gfx/menu/conback.lmp", false)) cb = (qpic_t *)COM_LoadHunkFile ("gfx/conback.lmp"); else cb = (qpic_t *)COM_LoadHunkFile ("gfx/menu/conback.lmp"); if (cb) { + TRACE(("dbg: GLDraw_ReInit: conback opened\n")); SwapPic (cb); if (draw_chars) @@ -856,6 +880,7 @@ void GLDraw_ReInit (void) // scale console to vid size dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback"); + TRACE(("dbg: GLDraw_ReInit: conback loading\n"); for (y=0 ; ydata + cb->width * (y*cb->height/vid.conheight); @@ -889,6 +914,7 @@ void GLDraw_ReInit (void) ncdata = NULL; } + TRACE(("dbg: GLDraw_ReInit: conback loaded\n")); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -941,6 +967,7 @@ void GLDraw_ReInit (void) // // get the other pics we need // + TRACE(("dbg: GLDraw_ReInit: Draw_SafePicFromWad\n")); draw_disc = Draw_SafePicFromWad ("disc"); draw_backtile = Draw_SafePicFromWad ("backtile"); if (!draw_backtile) @@ -951,6 +978,7 @@ void GLDraw_ReInit (void) inited15to8 = false; + TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); PPL_LoadSpecularFragmentProgram(); } @@ -982,8 +1010,10 @@ void GLDraw_DeInit (void) Cmd_RemoveCommand("gl_texturemode"); draw_disc = NULL; - BZ_Free(uploadmemorybuffer); //free the mem - BZ_Free(uploadmemorybufferintermediate); + if (uploadmemorybuffer) + BZ_Free(uploadmemorybuffer); //free the mem + if (uploadmemorybufferintermediate) + BZ_Free(uploadmemorybufferintermediate); uploadmemorybuffer = NULL; //make sure we know it's free uploadmemorybufferintermediate = NULL; sizeofuploadmemorybuffer = 0; //and give a nice safe sys_error if we try using it. @@ -1128,16 +1158,16 @@ void GLDraw_Crosshair(void) { int x, y; int sc; - vrect_t rect; + + float x1, x2, y1, y2; + float size; if (crosshair.value == 1) { for (sc = 0; sc < cl.splitclients; sc++) { - SCR_VRectForPlayer(&rect, sc); - GLDraw_Character (rect.x + rect.width/2-4 + cl_crossx.value, - rect.y + rect.height/2-4 + cl_crossy.value, - '+'); + SCR_CrosshairPosition(sc, &x, &y); + GLDraw_Character (x-4, y-4, '+'); } return; } @@ -1183,19 +1213,22 @@ void GLDraw_Crosshair(void) for (sc = 0; sc < cl.splitclients; sc++) { - SCR_VRectForPlayer(&rect, sc); + SCR_CrosshairPosition(sc, &x, &y); - x = rect.x + rect.width/2 - 3 + cl_crossx.value; - y = rect.y + rect.height/2 - 3 + cl_crossy.value; + size = crosshairsize.value; + x1 = x - size; + x2 = x + size; + y1 = y - size; + y2 = y + size; glBegin (GL_QUADS); glTexCoord2f (0, 0); - glVertex2f (x - 4, y - 4); + glVertex2f (x1, y1); glTexCoord2f (1, 0); - glVertex2f (x+12, y-4); + glVertex2f (x2, y1); glTexCoord2f (1, 1); - glVertex2f (x+12, y+12); + glVertex2f (x2, y2); glTexCoord2f (0, 1); - glVertex2f (x - 4, y+12); + glVertex2f (x1, y2); glEnd (); } @@ -2191,6 +2224,9 @@ qboolean GL_UploadCompressed (qbyte *file, int *out_width, int *out_height, unsi return true; } +qboolean supported_GL_ARB_texture_non_power_of_two; +qboolean supported_GL_SGIS_generate_mipmap; + /* =============== GL_Upload32 @@ -2203,14 +2239,27 @@ void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean m unsigned *scaled = (unsigned *)uploadmemorybuffer; int scaled_width, scaled_height; - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; + TRACE(("dbg: GL_Upload32: %s %i %i\n", name, width, height)); + if (supported_GL_ARB_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. + { + TRACE(("dbg: GL_Upload32: GL_ARB_texture_non_power_of_two\n")); + scaled_width = width; + scaled_height = height; + } + else + { + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + } + + TRACE(("dbg: GL_Upload32: %f\n", gl_picmip.value)); scaled_width >>= (int)gl_picmip.value; scaled_height >>= (int)gl_picmip.value; + TRACE(("dbg: GL_Upload32: %f\n", gl_max_size.value)); if (gl_max_size.value) { if (scaled_width > gl_max_size.value) @@ -2219,6 +2268,13 @@ void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean m scaled_height = gl_max_size.value; } + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + + TRACE(("dbg: GL_Upload32: %i %i\n", scaled_width, scaled_height)); + if (scaled_width * scaled_height > sizeofuploadmemorybuffer/4) Sys_Error ("GL_LoadTexture: too big"); @@ -2240,10 +2296,17 @@ void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean m #else texels += scaled_width * scaled_height; + if (supported_GL_SGIS_generate_mipmap&&mipmap) + { + TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n")); + glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + } + if (scaled_width == width && scaled_height == height) { - if (!mipmap) + if (!mipmap||supported_GL_SGIS_generate_mipmap) //gotta love this with NPOT textures... :) { + TRACE(("dbg: GL_Upload32: non-mipmapped/unscaled\n")); glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); goto done; } @@ -2252,10 +2315,12 @@ texels += scaled_width * scaled_height; else GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); + TRACE(("dbg: GL_Upload32: recaled\n")); glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - if (mipmap) + if (mipmap && !supported_GL_SGIS_generate_mipmap) { miplevel = 0; + TRACE(("dbg: GL_Upload32: mips\n")); while (scaled_width > 1 || scaled_height > 1) { GL_MipMap ((qbyte *)scaled, scaled_width, scaled_height); @@ -2321,7 +2386,9 @@ texels += scaled_width * scaled_height; } } } -done: ; +done: + if (supported_GL_SGIS_generate_mipmap&&mipmap) + glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); #endif @@ -2343,10 +2410,19 @@ void GL_Upload8Grey (unsigned char*data, int width, int height, qboolean mipmap unsigned char *scaled = uploadmemorybuffer; int scaled_width, scaled_height; - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; + if (supported_GL_ARB_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. + { + TRACE(("dbg: GL_Upload32: GL_ARB_texture_non_power_of_two\n")); + scaled_width = width; + scaled_height = height; + } + else + { + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + } scaled_width >>= (int)gl_picmip.value; scaled_height >>= (int)gl_picmip.value; @@ -2359,23 +2435,16 @@ void GL_Upload8Grey (unsigned char*data, int width, int height, qboolean mipmap scaled_height = gl_max_size.value; } + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + if (scaled_width * scaled_height > sizeofuploadmemorybuffer/4) Sys_Error ("GL_LoadTexture: too big"); samples = 1;//alpha ? gl_alpha_format : gl_solid_format; -#if 0 - if (mipmap) - gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans); - else if (scaled_width == width && scaled_height == height) - glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - else - { - gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans, - scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled); - glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - } -#else texels += scaled_width * scaled_height; if (scaled_width == width && scaled_height == height) @@ -2410,8 +2479,6 @@ texels += scaled_width * scaled_height; } } done: ; -#endif - if (mipmap) { @@ -2554,13 +2621,24 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap) { int scaled_width, scaled_height; qbyte *nmap; + TRACE(("dbg: GL_UploadBump entered: %i %i\n", width, height)); + s = width*height; //Resize to power of 2 and maximum texture size - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; + if (supported_GL_ARB_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. + { + TRACE(("dbg: GL_Upload32: GL_ARB_texture_non_power_of_two\n")); + scaled_width = width; + scaled_height = height; + } + else + { + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + } scaled_width >>= (int)gl_picmip.value; scaled_height >>= (int)gl_picmip.value; @@ -2573,6 +2651,11 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap) { scaled_height = gl_max_size.value; } + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + if (scaled_width * scaled_height > sizeofuploadmemorybuffer/4) Sys_Error ("GL_LoadTexture: too big"); @@ -2637,6 +2720,7 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap) { // if (gl_texturefilteranisotropic) // glTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl_texureanisotropylevel); + TRACE(("dbg: GL_UploadBump: escaped %i %i\n", width, height)); } @@ -2669,10 +2753,19 @@ void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qbool if (alpha && noalpha) alpha = false; } - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; + if (supported_GL_ARB_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. + { + TRACE(("dbg: GL_Upload32: GL_ARB_texture_non_power_of_two\n")); + scaled_width = width; + scaled_height = height; + } + else + { + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + } scaled_width >>= (int)gl_picmip.value; scaled_height >>= (int)gl_picmip.value; @@ -2685,6 +2778,11 @@ void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qbool scaled_height = gl_max_size.value; } + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + if (scaled_width * scaled_height > sizeofuploadmemorybufferintermediate/4) Sys_Error ("GL_LoadTexture: too big"); @@ -2932,9 +3030,15 @@ int GL_LoadTexture (char *identifier, int width, int height, qbyte *data, qboole { glt = GL_MatchTexture(identifier, 8, width, height); if (glt) + { + +TRACE(("dbg: GL_LoadTexture: duplicate %s\n", identifier)); return glt->texnum; + } } +TRACE(("dbg: GL_LoadTexture: new %s\n", identifier)); + glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt->next = gltextures; gltextures = glt; @@ -3170,9 +3274,14 @@ int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char { glt = GL_MatchTexture(identifier, 8, width, height); if (glt) + { + TRACE(("dbg: GL_LoadTexture8Bump: duplicated %s\n", identifier)); return glt->texnum; + } } + TRACE(("dbg: GL_LoadTexture8Bump: new %s\n", identifier)); + glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt->next = gltextures; gltextures = glt; diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 80b74313e..f73b26075 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -865,11 +865,13 @@ void GLR_NewMap (void) r_viewcluster = -1; r_oldviewcluster = 0; r_viewcluster2 = -1; +TRACE(("dbg: GLR_NewMap: clear particles\n")); R_ClearParticles (); +TRACE(("dbg: GLR_NewMap: wiping them stains (getting the cloth out)\n")); GLR_WipeStains(); - +TRACE(("dbg: GLR_NewMap: building lightmaps\n")); GL_BuildLightmaps (); - +TRACE(("dbg: GLR_NewMap: figuring out skys and mirrors\n")); // identify sky texture if (cl.worldmodel->fromgame != fg_quake2 && cl.worldmodel->fromgame != fg_quake3) { @@ -886,13 +888,13 @@ void GLR_NewMap (void) mirrortexturenum = i; cl.worldmodel->textures[i]->texturechain = NULL; } - +TRACE(("dbg: GLR_NewMap: that skybox thang\n")); //#ifdef QUAKE2 R_LoadSkys (); //#endif - +TRACE(("dbg: GLR_NewMap: ui\n")); UI_Reset(); - +TRACE(("dbg: GLR_NewMap: tp\n")); TP_NewMap(); } diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 639059268..0d6621ac6 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -93,6 +93,9 @@ void GLSCR_UpdateScreen (void) vid.recalc_refdef = true; Con_CheckResize(); + + Plug_ResChanged(); + GL_Set2D(); } vid.numpages = 2 + gl_triplebuffer.value; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 054288088..2c0b2a54c 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -180,6 +180,14 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglBindProgramARB = NULL; qglGenProgramsARB = NULL; + supported_GL_ARB_texture_non_power_of_two = false; + supported_GL_SGIS_generate_mipmap = false; + + if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) + supported_GL_ARB_texture_non_power_of_two = true; + if (strstr(gl_extensions, "GL_SGIS_generate_mipmap")) + supported_GL_SGIS_generate_mipmap = true; + if (strstr(gl_extensions, "GL_ARB_multitexture") && !COM_CheckParm("-noamtex")) { //ARB multitexture is the popular choice. Con_SafePrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n"); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 5a5bbb2ff..78d5bcc46 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -36,6 +36,9 @@ msurface_t *warpface; extern cvar_t gl_skyboxname; extern cvar_t gl_waterripples; +extern cvar_t gl_skyboxdist; +extern cvar_t r_fastsky; +extern cvar_t r_fastskycolour; char loadedskybox[256]; void R_DrawSkyBox (msurface_t *s); @@ -381,14 +384,35 @@ void R_DrawSkyChain (msurface_t *s) { msurface_t *fa; + GL_DisableMultitexture(); + + if (r_fastsky.value) //this is for visability only... we'd otherwise not stoop this low (and this IS low) + { + int fc; + qbyte *pal; + extern unsigned char vid_curpal[256*3]; + fc = r_fastskycolour.value; + if (fc > 255) + fc = 255; + if (fc < 0) + fc = 0; + pal = vid_curpal+fc*3; + glDisable(GL_TEXTURE_2D); + glColor3f(pal[0]/255.0f, pal[1]/255.0f, pal[2]/255.0f); + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + glColor3f(1, 1, 1); + glEnable(GL_TEXTURE_2D); + return; + } + if (usingskybox) { R_DrawSkyBoxChain(s); return; } - GL_DisableMultitexture(); - // used when gl_texsort is on GL_Bind(solidskytexture); speedscale = cl.gametime; @@ -778,10 +802,14 @@ void MakeSkyVec (float s, float t, int axis) { vec3_t v, b; int j, k; + float skydist = gl_skyboxdist.value; - b[0] = s*2300; - b[1] = t*2300; - b[2] = 2300; + if (r_shadows.value) //because r_shadows comes with an infinate depth perspective. + skydist*=20; //so we can put the distance at whatever distance needed. + + b[0] = s*skydist; + b[1] = t*skydist; + b[2] = skydist; for (j=0 ; j<3 ; j++) { diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 920ae4368..53efd2e87 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -229,6 +229,9 @@ extern qboolean gl_mtexable; void GL_DisableMultitexture(void); void GL_EnableMultitexture(void); +extern qboolean supported_GL_SGIS_generate_mipmap; +extern qboolean supported_GL_ARB_texture_non_power_of_two; + // // gl_warp.c // diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 78b88abb6..fe8f1a97c 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -5047,69 +5047,63 @@ typedef struct lh_extension_s { lh_extension_t QSG_Extensions[] = { - {"QW_ENGINE"}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ. - {"DP_HALFLIFE_MAP_CVAR"}, - {"FTE_MULTIPROGS"}, //multiprogs functions are available. - {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) - {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, - {"DP_REGISTERCVAR", 1, NULL, {"registercvar"}}, - - {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, - - {"DP_TE_BLOOD", 1, NULL, {"te_blood"}}, - {"QSG_CVARSTRING", 1, NULL, {"cvar_string"}}, - {"DP_QC_CVAR_STRING", 1, NULL, {"dp_cvar_string"}}, //448 builtin. -#ifndef NOMEDIA - {"FTE_MEDIA_AVI"}, //playfilm supports avi files. - {"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files - {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. -#endif - {"QWE_MVD_RECORD"}, //Quakeworld extended get the credit for this one. (mvdsv) - {"FTE_MVD_PLAYBACK"}, - {"DP_SPRITE32"}, //hmm... is it legal to advertise this one? - {"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension... - {"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, - {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code with hexen2 support. - {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. - {"DP_SV_DRAWONLYTOCLIENT"}, - {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. - {"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!! + {"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!! + {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. {"DP_EF_RED"}, - {"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, - {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, + {"DP_EXTRA_TEMPSTRING"}, //ftos returns 16 temp buffers. + {"DP_HALFLIFE_MAP_CVAR"}, + {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. + {"DP_MOVETYPEFOLLOW"}, {"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}}, - {"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}}, //very very similar to the mvdsv system. - {"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}}, - {"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}}, + {"DP_QC_CVAR_STRING", 1, NULL, {"dp_cvar_string"}}, //448 builtin. + {"DP_QC_ETOS", 1, NULL, {"etos"}}, {"DP_QC_FINDCHAIN", 1, NULL, {"findchain"}}, {"DP_QC_FINDCHAINFLOAT", 1, NULL, {"findchainfloat"}}, - {"TEI_MD3_MODEL"}, -// {"TQ_RAILTRAIL"}, //client supports it, server can't filter it, but can currently send it. + {"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}}, +// {"DP_QC_FS_SEARCH", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}}, + {"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, + {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, + {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, + {"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, + {"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension... + {"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}}, {"DP_QUAKE2_MODEL"}, {"DP_QUAKE3_MODEL"}, - {"DP_QC_ETOS", 1, NULL, {"etos"}}, + {"DP_REGISTERCVAR", 1, NULL, {"registercvar"}}, + {"DP_SPRITE32"}, //hmm... is it legal to advertise this one? + {"DP_SV_DRAWONLYTOCLIENT"}, + {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. {"DP_SV_PLAYERPHYSICS"}, - {"DP_EXTRA_TEMPSTRING"}, //ftos returns 16 temp buffers. - - {"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, { "te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", - "te_wizspike", "te_knightspike", "te_lavasplash", "te_teleport", "te_explosion2", - "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}}, //should we include QW ones?... - - {"ZQ_MOVETYPE_NOCLIP"}, - {"ZQ_MOVETYPE_FLY"}, - {"ZQ_MOVETYPE_NONE"}, - + {"DP_SV_SETCOLOR"}, + {"DP_TE_BLOOD", 1, NULL, {"te_blood"}}, + {"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, { "te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}}, //should we include QW ones?... {"EXT_DIMENSION_VISIBILITY"}, {"EXT_DIMENSION_PHYSICS"}, {"EXT_DIMENSION_GHOST"}, {"EXT_BITSHIFT", 1, NULL, {"bitshift"}}, - + {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, +#ifndef NOMEDIA + {"FTE_MEDIA_AVI"}, //playfilm supports avi files. + {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. + {"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files +#endif + {"FTE_MULTIPROGS"}, //multiprogs functions are available. {"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}}, + {"FTE_MVD_PLAYBACK"}, #ifdef SVCHAT {"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. #endif - {"DP_SV_SETCOLOR"} + {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) + {"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}}, //very very similar to the mvdsv system. + {"QSG_CVARSTRING", 1, NULL, {"cvar_string"}}, + {"QW_ENGINE"}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ. + {"QWE_MVD_RECORD"}, //Quakeworld extended get the credit for this one. (mvdsv) + {"TEI_MD3_MODEL"}, +// {"TQ_RAILTRAIL"}, //client supports it, server can't filter it, but can currently send it. + {"ZQ_MOVETYPE_FLY"}, + {"ZQ_MOVETYPE_NOCLIP"}, + {"ZQ_MOVETYPE_NONE"}, }; //some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available. @@ -5772,7 +5766,7 @@ void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent = EDICT_NUM(svprogfuncs, i); if (ent->isfree) continue; - t = *(string_t *)&((float*)&ent->v)[f]; + t = *(string_t *)&((float*)&ent->v)[f] + prinst->stringtable; if (!t) continue; if (strcmp(t, s)) @@ -6902,6 +6896,72 @@ void PF_ChangePic(progfuncs_t *prinst, struct globalvars_s *pr_globals) } } +//DP_QC_FS_SEARCH +void PF_Search_Begin(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_INT(OFS_RETURN) = 0; +} +void PF_Search_End(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_INT(OFS_RETURN) = 0; +} +void PF_Search_GetSize(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_INT(OFS_RETURN) = 0; +} +void PF_SearchGetFileName(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_INT(OFS_RETURN) = 0; +} + +void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + edict_t *e = G_EDICT(prinst, OFS_PARM0); + edict_t *tagentity = G_EDICT(prinst, OFS_PARM1); + char *tagname = PR_GetStringOfs(prinst, OFS_PARM2); + + eval_t *te; + eval_t *ti; + +// int i, modelindex; +// model_t *model; + + te = prinst->GetEdictFieldValue(prinst, e, "tag_entity", NULL); + ti = prinst->GetEdictFieldValue(prinst, e, "tag_index", NULL); + + e->tagent = tagentity->entnum; + e->tagindex = 0; + + if (tagentity != sv.edicts && tagname && tagname[0]) + { +/* modelindex = (int)tagentity->v->modelindex; + if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.modeltags[modelindex])) + { + if (v->_float == 0 && model->alias.aliasnum_tags) + for (i = 0;i < model->alias.aliasnum_tags;i++) + if (!strcmp(tagname, model->alias.aliasdata_tags[i].name)) + v->_float = i + 1; + if (v->_float == 0) + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name); + } + else + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity)); +*/ + } + + //fix me, move to somewhere nicer. + MSG_WriteByte(&sv.multicast, svc_setattachment); + MSG_WriteShort(&sv.multicast, e->entnum); + MSG_WriteShort(&sv.multicast, e->tagent); + MSG_WriteShort(&sv.multicast, e->tagindex); + + SV_MulticastProtExt(vec3_origin, MULTICAST_ALL_R, 0xffffffff, PEXT_SETATTACHMENT, 0); + + if (te) + te->edict = EDICT_TO_PROG(prinst,EDICT_NUM(prinst, e->tagent)); + if (ti) + te->_float = e->tagindex; +} BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs @@ -7195,6 +7255,13 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"clientcommand", PF_clientcommand, 0, 0, 0, 440},// #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) {"tokenize", PF_Tokenize, 0, 0, 0, 441},// #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) {"argv", PF_ArgV, 0, 0, 0, 442},// #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND + + {"setattachment", PF_setattachment, 0, 0, 0, 443},// #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) + + {"search_begin", PF_Search_Begin, 0, 0, 0, 444}, + {"search_end", PF_Search_End, 0, 0, 0, 445}, + {"search_getsize", PF_Search_GetSize, 0, 0, 0, 446}, + {"search_getfilename", PF_SearchGetFileName,0, 0, 0, 447}, //DP_QC_CVAR_STRING {"dp_cvar_string", PF_cvar_string, 0, 0, 0, 448},// #448 string(float n) cvar_string //end other peoples extras @@ -7333,6 +7400,8 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any PR_EnableEBFSBuiltin("calltimeofday", 0)!= 102 || PR_EnableEBFSBuiltin("forcedemoframe", 0)!= 103) Con_Printf("Failed to register all MVDSV builtins\n"); + else + Con_Printf("Be aware that MVDSV does not follow standards. Please encourage your mod developers to not require pr_imitatemvdsv to be set.\n"); } } @@ -7475,6 +7544,7 @@ void PR_RegisterFields(void) //it's just easier to do it this way. fieldfloat(gravity); //standard extension fieldfloat(maxspeed); //standard extension fieldfloat(items2); //standard nq + fieldvector(punchangle);//standard nq fieldfloat(scale); //fieldfloat(transparency); fieldfloat(alpha); @@ -7502,8 +7572,9 @@ void PR_RegisterFields(void) //it's just easier to do it this way. //hexen 2 stuff fieldfloat(playerclass); fieldfloat(hull); + fieldfloat(hasted); -//stats - only a couple... +//stats - only a couple... (optimise me...) fieldfloat(level); fieldfloat(intelligence); fieldfloat(experience); @@ -7537,7 +7608,6 @@ void PR_RegisterFields(void) //it's just easier to do it this way. fieldstring(puzzle_inv7); fieldstring(puzzle_inv8); - fieldfloat(hasted); fieldfloat(inventory); fieldfloat(cnt_torch); fieldfloat(cnt_h_boost); diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index fb0d595b3..d8b456c46 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -227,6 +227,7 @@ typedef struct entvars_s float gravity; float maxspeed; float items2; + vec3_t punchangle; float scale; float alpha; float fatness; @@ -257,6 +258,7 @@ typedef struct entvars_s float seefsizez; float seefoffset; + //hexen2 stuff float playerclass; //hexen2 requirements float hull; float drawflags; @@ -264,9 +266,12 @@ typedef struct entvars_s int movechain; func_t chainmoved; - float light_level; - float abslight; + float light_level;//hexen2's grabbing light level from client + float abslight; //hexen2's force a lightlevel + float hasted; //hexen2 uses this AS WELL as maxspeed + + //FIXME: remove these, use evalc_ts float level; float intelligence; float experience; @@ -300,7 +305,6 @@ typedef struct entvars_s string_t puzzle_inv7; string_t puzzle_inv8; - float hasted; float inventory; float cnt_torch; float cnt_h_boost; diff --git a/engine/server/progs.h b/engine/server/progs.h index b8db3a870..d4200ce0c 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -78,6 +78,9 @@ typedef struct edict_s entity_state_t baseline; + unsigned short tagent; + unsigned short tagindex; + entvars_t v; // C exported fields from progs // other fields from progs come immediately after } edict_t; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index dd9a28c83..0cd169521 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -654,7 +654,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) if (ent->spectator == 2 && ent->weaponframe) pflags |= PF_WEAPONFRAME; - if (!ent->isself) + if (!ent->isself || ent->fteext & PEXT_SPLITSCREEN) { #ifdef PEXT_SCALE //this is graphics, not physics if (ent->fteext & PEXT_SCALE) @@ -872,14 +872,14 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) #define EFQW_DARKFIELD 512 #define EFQW_LIGHT 1024 -void SV_RemoveEffect(client_t *to, edict_t *ent, int seefno) +void SV_RemoveEffect(client_t *to, edict_t *ent, int seefmask) { specialenteffects_t *prev = NULL; specialenteffects_t *ef; int en = NUM_FOR_EDICT(svprogfuncs, ent); for (ef = to->enteffects; ef; ef = ef->next) { - if (ef->entnum == en && ef->efnum == seefno) + if (ef->entnum == en && ef->efnum & seefmask) { if (prev) prev->next = ef->next; @@ -887,9 +887,30 @@ void SV_RemoveEffect(client_t *to, edict_t *ent, int seefno) to->enteffects = ef->next; Z_Free(ef); - ClientReliableWrite_Begin(to, svc_temp_entity, 4); - ClientReliableWrite_Byte(to, TE_SEEF_BRIGHTFIELD+seefno); - ClientReliableWrite_Short(to, en|0x8000); + if (ef->efnum & seefmask & 1>>SEEF_BRIGHTFIELD) + { + ClientReliableWrite_Begin(to, svc_temp_entity, 4); + ClientReliableWrite_Byte(to, TE_SEEF_BRIGHTFIELD); + ClientReliableWrite_Short(to, en|0x8000); + } + if (ef->efnum & seefmask & 1>>SEEF_DARKLIGHT) + { + ClientReliableWrite_Begin(to, svc_temp_entity, 4); + ClientReliableWrite_Byte(to, SEEF_DARKLIGHT); + ClientReliableWrite_Short(to, en|0x8000); + } + if (ef->efnum & seefmask & 1>>SEEF_DARKFIELD) + { + ClientReliableWrite_Begin(to, svc_temp_entity, 4); + ClientReliableWrite_Byte(to, SEEF_DARKFIELD); + ClientReliableWrite_Short(to, en|0x8000); + } + if (ef->efnum & seefmask & 1>>SEEF_LIGHT) + { + ClientReliableWrite_Begin(to, svc_temp_entity, 4); + ClientReliableWrite_Byte(to, SEEF_LIGHT); + ClientReliableWrite_Short(to, en|0x8000); + } return; } prev = ef; @@ -904,7 +925,7 @@ void SV_AddEffect(client_t *to, edict_t *ent, int seefno) for (ef = to->enteffects; ef; ef = ef->next) { - if (ef->entnum == en && ef->efnum == seefno) + if (ef->entnum == en && ef->efnum == 1<colour != ent->v.seefcolour || ef->offset != ent->v.seefoffset || ef->size[0] != ent->v.seefsizex || ef->size[1] != ent->v.seefsizey || ef->size[2] != ent->v.seefsizez || ef->die < sv.time) { @@ -925,7 +946,7 @@ void SV_AddEffect(client_t *to, edict_t *ent, int seefno) ef->die = sv.time + 10; ef->next = to->enteffects; to->enteffects = ef; - ef->efnum = seefno; + ef->efnum = 1<entnum = en; ef->colour = ent->v.seefcolour; ef->offset = ent->v.seefoffset; @@ -958,63 +979,65 @@ void SV_AddEffect(client_t *to, edict_t *ent, int seefno) void SV_SendExtraEntEffects(client_t *to, edict_t *ent) { - if (!pr_udc_exteffect_enabled) - return; - - if (to->fteprotocolextensions & PEXT_SEEF1) + int removeeffects = 0; + if (pr_udc_exteffect_enabled) { - if (progstype != PROG_QW) + if (to->fteprotocolextensions & PEXT_SEEF1) { - if ((int)ent->v.effects & (EF_BRIGHTFIELD|EFNQ_DARKLIGHT|EFNQ_DARKFIELD|EFNQ_LIGHT) || to->enteffects) + if (progstype != PROG_QW) { - if ((int)ent->v.effects & EF_BRIGHTFIELD) - SV_AddEffect(to, ent, SEEF_BRIGHTFIELD); - else - SV_RemoveEffect(to, ent, SEEF_BRIGHTFIELD); + if ((int)ent->v.effects & (EF_BRIGHTFIELD|EFNQ_DARKLIGHT|EFNQ_DARKFIELD|EFNQ_LIGHT) || to->enteffects) + { + if ((int)ent->v.effects & EF_BRIGHTFIELD) + SV_AddEffect(to, ent, SEEF_BRIGHTFIELD); + else + removeeffects |= 1<v.effects & EFNQ_DARKLIGHT) - SV_AddEffect(to, ent, SEEF_DARKLIGHT); - else - SV_RemoveEffect(to, ent, SEEF_DARKLIGHT); + if ((int)ent->v.effects & EFNQ_DARKLIGHT) + SV_AddEffect(to, ent, SEEF_DARKLIGHT); + else + removeeffects |= 1<v.effects & EFNQ_DARKFIELD) - SV_AddEffect(to, ent, SEEF_DARKFIELD); - else - SV_RemoveEffect(to, ent, SEEF_DARKFIELD); + if ((int)ent->v.effects & EFNQ_DARKFIELD) + SV_AddEffect(to, ent, SEEF_DARKFIELD); + else + removeeffects |= 1<v.effects & EFNQ_LIGHT) - SV_AddEffect(to, ent, SEEF_LIGHT); - else - SV_RemoveEffect(to, ent, SEEF_LIGHT); + if ((int)ent->v.effects & EFNQ_LIGHT) + SV_AddEffect(to, ent, SEEF_LIGHT); + else + removeeffects |= 1<v.effects & (EF_BRIGHTFIELD|EFQW_DARKLIGHT|EFQW_DARKFIELD|EFQW_LIGHT) || to->enteffects) + else { - if ((int)ent->v.effects & EF_BRIGHTFIELD) - SV_AddEffect(to, ent, SEEF_BRIGHTFIELD); - else - SV_RemoveEffect(to, ent, SEEF_BRIGHTFIELD); + if ((int)ent->v.effects & (EF_BRIGHTFIELD|EFQW_DARKLIGHT|EFQW_DARKFIELD|EFQW_LIGHT) || to->enteffects) + { + if ((int)ent->v.effects & EF_BRIGHTFIELD) + SV_AddEffect(to, ent, SEEF_BRIGHTFIELD); + else + removeeffects |= 1<v.effects & EFQW_DARKLIGHT) - SV_AddEffect(to, ent, SEEF_DARKLIGHT); - else - SV_RemoveEffect(to, ent, SEEF_DARKLIGHT); + if ((int)ent->v.effects & EFQW_DARKLIGHT) + SV_AddEffect(to, ent, SEEF_DARKLIGHT); + else + removeeffects |= 1<v.effects & EFQW_DARKFIELD) - SV_AddEffect(to, ent, SEEF_DARKFIELD); - else - SV_RemoveEffect(to, ent, SEEF_DARKFIELD); + if ((int)ent->v.effects & EFQW_DARKFIELD) + SV_AddEffect(to, ent, SEEF_DARKFIELD); + else + removeeffects |= 1<v.effects & EFQW_LIGHT) - SV_AddEffect(to, ent, SEEF_LIGHT); - else - SV_RemoveEffect(to, ent, SEEF_LIGHT); + if ((int)ent->v.effects & EFQW_LIGHT) + SV_AddEffect(to, ent, SEEF_LIGHT); + else + removeeffects |= 1<enteffects) + SV_RemoveEffect(to, ent, removeeffects); } } - } /* ============= @@ -1868,8 +1891,22 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (!ignorepvs) { - if (!sv.worldmodel->funcs.EdictInFatPVS(ent)) - continue; + if (ent->tagent) + { + edict_t *p = ent; + int c = 10; + while(p->tagent&&c-->0) + { + p = EDICT_NUM(svprogfuncs, p->tagent); + } + if (!sv.worldmodel->funcs.EdictInFatPVS(p)) + continue; + } + else + { + if (!sv.worldmodel->funcs.EdictInFatPVS(ent)) + continue; + } /* #ifdef Q2BSPS if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 0f41bd346..6d8eed1f6 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2991,6 +2991,7 @@ void SV_InitLocal (void) svs.fteprotocolextensions |= PEXT_256PACKETENTITIES; // svs.fteprotocolextensions |= PEXT_64PLAYERS; svs.fteprotocolextensions |= PEXT_SHOWPIC; + svs.fteprotocolextensions |= PEXT_SETATTACHMENT; // if (svs.protocolextensions) // Info_SetValueForStarKey (svs.info, "*"DISTRIBUTION"_ext", va("%x", svs.protocolextensions), MAX_SERVERINFO_STRING); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 5a9fc1f66..757effc37 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -83,6 +83,7 @@ void SV_CheckAllEnts (void) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW || check->v.movetype == MOVETYPE_NOCLIP) continue; @@ -665,6 +666,7 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW || check->v.movetype == MOVETYPE_NOCLIP) continue; @@ -856,6 +858,51 @@ void SV_Physics_None (edict_t *ent) SV_RunThink (ent); } + +/* +============= +SV_Physics_Follow + +Entities that are "stuck" to another entity +============= +*/ +void SV_Physics_Follow (edict_t *ent) +{ + vec3_t vf, vr, vu, angles, v; + edict_t *e; + + // regular thinking + if (!SV_RunThink (ent)) + return; + + // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects + e = PROG_TO_EDICT(svprogfuncs, ent->v.aiment); + if (e->v.angles[0] == ent->v.punchangle[0] && e->v.angles[1] == ent->v.punchangle[1] && e->v.angles[2] == ent->v.punchangle[2]) + { + // quick case for no rotation + VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin); + } + else + { + angles[0] = -ent->v.punchangle[0]; + angles[1] = ent->v.punchangle[1]; + angles[2] = ent->v.punchangle[2]; + AngleVectors (angles, vf, vr, vu); + v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0]; + v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1]; + v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2]; + angles[0] = -e->v.angles[0]; + angles[1] = e->v.angles[1]; + angles[2] = e->v.angles[2]; + AngleVectors (angles, vf, vr, vu); + ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0]; + ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1]; + ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2]; + } + VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles); + SV_LinkEdict (ent, true); +} + /* ============= SV_Physics_Noclip @@ -1439,7 +1486,7 @@ From normal Quake in an attempt to fix physics in QuakeRally void SV_Physics_Client (edict_t *ent, int num) { qboolean readyforjump; - float oldvel; +// float oldvel; if ( svs.clients[num-1].state < cs_spawned ) return; // unconnected slot @@ -1477,27 +1524,31 @@ void SV_Physics_Client (edict_t *ent, int num) break; case MOVETYPE_WALK: - oldvel = ent->v.velocity[0]; +// oldvel = ent->v.velocity[0]; if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent, ent->v.gravity); - if (fabs(oldvel - ent->v.velocity[0])> 100) - Con_Printf("grav: %f -> %f\n", oldvel, ent->v.velocity[0]); +// if (fabs(oldvel - ent->v.velocity[0])> 100) +// Con_Printf("grav: %f -> %f\n", oldvel, ent->v.velocity[0]); SV_CheckStuck (ent); - if (fabs(oldvel - ent->v.velocity[0])> 100) - Con_Printf("stuck: %f -> %f\n", oldvel, ent->v.velocity[0]); +// if (fabs(oldvel - ent->v.velocity[0])> 100) +// Con_Printf("stuck: %f -> %f\n", oldvel, ent->v.velocity[0]); SV_WalkMove (ent); - if (fabs(oldvel - ent->v.velocity[0])> 100) - Con_Printf("walk: %f -> %f\n", oldvel, ent->v.velocity[0]); +// if (fabs(oldvel - ent->v.velocity[0])> 100) +// Con_Printf("walk: %f -> %f\n", oldvel, ent->v.velocity[0]); break; + case MOVETYPE_FOLLOW: + SV_Physics_Follow (ent); + break; + case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: SV_Physics_Toss (ent); @@ -1570,6 +1621,9 @@ void SV_RunEntity (edict_t *ent) case MOVETYPE_PUSHPULL: SV_Physics_Step (ent); break; + case MOVETYPE_FOLLOW: + SV_Physics_Follow (ent); + break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: @@ -1589,7 +1643,7 @@ void SV_RunEntity (edict_t *ent) break; default: - SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v.movetype, ent->v.classname); + SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v.movetype, svprogfuncs->stringtable + ent->v.classname); } if (ent2 != sv.edicts) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 178612e25..c911dd33d 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -585,6 +585,9 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int if (client->state != cs_spawned) continue; + if (client->controller) + continue; //FIXME: send if at least one of the players is near enough. + if (client->fteprotocolextensions & without) { // Con_Printf ("Version supressed multicast - without pext\n"); @@ -1160,7 +1163,7 @@ void SV_UpdateClientStats (client_t *client, int pnum) #define FL_SPECIAL_ABILITY1 4194304 // has 1st special ability #define FL_SPECIAL_ABILITY2 8388608 // has 2nd special ability stats[STAT_H2_FLAGS] = (int)ent->v.flags & (FL_SPECIAL_ABILITY1 | FL_SPECIAL_ABILITY2); - + //dmw tweek for stats pr_globals = PR_globals(svprogfuncs, PR_CURRENT); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 26441894d..5a10893c8 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -768,8 +768,16 @@ void SV_PreSpawn_f (void) break; ent = EDICT_NUM(svprogfuncs, buf - bufs - sv.numextrastatics); - state = &ent->baseline; + if (ent->tagent) + { + MSG_WriteByte(&host_client->netchan.message, svc_setattachment); + MSG_WriteShort(&host_client->netchan.message, ent->entnum); + MSG_WriteShort(&host_client->netchan.message, ent->tagent); + MSG_WriteShort(&host_client->netchan.message, ent->tagindex); + } + + state = &ent->baseline; if (!state->number || !state->modelindex) { //ent doesn't have a baseline buf++; @@ -1130,6 +1138,7 @@ void SV_Begin_f (void) SV_PreRunCmd(); { usercmd_t cmd; + memset(&cmd, 0, sizeof(cmd)); cmd.msec = 0; #define ANGLE2SHORT(x) (x) * (65536/360.0) cmd.angles[0] = ANGLE2SHORT(split->edict->v.v_angle[0]); @@ -3911,8 +3920,19 @@ haveannothergo: if (newcmd.impulse)// && SV_FiltureImpulse(newcmd.impulse, host_client->trustlevel)) sv_player->v.impulse = newcmd.impulse; + sv_player->v.button0 = newcmd.buttons & 1; - sv_player->v.button2 = (newcmd.buttons & 2)>>1; + sv_player->v.button2 = (newcmd.buttons >> 1) & 1; + if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. + sv_player->v.button1 = ((newcmd.buttons >> 2) & 1); + // DP_INPUTBUTTONS + sv_player->v.button3 = ((newcmd.buttons >> 2) & 1); + sv_player->v.button4 = ((newcmd.buttons >> 3) & 1); + sv_player->v.button5 = ((newcmd.buttons >> 4) & 1); + sv_player->v.button6 = ((newcmd.buttons >> 5) & 1); + sv_player->v.button7 = ((newcmd.buttons >> 6) & 1); + sv_player->v.button8 = ((newcmd.buttons >> 7) & 1); + cl->lastcmd = newcmd; cl->lastcmd.buttons = 0; // avoid multiple fires on lag diff --git a/engine/sw/d_edge.c b/engine/sw/d_edge.c index 3a38b87c4..6b3dd939a 100644 --- a/engine/sw/d_edge.c +++ b/engine/sw/d_edge.c @@ -198,6 +198,7 @@ void D_DrawSurfaces (void) vec3_t world_transformed_modelorg; vec3_t local_modelorg; extern int r_dosirds; + extern cvar_t r_fastsky, r_fastskycolour; currententity = &r_worldentity; TransformVector (modelorg, transformed_modelorg); @@ -253,17 +254,24 @@ void D_DrawSurfaces (void) { if (r_worldentity.model->fromgame == fg_halflife) continue; - if (!r_skymade) + if (r_fastsky.value) { - R_MakeSky (); + D_DrawSolidSurface (s, (int)r_fastskycolour.value & 0xFF); } - - if (r_pixbytes == 4) - D_DrawSkyScans32 (s->spans); - else if (r_pixbytes == 2) - D_DrawSkyScans16 (s->spans); else - D_DrawSkyScans8 (s->spans); + { + if (!r_skymade) + { + R_MakeSky (); + } + + if (r_pixbytes == 4) + D_DrawSkyScans32 (s->spans); + else if (r_pixbytes == 2) + D_DrawSkyScans16 (s->spans); + else + D_DrawSkyScans8 (s->spans); + } D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWSKYBOX) diff --git a/engine/sw/sw_draw.c b/engine/sw/sw_draw.c index 43af5e239..7b5f0c320 100644 --- a/engine/sw/sw_draw.c +++ b/engine/sw/sw_draw.c @@ -760,70 +760,74 @@ void SWDraw_Crosshair(void) qbyte c = (qbyte)crosshaircolor.value; qbyte c2 = (qbyte)crosshaircolor.value; - x = scr_vrect.x + scr_vrect.width/2 + cl_crossx.value; - y = scr_vrect.y + scr_vrect.height/2 + cl_crossy.value; - -#define Pix(xp,yp,c) SWDraw_Pixel(x+xp, y+yp, c) - - switch((int)crosshair.value) + int sc; + + for (sc = 0; sc < cl.splitclients; sc++) { - case 0: - if (*crosshair.string>='a' && *crosshair.string<='z') + SCR_CrosshairPosition(sc, &x, &y); + + #define Pix(xp,yp,c) SWDraw_Pixel(x+xp, y+yp, c) + + switch((int)crosshair.value) { - static qbyte *crosshairfile; - static int crosshairfilesize; - static char cachedcrosshairfile[64]; - int fx, fy; - qbyte *f; - - if (!strncmp(cachedcrosshairfile, crosshair.string, sizeof(cachedcrosshairfile))) + case 0: + if (*crosshair.string>='a' && *crosshair.string<='z') { - if (crosshairfile) - Z_Free(crosshairfile); - crosshairfile = COM_LoadFile(va("%s.csh", crosshair.string), 0); - crosshairfilesize = com_filesize; - Q_strncpyz(cachedcrosshairfile, crosshair.string, sizeof(cachedcrosshairfile)); - } + static qbyte *crosshairfile; + static int crosshairfilesize; + static char cachedcrosshairfile[64]; + int fx, fy; + qbyte *f; - f = crosshairfile; - if (!f) - return; - for (fy = 0; fy < 8; fy++) - { - for (fx = 0; fx < 8; ) + if (!strncmp(cachedcrosshairfile, crosshair.string, sizeof(cachedcrosshairfile))) { - if (f - crosshairfile > crosshairfilesize) - { - Con_Printf("Crosshair file has overrun"); - fy=10; - break; - } - if (*f == 'x') - { - Pix(fx-3, fy-3, c); - fx++; - } - else if (*f == 'X') - { - Pix(fx-3, fy-3, c2); - fx++; - } - else if (*f == '0' || *f == 'o' || *f == 'O') - fx++; + if (crosshairfile) + Z_Free(crosshairfile); + crosshairfile = COM_LoadFile(va("%s.csh", crosshair.string), 0); + crosshairfilesize = com_filesize; + Q_strncpyz(cachedcrosshairfile, crosshair.string, sizeof(cachedcrosshairfile)); + } - f++; - } + f = crosshairfile; + if (!f) + return; + for (fy = 0; fy < 8; fy++) + { + for (fx = 0; fx < 8; ) + { + if (f - crosshairfile > crosshairfilesize) + { + Con_Printf("Crosshair file has overrun"); + fy=10; + break; + } + if (*f == 'x') + { + Pix(fx-3, fy-3, c); + fx++; + } + else if (*f == 'X') + { + Pix(fx-3, fy-3, c2); + fx++; + } + else if (*f == '0' || *f == 'o' || *f == 'O') + fx++; + + f++; + } + } } + break; + default: + case 1: + Draw_Character ( + scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, + scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, + '+'); + break; + #include "crosshairs.dat" } - break; - default: - case 1: - Draw_Character ( - scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, - scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, - '+'); - break; -#include "crosshairs.dat" } }