From da273b434ebf1d1e7d3c920de55ee740f5f11cec Mon Sep 17 00:00:00 2001 From: Joseph Carter Date: Sun, 23 Jan 2000 06:35:16 +0000 Subject: [PATCH] Fixed sbar problems! This ended up requiring backports from the unstable tree, but this is AFAIK the last issue before release. --- NEWS | 6 + uquake/gl_screen.c | 227 ++++---- uquake/r_main.c | 1106 ++++++++++++++++++++++++++++++++++++++ uquake/sbar.c | 1273 ++++++++++++++++++++++++++++++++++++++++++++ uquake/screen.c | 130 +++-- 5 files changed, 2595 insertions(+), 147 deletions(-) create mode 100644 uquake/r_main.c create mode 100644 uquake/sbar.c diff --git a/NEWS b/NEWS index 60f1168..67f0a04 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,12 @@ NEWS for the QuakeForge project ------------------------------- +22 Jan 2000 - cl_sbar and cl_hudswap in uquake + The cvars cl_sbar and cl_hudswap noe work in uquake just like they + do in qw-client. In uquake, cl_sbar defaults to 1 to satisfy the + least-surprise principle. Set it to 0 if you want a qw-client like + HUD. + 22 Jan 2000 - changes to command line option -game You may now specify multiple game directories with -game. If for example you wanted to use the original registered game with MegaTF diff --git a/uquake/gl_screen.c b/uquake/gl_screen.c index 50aa7e2..5e0f676 100644 --- a/uquake/gl_screen.c +++ b/uquake/gl_screen.c @@ -1,6 +1,8 @@ /* Copyright (C) 1996-1997 Id Software, Inc. Portions Copyright (C) 1999,2000 Nelson Rush. +Copyright (C) 1999,2000 contributors of the QuakeForge project +Please see the file "AUTHORS" for a list of contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +#include + /* background clear @@ -71,50 +75,49 @@ console is: */ -int glx, gly, glwidth, glheight; +int glx, gly, glwidth, glheight; // only the refresh window will be updated unless these variables are flagged -int scr_copytop; -int scr_copyeverything; +int scr_copytop; +int scr_copyeverything; -float scr_con_current; -float scr_conlines; // lines of console to display +float scr_con_current; +float scr_conlines; // lines of console to display -float oldscreensize, oldfov; -cvar_t scr_viewsize = {"viewsize","100", true}; -cvar_t scr_fov = {"fov","90"}; // 10 - 170 -cvar_t scr_conspeed = {"scr_conspeed","300"}; -cvar_t scr_centertime = {"scr_centertime","2"}; -cvar_t scr_showram = {"showram","1"}; -cvar_t scr_showturtle = {"showturtle","0"}; -cvar_t scr_showpause = {"showpause","1"}; -cvar_t scr_printspeed = {"scr_printspeed","8"}; -cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; +float oldscreensize, oldfov; +cvar_t scr_viewsize = {"viewsize","100", true}; +cvar_t scr_fov = {"fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {"scr_conspeed","300"}; +cvar_t scr_centertime = {"scr_centertime","2"}; +cvar_t scr_showram = {"showram","1"}; +cvar_t scr_showturtle = {"showturtle","0"}; +cvar_t scr_showpause = {"showpause","1"}; +cvar_t scr_printspeed = {"scr_printspeed","8"}; +cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; +extern cvar_t crosshair; -extern cvar_t crosshair; +qboolean scr_initialized; // ready to draw -qboolean scr_initialized; // ready to draw +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; -qpic_t *scr_ram; -qpic_t *scr_net; -qpic_t *scr_turtle; +int scr_fullupdate; -int scr_fullupdate; +int clearconsole; +int clearnotify; -int clearconsole; -int clearnotify; +int sb_lines; -int sb_lines; +viddef_t vid; // global video state -viddef_t vid; // global video state +vrect_t scr_vrect; -vrect_t scr_vrect; +qboolean scr_disabled_for_loading; +qboolean scr_drawloading; +float scr_disabled_time; -qboolean scr_disabled_for_loading; -qboolean scr_drawloading; -float scr_disabled_time; - -qboolean block_drawing; +qboolean block_drawing; void SCR_ScreenShot_f (void); @@ -126,12 +129,12 @@ CENTER PRINTING =============================================================================== */ -char scr_centerstring[1024]; -float scr_centertime_start; // for slow victory printing -float scr_centertime_off; -int scr_center_lines; -int scr_erase_lines; -int scr_erase_center; +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; /* ============== @@ -160,11 +163,11 @@ void SCR_CenterPrint (char *str) void SCR_DrawCenterString (void) { - char *start; - int l; - int j; - int x, y; - int remaining; + char *start; + int l; + int j; + int x, y; + int remaining; // the finale prints the characters one at a time if (cl.intermission) @@ -180,7 +183,7 @@ void SCR_DrawCenterString (void) else y = 48; - do + do { // scan the width of the line for (l=0 ; l<40 ; l++) @@ -189,7 +192,7 @@ void SCR_DrawCenterString (void) x = (vid.width - l*8)/2; for (j=0 ; j 170) Cvar_Set ("fov","170"); -// intermission is always full screen +// intermission is always full screen if (cl.intermission) size = 120; else size = scr_viewsize.value; if (size >= 120) - sb_lines = 0; // no status bar at all + sb_lines = 0; // no status bar at all else if (size >= 110) - sb_lines = 24; // no inventory + sb_lines = 24; // no inventory else sb_lines = 24+16+8; @@ -301,24 +304,28 @@ static void SCR_CalcRefdef (void) if (cl.intermission) { full = true; - size = 100; + size = 100.0; sb_lines = 0; } size /= 100.0; - h = vid.height - sb_lines; + if (!cl_sbar.value && full) + h = vid.height; + else + h = vid.height - sb_lines; r_refdef.vrect.width = vid.width * size; if (r_refdef.vrect.width < 96) { size = 96.0 / r_refdef.vrect.width; - r_refdef.vrect.width = 96; // min for icons + r_refdef.vrect.width = 96; // min for icons } r_refdef.vrect.height = vid.height * size; - if (r_refdef.vrect.height > vid.height - sb_lines) - r_refdef.vrect.height = vid.height - sb_lines; - if (r_refdef.vrect.height > vid.height) + if (cl_sbar.value || !full) { + if (r_refdef.vrect.height > vid.height - sb_lines) + r_refdef.vrect.height = vid.height - sb_lines; + } else if (r_refdef.vrect.height > vid.height) r_refdef.vrect.height = vid.height; r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; if (full) @@ -369,7 +376,6 @@ SCR_Init */ void SCR_Init (void) { - Cvar_RegisterVariable (&scr_fov); Cvar_RegisterVariable (&scr_viewsize); Cvar_RegisterVariable (&scr_conspeed); @@ -419,7 +425,7 @@ SCR_DrawTurtle */ void SCR_DrawTurtle (void) { - static int count; + static int count; if (!scr_showturtle.value) return; @@ -460,10 +466,9 @@ Backported by Jules Bean from quakeworld client =============== */ - void SCR_DrawFPS (void) { - extern cvar_t show_fps; + extern cvar_t show_fps; static double lastframetime; double t; extern int fps_count; @@ -471,8 +476,8 @@ void SCR_DrawFPS (void) int x, y; char st[80]; - if (!show_fps.value) - return; + if (!show_fps.value) + return; t = Sys_DoubleTime(); if ((t - lastframetime) >= 1.0) { @@ -488,6 +493,7 @@ void SCR_DrawFPS (void) Draw_String(x, y, st); } + /* ============== DrawPause @@ -495,9 +501,9 @@ DrawPause */ void SCR_DrawPause (void) { - qpic_t *pic; + qpic_t *pic; - if (!scr_showpause.value) // turn off for screenshots + if (!scr_showpause.value) // turn off for screenshots return; if (!cl.paused) @@ -517,7 +523,7 @@ SCR_DrawLoading */ void SCR_DrawLoading (void) { - qpic_t *pic; + qpic_t *pic; if (!scr_drawloading) return; @@ -542,20 +548,20 @@ void SCR_SetUpToDrawConsole (void) Con_CheckResize (); if (scr_drawloading) - return; // never a console with loading plaque + return; // never a console with loading plaque // decide on the height of the console con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; if (con_forcedup) { - scr_conlines = vid.height; // full screen + scr_conlines = vid.height; // full screen scr_con_current = scr_conlines; } else if (key_dest == key_console) - scr_conlines = vid.height/2; // half screen + scr_conlines = vid.height/2; // half screen else - scr_conlines = 0; // none visible + scr_conlines = 0; // none visible if (scr_conlines < scr_con_current) { @@ -598,7 +604,7 @@ void SCR_DrawConsole (void) else { if (key_dest == key_game || key_dest == key_message) - Con_DrawNotify (); // only draw notify in game + Con_DrawNotify (); // only draw notify in game } } @@ -612,11 +618,11 @@ void SCR_DrawConsole (void) */ typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; } TargaHeader; @@ -627,10 +633,10 @@ SCR_ScreenShot_f */ void SCR_ScreenShot_f (void) { - byte *buffer; - char pcxname[80]; - char checkname[MAX_OSPATH]; - int i, c, temp; + byte *buffer; + char pcxname[80]; + char checkname[MAX_OSPATH]; + int i, c, temp; // // find a file name to save it to // @@ -642,23 +648,23 @@ void SCR_ScreenShot_f (void) pcxname[6] = i%10 + '0'; snprintf(checkname, sizeof(checkname), "%s/%s", com_gamedir, pcxname); if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist + break; // file doesn't exist } if (i==100) { Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); return; - } + } buffer = malloc(glwidth*glheight*3 + 18); memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type + buffer[2] = 2; // uncompressed type buffer[12] = glwidth&255; buffer[13] = glwidth>>8; buffer[14] = glheight&255; buffer[15] = glheight>>8; - buffer[16] = 24; // pixel size + buffer[16] = 24; // pixel size glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); @@ -676,10 +682,6 @@ void SCR_ScreenShot_f (void) Con_Printf ("Wrote %s\n", pcxname); } - -//============================================================================= - - /* =============== SCR_BeginLoadingPlaque @@ -726,21 +728,21 @@ void SCR_EndLoadingPlaque (void) //============================================================================= -char *scr_notifystring; -qboolean scr_drawdialog; +char *scr_notifystring; +qboolean scr_drawdialog; void SCR_DrawNotifyString (void) { - char *start; - int l; - int j; - int x, y; + char *start; + int l; + int j; + int x, y; start = scr_notifystring; y = vid.height*0.35; - do + do { // scan the width of the line for (l=0 ; l<40 ; l++) @@ -748,7 +750,7 @@ void SCR_DrawNotifyString (void) break; x = (vid.width - l*8)/2; for (j=0 ; jwidth = r_notexture_mip->height = 16; + r_notexture_mip->offsets[0] = sizeof(texture_t); + r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; + r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; + r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; + + for (m=0 ; m<4 ; m++) + { + dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; + for (y=0 ; y< (16>>m) ; y++) + for (x=0 ; x< (16>>m) ; x++) + { + if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) + *dest++ = 0; + else + *dest++ = 0xff; + } + } +} + +/* +=============== +R_Init +=============== +*/ +void R_Init (void) +{ + int dummy; + +// get stack position so we can guess if we are going to overflow + r_stack_start = (byte *)&dummy; + + R_InitTurb (); + + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + + Cvar_RegisterVariable (&r_draworder); + Cvar_RegisterVariable (&r_speeds); + Cvar_RegisterVariable (&r_timegraph); + Cvar_RegisterVariable (&r_graphheight); + Cvar_RegisterVariable (&r_drawflat); + Cvar_RegisterVariable (&r_ambient); + Cvar_RegisterVariable (&r_clearcolor); + Cvar_RegisterVariable (&r_waterwarp); + Cvar_RegisterVariable (&r_fullbright); + Cvar_RegisterVariable (&r_drawentities); + Cvar_RegisterVariable (&r_drawviewmodel); + Cvar_RegisterVariable (&r_aliasstats); + Cvar_RegisterVariable (&r_dspeeds); + Cvar_RegisterVariable (&r_reportsurfout); + Cvar_RegisterVariable (&r_maxsurfs); + Cvar_RegisterVariable (&r_numsurfs); + Cvar_RegisterVariable (&r_reportedgeout); + Cvar_RegisterVariable (&r_maxedges); + Cvar_RegisterVariable (&r_numedges); + Cvar_RegisterVariable (&r_aliastransbase); + Cvar_RegisterVariable (&r_aliastransadj); + + Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); + Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); + + view_clipplanes[0].leftedge = true; + view_clipplanes[1].rightedge = true; + view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = + view_clipplanes[3].leftedge = false; + view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = + view_clipplanes[3].rightedge = false; + + r_refdef.xOrigin = XCENTERING; + r_refdef.yOrigin = YCENTERING; + + R_InitParticles (); + +// TODO: collect 386-specific code in one place +#if id386 + Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, + (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); +#endif // id386 + + D_Init (); +} + +/* +=============== +R_NewMap +=============== +*/ +void R_NewMap (void) +{ + int i; + +// clear out efrags in case the level hasn't been reloaded +// FIXME: is this one short? + for (i=0 ; inumleafs ; i++) + cl.worldmodel->leafs[i].efrags = NULL; + + r_viewleaf = NULL; + R_ClearParticles (); + + r_cnumsurfs = r_maxsurfs.value; + + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; + + if (r_cnumsurfs > NUMSTACKSURFACES) + { + surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + else + { + r_surfsonstack = true; + } + + r_maxedgesseen = 0; + r_maxsurfsseen = 0; + + r_numallocatededges = r_maxedges.value; + + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; + + if (r_numallocatededges <= NUMSTACKEDGES) + { + auxedges = NULL; + } + else + { + auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), + "edges"); + } + + r_dowarpold = false; + r_viewchanged = false; +#ifdef PASSAGES +CreatePassages (); +#endif +} + + +/* +=============== +R_SetVrect +=============== +*/ +void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) +{ + int h; + float size; + qboolean full = false; + + if (scr_viewsize.value >= 100.0) { + size = 100.0; + full = true; + } else + size = scr_viewsize.value; + + if (cl.intermission) + { + full = true; + size = 100.0; + lineadj = 0; + } + size /= 100.0; + + if (!cl_sbar.value && full) + h = pvrectin->height; + else + h = pvrectin->height - lineadj; + + if (full) + pvrect->width = pvrectin->width; + else + pvrect->width = pvrectin->width * size; + if (pvrect->width < 96) + { + size = 96.0 / pvrectin->width; + pvrect->width = 96; // min for icons + } + pvrect->width &= ~7; + pvrect->height = pvrectin->height * size; + if (cl_sbar.value || !full) { + if (pvrect->height > pvrectin->height - lineadj) + pvrect->height = pvrectin->height - lineadj; + } else + if (pvrect->height > pvrectin->height) + pvrect->height = pvrectin->height; + + pvrect->height &= ~1; + + pvrect->x = (pvrectin->width - pvrect->width)/2; + if (full) + pvrect->y = 0; + else + pvrect->y = (h - pvrect->height)/2; + + if (lcd_x.value) + { + pvrect->y >>= 1; + pvrect->height >>= 1; + } +} + + +/* +=============== +R_ViewChanged + +Called every time the vid structure or r_refdef changes. +Guaranteed to be called before the first refresh +=============== +*/ +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) +{ + int i; + float res_scale; + + r_viewchanged = true; + + R_SetVrect (pvrect, &r_refdef.vrect, lineadj); + + r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); + r_refdef.fvrectx = (float)r_refdef.vrect.x; + r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; + r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; + r_refdef.fvrecty = (float)r_refdef.vrect.y; + r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; + r_refdef.fvrectright = (float)r_refdef.vrectright; + r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; + r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; + r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; + + r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); + r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); + r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); + r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); + r_refdef.aliasvrectright = r_refdef.aliasvrect.x + + r_refdef.aliasvrect.width; + r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + + r_refdef.aliasvrect.height; + + pixelAspect = aspect; + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + + screenAspect = r_refdef.vrect.width*pixelAspect / + r_refdef.vrect.height; +// 320*200 1.0 pixelAspect = 1.6 screenAspect +// 320*240 1.0 pixelAspect = 1.3333 screenAspect +// proper 320*200 pixelAspect = 0.8333333 + + verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; + +// values for perspective projection +// if math were exact, the values would range from 0.5 to to range+0.5 +// hopefully they wll be in the 0.000001 to range+.999999 and truncate +// the polygon rasterization will never render in the first row or column +// but will definately render in the [range] row and column, so adjust the +// buffer origin to get an exact edge to edge fill + xcenter = ((float)r_refdef.vrect.width * XCENTERING) + + r_refdef.vrect.x - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float)r_refdef.vrect.height * YCENTERING) + + r_refdef.vrect.y - 0.5; + aliasycenter = ycenter * r_aliasuvscale; + + xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; + aliasxscale = xscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; + yscale = xscale * pixelAspect; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink*pixelAspect; + +// left side clip + screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + +// right side clip + screenedge[1].normal[0] = + 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + +// top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + +// bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; + + for (i=0 ; i<4 ; i++) + VectorNormalize (screenedge[i].normal); + + res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / + (320.0 * 152.0)) * + (2.0 / r_refdef.horizontalFieldOfView); + r_aliastransition = r_aliastransbase.value * res_scale; + r_resfudge = r_aliastransadj.value * res_scale; + + if (scr_fov.value <= 90.0) + r_fov_greater_than_90 = false; + else + r_fov_greater_than_90 = true; + +// TODO: collect 386-specific code in one place +#if id386 + if (r_pixbytes == 1) + { + Sys_MakeCodeWriteable ((long)R_Surf8Start, + (long)R_Surf8End - (long)R_Surf8Start); + colormap = vid.colormap; + R_Surf8Patch (); + } + else + { + Sys_MakeCodeWriteable ((long)R_Surf16Start, + (long)R_Surf16End - (long)R_Surf16Start); + colormap = vid.colormap16; + R_Surf16Patch (); + } +#endif // id386 + + D_ViewChanged (); +} + + +/* +=============== +R_MarkLeaves +=============== +*/ +void R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewleaf == r_viewleaf) + return; + + r_visframecount++; + r_oldviewleaf = r_viewleaf; + + vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + + for (i=0 ; inumleafs ; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *)&cl.worldmodel->leafs[i+1]; + do + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i, j; + int lnum; + alight_t lighting; +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + vec3_t dist; + float add; + + if (!r_drawentities.value) + return; + + for (i=0 ; imodel->type) + { + case mod_sprite: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + R_DrawSprite (); + break; + + case mod_alias: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + if (R_AliasCheckBBox ()) + { + j = R_LightPoint (currententity->origin); + + lighting.ambientlight = j; + lighting.shadelight = j; + + lighting.plightvec = lightvec; + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + + if (add > 0) + lighting.ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting.ambientlight > 128) + lighting.ambientlight = 128; + if (lighting.ambientlight + lighting.shadelight > 192) + lighting.shadelight = 192 - lighting.ambientlight; + + R_AliasDrawModel (&lighting); + } + + break; + + default: + break; + } + } +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + + if (!r_drawviewmodel.value || r_fov_greater_than_90) + return; + + if (cl.items & IT_INVISIBILITY) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + VectorCopy (vup, viewlightvec); + VectorInverse (viewlightvec); + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // allways give some light on gun + r_viewlighting.ambientlight = j; + r_viewlighting.shadelight = j; + +// add dynamic lights + for (lnum=0 ; lnumradius) + continue; + if (!dl->radius) + continue; + if (dl->die < cl.time) + continue; + + VectorSubtract (currententity->origin, dl->origin, dist); + add = dl->radius - Length(dist); + if (add > 0) + r_viewlighting.ambientlight += add; + } + +// clamp lighting so it doesn't overbright as much + if (r_viewlighting.ambientlight > 128) + r_viewlighting.ambientlight = 128; + if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) + r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; + + r_viewlighting.plightvec = lightvec; + +#ifdef QUAKE2 + cl.light_level = r_viewlighting.ambientlight; +#endif + + R_AliasDrawModel (&r_viewlighting); +} + + +/* +============= +R_BmodelCheckBBox +============= +*/ +int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) +{ + int i, *pindex, clipflags; + vec3_t acceptpt, rejectpt; + double d; + + clipflags = 0; + + if (currententity->angles[0] || currententity->angles[1] + || currententity->angles[2]) + { + for (i=0 ; i<4 ; i++) + { + d = DotProduct (currententity->origin, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= -clmodel->radius) + return BMODEL_FULLY_CLIPPED; + + if (d <= clmodel->radius) + clipflags |= (1<model->type) + { + case mod_brush: + + clmodel = currententity->model; + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + for (j=0 ; j<3 ; j++) + { + minmaxs[j] = currententity->origin[j] + + clmodel->mins[j]; + minmaxs[3+j] = currententity->origin[j] + + clmodel->maxs[j]; + } + + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + + if (clipflags != BMODEL_FULLY_CLIPPED) + { + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + // FIXME: is this needed? + VectorCopy (modelorg, r_worldmodelorg); + + r_pcurrentvertbase = clmodel->vertexes; + + // FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); + } + } + + // if the driver wants polygons, deliver those. Z-buffering is on + // at this point, so no clipping to the world tree is needed, just + // frustum clipping + if (r_drawpolys | r_drawculledpolys) + { + R_ZDrawSubmodelPolys (clmodel); + } + else + { + r_pefragtopnode = NULL; + + for (j=0 ; j<3 ; j++) + { + r_emins[j] = minmaxs[j]; + r_emaxs[j] = minmaxs[3+j]; + } + + R_SplitEntityOnNode2 (cl.worldmodel->nodes); + + if (r_pefragtopnode) + { + currententity->topnode = r_pefragtopnode; + + if (r_pefragtopnode->contents >= 0) + { + // not a leaf; has to be clipped to the world BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (clmodel); + } + else + { + // falls entirely in one leaf, so we just put all the + // edges in the edge list and let 1/z sorting handle + // drawing order + R_DrawSubmodelPolygons (clmodel, clipflags); + } + + currententity->topnode = NULL; + } + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + } + + break; + + default: + break; + } + } + + insubmodel = false; +} + + +/* +================ +R_EdgeDrawing +================ +*/ +void R_EdgeDrawing (void) +{ + edge_t ledges[NUMSTACKEDGES + + ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; + + if (auxedges) + { + r_edges = auxedges; + } + else + { + r_edges = (edge_t *) + (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) + { + surfaces = (surf_t *) + (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + + R_BeginEdgeFrame (); + + if (r_dspeeds.value) + { + rw_time1 = Sys_DoubleTime (); + } + + R_RenderWorld (); + + if (r_drawculledpolys) + R_ScanEdges (); + +// only the world can be drawn back to front with no z reads or compares, just +// z writes, so have the driver turn z compares on now + D_TurnZOn (); + + if (r_dspeeds.value) + { + rw_time2 = Sys_DoubleTime (); + db_time1 = rw_time2; + } + + R_DrawBEntitiesOnList (); + + if (r_dspeeds.value) + { + db_time2 = Sys_DoubleTime (); + se_time1 = db_time2; + } + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (!(r_drawpolys | r_drawculledpolys)) + R_ScanEdges (); +} + + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView_ (void) +{ + byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; + + r_warpbuffer = warpbuffer; + + if (r_timegraph.value || r_speeds.value || r_dspeeds.value) + r_time1 = Sys_DoubleTime (); + + R_SetupFrame (); + +#ifdef PASSAGES +SetVisibilityByPassages (); +#else + R_MarkLeaves (); // done here so we know if we're in water +#endif + +// make FDIV fast. This reduces timing precision after we've been running for a +// while, so we don't do it globally. This also sets chop mode, and we do it +// here so that setup stuff like the refresh area calculations match what's +// done in screen.c + Sys_LowFPPrecision (); + + if (!cl_entities[0].model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + R_EdgeDrawing (); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (r_dspeeds.value) + { + se_time2 = Sys_DoubleTime (); + de_time1 = se_time2; + } + + R_DrawEntitiesOnList (); + + if (r_dspeeds.value) + { + de_time2 = Sys_DoubleTime (); + dv_time1 = de_time2; + } + + R_DrawViewModel (); + + if (r_dspeeds.value) + { + dv_time2 = Sys_DoubleTime (); + dp_time1 = Sys_DoubleTime (); + } + + R_DrawParticles (); + + if (r_dspeeds.value) + dp_time2 = Sys_DoubleTime (); + + if (r_dowarp) + D_WarpScreen (); + + V_SetContentsColor (r_viewleaf->contents); + + if (r_timegraph.value) + R_TimeGraph (); + + if (r_aliasstats.value) + R_PrintAliasStats (); + + if (r_speeds.value) + R_PrintTimes (); + + if (r_dspeeds.value) + R_PrintDSpeeds (); + + if (r_reportsurfout.value && r_outofsurfaces) + Con_Printf ("Short %d surfaces\n", r_outofsurfaces); + + if (r_reportedgeout.value && r_outofedges) + Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); + +// back to high floating-point precision + Sys_HighFPPrecision (); +} + +void R_RenderView (void) +{ + int dummy; + int delta; + + delta = (byte *)&dummy - r_stack_start; + if (delta < -10000 || delta > 10000) + Sys_Error ("R_RenderView: called without enough stack"); + + if ( Hunk_LowMark() & 3 ) + Sys_Error ("Hunk is missaligned"); + + if ( (long)(&dummy) & 3 ) + Sys_Error ("Stack is missaligned"); + + if ( (long)(&r_warpbuffer) & 3 ) + Sys_Error ("Globals are missaligned"); + + R_RenderView_ (); +} + +/* +================ +R_InitTurb +================ +*/ +void R_InitTurb (void) +{ + int i; + + for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++) + { + sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; + intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 + } +} + diff --git a/uquake/sbar.c b/uquake/sbar.c new file mode 100644 index 0000000..6c078d0 --- /dev/null +++ b/uquake/sbar.c @@ -0,0 +1,1273 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Portions Copyright (C) 1999,2000 Nelson Rush. +Copyright (C) 1999,2000 contributors of the QuakeForge project +Please see the file "AUTHORS" for a list of contributors + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sbar.c -- status bar code + +#include "quakedef.h" +#include "client.h" + +int sb_updates; // if >= vid.numpages, no update needed + +#define STAT_MINUS 10 // num frame for '-' stats digit +qpic_t *sb_nums[2][11]; +qpic_t *sb_colon, *sb_slash; +qpic_t *sb_ibar; +qpic_t *sb_sbar; +qpic_t *sb_scorebar; + +qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes +qpic_t *sb_ammo[4]; +qpic_t *sb_sigil[4]; +qpic_t *sb_armor[3]; +qpic_t *sb_items[32]; + +qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive + // 0 is static, 1 is temporary animation +qpic_t *sb_face_invis; +qpic_t *sb_face_quad; +qpic_t *sb_face_invuln; +qpic_t *sb_face_invis_invuln; + +qboolean sb_showscores; + +int sb_lines; // scan lines to draw + +qpic_t *rsb_invbar[2]; +qpic_t *rsb_weapons[5]; +qpic_t *rsb_items[2]; +qpic_t *rsb_ammo[3]; +qpic_t *rsb_teambord; // PGM 01/19/97 - team color border + +//MED 01/04/97 added two more weapons + 3 alternates for grenade launcher +qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes +//MED 01/04/97 added array to simplify weapon parsing +int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT}; +//MED 01/04/97 added hipnotic items array +qpic_t *hsb_items[2]; + +void Sbar_DeathmatchOverlay (void); +void Sbar_MiniDeathmatchOverlay (void); + +/* + Sbar_Items + + Return a target-independant items list +*/ +int +Sbar_Items ( void ) +{ + return cl.items; +} +/* +=============== +Sbar_ShowScores + +Tab key down +=============== +*/ +void Sbar_ShowScores (void) +{ + if (sb_showscores) + return; + + sb_showscores = true; + sb_updates = 0; +} + +/* +=============== +Sbar_DontShowScores + +Tab key up +=============== +*/ +void Sbar_DontShowScores (void) +{ + sb_showscores = false; + sb_updates = 0; +} + +/* +=============== +Sbar_Changed +=============== +*/ +void Sbar_Changed (void) +{ + sb_updates = 0; // update next frame +} + +/* +=============== +Sbar_Init +=============== +*/ +void Sbar_Init (void) +{ + int i; + + for (i=0 ; i<10 ; i++) + { + sb_nums[0][i] = Draw_PicFromWad (va("num_%i",i)); + sb_nums[1][i] = Draw_PicFromWad (va("anum_%i",i)); + } + + sb_nums[0][10] = Draw_PicFromWad ("num_minus"); + sb_nums[1][10] = Draw_PicFromWad ("anum_minus"); + + sb_colon = Draw_PicFromWad ("num_colon"); + sb_slash = Draw_PicFromWad ("num_slash"); + + sb_weapons[0][0] = Draw_PicFromWad ("inv_shotgun"); + sb_weapons[0][1] = Draw_PicFromWad ("inv_sshotgun"); + sb_weapons[0][2] = Draw_PicFromWad ("inv_nailgun"); + sb_weapons[0][3] = Draw_PicFromWad ("inv_snailgun"); + sb_weapons[0][4] = Draw_PicFromWad ("inv_rlaunch"); + sb_weapons[0][5] = Draw_PicFromWad ("inv_srlaunch"); + sb_weapons[0][6] = Draw_PicFromWad ("inv_lightng"); + + sb_weapons[1][0] = Draw_PicFromWad ("inv2_shotgun"); + sb_weapons[1][1] = Draw_PicFromWad ("inv2_sshotgun"); + sb_weapons[1][2] = Draw_PicFromWad ("inv2_nailgun"); + sb_weapons[1][3] = Draw_PicFromWad ("inv2_snailgun"); + sb_weapons[1][4] = Draw_PicFromWad ("inv2_rlaunch"); + sb_weapons[1][5] = Draw_PicFromWad ("inv2_srlaunch"); + sb_weapons[1][6] = Draw_PicFromWad ("inv2_lightng"); + + for (i=0 ; i<5 ; i++) + { + sb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_shotgun",i+1)); + sb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_sshotgun",i+1)); + sb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_nailgun",i+1)); + sb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_snailgun",i+1)); + sb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_rlaunch",i+1)); + sb_weapons[2+i][5] = Draw_PicFromWad (va("inva%i_srlaunch",i+1)); + sb_weapons[2+i][6] = Draw_PicFromWad (va("inva%i_lightng",i+1)); + } + + sb_ammo[0] = Draw_PicFromWad ("sb_shells"); + sb_ammo[1] = Draw_PicFromWad ("sb_nails"); + sb_ammo[2] = Draw_PicFromWad ("sb_rocket"); + sb_ammo[3] = Draw_PicFromWad ("sb_cells"); + + sb_armor[0] = Draw_PicFromWad ("sb_armor1"); + sb_armor[1] = Draw_PicFromWad ("sb_armor2"); + sb_armor[2] = Draw_PicFromWad ("sb_armor3"); + + sb_items[0] = Draw_PicFromWad ("sb_key1"); + sb_items[1] = Draw_PicFromWad ("sb_key2"); + sb_items[2] = Draw_PicFromWad ("sb_invis"); + sb_items[3] = Draw_PicFromWad ("sb_invuln"); + sb_items[4] = Draw_PicFromWad ("sb_suit"); + sb_items[5] = Draw_PicFromWad ("sb_quad"); + + sb_sigil[0] = Draw_PicFromWad ("sb_sigil1"); + sb_sigil[1] = Draw_PicFromWad ("sb_sigil2"); + sb_sigil[2] = Draw_PicFromWad ("sb_sigil3"); + sb_sigil[3] = Draw_PicFromWad ("sb_sigil4"); + + sb_faces[4][0] = Draw_PicFromWad ("face1"); + sb_faces[4][1] = Draw_PicFromWad ("face_p1"); + sb_faces[3][0] = Draw_PicFromWad ("face2"); + sb_faces[3][1] = Draw_PicFromWad ("face_p2"); + sb_faces[2][0] = Draw_PicFromWad ("face3"); + sb_faces[2][1] = Draw_PicFromWad ("face_p3"); + sb_faces[1][0] = Draw_PicFromWad ("face4"); + sb_faces[1][1] = Draw_PicFromWad ("face_p4"); + sb_faces[0][0] = Draw_PicFromWad ("face5"); + sb_faces[0][1] = Draw_PicFromWad ("face_p5"); + + sb_face_invis = Draw_PicFromWad ("face_invis"); + sb_face_invuln = Draw_PicFromWad ("face_invul2"); + sb_face_invis_invuln = Draw_PicFromWad ("face_inv2"); + sb_face_quad = Draw_PicFromWad ("face_quad"); + + Cmd_AddCommand ("+showscores", Sbar_ShowScores); + Cmd_AddCommand ("-showscores", Sbar_DontShowScores); + + sb_sbar = Draw_PicFromWad ("sbar"); + sb_ibar = Draw_PicFromWad ("ibar"); + sb_scorebar = Draw_PicFromWad ("scorebar"); + + if (hipnotic) //MED 01/04/97 added new hipnotic weapons + { + hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser"); + hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir"); + hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox"); + hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren"); + hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox"); + + hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser"); + hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir"); + hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox"); + hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren"); + hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox"); + + for (i=0 ; i<5 ; i++) + { + hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1)); + hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1)); + hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1)); + hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1)); + hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1)); + } + + hsb_items[0] = Draw_PicFromWad ("sb_wsuit"); + hsb_items[1] = Draw_PicFromWad ("sb_eshld"); + } + + if (rogue) + { + rsb_invbar[0] = Draw_PicFromWad ("r_invbar1"); + rsb_invbar[1] = Draw_PicFromWad ("r_invbar2"); + + rsb_weapons[0] = Draw_PicFromWad ("r_lava"); + rsb_weapons[1] = Draw_PicFromWad ("r_superlava"); + rsb_weapons[2] = Draw_PicFromWad ("r_gren"); + rsb_weapons[3] = Draw_PicFromWad ("r_multirock"); + rsb_weapons[4] = Draw_PicFromWad ("r_plasma"); + + rsb_items[0] = Draw_PicFromWad ("r_shield1"); + rsb_items[1] = Draw_PicFromWad ("r_agrav1"); + +// PGM 01/19/97 - team color border + rsb_teambord = Draw_PicFromWad ("r_teambord"); +// PGM 01/19/97 - team color border + + rsb_ammo[0] = Draw_PicFromWad ("r_ammolava"); + rsb_ammo[1] = Draw_PicFromWad ("r_ammomulti"); + rsb_ammo[2] = Draw_PicFromWad ("r_ammoplasma"); + } +} + + +//============================================================================= + +// drawing routines are reletive to the status bar location + +/* +============= +Sbar_DrawPic +============= +*/ +void Sbar_DrawPic (int x, int y, qpic_t *pic) +{ + if ((!hipnotic && !rogue) + && (!cl_sbar.value || cl.gametype == GAME_DEATHMATCH)) + Draw_Pic (x, y + (vid.height-SBAR_HEIGHT), pic); + else + Draw_Pic (x + ((vid.width - 320)>>1), + y + (vid.height-SBAR_HEIGHT), pic); +} + +/* +============= +Sbar_DrawSubPic +============= +JACK: Draws a portion of the picture in the status bar. +*/ +void Sbar_DrawSubPic(int x, int y, qpic_t *pic, + int srcx, int srcy, int width, int height) +{ + if ((!hipnotic && !rogue) + && (!cl_sbar.value || cl.gametype == GAME_DEATHMATCH)) + Draw_SubPic (x, y + (vid.height-SBAR_HEIGHT), + pic, srcx, srcy, width, height); + else + Draw_SubPic (x + ((vid.width - 320)>>1), + y + (vid.height-SBAR_HEIGHT), + pic, srcx, srcy, width, height); +} + + +/* +============= +Sbar_DrawTransPic +============= +*/ +void Sbar_DrawTransPic (int x, int y, qpic_t *pic) +{ + if ((!hipnotic && !rogue) + && (!cl_sbar.value || cl.gametype == GAME_DEATHMATCH)) + Draw_TransPic (x, y + (vid.height-SBAR_HEIGHT), pic); + else + Draw_TransPic (x + ((vid.width - 320)>>1), + y + (vid.height-SBAR_HEIGHT), pic); +} + +/* +================ +Sbar_DrawCharacter + +Draws one solid graphics character +================ +*/ +void Sbar_DrawCharacter (int x, int y, int num) +{ + if ((!hipnotic && !rogue) + && (!cl_sbar.value || cl.gametype == GAME_DEATHMATCH)) + Draw_Character (x + 4, y + (vid.height-SBAR_HEIGHT), num); + else + Draw_Character (x + ((vid.width - 320)>>1) + 4, + y + (vid.height-SBAR_HEIGHT), num); +} + +/* +================ +Sbar_DrawString +================ +*/ +void Sbar_DrawString (int x, int y, char *str) +{ + if ((!hipnotic && !rogue) + && (!cl_sbar.value || cl.gametype == GAME_DEATHMATCH)) + Draw_String (x, y + (vid.height-SBAR_HEIGHT), str); + else + Draw_String (x + ((vid.width - 320)>>1), + y + (vid.height-SBAR_HEIGHT), str); +} + +/* +============= +Sbar_itoa +============= +*/ +int Sbar_itoa (int num, char *buf) +{ + char *str; + int pow10; + int dig; + + str = buf; + + if (num < 0) + { + *str++ = '-'; + num = -num; + } + + for (pow10 = 10 ; num >= pow10 ; pow10 *= 10); + + do { + pow10 /= 10; + dig = num/pow10; + *str++ = '0'+dig; + num -= dig*pow10; + } while (pow10 != 1); + + *str = 0; + + return (str - buf); +} + + +/* +============= +Sbar_DrawNum +============= +*/ +void Sbar_DrawNum (int x, int y, int num, int digits, int color) +{ + char str[12]; + char *ptr; + int l, frame; + + l = Sbar_itoa (num, str); + ptr = str; + if (l > digits) + ptr += (l-digits); + if (l < digits) + x += (digits-l)*24; + + while (*ptr) + { + if (*ptr == '-') + frame = STAT_MINUS; + else + frame = *ptr -'0'; + + Sbar_DrawTransPic (x,y,sb_nums[color][frame]); + x += 24; + ptr++; + } +} + +//============================================================================= + +int fragsort[MAX_SCOREBOARD]; + +char scoreboardtext[MAX_SCOREBOARD][20]; +int scoreboardtop[MAX_SCOREBOARD]; +int scoreboardbottom[MAX_SCOREBOARD]; +int scoreboardcount[MAX_SCOREBOARD]; +int scoreboardlines; + +/* +=============== +Sbar_SortFrags +=============== +*/ +void Sbar_SortFrags (void) +{ + int i, j, k; + +// sort by frags + scoreboardlines = 0; + for (i=0 ; i= RIT_LAVA_NAILGUN ) + Sbar_DrawPic (0, -24, rsb_invbar[0]); + else + Sbar_DrawPic (0, -24, rsb_invbar[1]); + } else + if (!headsup) + Sbar_DrawPic (0, -24, sb_ibar); +// weapons + for (i=0 ; i<7 ; i++) + { + if (Sbar_Items() & (IT_SHOTGUN << i) ) { + time = cl.item_gettime[i]; + flashon = (int)((cl.time - time)*10); + if (flashon < 0) + flashon = 0; + if (flashon >= 10) { + if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<200) + Sbar_DrawSubPic ((hudswap) ? 0 : (vid.width-24),-68-(7-i)*16 , sb_weapons[flashon][i],0,0,24,16); + + } else + Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]); + + if (flashon > 1) + sb_updates = 0; // force update to remove flash + } + } + + // hipnotic weapons + if (hipnotic) { + + int grenadeflashing=0; + + for (i=0 ; i<4 ; i++) { + if (Sbar_Items() & (1<= 10) { + if ( cl.stats[STAT_ACTIVEWEAPON] == (1< 1) + sb_updates = 0; // force update to remove flash + } + } + } + + if (rogue) { + // check for powered up weapon. + if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) { + for (i=0;i<5;i++) { + if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) { + Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]); + } + } + } + } +// ammo counts + for (i=0 ; i<4 ; i++) + { + snprintf(num, sizeof(num), "%3i",cl.stats[STAT_SHELLS+i] ); + if (headsup) { + Sbar_DrawSubPic((hudswap) ? 0 : (vid.width-42), -24 - (4-i)*11, sb_ibar, 3+(i*48), 0, 42, 11); + if (num[0] != ' ') + Sbar_DrawCharacter ( (hudswap) ? 3 : (vid.width-39), -24 - (4-i)*11, 18 + num[0] - '0'); + if (num[1] != ' ') + Sbar_DrawCharacter ( (hudswap) ? 11 : (vid.width-31), -24 - (4-i)*11, 18 + num[1] - '0'); + if (num[2] != ' ') + Sbar_DrawCharacter ( (hudswap) ? 19 : (vid.width-23), -24 - (4-i)*11, 18 + num[2] - '0'); + } else { + if (num[0] != ' ') + Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0'); + if (num[1] != ' ') + Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0'); + if (num[2] != ' ') + Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0'); + } + } + + flashon = 0; + + // items + for (i=0 ; i<6 ; i++) + if (Sbar_Items() & (1<<(17+i))) { + time = cl.item_gettime[17+i]; + if (time && time > cl.time - 2 && flashon ) { // flash frame + sb_updates = 0; + } + else { + //MED 01/04/97 changed keys + if (!hipnotic || (i>1)) { + Sbar_DrawPic (192 + i*16, -16, sb_items[i]); + } + } + if (time && time > cl.time - 2) + sb_updates = 0; + } + // hipnotic items + if (hipnotic) { + for (i=0 ; i<2 ; i++) { + if (Sbar_Items() & (1<<(24+i))) { + time = cl.item_gettime[24+i]; + if (time && time > cl.time - 2 && flashon ) { // flash frame + sb_updates = 0; + } else { + Sbar_DrawPic (288 + i*16, -16, hsb_items[i]); + } + + if (time && time > cl.time - 2) + sb_updates = 0; + } + } + } + + if (rogue) { + // new rogue items + for (i=0 ; i<2 ; i++) { + if (Sbar_Items() & (1<<(29+i))) { + time = cl.item_gettime[29+i]; + + if (time && time > cl.time - 2 && flashon ) { // flash frame + sb_updates = 0; + } else { + Sbar_DrawPic (288 + i*16, -16, rsb_items[i]); + } + + if (time && time > cl.time - 2) + sb_updates = 0; + } + } + } else { + // sigils + for (i=0 ; i<4 ; i++) { + if (Sbar_Items() & (1<<(28+i))) { + time = cl.item_gettime[28+i]; + if (time && time > cl.time - 2 && flashon ) { // flash frame + sb_updates = 0; + } else + Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]); + if (time && time > cl.time - 2) + sb_updates = 0; + } + } + } +} + +//============================================================================= + +/* +=============== +Sbar_DrawFrags +=============== +*/ +void Sbar_DrawFrags (void) +{ + int i, k, l; + int top, bottom; + int x, y, f; + char num[12]; + int xofs; + scoreboard_t *s; + + Sbar_SortFrags (); + +// draw the text + l = scoreboardlines <= 4 ? scoreboardlines : 4; + + x = 23; + if (cl.gametype == GAME_DEATHMATCH) + xofs = 0; + else + xofs = (vid.width - 320)>>1; + y = vid.height - SBAR_HEIGHT - 23; + + for (i=0 ; i < l ; i++) + { + k = fragsort[i]; + s = &cl.scores[k]; + if (!s->name[0]) + continue; + + // draw background + top = s->colors & 0xf0; + bottom = (s->colors & 15)<<4; + top = Sbar_ColorForMap (top); + bottom = Sbar_ColorForMap (bottom); + + Draw_Fill (xofs + x * 8 + 10, y, 28, 4, top); + Draw_Fill (xofs + x * 8 + 10, y + 4, 28, 3, bottom); + + // draw number + f = s->frags; + snprintf(num, sizeof(num), "%3i", f); + + Sbar_DrawCharacter ( (x + 1) * 8 , -24, num[0]); + Sbar_DrawCharacter ( (x + 2) * 8 , -24, num[1]); + Sbar_DrawCharacter ( (x + 3) * 8 , -24, num[2]); + + if (k == cl.viewentity - 1) { + Sbar_DrawCharacter ( x * 8 + 2, -24, 16); + Sbar_DrawCharacter ( (x + 4) * 8 -4, -24, 17); + } + x += 4; + } +} + +//============================================================================= + + +/* +=============== +Sbar_DrawFace +=============== +*/ +void Sbar_DrawFace (void) +{ + int f, anim; + + // PGM 01/19/97 - team color drawing + // PGM 03/02/97 - fixed so color swatch only appears in CTF modes + if (rogue && + (cl.maxclients != 1) && + (teamplay.value>3) && + (teamplay.value<7)) { + int top, bottom; + int xofs; + char num[12]; + scoreboard_t *s; + + s = &cl.scores[cl.viewentity - 1]; + // draw background + top = s->colors & 0xf0; + bottom = (s->colors & 15)<<4; + top = Sbar_ColorForMap (top); + bottom = Sbar_ColorForMap (bottom); + + if (cl.gametype == GAME_DEATHMATCH) + xofs = 113; + else + xofs = ((vid.width - 320)>>1) + 113; + + Sbar_DrawPic (112, 0, rsb_teambord); + Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top); + Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom); + + // draw number + f = s->frags; + snprintf(num, sizeof(num), "%3i",f); + + if (top==8) + { + if (num[0] != ' ') + Sbar_DrawCharacter(109, 3, 18 + num[0] - '0'); + if (num[1] != ' ') + Sbar_DrawCharacter(116, 3, 18 + num[1] - '0'); + if (num[2] != ' ') + Sbar_DrawCharacter(123, 3, 18 + num[2] - '0'); + } + else + { + Sbar_DrawCharacter ( 109, 3, num[0]); + Sbar_DrawCharacter ( 116, 3, num[1]); + Sbar_DrawCharacter ( 123, 3, num[2]); + } + + return; + } + // PGM 01/19/97 - team color drawing + + if ( (Sbar_Items() & (IT_INVISIBILITY | IT_INVULNERABILITY) ) + == (IT_INVISIBILITY | IT_INVULNERABILITY) ) { + Sbar_DrawPic (112, 0, sb_face_invis_invuln); + return; + } + if (Sbar_Items() & IT_QUAD) { + Sbar_DrawPic (112, 0, sb_face_quad ); + return; + } + if (Sbar_Items() & IT_INVISIBILITY) { + Sbar_DrawPic (112, 0, sb_face_invis ); + return; + } + if (Sbar_Items() & IT_INVULNERABILITY) { + Sbar_DrawPic (112, 0, sb_face_invuln); + return; + } + + if (cl.stats[STAT_HEALTH] >= 100) + f = 4; + else + f = cl.stats[STAT_HEALTH] / 20; + + if (cl.time <= cl.faceanimtime) + { + anim = 1; + sb_updates = 0; // make sure the anim gets drawn over + } + else + anim = 0; + Sbar_DrawPic (112, 0, sb_faces[f][anim]); +} + +/* +============= +Sbar_DrawNormal +============= +*/ +void Sbar_DrawNormal (void) +{ + if (cl_sbar.value || scr_viewsize.value<100) + Sbar_DrawPic (0, 0, sb_sbar); + + if (hipnotic) { + if (Sbar_Items() & IT_KEY1) + Sbar_DrawPic (209, 3, sb_items[0]); + if (Sbar_Items() & IT_KEY2) + Sbar_DrawPic (209, 12, sb_items[1]); + } + + // armor + if (Sbar_Items() & IT_INVULNERABILITY) { + Sbar_DrawNum (24, 0, 666, 3, 1); + Sbar_DrawPic (0, 0, draw_disc); + } else { + if (rogue) { + Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, + cl.stats[STAT_ARMOR] <= 25); + if (Sbar_Items() & RIT_ARMOR3) + Sbar_DrawPic (0, 0, sb_armor[2]); + else if (Sbar_Items() & RIT_ARMOR2) + Sbar_DrawPic (0, 0, sb_armor[1]); + else if (Sbar_Items() & RIT_ARMOR1) + Sbar_DrawPic (0, 0, sb_armor[0]); + } else { + Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3 + , cl.stats[STAT_ARMOR] <= 25); + if (Sbar_Items() & IT_ARMOR3) + Sbar_DrawPic (0, 0, sb_armor[2]); + else if (Sbar_Items() & IT_ARMOR2) + Sbar_DrawPic (0, 0, sb_armor[1]); + else if (Sbar_Items() & IT_ARMOR1) + Sbar_DrawPic (0, 0, sb_armor[0]); + } + } + + // face + Sbar_DrawFace (); + + // health + Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3 + , cl.stats[STAT_HEALTH] <= 25); + +// ammo icon + if (rogue) { + if (Sbar_Items() & RIT_SHELLS) + Sbar_DrawPic (224, 0, sb_ammo[0]); + else if (Sbar_Items() & RIT_NAILS) + Sbar_DrawPic (224, 0, sb_ammo[1]); + else if (Sbar_Items() & RIT_ROCKETS) + Sbar_DrawPic (224, 0, sb_ammo[2]); + else if (Sbar_Items() & RIT_CELLS) + Sbar_DrawPic (224, 0, sb_ammo[3]); + else if (Sbar_Items() & RIT_LAVA_NAILS) + Sbar_DrawPic (224, 0, rsb_ammo[0]); + else if (Sbar_Items() & RIT_PLASMA_AMMO) + Sbar_DrawPic (224, 0, rsb_ammo[1]); + else if (Sbar_Items() & RIT_MULTI_ROCKETS) + Sbar_DrawPic (224, 0, rsb_ammo[2]); + } else { + if (Sbar_Items() & IT_SHELLS) + Sbar_DrawPic (224, 0, sb_ammo[0]); + else if (Sbar_Items() & IT_NAILS) + Sbar_DrawPic (224, 0, sb_ammo[1]); + else if (Sbar_Items() & IT_ROCKETS) + Sbar_DrawPic (224, 0, sb_ammo[2]); + else if (Sbar_Items() & IT_CELLS) + Sbar_DrawPic (224, 0, sb_ammo[3]); + } + Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3 + , cl.stats[STAT_AMMO] <= 10); +} + +/* +=============== +Sbar_Draw +=============== +*/ +void Sbar_Draw (void) +{ + qboolean headsup; + char st[512]; + + headsup = !(cl_sbar.value || scr_viewsize.value<100); + + if (rogue || hipnotic) + headsup = false; + + if ((sb_updates >= vid.numpages) && !headsup) + return; + + if (scr_con_current == vid.height) + return; // console is full screen + + if (!headsup && sb_lines && vid.width > 320) + Draw_TileClear (0, vid.height - sb_lines, vid.width, sb_lines); + + + if (sb_lines > 24) + { + Sbar_DrawInventory (); + if (cl.maxclients != 1) + Sbar_DrawFrags (); + } + + scr_copyeverything = 1; + + sb_updates++; + + // top line + if (sb_lines > 24) { + Sbar_DrawInventory (); + if (!headsup || vid.width<512) + if (cl.maxclients != 1) + Sbar_DrawFrags (); + } + + // main area + if (sb_lines > 0) { + Sbar_DrawNormal (); + } + + if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + Sbar_DrawPic (0, 0, sb_scorebar); + Sbar_DrawScoreboard (); + sb_updates = 0; + } +} + +//============================================================================= + +/* +================== +Sbar_IntermissionNumber + +================== +*/ +void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color) +{ + char str[12]; + char *ptr; + int l, frame; + + l = Sbar_itoa (num, str); + ptr = str; + if (l > digits) + ptr += (l-digits); + if (l < digits) + x += (digits-l) * 24; + + while (*ptr) { + if (*ptr == '-') + frame = STAT_MINUS; + else + frame = *ptr -'0'; + + Draw_TransPic (x, y, sb_nums[color][frame]); + x += 24; + ptr++; + } +} + +/* +================== +Sbar_DeathmatchOverlay + +ping time frags name +================== +*/ +void Sbar_DeathmatchOverlay (void) +{ + qpic_t *pic; + int i, k, l; + int top, bottom; + int x, y, f; + char num[12]; + scoreboard_t *s; + + scr_copyeverything = 1; + scr_fullupdate = 0; + + pic = Draw_CachePic ("gfx/ranking.lmp"); + M_DrawPic ((320-pic->width)/2, 8, pic); + +// scores + Sbar_SortFrags (); + +// draw the text + l = scoreboardlines; + + x = 80 + ((vid.width - 320)>>1); + y = 40; + for (i=0 ; iname[0]) + continue; + + // draw background + top = s->colors & 0xf0; + bottom = (s->colors & 15)<<4; + top = Sbar_ColorForMap (top); + bottom = Sbar_ColorForMap (bottom); + + Draw_Fill ( x, y, 40, 4, top); + Draw_Fill ( x, y+4, 40, 4, bottom); + + // draw number + f = s->frags; + snprintf(num, sizeof(num), "%3i",f); + + Draw_Character ( x+8 , y, num[0]); + Draw_Character ( x+16 , y, num[1]); + Draw_Character ( x+24 , y, num[2]); + + if (k == cl.viewentity - 1) + Draw_Character ( x - 8, y, 12); + +#if 0 +{ + int total; + int n, minutes, tens, units; + + // draw time + total = cl.completed_time - s->entertime; + minutes = (int)total/60; + n = total - minutes*60; + tens = n/10; + units = n%10; + + snprintf(num, sizeof(num), "%3i:%i%i", minutes, tens, units); + + Draw_String ( x+48 , y, num); +} +#endif + + // draw name + Draw_String (x+64, y, s->name); + + y += 10; + } +} + +/* +================== +Sbar_DeathmatchOverlay + +================== +*/ +void Sbar_MiniDeathmatchOverlay (void) +{ + int i, k, l; + int top, bottom; + int x, y, f; + char num[12]; + scoreboard_t *s; + int numlines; + + if (vid.width < 512 || !sb_lines) + return; + + scr_copyeverything = 1; + scr_fullupdate = 0; + +// scores + Sbar_SortFrags (); + +// draw the text + l = scoreboardlines; + y = vid.height - sb_lines; + numlines = sb_lines/8; + if (numlines < 3) + return; + + //find us + for (i = 0; i < scoreboardlines; i++) + if (fragsort[i] == cl.viewentity - 1) + break; + + if (i == scoreboardlines) // we're not there + i = 0; + else // figure out start + i = i - numlines/2; + + if (i > scoreboardlines - numlines) + i = scoreboardlines - numlines; + if (i < 0) + i = 0; + + x = 324; + for (/* */; i < scoreboardlines && y < vid.height - 8 ; i++) + { + k = fragsort[i]; + s = &cl.scores[k]; + if (!s->name[0]) + continue; + + // draw background + top = s->colors & 0xf0; + bottom = (s->colors & 15)<<4; + top = Sbar_ColorForMap (top); + bottom = Sbar_ColorForMap (bottom); + + Draw_Fill ( x, y+1, 40, 3, top); + Draw_Fill ( x, y+4, 40, 4, bottom); + + // draw number + f = s->frags; + snprintf(num, sizeof(num), "%3i",f); + + Draw_Character ( x+8 , y, num[0]); + Draw_Character ( x+16 , y, num[1]); + Draw_Character ( x+24 , y, num[2]); + + if (k == cl.viewentity - 1) { + Draw_Character ( x, y, 16); + Draw_Character ( x + 32, y, 17); + } + +#if 0 +{ + int total; + int n, minutes, tens, units; + + // draw time + total = cl.completed_time - s->entertime; + minutes = (int)total/60; + n = total - minutes*60; + tens = n/10; + units = n%10; + + snprintf(num, sizeof(num), "%3i:%i%i", minutes, tens, units); + + Draw_String ( x+48 , y, num); +} +#endif + + // draw name + Draw_String (x+48, y, s->name); + + y += 8; + } +} + +/* +================== +Sbar_IntermissionOverlay + +================== +*/ +void Sbar_IntermissionOverlay (void) +{ + qpic_t *pic; + int dig; + int num; + + scr_copyeverything = 1; + scr_fullupdate = 0; + + if (cl.gametype == GAME_DEATHMATCH) { + Sbar_DeathmatchOverlay (); + return; + } + + pic = Draw_CachePic ("gfx/complete.lmp"); + Draw_Pic (64, 24, pic); + + pic = Draw_CachePic ("gfx/inter.lmp"); + Draw_TransPic (0, 56, pic); + + // time + dig = cl.completed_time/60; + Sbar_IntermissionNumber (160, 64, dig, 3, 0); + num = cl.completed_time - dig*60; + Draw_TransPic (234,64,sb_colon); + Draw_TransPic (246,64,sb_nums[0][num/10]); + Draw_TransPic (266,64,sb_nums[0][num%10]); + + Sbar_IntermissionNumber (160, 104, cl.stats[STAT_SECRETS], 3, 0); + Draw_TransPic (232,104,sb_slash); + Sbar_IntermissionNumber (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0); + + Sbar_IntermissionNumber (160, 144, cl.stats[STAT_MONSTERS], 3, 0); + Draw_TransPic (232,144,sb_slash); + Sbar_IntermissionNumber (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0); +} + + +/* +================== +Sbar_FinaleOverlay + +================== +*/ +void Sbar_FinaleOverlay (void) +{ + qpic_t *pic; + + scr_copyeverything = 1; + + pic = Draw_CachePic ("gfx/finale.lmp"); + Draw_TransPic ( (vid.width-pic->width)/2, 16, pic); +} + diff --git a/uquake/screen.c b/uquake/screen.c index 29831bc..f7e1a79 100644 --- a/uquake/screen.c +++ b/uquake/screen.c @@ -1,6 +1,8 @@ /* Copyright (C) 1996-1997 Id Software, Inc. Portions Copyright (C) 1999,2000 Nelson Rush. +Copyright (C) 1999,2000 contributors of the QuakeForge project +Please see the file "AUTHORS" for a list of contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,6 +25,56 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "r_local.h" +#include + +/* + +background clear +rendering +turtle/net/ram icons +sbar +centerprint / slow centerprint +notify lines +intermission / finale overlay +loading plaque +console +menu + +required background clears +required update regions + + +syncronous draw mode or async +One off screen buffer, with updates either copied or xblited +Need to double buffer? + + +async draw will require the refresh area to be cleared, because it will be +xblited, but sync draw can just ignore it. + +sync +draw + +CenterPrint () +SlowPrint () +Screen_Update (); +Con_Printf (); + +net +turn off messages option + +the refresh is allways rendered, unless the console is full screen + + +console is: + notify lines + half + full + + +*/ + + // only the refresh window will be updated unless these variables are flagged int scr_copytop; int scr_copyeverything; @@ -31,6 +83,7 @@ float scr_con_current; float scr_conlines; // lines of console to display float oldscreensize, oldfov; +float oldsbar; cvar_t scr_viewsize = {"viewsize","100", true}; cvar_t scr_fov = {"fov","90"}; // 10 - 170 cvar_t scr_conspeed = {"scr_conspeed","300"}; @@ -51,6 +104,8 @@ int scr_fullupdate; int clearconsole; int clearnotify; +int sb_lines; + viddef_t vid; // global video state vrect_t *pconupdate; @@ -59,6 +114,7 @@ vrect_t scr_vrect; qboolean scr_disabled_for_loading; qboolean scr_drawloading; float scr_disabled_time; + qboolean scr_skipupdate; qboolean block_drawing; @@ -120,7 +176,7 @@ void SCR_EraseCenterString (void) y = 48; scr_copytop = 1; - Draw_TileClear (0, y,vid.width, 8*scr_erase_lines); + Draw_TileClear (0, y, vid.width, min(8*scr_erase_lines, vid.height - y - 1)); } void SCR_DrawCenterString (void) @@ -287,8 +343,10 @@ Keybinding command */ void SCR_SizeUp_f (void) { + if (scr_viewsize.value < 120) { Cvar_SetValue ("viewsize",scr_viewsize.value+10); vid.recalc_refdef = 1; + } } @@ -330,9 +388,9 @@ void SCR_Init (void) Cmd_AddCommand ("sizeup",SCR_SizeUp_f); Cmd_AddCommand ("sizedown",SCR_SizeDown_f); - scr_ram = Draw_PicFromWad ("ram"); - scr_net = Draw_PicFromWad ("net"); - scr_turtle = Draw_PicFromWad ("turtle"); + scr_ram = W_GetLumpName ("ram"); + scr_net = W_GetLumpName ("net"); + scr_turtle = W_GetLumpName ("turtle"); scr_initialized = true; } @@ -403,10 +461,9 @@ Backported by Jules Bean from quakeworld client =============== */ - void SCR_DrawFPS (void) { - extern cvar_t show_fps; + extern cvar_t show_fps; static double lastframetime; double t; extern int fps_count; @@ -414,8 +471,8 @@ void SCR_DrawFPS (void) int x, y; char st[80]; - if (!show_fps.value) - return; + if (!show_fps.value) + return; t = Sys_DoubleTime(); if ((t - lastframetime) >= 1.0) { @@ -452,7 +509,6 @@ void SCR_DrawPause (void) } - /* ============== SCR_DrawLoading @@ -470,8 +526,6 @@ void SCR_DrawLoading (void) (vid.height - 48 - pic->height)/2, pic); } - - //============================================================================= @@ -486,7 +540,7 @@ void SCR_SetUpToDrawConsole (void) if (scr_drawloading) return; // never a console with loading plaque - + // decide on the height of the console con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; @@ -557,7 +611,6 @@ void SCR_DrawConsole (void) ============================================================================== */ - typedef struct { @@ -582,7 +635,7 @@ WritePCXfile ============== */ void WritePCXfile (char *filename, byte *data, int width, int height, - int rowbytes, byte *palette) + int rowbytes, byte *palette) { int i, j, length; pcx_t *pcx; @@ -668,10 +721,10 @@ void SCR_ScreenShot_f (void) } if (i==100) { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); return; - } - + } + // // save the pcx file // @@ -687,10 +740,8 @@ void SCR_ScreenShot_f (void) Con_Printf ("Wrote %s\n", pcxname); } - //============================================================================= - /* =============== SCR_BeginLoadingPlaque @@ -734,9 +785,6 @@ void SCR_EndLoadingPlaque (void) scr_fullupdate = 0; Con_ClearNotify (); } - -//============================================================================= - char *scr_notifystring; qboolean scr_drawdialog; @@ -772,6 +820,8 @@ void SCR_DrawNotifyString (void) } while (1); } +//============================================================================= + /* ================== SCR_ModalMessage @@ -845,9 +895,9 @@ needs almost the entire 256k of stack space! void SCR_UpdateScreen (void) { static float oldscr_viewsize; - static float oldlcd_x; + static float oldlcd_x; vrect_t vrect; - + if (scr_skipupdate || block_drawing) return; @@ -862,11 +912,20 @@ void SCR_UpdateScreen (void) Con_Printf ("load failed.\n"); } else - return; + return; } +#ifdef _WIN32 + { // don't suck up any cpu if minimized + extern int Minimized; + + if (Minimized) + return; + } +#endif + if (cls.state == ca_dedicated) - return; // stdout only + return; if (!scr_initialized || !con_initialized) return; // not initialized yet @@ -897,10 +956,16 @@ void SCR_UpdateScreen (void) oldscreensize = scr_viewsize.value; vid.recalc_refdef = true; } + + if (oldsbar != cl_sbar.value) + { + oldsbar = cl_sbar.value; + vid.recalc_refdef = true; + } if (vid.recalc_refdef) { - // something changed, so reorder the screen + // something changed, so reorder the screen SCR_CalcRefdef (); } @@ -921,14 +986,12 @@ void SCR_UpdateScreen (void) SCR_SetUpToDrawConsole (); SCR_EraseCenterString (); - + D_DisableBackBufferAccess (); // for adapters that can't stay mapped in // for linear writes all the time VID_LockBuffer (); - V_RenderView (); - VID_UnlockBuffer (); D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly @@ -967,10 +1030,11 @@ void SCR_UpdateScreen (void) SCR_DrawFPS (); SCR_CheckDrawCenterString (); Sbar_Draw (); - SCR_DrawConsole (); + SCR_DrawConsole (); M_Draw (); } + D_DisableBackBufferAccess (); // for adapters that can't stay mapped in // for linear writes all the time if (pconupdate) @@ -983,7 +1047,6 @@ void SCR_UpdateScreen (void) // // update one of three areas // - if (scr_copyeverything) { vrect.x = 0; @@ -1013,10 +1076,9 @@ void SCR_UpdateScreen (void) vrect.pnext = 0; VID_Update (&vrect); - } + } } - /* ================== SCR_UpdateWholeScreen