From ba0c93d814e782b7365b6bb1119c6b66c0699f52 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Wed, 19 Mar 2014 23:10:37 +0000 Subject: [PATCH 01/19] MD2 & Patch drawing fixes MD2's can be translucent again. MD2's can use sprites instead of another random texture if they have no texture. Patches are drawn in the correct place on non aspect correct resolutions. Cropped Patches are drawn. --- src/doomdef.h | 2 +- src/hardware/hw_draw.c | 70 ++++++++++++++++++++++++++++++++++++++++++ src/hardware/hw_main.c | 39 ++++++----------------- src/hardware/hw_main.h | 1 + src/hardware/hw_md2.c | 40 +++++++++--------------- src/screen.c | 4 +-- src/v_video.c | 3 +- 7 files changed, 100 insertions(+), 59 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 3649db08..d4ad4a68 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -469,7 +469,7 @@ extern const char *compdate, *comptime, *comprevision; #if !defined (_NDS) && !defined (_PSP) /// Shuffle's incomplete OpenGL sorting code. -//#define SHUFFLE +#define SHUFFLE // This has nothing to do with sorting, why was it disabled? #endif #if !defined (_NDS) && !defined (_PSP) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 6dc0f0f7..43d4537f 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -209,6 +209,76 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, HWD.pfnDrawPolygon(NULL, v, 4, flags); } +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +{ + FOutVector v[4]; + FBITFIELD flags; + + float cx = FIXED_TO_FLOAT(x); + float cy = FIXED_TO_FLOAT(y); + +// 3--2 +// | /| +// |/ | +// 0--1 + float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; + float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; + float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(scale); + float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(scale); + + // make patch ready in hardware cache + HWR_GetPatch(gpatch); + + switch (option & V_SCALEPATCHMASK) + { + case V_NOSCALEPATCH: + pdupx = pdupy = 2.0f; + break; + case V_SMALLSCALEPATCH: + pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); + pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + break; + case V_MEDSCALEPATCH: + pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); + pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + break; + } + + if (option & V_NOSCALESTART) + sdupx = sdupy = 2.0f; + + v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; + v[2].x = v[1].x = ((cx-sx)*sdupx+(w-gpatch->leftoffset)*pdupx)/vid.width - 1; + v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height; + v[2].y = v[3].y = 1-((cy-sy)*sdupy+(h-gpatch->topoffset)*pdupy)/vid.height; + + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].sow = v[3].sow = ((float)sx/(float)gpatch->height); + v[2].sow = v[1].sow = gpatch->max_s*((float)w/(float)gpatch->width); + v[0].tow = v[1].tow = ((float)sy/(float)gpatch->height); + v[2].tow = v[3].tow = gpatch->max_t*((float)h/(float)gpatch->height); + + flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + + if (option & V_WRAPX) + flags |= PF_ForceWrapX; + if (option & V_WRAPY) + flags |= PF_ForceWrapY; + + // clip it since it is used for bunny scroll in doom I + if (option & V_TRANSLUCENT) + { + FSurfaceInfo Surf; + Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; + Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; + flags |= PF_Modulated; + HWD.pfnDrawPolygon(&Surf, v, 4, flags); + } + else + HWD.pfnDrawPolygon(NULL, v, 4, flags); +} + void HWR_DrawClippedPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) { // hardware clips the patch quite nicely anyway :) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b2b51773..18a287ee 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1212,23 +1212,17 @@ static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* if (list[i].caster) { - if (sector->lightlist[i].caster->flags & FF_SOLID && !(cutflag & FF_EXTRA)) - solid = true; - else if (sector->lightlist[i].caster->flags & FF_CUTEXTRA && cutflag & FF_EXTRA) + if (sector->lightlist[i].caster->flags & FF_FOG && cutflag & FF_FOG) // Only fog cuts fog { if (sector->lightlist[i].caster->flags & FF_EXTRA) { - if (sector->lightlist[i].caster->flags == cutflag) + if (sector->lightlist[i].caster->flags == cutflag) // only cut by the same solid = true; } else solid = true; } - else - solid = false; } - else - solid = false; height = FIXED_TO_FLOAT(list[i].height); @@ -3385,30 +3379,17 @@ noshadow: if (sector->numlights) { - INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false); + INT32 light; - if ((sector->lightlist[light].height > (spr->mobj->z + spr->mobj->height)) && !(sector->lightlist[light].flags & FF_NOSHADE)) - { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); - else - lightlevel = LightLevelToLum(255); + light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else // If we can't use the light at its bottom, we'll use the light at its top - { - light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); + else + lightlevel = LightLevelToLum(255); - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); - else - lightlevel = LightLevelToLum(255); - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } + if (sector->lightlist[light].extra_colormap) + colormap = sector->lightlist[light].extra_colormap; } else { diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index d3b3df66..2fc0ba8a 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -45,6 +45,7 @@ void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawClippedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale); +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawTranslucentPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawSmallPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); void HWR_DrawMappedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index fb012535..79f7c905 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1087,30 +1087,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (sector->numlights) { - INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false); + INT32 light; - if (sector->lightlist[light].height > (spr->mobj->z + spr->mobj->height)) - { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); - else - lightlevel = LightLevelToLum(255); + light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else // If we can't use the light at its bottom, we'll use the light at its top - { - light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); + else + lightlevel = LightLevelToLum(255); - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel); - else - lightlevel = LightLevelToLum(255); - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } + if (sector->lightlist[light].extra_colormap) + colormap = sector->lightlist[light].extra_colormap; } else { @@ -1156,7 +1143,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else { Surf.FlatColor.s.alpha = 0xFF; - blend = PF_Translucent; + blend = PF_Translucent|PF_Occlude; } // dont forget to enabled the depth test because we can't do this like @@ -1164,7 +1151,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // 1. load model+texture if not already loaded // 2. draw model with correct position, rotation,... - if (spr->mobj->skin) + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // Use the player MD2 list if the mobj has a skin and is using the player sprites { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; @@ -1188,13 +1175,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr) return; } } - HWD.pfnSetBlend(blend); + //HWD.pfnSetBlend(blend); // This seems to actually break translucency? finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy gpatch = md2->grpatch; if (!gpatch || !gpatch->mipmap.grInfo.format || !gpatch->mipmap.downloaded) md2_loadTexture(md2); - else if (gpatch->mipmap.grInfo.format) + + if (gpatch && gpatch->mipmap.grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture { // This is safe, since we know the texture has been downloaded HWD.pfnSetTexture(&gpatch->mipmap); @@ -1211,7 +1199,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) buff = md2->model->glCommandBuffer; curr = &md2->model->frames[frame]; if (cv_grmd2.value == 1 - && spr->mobj->state->nextstate != S_NULL + && spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL && !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND])) { const INT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; diff --git a/src/screen.c b/src/screen.c index 666f2e1e..4389a15d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -227,7 +227,7 @@ void SCR_Startup(void) vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + //vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); // This was just placing it incorrectly at non aspect correct resolutions vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; @@ -269,7 +269,7 @@ void SCR_Recalc(void) vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + //vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); // This was just placing it incorrectly at non aspect correct resolutions //vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS); vid.baseratio = FRACUNIT; diff --git a/src/v_video.c b/src/v_video.c index 17cd4362..034c5214 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1040,8 +1040,9 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ const UINT8 *source, *deststop; #ifdef HWRENDER - // fuck off + // Done if (rendermode != render_soft && rendermode != render_none) + HWR_DrawCroppedPatch((GLPatch_t *)patch, x, y, scrn, science, sx, sy, w, h); return; #endif From 2b80874646c89ea5a4cd3487240a0d912f4deb0b Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Wed, 19 Mar 2014 23:40:02 +0000 Subject: [PATCH 02/19] MD2's replacing skinned mobj fix MD2's that replace mobjs that have a skin, but the skin doesn't have an MD2 now display. --- src/hardware/hw_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 18a287ee..61e50f92 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3836,7 +3836,7 @@ static void HWR_DrawSprites(void) HWR_DrawPrecipitationSprite(spr); else #endif - if (spr->mobj->skin) + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if (!cv_grmd2.value || (cv_grmd2.value && md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == true)) HWR_DrawSprite(spr); @@ -3865,7 +3865,7 @@ static void HWR_DrawMD2S(void) if (!spr->precip) { #endif - if (spr->mobj && spr->mobj->skin) + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false) && (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)) HWR_DrawMD2(spr); From 7aa960d6d54abc0432fb3247ffcdd045c19a2177 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Thu, 20 Mar 2014 10:29:53 +0000 Subject: [PATCH 03/19] Software Cropped Patches Fixed the stupid error I made that was causing software to not draw cropped patches. --- src/screen.c | 13 +++++++++++-- src/v_video.c | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/screen.c b/src/screen.c index 4389a15d..08505606 100644 --- a/src/screen.c +++ b/src/screen.c @@ -227,7 +227,11 @@ void SCR_Startup(void) vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - //vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); // This was just placing it incorrectly at non aspect correct resolutions + +#ifdef HWRENDER + if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions, not sure if it does anything in software +#endif + vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; @@ -269,7 +273,12 @@ void SCR_Recalc(void) vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - //vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); // This was just placing it incorrectly at non aspect correct resolutions + +#ifdef HWRENDER + if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions, not sure if it does anything in software +#endif + vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + //vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS); vid.baseratio = FRACUNIT; diff --git a/src/v_video.c b/src/v_video.c index 034c5214..76728a35 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1042,8 +1042,10 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ #ifdef HWRENDER // Done if (rendermode != render_soft && rendermode != render_none) + { HWR_DrawCroppedPatch((GLPatch_t *)patch, x, y, scrn, science, sx, sy, w, h); return; + } #endif // only use one dup, to avoid stretching (har har) From dd16f58e38c209a53702d6f6b22cf5a29a6fd9ba Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Thu, 20 Mar 2014 20:13:15 +0000 Subject: [PATCH 04/19] OpenGL Skybox OpenGL skyboxes. Slight change to sky vertical offsetting. --- src/hardware/hw_main.c | 224 ++++++++++++++++++++++++++++++++++++++++- src/hardware/hw_main.h | 1 + src/r_main.c | 2 +- src/r_main.h | 2 + 4 files changed, 224 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 61e50f92..b4d8272f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4304,6 +4304,8 @@ static void HWR_DrawSkyBackground(player_t *player) v[0].z = v[1].z = v[2].z = v[3].z = 4.0f; + // X + if (textures[skytexture]->width > 256) angle = (angle_t)((float)(dup_viewangle + gr_xtoviewangle[0]) /((float)textures[skytexture]->width/256.0f)) @@ -4318,9 +4320,19 @@ static void HWR_DrawSkyBackground(player_t *player) v[0].sow = v[3].sow = 0.22f+(f)/(textures[skytexture]->width/2); v[2].sow = v[1].sow = 0.22f+(f+(127))/(textures[skytexture]->width/2); + + // Y + + if (textures[skytexture]->height > 256) + angle = (angle_t)((float)(aimingangle) + *(256.0f/(float)textures[skytexture]->height)) + %(ANGLE_90-1); // Just so that looking up and down scales right + else + angle = (aimingangle); + f = (float)((textures[skytexture]->height/2) * FIXED_TO_FLOAT(FINETANGENT((2048 - - ((INT32)aimingangle>>(ANGLETOFINESHIFT + 1))) & FINEMASK))); + - ((INT32)angle>>(ANGLETOFINESHIFT + 1))) & FINEMASK))); v[3].tow = v[2].tow = 0.22f+(f)/(textures[skytexture]->height/2); v[0].tow = v[1].tow = 0.22f+(f+(127))/(textures[skytexture]->height/2); @@ -4387,9 +4399,9 @@ void HWR_SetViewSize(void) } // ========================================================================== -// +// Same as rendering the player view, but from the skybox object // ========================================================================== -void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) +void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); FTransform stransform; @@ -4406,7 +4418,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) } // note: sets viewangle, viewx, viewy, viewz - R_SetupFrame(player, false); + R_SkyboxFrame(player); // copy view cam position for local use dup_viewx = viewx; @@ -4585,6 +4597,210 @@ if (0) HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } +// ========================================================================== +// +// ========================================================================== +void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) +{ + const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + FTransform stransform; + + const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on + + if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox + HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind + + { + // do we really need to save player (is it not the same)? + player_t *saved_player = stplyr; + stplyr = player; + ST_doPaletteStuff(); + stplyr = saved_player; +#ifdef ALAM_LIGHTING + HWR_SetLights(viewnumber); +#endif + } + + // note: sets viewangle, viewx, viewy, viewz + R_SetupFrame(player, false); // This can stay false because it is only used to set viewsky in r_main.c, which isn't used here + + // copy view cam position for local use + dup_viewx = viewx; + dup_viewy = viewy; + dup_viewz = viewz; + dup_viewangle = viewangle; + + // set window position + gr_centery = gr_basecentery; + gr_viewwindowy = gr_baseviewwindowy; + gr_windowcentery = gr_basewindowcentery; + if (splitscreen && viewnumber == 1) + { + gr_viewwindowy += (vid.height/2); + gr_windowcentery += (vid.height/2); + } + + // check for new console commands. + NetUpdate(); + + gr_viewx = FIXED_TO_FLOAT(dup_viewx); + gr_viewy = FIXED_TO_FLOAT(dup_viewy); + gr_viewz = FIXED_TO_FLOAT(dup_viewz); + gr_viewsin = FIXED_TO_FLOAT(viewsin); + gr_viewcos = FIXED_TO_FLOAT(viewcos); + + gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); + gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); + + //04/01/2000: Hurdler: added for T&L + // It should replace all other gr_viewxxx when finished + atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + atransform.x = gr_viewx; // FIXED_TO_FLOAT(viewx) + atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) + atransform.z = gr_viewz; // FIXED_TO_FLOAT(viewz) + atransform.scalex = 1; + atransform.scaley = ORIGINAL_ASPECT; + atransform.scalez = 1; + atransform.fovxangle = fpov; // Tails + atransform.fovyangle = fpov; // Tails + atransform.splitscreen = splitscreen; + + // Transform for sprites + stransform.anglex = 0.0f; + stransform.angley = -270.0f; + stransform.x = 0.0f; + stransform.y = 0.0f; + stransform.z = 0.0f; + stransform.scalex = 1; + stransform.scaley = 1; + stransform.scalez = 1; + stransform.fovxangle = 90.0f; + stransform.fovyangle = 90.0f; + stransform.splitscreen = splitscreen; + + gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); + + //------------------------------------------------------------------------ + HWR_ClearView(); + +if (0) +{ // I don't think this is ever used. + if (cv_grfog.value) + HWR_FoggingOn(); // First of all, turn it on, set the default user settings too + else + HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off +} + +#ifndef _NDS + if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox + HWR_DrawSkyBackground(player); +#else + (void)HWR_DrawSkyBackground; +#endif + + //Hurdler: it doesn't work in splitscreen mode + drawsky = splitscreen; + + HWR_ClearSprites(); + +#ifdef SORTING + drawcount = 0; +#endif + HWR_ClearClipSegs(); + + //04/01/2000: Hurdler: added for T&L + // Actually it only works on Walls and Planes + HWD.pfnSetTransform(&atransform); + + validcount++; + + HWR_RenderBSPNode((INT32)numnodes-1); + + // Make a viewangle int so we can render things based on mouselook + if (player == &players[consoleplayer]) + viewangle = localaiming; + else if (splitscreen && player == &players[secondarydisplayplayer]) + viewangle = localaiming2; + + // Handle stuff when you are looking farther up or down. + if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) + { + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //left + + dup_viewangle += ANGLE_90; + if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) + { + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //back + } + + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //right + + dup_viewangle += ANGLE_90; + } + + // Check for new console commands. + NetUpdate(); + +#ifdef ALAM_LIGHTING + //14/11/99: Hurdler: moved here because it doesn't work with + // subsector, see other comments; + HWR_ResetLights(); +#endif + + // Draw MD2 and sprites +#ifdef SORTING + HWR_SortVisSprites(); +#endif + HWR_DrawMD2S(); + + // Draw the sprites with trivial transform + HWD.pfnSetTransform(&stransform); +#ifdef SORTING + HWR_DrawSprites(); +#endif +#ifdef NEWCORONAS + //Hurdler: they must be drawn before translucent planes, what about gl fog? + HWR_DrawCoronas(); +#endif + +#ifdef SORTING + if (numplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything + { + HWR_CreateDrawNodes(); + } +#else + if (numfloors || numwalls) + { + HWD.pfnSetTransform(&atransform); + if (numfloors) + HWR_Render3DWater(); + if (numwalls) + HWR_RenderTransparentWalls(); + } +#endif + + HWD.pfnSetTransform(NULL); + + // put it off for menus etc + if (cv_grfog.value) + HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + + HWR_DoPostProcessor(player); + + // Check for new console commands. + NetUpdate(); + + // added by Hurdler for correct splitscreen + // moved here by hurdler so it works with the new near clipping plane + HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); +} + // ========================================================================== // FOG // ========================================================================== diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 2fc0ba8a..a6cf3fb7 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -35,6 +35,7 @@ void HWR_clearAutomap(void); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT32 color, INT32 height); void HWR_DrawConsoleBack(UINT32 color, INT32 height); +void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player); void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); diff --git a/src/r_main.c b/src/r_main.c index 10228c29..c55de394 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -732,7 +732,7 @@ static mobj_t *viewmobj; // WARNING: a should be unsigned but to add with 2048, it isn't! #define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS) -static void R_SkyboxFrame(player_t *player) +void R_SkyboxFrame(player_t *player) { INT32 dy = 0; camera_t *thiscam; diff --git a/src/r_main.h b/src/r_main.h index a6387bbc..8a39b7d3 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -101,6 +101,8 @@ void R_SetViewSize(void); // do it (sometimes explicitly called) void R_ExecuteSetViewSize(void); +void R_SkyboxFrame(player_t *player); + void R_SetupFrame(player_t *player, boolean skybox); // Called by G_Drawer. void R_RenderPlayerView(player_t *player); From 24681013d1a6962e644b0c536540dcaa277f6038 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Thu, 20 Mar 2014 20:34:56 +0000 Subject: [PATCH 05/19] Opaque translucent midtextures Fixed translucent midtextures being opaque when there were multiple lights in a sector. --- src/hardware/hw_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b4d8272f..14b15561 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1639,7 +1639,12 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Environment; if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + { + if (!(blendmode & PF_Masked)) + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS|FF_TRANSLUCENT); + else + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + } else if (!(blendmode & PF_Masked)) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); else From c72fc0f10df10ea232a53a82536fdbecf46d6d0f Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Fri, 21 Mar 2014 18:03:40 +0000 Subject: [PATCH 06/19] Warning gone. Hopefully. --- src/hardware/hw_md2.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 79f7c905..a173971c 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1123,7 +1123,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (cv_grmd2.value && ((md2_models[spr->mobj->sprite].scale > 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)) && !spr->precip) { GLPatch_t *gpatch; - FBITFIELD blend = 0; INT32 *buff; UINT32 durs = spr->mobj->state->tics; UINT32 tics = spr->mobj->tics; @@ -1136,14 +1135,12 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (spr->mobj->flags2 & MF2_SHADOW) { Surf.FlatColor.s.alpha = 0x40; - blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else { Surf.FlatColor.s.alpha = 0xFF; - blend = PF_Translucent|PF_Occlude; } // dont forget to enabled the depth test because we can't do this like From 505ea768340356ff0e49d6835f932b0a8e3fc66d Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Fri, 21 Mar 2014 14:42:55 -0400 Subject: [PATCH 07/19] SRB2 2.1.4 release --- src/d_clisrv.c | 1135 ++++++++++++++++----------- src/d_clisrv.h | 290 +++---- src/d_main.c | 5 +- src/d_net.c | 12 - src/d_netcmd.c | 13 +- src/d_player.h | 21 +- src/dehacked.c | 28 +- src/doomdata.h | 1 + src/doomdef.h | 6 +- src/doomstat.h | 2 +- src/g_game.c | 20 +- src/hardware/hw_draw.c | 287 +------ src/hardware/hw_main.h | 7 +- src/hu_stuff.c | 10 +- src/lua_hudlib.c | 61 +- src/lua_infolib.c | 2 +- src/lua_playerlib.c | 24 +- src/m_cheat.c | 10 +- src/m_menu.c | 32 +- src/p_map.c | 2 +- src/p_saveg.c | 36 +- src/p_spec.c | 27 +- src/p_user.c | 18 +- src/r_main.c | 6 +- src/r_main.h | 3 +- src/st_stuff.c | 326 ++++---- src/st_stuff.h | 23 +- src/v_video.c | 1684 +++------------------------------------- src/v_video.h | 43 +- src/y_inter.c | 4 +- src/y_inter.h | 2 + 31 files changed, 1383 insertions(+), 2757 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f4b262ba..46a711aa 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -95,10 +95,21 @@ static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet static UINT8 nodewaiting[MAXNETNODES]; static tic_t firstticstosend; // min of the nettics -static INT16 consistancy[BACKUPTICS]; static tic_t tictoclear = 0; // optimize d_clearticcmd static tic_t maketic; +static INT16 consistancy[BACKUPTICS]; + +// Resynching shit! +static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick +static UINT16 resynch_delay[MAXNETNODES]; // delay time before the player can be considered to have desynched +static UINT32 resynch_status[MAXNETNODES]; // 0 bit means synched for that player, 1 means possibly desynched +static UINT8 resynch_sent[MAXNETNODES][MAXNETNODES]; // what synch packets have we attempted to send to the player +static UINT8 resynch_inprogress[MAXNETNODES]; +static UINT8 resynch_local_inprogress = false; // WE are desynched and getting packets to fix it. +static UINT8 player_joining = false; +UINT8 hu_resynching = 0; + // client specific static ticcmd_t localcmds; static ticcmd_t localcmds2; @@ -463,6 +474,541 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) // end extra data function for lmps // ----------------------------------------------------------------- +// ----------------------------------------------------------------- +// resynch player data +// ----------------------------------------------------------------- +static inline void resynch_write_player(resynch_pak *rsp, const size_t i) +{ + size_t j; + + rsp->playernum = (UINT8)i; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + rsp->playerstate = (UINT8)players[i].playerstate; //playerstate_t + rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t + rsp->panim = (UINT8)players[i].panim; //panim_t + + rsp->aiming = (angle_t)LONG(players[i].aiming); + rsp->currentweapon = LONG(players[i].currentweapon); + rsp->ringweapons = LONG(players[i].ringweapons); + + for (j = 0; j < NUMPOWERS; ++j) + rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); + + // Score is resynched in the rspfirm resync packet + rsp->health = 0; // resynched with mo health + rsp->lives = players[i].lives; + rsp->continues = players[i].continues; + rsp->scoreadd = players[i].scoreadd; + rsp->xtralife = players[i].xtralife; + rsp->pity = players[i].pity; + + rsp->skincolor = players[i].skincolor; + rsp->skin = LONG(players[i].skin); + // Just in case Lua does something like + // modify these at runtime + rsp->normalspeed = (fixed_t)LONG(players[i].normalspeed); + rsp->runspeed = (fixed_t)LONG(players[i].runspeed); + rsp->thrustfactor = players[i].thrustfactor; + rsp->accelstart = players[i].accelstart; + rsp->acceleration = players[i].acceleration; + rsp->charability = players[i].charability; + rsp->charability2 = players[i].charability2; + rsp->charflags = (UINT32)LONG(players[i].charflags); + rsp->thokitem = (UINT32)LONG(players[i].thokitem); //mobjtype_t + rsp->spinitem = (UINT32)LONG(players[i].spinitem); //mobjtype_t + rsp->revitem = (UINT32)LONG(players[i].revitem); //mobjtype_t + rsp->actionspd = LONG(players[i].actionspd); + rsp->mindash = LONG(players[i].mindash); + rsp->maxdash = LONG(players[i].maxdash); + rsp->jumpfactor = (fixed_t)LONG(players[i].jumpfactor); + + rsp->speed = (fixed_t)LONG(players[i].speed); + rsp->jumping = players[i].jumping; + rsp->secondjump = players[i].secondjump; + rsp->fly1 = players[i].fly1; + rsp->glidetime = (tic_t)LONG(players[i].glidetime); + rsp->climbing = players[i].climbing; + rsp->deadtimer = players[i].deadtimer; + rsp->exiting = (tic_t)LONG(players[i].exiting); + rsp->homing = players[i].homing; + rsp->cmomx = (fixed_t)LONG(players[i].cmomx); + rsp->cmomy = (fixed_t)LONG(players[i].cmomy); + rsp->rmomx = (fixed_t)LONG(players[i].rmomx); + rsp->rmomy = (fixed_t)LONG(players[i].rmomy); + + rsp->weapondelay = LONG(players[i].weapondelay); + rsp->tossdelay = LONG(players[i].tossdelay); + + rsp->starpostx = SHORT(players[i].starpostx); + rsp->starposty = SHORT(players[i].starposty); + rsp->starpostz = SHORT(players[i].starpostz); + rsp->starpostnum = LONG(players[i].starpostnum); + rsp->starposttime = (tic_t)LONG(players[i].starposttime); + rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); + + rsp->maxlink = LONG(players[i].maxlink); + rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed); + rsp->dashtime = LONG(players[i].dashtime); + rsp->angle_pos = (angle_t)LONG(players[i].angle_pos); + rsp->old_angle_pos = (angle_t)LONG(players[i].old_angle_pos); + rsp->bumpertime = (tic_t)LONG(players[i].bumpertime); + rsp->flyangle = LONG(players[i].flyangle); + rsp->drilltimer = (tic_t)LONG(players[i].drilltimer); + rsp->linkcount = LONG(players[i].linkcount); + rsp->linktimer = (tic_t)LONG(players[i].linktimer); + rsp->anotherflyangle = LONG(players[i].anotherflyangle); + rsp->nightstime = (tic_t)LONG(players[i].nightstime); + rsp->drillmeter = LONG(players[i].drillmeter); + rsp->drilldelay = players[i].drilldelay; + rsp->bonustime = players[i].bonustime; + rsp->mare = players[i].mare; + rsp->lastsidehit = SHORT(players[i].lastsidehit); + rsp->lastlinehit = SHORT(players[i].lastlinehit); + + rsp->losstime = (tic_t)LONG(players[i].losstime); + rsp->timeshit = players[i].timeshit; + rsp->onconveyor = LONG(players[i].onconveyor); + + rsp->hasmo = false; + //Transfer important mo information if the player has a body. + //This lets us resync players even if they are dead. + if (!players[i].mo) + return; + rsp->hasmo = true; + + rsp->health = LONG(players[i].mo->health); + + rsp->angle = (angle_t)LONG(players[i].mo->angle); + rsp->x = LONG(players[i].mo->x); + rsp->y = LONG(players[i].mo->y); + rsp->z = LONG(players[i].mo->z); + rsp->momx = LONG(players[i].mo->momx); + rsp->momy = LONG(players[i].mo->momy); + rsp->momz = LONG(players[i].mo->momz); + rsp->friction = LONG(players[i].mo->friction); + rsp->movefactor = LONG(players[i].mo->movefactor); + + rsp->tics = LONG(players[i].mo->tics); + rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( + rsp->eflags = (UINT32)LONG(players[i].mo->eflags); + rsp->flags = LONG(players[i].mo->flags); + rsp->flags2 = LONG(players[i].mo->flags2); + + rsp->radius = LONG(players[i].mo->radius); + rsp->height = LONG(players[i].mo->height); + rsp->scale = LONG(players[i].mo->scale); + rsp->destscale = LONG(players[i].mo->destscale); + rsp->scalespeed = LONG(players[i].mo->scalespeed); +} + +static void resynch_read_player(resynch_pak *rsp) +{ + INT32 i = rsp->playernum, j; + mobj_t *savedmo = players[i].mo; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + players[i].playerstate = (UINT8)rsp->playerstate; //playerstate_t + players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t + players[i].panim = (UINT8)rsp->panim; //panim_t + + players[i].aiming = (angle_t)LONG(rsp->aiming); + players[i].currentweapon = LONG(rsp->currentweapon); + players[i].ringweapons = LONG(rsp->ringweapons); + + for (j = 0; j < NUMPOWERS; ++j) + players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); + + // Score is resynched in the rspfirm resync packet + players[i].health = rsp->health; + players[i].lives = rsp->lives; + players[i].continues = rsp->continues; + players[i].scoreadd = rsp->scoreadd; + players[i].xtralife = rsp->xtralife; + players[i].pity = rsp->pity; + + players[i].skincolor = rsp->skincolor; + players[i].skin = LONG(rsp->skin); + // Just in case Lua does something like + // modify these at runtime + players[i].normalspeed = (fixed_t)LONG(rsp->normalspeed); + players[i].runspeed = (fixed_t)LONG(rsp->runspeed); + players[i].thrustfactor = rsp->thrustfactor; + players[i].accelstart = rsp->accelstart; + players[i].acceleration = rsp->acceleration; + players[i].charability = rsp->charability; + players[i].charability2 = rsp->charability2; + players[i].charflags = (UINT32)LONG(rsp->charflags); + players[i].thokitem = (UINT32)LONG(rsp->thokitem); //mobjtype_t + players[i].spinitem = (UINT32)LONG(rsp->spinitem); //mobjtype_t + players[i].revitem = (UINT32)LONG(rsp->revitem); //mobjtype_t + players[i].actionspd = LONG(rsp->actionspd); + players[i].mindash = LONG(rsp->mindash); + players[i].maxdash = LONG(rsp->maxdash); + players[i].jumpfactor = (fixed_t)LONG(rsp->jumpfactor); + + players[i].speed = (fixed_t)LONG(rsp->speed); + players[i].jumping = rsp->jumping; + players[i].secondjump = rsp->secondjump; + players[i].fly1 = rsp->fly1; + players[i].glidetime = (tic_t)LONG(rsp->glidetime); + players[i].climbing = rsp->climbing; + players[i].deadtimer = rsp->deadtimer; + players[i].exiting = (tic_t)LONG(rsp->exiting); + players[i].homing = rsp->homing; + players[i].cmomx = (fixed_t)LONG(rsp->cmomx); + players[i].cmomy = (fixed_t)LONG(rsp->cmomy); + players[i].rmomx = (fixed_t)LONG(rsp->rmomx); + players[i].rmomy = (fixed_t)LONG(rsp->rmomy); + + players[i].weapondelay = LONG(rsp->weapondelay); + players[i].tossdelay = LONG(rsp->tossdelay); + + players[i].starpostx = SHORT(rsp->starpostx); + players[i].starposty = SHORT(rsp->starposty); + players[i].starpostz = SHORT(rsp->starpostz); + players[i].starpostnum = LONG(rsp->starpostnum); + players[i].starposttime = (tic_t)LONG(rsp->starposttime); + players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); + + players[i].maxlink = LONG(rsp->maxlink); + players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed); + players[i].dashtime = LONG(rsp->dashtime); + players[i].angle_pos = (angle_t)LONG(rsp->angle_pos); + players[i].old_angle_pos = (angle_t)LONG(rsp->old_angle_pos); + players[i].bumpertime = (tic_t)LONG(rsp->bumpertime); + players[i].flyangle = LONG(rsp->flyangle); + players[i].drilltimer = (tic_t)LONG(rsp->drilltimer); + players[i].linkcount = LONG(rsp->linkcount); + players[i].linktimer = (tic_t)LONG(rsp->linktimer); + players[i].anotherflyangle = LONG(rsp->anotherflyangle); + players[i].nightstime = (tic_t)LONG(rsp->nightstime); + players[i].drillmeter = LONG(rsp->drillmeter); + players[i].drilldelay = rsp->drilldelay; + players[i].bonustime = rsp->bonustime; + players[i].mare = rsp->mare; + players[i].lastsidehit = SHORT(rsp->lastsidehit); + players[i].lastlinehit = SHORT(rsp->lastlinehit); + + players[i].losstime = (tic_t)LONG(rsp->losstime); + players[i].timeshit = rsp->timeshit; + players[i].onconveyor = LONG(rsp->onconveyor); + + //We get a packet for each player in game. + if (!playeringame[i]) + return; + + //...but keep old mo even if it is corrupt or null! + players[i].mo = savedmo; + + //Transfer important mo information if they have a valid mo. + if (!rsp->hasmo) + return; + + //server thinks player has a body. + //Give them a new body that can be then manipulated by the server's info. + if (!players[i].mo) //client thinks it has no body. + P_SpawnPlayer(i); + + //At this point, the player should have a body, whether they were respawned or not. + P_UnsetThingPosition(players[i].mo); + players[i].mo->angle = (angle_t)LONG(rsp->angle); + players[i].mo->eflags = (UINT32)LONG(rsp->eflags); + players[i].mo->flags = LONG(rsp->flags); + players[i].mo->flags2 = LONG(rsp->flags2); + players[i].mo->friction = LONG(rsp->friction); + players[i].mo->health = LONG(rsp->health); + players[i].mo->momx = LONG(rsp->momx); + players[i].mo->momy = LONG(rsp->momy); + players[i].mo->momz = LONG(rsp->momz); + players[i].mo->movefactor = LONG(rsp->movefactor); + players[i].mo->tics = LONG(rsp->tics); + P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum)); + players[i].mo->x = LONG(rsp->x); + players[i].mo->y = LONG(rsp->y); + players[i].mo->z = LONG(rsp->z); + players[i].mo->radius = LONG(rsp->radius); + players[i].mo->height = LONG(rsp->height); + // P_SetScale is redundant for this, as all related variables are already restored properly. + players[i].mo->scale = LONG(rsp->scale); + players[i].mo->destscale = LONG(rsp->destscale); + players[i].mo->scalespeed = LONG(rsp->scalespeed); + + // And finally, SET THE MOBJ SKIN damn it. + players[i].mo->skin = &skins[players[i].skin]; + players[i].mo->color = players[i].skincolor; + + P_SetThingPosition(players[i].mo); +} + +static inline void resynch_write_ctf(resynchend_pak *rst) +{ + mobj_t *mflag; + UINT8 i, j; + + for (i = 0, mflag = redflag; i < 2; ++i, mflag = blueflag) + { + rst->flagx[i] = rst->flagy[i] = rst->flagz[i] = 0; + rst->flagloose[i] = rst->flagflags[i] = 0; + rst->flagplayer[i] = -1; + + if (!mflag) + { + // Should be held by a player + for (j = 0; j < MAXPLAYERS; ++j) + { + if (!playeringame[j] || players[j].gotflag != i) + continue; + rst->flagplayer[i] = (SINT8)j; + break; + } + if (j == MAXPLAYERS) + I_Error("One of the flags has gone completely missing!"); + + continue; + } + + rst->flagx[i] = (fixed_t)LONG(mflag->x); + rst->flagy[i] = (fixed_t)LONG(mflag->y); + rst->flagz[i] = (fixed_t)LONG(mflag->z); + rst->flagflags[i] = LONG(mflag->flags2); + rst->flagloose[i] = LONG(mflag->fuse); // Dropped or not? + } +} + +static inline void resynch_read_ctf(resynchend_pak *p) +{ + UINT8 i; + + for (i = 0; i < MAXPLAYERS; ++i) + players[i].gotflag = 0; + + // Red flag + if (p->flagplayer[0] != -1) // Held by a player + { + if (!playeringame[p->flagplayer[0]]) + I_Error("Invalid red flag player %d who isn't in the game!", (INT32)p->flagplayer[0]); + players[p->flagplayer[0]].gotflag = GF_REDFLAG; + if (redflag) + { + P_RemoveMobj(redflag); + redflag = NULL; + } + } + else + { + if (!redflag) + redflag = P_SpawnMobj(0,0,0,MT_REDFLAG); + + P_UnsetThingPosition(redflag); + redflag->x = (fixed_t)LONG(p->flagx[0]); + redflag->y = (fixed_t)LONG(p->flagy[0]); + redflag->z = (fixed_t)LONG(p->flagz[0]); + redflag->flags2 = LONG(p->flagflags[0]); + redflag->fuse = LONG(p->flagloose[0]); + P_SetThingPosition(redflag); + } + + // Blue flag + if (p->flagplayer[1] != -1) // Held by a player + { + if (!playeringame[p->flagplayer[1]]) + I_Error("Invalid blue flag player %d who isn't in the game!", (INT32)p->flagplayer[1]); + players[p->flagplayer[1]].gotflag = GF_REDFLAG; + if (blueflag) + { + P_RemoveMobj(blueflag); + blueflag = NULL; + } + } + else + { + if (!blueflag) + blueflag = P_SpawnMobj(0,0,0,MT_BLUEFLAG); + + P_UnsetThingPosition(blueflag); + blueflag->x = (fixed_t)LONG(p->flagx[0]); + blueflag->y = (fixed_t)LONG(p->flagy[0]); + blueflag->z = (fixed_t)LONG(p->flagz[0]); + blueflag->flags2 = LONG(p->flagflags[0]); + blueflag->fuse = LONG(p->flagloose[0]); + P_SetThingPosition(blueflag); + } +} + +static inline void resynch_write_others(resynchend_pak *rst) +{ + UINT8 i; + + rst->ingame = rst->ctfteam = 0; + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!playeringame[i]) + { + rst->score[i] = 0; + rst->numboxes[i] = 0; + rst->totalring[i] = 0; + rst->realtime[i] = 0; + rst->laps[i] = 0; + continue; + } + + if (!players[i].spectator) + { + rst->ingame |= (1< 1) + rst->ctfteam |= (1<score[i] = (UINT32)LONG(players[i].score); + rst->numboxes[i] = SHORT(players[i].numboxes); + rst->totalring[i] = SHORT(players[i].totalring); + rst->realtime[i] = (tic_t)LONG(players[i].realtime); + rst->laps[i] = players[i].laps; + } + + // endian safeness + rst->ingame = (UINT32)LONG(rst->ingame); + rst->ctfteam = (UINT32)LONG(rst->ctfteam); +} + +static inline void resynch_read_others(resynchend_pak *p) +{ + UINT8 i; + UINT32 loc_ingame = (UINT32)LONG(p->ingame); + UINT32 loc_ctfteam = (UINT32)LONG(p->ctfteam); + + for (i = 0; i < MAXPLAYERS; ++i) + { + // We don't care if they're in the game or not, just write all the data. + if (loc_ingame & (1<score[i]); + players[i].numboxes = SHORT(p->numboxes[i]); + players[i].totalring = SHORT(p->totalring[i]); + players[i].realtime = (tic_t)LONG(p->realtime[i]); + players[i].laps = p->laps[i]; + } +} + +static void SV_InitResynchVars(INT32 node) +{ + resynch_delay[node] = TICRATE; // initial one second delay + resynch_score[node] = 0; // clean slate + resynch_status[node] = 0x00; + resynch_inprogress[node] = false; + memset(resynch_sent[node], 0, MAXNETNODES); +} + +static void SV_RequireResynch(INT32 node) +{ + INT32 i; + + resynch_delay[node] = 10; // Delay before you can fail sync again + resynch_score[node] += 200; // Add score for initial desynch + resynch_status[node] = 0xFF; // No players assumed synched + resynch_inprogress[node] = true; // so we know to send a PT_RESYNCHEND after sync + + // Initial setup + memset(resynch_sent[node], 0, MAXNETNODES); + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!playeringame[i]) // Player not in game so just drop it from required synch + resynch_status[node] &= ~(1<>1)+1; + } +} + +static void SV_SendResynch(INT32 node) +{ + INT32 i, j; + + // resynched? + if (!resynch_status[node]) + { + // you are now synched + resynch_inprogress[node] = false; + + netbuffer->packettype = PT_RESYNCHEND; + + netbuffer->u.resynchend.randomseed = P_GetRandSeed(); + if (gametype == GT_CTF) + resynch_write_ctf(&netbuffer->u.resynchend); + resynch_write_others(&netbuffer->u.resynchend); + + HSendPacket(node, true, 0, (sizeof(resynchend_pak))); + return; + } + + netbuffer->packettype = PT_RESYNCHING; + for (i = 0, j = 0; i < MAXPLAYERS; ++i) + { + // if already synched don't bother + if (!(resynch_status[node] & 1<u.resynchpak, i); + HSendPacket(node, false, 0, (sizeof(resynch_pak))); + + resynch_sent[node][i] = TICRATE; + resynch_score[node] += 2; // penalty for send + + if (++j > 3) + break; + } + + if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)nodetoplayer[node]; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + resynch_score[node] = 0; + } +} + +static void CL_AcknowledgeResynch(resynch_pak *rsp) +{ + resynch_read_player(rsp); + + netbuffer->packettype = PT_RESYNCHGET; + netbuffer->u.resynchgot = rsp->playernum; + HSendPacket(servernode, true, 0, sizeof(UINT8)); +} + +static void SV_AcknowledgeResynchAck(INT32 node, UINT8 rsg) +{ + if (rsg >= MAXPLAYERS) + resynch_score[node] += 16384; // lol. + else + { + resynch_status[node] &= ~(1<playernum = (UINT8)i; - - con->playerstate = (UINT8)players[i].playerstate; - G_MoveTiccmd(&con->cmd, &players[i].cmd, 1); - con->viewz = LONG(players[i].viewz); - con->viewheight = LONG(players[i].viewheight); - con->deltaviewheight = LONG(players[i].deltaviewheight); - con->bob = LONG(players[i].bob); - con->aiming = (angle_t)LONG(players[i].aiming); - con->awayviewaiming = (angle_t)LONG(players[i].awayviewaiming); - con->phealth = LONG(players[i].health); - con->pity = players[i].pity; - con->currentweapon = LONG(players[i].currentweapon); - con->ringweapons = LONG(players[i].ringweapons); - - for (j = 0; j < NUMPOWERS; j++) - con->powers[j] = (UINT16)SHORT(players[i].powers[j]); - - con->pflags = (UINT32)LONG(players[i].pflags); - con->panim = (UINT8)players[i].panim; - con->flashcount = LONG(players[i].flashcount); - con->skincolor = players[i].skincolor; - con->skin = LONG(players[i].skin); - con->score = (UINT32)LONG(players[i].score); - con->maxlink = LONG(players[i].maxlink); - con->dashspeed = LONG(players[i].dashspeed); - con->dashtime = LONG(players[i].dashtime); - con->normalspeed = LONG(players[i].normalspeed); - con->runspeed = LONG(players[i].runspeed); - con->thrustfactor = players[i].thrustfactor; - con->accelstart = players[i].accelstart; - con->acceleration = players[i].acceleration; - con->charability = players[i].charability; - con->charability2 = players[i].charability2; - con->charflags = (UINT32)LONG(players[i].charflags); - con->thokitem = (UINT32)LONG(players[i].thokitem); - con->spinitem = (UINT32)LONG(players[i].spinitem); - con->revitem = (UINT32)LONG(players[i].revitem); - con->actionspd = LONG(players[i].actionspd); - con->mindash = LONG(players[i].mindash); - con->maxdash = LONG(players[i].maxdash); - con->jumpfactor = LONG(players[i].jumpfactor); - con->lives = LONG(players[i].lives); - con->continues = LONG(players[i].continues); - con->xtralife = LONG(players[i].xtralife); - con->speed = LONG(players[i].speed); - con->jumping = LONG(players[i].jumping); - con->secondjump =players[i].secondjump; - con->fly1 = players[i].fly1; - con->scoreadd = (UINT32)LONG(players[i].scoreadd); - con->glidetime = (tic_t)LONG(players[i].glidetime); - con->climbing = players[i].climbing; - con->deadtimer = LONG(players[i].deadtimer); - con->exiting = (tic_t)LONG(players[i].exiting); - con->homing = players[i].homing; - con->skidtime = (tic_t)LONG(players[i].skidtime); - con->cmomx = LONG(players[i].cmomx); - con->cmomy = LONG(players[i].cmomy); - con->rmomx = LONG(players[i].rmomx); - con->rmomy = LONG(players[i].rmomy); - con->numboxes = LONG(players[i].numboxes); - con->totalring = LONG(players[i].totalring); - con->realtime = (tic_t)LONG(players[i].realtime); - con->laps = (UINT32)LONG(players[i].laps); - con->ctfteam = LONG(players[i].ctfteam); - con->gotflag = (UINT16)SHORT(players[i].gotflag); - con->weapondelay = LONG(players[i].weapondelay); - con->tossdelay = LONG(players[i].tossdelay); - con->starpostx = SHORT(players[i].starpostx); - con->starposty = SHORT(players[i].starposty); - con->starpostz = SHORT(players[i].starpostz); - con->starpostnum = LONG(players[i].starpostnum); - con->starposttime = (tic_t)LONG(players[i].starposttime); - con->starpostangle = (angle_t)LONG(players[i].starpostangle); - con->angle_pos = (angle_t)LONG(players[i].angle_pos); - con->old_angle_pos = (angle_t)LONG(players[i].old_angle_pos); - con->bumpertime = (tic_t)LONG(players[i].bumpertime); - con->flyangle = LONG(players[i].flyangle); - con->drilltimer = (tic_t)LONG(players[i].drilltimer); - con->linkcount = LONG(players[i].linkcount); - con->linktimer = (tic_t)LONG(players[i].linktimer); - con->anotherflyangle = LONG(players[i].anotherflyangle); - con->nightstime = (tic_t)LONG(players[i].nightstime); - con->drillmeter = LONG(players[i].drillmeter); - con->drilldelay = players[i].drilldelay; - con->bonustime = (UINT8)players[i].bonustime; - con->mare = players[i].mare; - con->lastsidehit = SHORT(players[i].lastsidehit); - con->lastlinehit = SHORT(players[i].lastlinehit); - con->losstime = (tic_t)LONG(players[i].losstime); - con->timeshit = (UINT8)players[i].timeshit; - con->onconveyor = LONG(players[i].onconveyor); - con->spectator = (UINT8)players[i].spectator; - con->jointime = (tic_t)LONG(players[i].jointime); - - con->hasmo = false; - //Transfer important mo information if the player has a body. - //This lets us resync players even if they are dead. - if (!players[i].mo) - return; - - con->hasmo = true; - con->angle = (angle_t)LONG(players[i].mo->angle); - con->eflags = (UINT32)LONG(players[i].mo->eflags); - con->flags = LONG(players[i].mo->flags); - con->flags2 = LONG(players[i].mo->flags2); - con->friction = LONG(players[i].mo->friction); - con->health = LONG(players[i].mo->health); - con->momx = LONG(players[i].mo->momx); - con->momy = LONG(players[i].mo->momy); - con->momz = LONG(players[i].mo->momz); - con->movefactor = LONG(players[i].mo->movefactor); - con->tics = LONG(players[i].mo->tics); - con->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( - con->x = LONG(players[i].mo->x); - con->y = LONG(players[i].mo->y); - con->z = LONG(players[i].mo->z); - con->radius = LONG(players[i].mo->radius); - con->height = LONG(players[i].mo->height); - con->scale = LONG(players[i].mo->scale); - con->destscale = LONG(players[i].mo->destscale); - con->scalespeed = LONG(players[i].mo->scalespeed); -} - -static void readconplayer(cons_pak *con, const INT32 playernum) -{ - size_t i; - mobj_t *savedmo = players[playernum].mo; - - //We get a packet for each player in game. - - //Restore CTF information - if (gametype == GT_CTF) - { - // Remove old flags. - if (redflag) - { - P_RemoveMobj(redflag); - redflag = NULL; - } - if (blueflag) - { - P_RemoveMobj(blueflag); - blueflag = NULL; - } - - // Spawn the flags if players aren't carrying them. - if (con->rflagloose != 2) - { - mobj_t *newflag = P_SpawnMobj(con->rflagx << FRACBITS, con->rflagy << FRACBITS, con->rflagz << FRACBITS, MT_REDFLAG); - newflag->flags |= MF_SPECIAL; - newflag->flags2 = con->rflags2; - newflag->fuse = con->rfuse; - newflag->spawnpoint = rflagpoint; - redflag = newflag; - } - - if (con->bflagloose != 2) - { - mobj_t *newflag = P_SpawnMobj(con->bflagx << FRACBITS, con->bflagy << FRACBITS, con->bflagz << FRACBITS, MT_BLUEFLAG); - newflag->flags |= MF_SPECIAL; - newflag->flags2 = con->bflags2; - newflag->fuse = con->bfuse; - newflag->spawnpoint = bflagpoint; - blueflag = newflag; - } - } - - if (!playeringame[playernum]) - return; - - //Tranfer player information. - players[playernum].playerstate = (playerstate_t)con->playerstate; - G_MoveTiccmd(&players[playernum].cmd, &con->cmd, 1); - players[playernum].viewz = LONG(con->viewz); - players[playernum].viewheight = LONG(con->viewheight); - players[playernum].deltaviewheight = LONG(con->deltaviewheight); - players[playernum].bob = LONG(con->bob); - players[playernum].aiming = (angle_t)LONG(con->aiming); - players[playernum].awayviewaiming = (angle_t)LONG(con->awayviewaiming); - players[playernum].health = LONG(con->phealth); - players[playernum].pity = con->pity; - players[playernum].currentweapon = LONG(con->currentweapon); - players[playernum].ringweapons = LONG(con->ringweapons); - - for (i = 0; i < NUMPOWERS; i++) - players[playernum].powers[i] = (UINT16)SHORT(con->powers[i]); - - players[playernum].pflags = (pflags_t)LONG(con->pflags); - players[playernum].panim = (panim_t)con->panim; - players[playernum].flashcount = LONG(con->flashcount); - players[playernum].skincolor = con->skincolor; - players[playernum].skin = LONG(con->skin); - players[playernum].score = (UINT32)LONG(con->score); - players[playernum].maxlink = LONG(con->maxlink); - players[playernum].dashspeed = LONG(con->dashspeed); - players[playernum].dashtime = LONG(con->dashtime); - players[playernum].normalspeed = LONG(con->normalspeed); - players[playernum].runspeed = LONG(con->runspeed); - players[playernum].thrustfactor = con->thrustfactor; - players[playernum].accelstart = con->accelstart; - players[playernum].acceleration = con->acceleration; - players[playernum].charability = con->charability; - players[playernum].charability2 = con->charability2; - players[playernum].charflags = (UINT32)LONG(con->charflags); - players[playernum].thokitem = (mobjtype_t)LONG(con->thokitem); - players[playernum].spinitem = (mobjtype_t)LONG(con->spinitem); - players[playernum].revitem = (mobjtype_t)LONG(con->revitem); - players[playernum].actionspd = LONG(con->actionspd); - players[playernum].mindash = LONG(con->mindash); - players[playernum].maxdash = LONG(con->maxdash); - players[playernum].jumpfactor = LONG(con->jumpfactor); - players[playernum].lives = LONG(con->lives); - players[playernum].continues = LONG(con->continues); - players[playernum].xtralife = LONG(con->xtralife); - players[playernum].speed = LONG(con->speed); - players[playernum].jumping = LONG(con->jumping); - players[playernum].secondjump = con->secondjump; - players[playernum].fly1 = con->fly1; - players[playernum].scoreadd = (UINT32)LONG(con->scoreadd); - players[playernum].glidetime = (tic_t)LONG(con->glidetime); - players[playernum].climbing = con->climbing; - players[playernum].deadtimer = LONG(con->deadtimer); - players[playernum].exiting = (tic_t)LONG(con->exiting); - players[playernum].homing = con->homing; - players[playernum].skidtime = (tic_t)LONG(con->skidtime); - players[playernum].cmomx = LONG(con->cmomx); - players[playernum].cmomy = LONG(con->cmomy); - players[playernum].rmomx = LONG(con->rmomx); - players[playernum].rmomy = LONG(con->rmomy); - players[playernum].numboxes = LONG(con->numboxes); - players[playernum].totalring = LONG(con->totalring); - players[playernum].realtime = (tic_t)LONG(con->realtime); - players[playernum].laps = (UINT32)LONG(con->laps); - players[playernum].ctfteam = LONG(con->ctfteam); - players[playernum].gotflag = (UINT16)SHORT(con->gotflag); - players[playernum].weapondelay = LONG(con->weapondelay); - players[playernum].tossdelay = LONG(con->tossdelay); - players[playernum].starpostx = LONG(con->starpostx); - players[playernum].starposty = LONG(con->starposty); - players[playernum].starpostz = LONG(con->starpostz); - players[playernum].starpostnum = LONG(con->starpostnum); - players[playernum].starposttime = (tic_t)LONG(con->starposttime); - players[playernum].starpostangle = (angle_t)LONG(con->starpostangle); - players[playernum].angle_pos = (angle_t)LONG(con->angle_pos); - players[playernum].old_angle_pos = (angle_t)LONG(con->old_angle_pos); - players[playernum].bumpertime = (tic_t)LONG(con->bumpertime); - players[playernum].flyangle = LONG(con->flyangle); - players[playernum].drilltimer = (tic_t)LONG(con->drilltimer); - players[playernum].linkcount = LONG(con->linkcount); - players[playernum].linktimer = (tic_t)LONG(con->linktimer); - players[playernum].anotherflyangle = LONG(con->anotherflyangle); - players[playernum].nightstime = (tic_t)LONG(con->nightstime); - players[playernum].drillmeter = LONG(con->drillmeter); - players[playernum].drilldelay = con->drilldelay; - players[playernum].bonustime = (boolean)con->bonustime; - players[playernum].mare = con->mare; - players[playernum].lastsidehit = SHORT(con->lastsidehit); - players[playernum].lastlinehit = SHORT(con->lastlinehit); - players[playernum].losstime = (tic_t)LONG(con->losstime); - players[playernum].timeshit = (UINT8)con->timeshit; - players[playernum].onconveyor = LONG(con->onconveyor); - players[playernum].spectator = (boolean)con->spectator; - players[playernum].jointime = (tic_t)LONG(con->jointime); - - //...but keep old mo even if it is corrupt or null! - players[playernum].mo = savedmo; - - //Transfer important mo information if they have a valid mo. - if (!con->hasmo) - return; - //server thinks player has a body. - //Give them a new body that can be then manipulated by the server's info. - if (!players[playernum].mo) //client thinks it has no body. - P_SpawnPlayer(playernum); - - //At this point, the player should have a body, whether they were respawned or not. - P_UnsetThingPosition(players[playernum].mo); - players[playernum].mo->angle = (angle_t)LONG(con->angle); - players[playernum].mo->eflags = (UINT32)LONG(con->eflags); - players[playernum].mo->flags = LONG(con->flags); - players[playernum].mo->flags2 = LONG(con->flags2); - players[playernum].mo->friction = LONG(con->friction); - players[playernum].mo->health = LONG(con->health); - players[playernum].mo->momx = LONG(con->momx); - players[playernum].mo->momy = LONG(con->momy); - players[playernum].mo->momz = LONG(con->momz); - players[playernum].mo->movefactor = LONG(con->movefactor); - players[playernum].mo->tics = LONG(con->tics); - P_SetPlayerMobjState(players[playernum].mo, LONG(con->statenum)); - players[playernum].mo->x = LONG(con->x); - players[playernum].mo->y = LONG(con->y); - players[playernum].mo->z = LONG(con->z); - players[playernum].mo->radius = LONG(con->radius); - players[playernum].mo->height = LONG(con->height); - // P_SetScale is redundant for this, as all related variables are already restored properly. - players[playernum].mo->scale = LONG(con->scale); - players[playernum].mo->destscale = LONG(con->destscale); - players[playernum].mo->scalespeed = LONG(con->scalespeed); - - // And finally, SET THE MOBJ SKIN damn it. - players[playernum].mo->skin = &skins[players[playernum].skin]; - players[playernum].mo->color = players[playernum].skincolor; - - P_SetThingPosition(players[playernum].mo); -} - -static inline void handlectfconstuff(cons_pak *con) -{ - if (redflag) - { - // Flag is loose - if (redflag->fuse) - { - con->rflagloose = 1; - con->rflagx = SHORT(redflag->x >> FRACBITS); - con->rflagy = SHORT(redflag->y >> FRACBITS); - con->rflagz = SHORT(redflag->z >> FRACBITS); - con->rflags2 = LONG(redflag->flags2); - con->rfuse = LONG(redflag->fuse); - } - else // flag is at base - { - con->rflagloose = 0; - con->rflagx = SHORT(rflagpoint->x); - con->rflagy = SHORT(rflagpoint->y); - con->rflagz = SHORT(rflagpoint->z); - con->rflags2 = 0; - con->rfuse = 0; - } - } - else // player has flag - con->rflagloose = 2; - - if (blueflag) - { - // Flag is loose - if (blueflag->fuse) - { - con->bflagloose = 1; - con->bflagx = SHORT(blueflag->x >> FRACBITS); - con->bflagy = SHORT(blueflag->y >> FRACBITS); - con->bflagz = SHORT(blueflag->z >> FRACBITS); - con->bflags2 = LONG(blueflag->flags2); - con->bfuse = LONG(blueflag->fuse); - } - else // flag is at base - { - con->bflagloose = 0; - con->bflagx = SHORT(bflagpoint->x); - con->bflagy = SHORT(bflagpoint->y); - con->bflagz = SHORT(bflagpoint->z); - con->bflags2 = 0; - con->bfuse = 0; - } - } - else // player has flag - con->bflagloose = 2; -} - -/// \todo Remove this AWFUL consistency fixing packet and replace it with re-sending $$$.sav, or at least pause the game until it gets acked! -static void SV_SendConsistency(INT32 node) -{ - INT32 i; - - netbuffer->packettype = PT_CONSISTENCY; - - if (gametype == GT_CTF) - handlectfconstuff(&netbuffer->u.consistency); - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - writeconplayer(&netbuffer->u.consistency, i); - HSendPacket(node, true, 0, (sizeof(cons_pak))); - } -} - // used at txtcmds received to check packetsize bound static size_t TotalTextCmdPerTic(tic_t tic) { @@ -2910,6 +3071,10 @@ static void HandleConnect(SINT8 node) newnode = true; #endif SV_AddNode(node); + + // you get a free second before desynch checks. use it wisely. + SV_InitResynchVars(node); + if (cv_joinnextround.value && gameaction == ga_nothing) G_SetGamestate(GS_WAITINGPLAYERS); if (!SV_SendServerConfig(node)) @@ -2934,6 +3099,7 @@ static void HandleConnect(SINT8 node) DEBFILE("send savegame\n"); } SV_AddWaitingPlayers(); + player_joining = true; } #endif } @@ -2982,6 +3148,9 @@ static void GetPackets(void) XBOXSTATIC tic_t realend,realstart; XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak; FILESTAMP + + player_joining = false; + while (HGetPacket()) { node = (SINT8)doomcom->remotenode; @@ -3153,9 +3322,14 @@ FILESTAMP I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); #endif + txtpak = NULL; + switch (netbuffer->packettype) { // -------------------------------------------- SERVER RECEIVE ---------- + case PT_RESYNCHGET: + SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); + break; case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: @@ -3165,6 +3339,10 @@ FILESTAMP if (!server) break; + // ignore tics from those not synched + if (resynch_inprogress[node]) + break; + // to save bytes, only the low byte of tic numbers are sent // Figure out what the rest of the bytes are realstart = ExpandTics(netbuffer->u.clientpak.client_tic); @@ -3213,42 +3391,30 @@ FILESTAMP G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); + // a delay before we check resynching + // used on join or just after a synch fail + if (resynch_delay[node]) + { + --resynch_delay[node]; + break; + } // check player consistancy during the level - // Careful: When a consistency packet is sent, it overwrites the incoming packet containing the ticcmd. - // Keep this in mind when changing the code that responds to these packets. - if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 - && gamestate == GS_LEVEL && playeringame[netconsole] - && players[netconsole].playerstate == PST_LIVE - && !players[netconsole].spectator - && players[netconsole].jointime > 10 + if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) { - if (cv_consfailprotect.value && consfailcount[netconsole] < cv_consfailprotect.value) + SV_RequireResynch(node); + + if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) { - if (!consfailstatus[netconsole]) - { - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Consistency failure for player %d (%s), restoring...\n"), netconsole+1, player_names[netconsole]); - - DEBFILE(va("Restoring player %d (consistency failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - - SV_SendConsistency(netconsole); - consfailstatus[netconsole] = 1; - consfailcount[netconsole]++; - break; // ticcmd packet is gone. - } - else - { - //We don't want to send any more packets than we have to. - //If the client doesn't resync in a certain time, - //assume they didn't get the packet. Send another. - if (consfailstatus[netconsole] < 10) - consfailstatus[netconsole]++; - else - consfailstatus[netconsole] = 0; - } + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; } else { @@ -3257,19 +3423,14 @@ FILESTAMP buf[0] = (UINT8)netconsole; buf[1] = KICK_MSG_CON_FAIL; SendNetXCmd(XD_KICK, &buf, 2); - DEBFILE(va("player %d kicked (consistency failure) [%u] %d!=%d\n", + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", netconsole, realstart, consistancy[realstart%BACKUPTICS], SHORT(netbuffer->u.clientpak.consistancy))); - consfailstatus[netconsole] = 0; - consfailcount[netconsole] = 0; break; } } - else - { - consfailstatus[netconsole] = 0; - consfailcount[netconsole] = 0; - } + else if (resynch_score[node]) + --resynch_score[node]; break; case PT_TEXTCMD2: // splitscreen special netconsole = nodetoplayer2[node]; @@ -3346,6 +3507,31 @@ FILESTAMP nodeingame[node] = false; break; // -------------------------------------------- CLIENT RECEIVE ---------- + case PT_RESYNCHEND: + // Only accept PT_RESYNCHEND from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node); + + if (server) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + resynch_local_inprogress = false; + + P_SetRandSeed(netbuffer->u.resynchend.randomseed); + + if (gametype == GT_CTF) + resynch_read_ctf(&netbuffer->u.resynchend); + resynch_read_others(&netbuffer->u.resynchend); + + break; case PT_SERVERTICS: // Only accept PT_SERVERTICS from the server. if (node != servernode) @@ -3366,8 +3552,9 @@ FILESTAMP realstart = ExpandTics(netbuffer->u.serverpak.starttic); realend = realstart + netbuffer->u.serverpak.numtics; - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; + if (!txtpak) + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; if (realend > gametic + BACKUPTICS) realend = gametic + BACKUPTICS; @@ -3404,11 +3591,11 @@ FILESTAMP else DEBFILE(va("frame not in bound: %u\n", neededtic)); break; - case PT_CONSISTENCY: - // Only accept PT_CONSISTENCY from the server. + case PT_RESYNCHING: + // Only accept PT_RESYNCHING from the server. if (node != servernode) { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_CONSISTENCY", node); + CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node); if (server) { @@ -3420,8 +3607,8 @@ FILESTAMP break; } - - readconplayer(&netbuffer->u.consistency, netbuffer->u.consistency.playernum); + resynch_local_inprogress = true; + CL_AcknowledgeResynch(&netbuffer->u.resynchpak); break; #ifdef NEWPING case PT_PING: @@ -3470,25 +3657,35 @@ FILESTAMP // Builds ticcmds for console player, // sends out a packet // +// no more use random generator, because at very first tic isn't yet synchronized // Note: It is called consistAncy on purpose. // static INT16 Consistancy(void) { - INT16 ret = 0; INT32 i; + UINT32 ret = 0; DEBFILE(va("TIC %u ", gametic)); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].playerstate == PST_LIVE && !players[i].spectator) - { - //DEBFILE(va("p[%d].x = %f ", i, (double)FIXED_TO_FLOAT(players[i].mo->x))); - ret = (INT16)((ret + (players[i].mo->x>>8)) & 0xFFFF); - ret = (INT16)((ret + players[i].powers[pw_shield]) & 0xFFFF); - } - DEBFILE(va("players = %d, rnd %d\n", ret, P_GetRandSeed())); - ret = (INT16)(ret + P_GetRandSeed()); - return ret; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + ret ^= 0xCCCC; + else if (!players[i].mo); + else + { + ret += players[i].mo->x; + ret -= players[i].mo->y; + ret += players[i].powers[pw_shield]; + ret *= i+1; + } + } + // I give up + // Coop desynching enemies is painful + if (!G_PlatformGametype()) + ret += P_GetRandSeed(); + + return (INT16)(ret & 0xFFFF); } // send the client packet to the server @@ -3776,6 +3973,9 @@ void TryRunTics(tic_t realtics) } #endif + if (player_joining) + return; + if (neededtic > gametic) { if (advancedemo) @@ -3911,13 +4111,19 @@ FILESTAMP MasterClient_Ticker(); // acking the master server if (!server) - CL_SendClientCmd(); // send tic cmd + { + if (!resynch_local_inprogress) + CL_SendClientCmd(); // send tic cmd + hu_resynching = resynch_local_inprogress; + } else { if (!demoplayback) { INT32 counts; + hu_resynching = false; + firstticstosend = gametic; for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i] && nettics[i] < firstticstosend) @@ -3926,18 +4132,31 @@ FILESTAMP // Don't erase tics not acknowledged counts = realtics; - if (maketic + counts >= firstticstosend + BACKUPTICS) - counts = firstticstosend+BACKUPTICS-maketic-1; + for (i = 0; i < MAXNETNODES; ++i) + if (resynch_inprogress[i]) + { + SV_SendResynch(i); + counts = -666; + } - for (i = 0; i < counts; i++) - SV_Maketic(); // create missed tics and increment maketic + // do not make tics while resynching + if (counts != -666) + { + if (maketic + counts >= firstticstosend + BACKUPTICS) + counts = firstticstosend+BACKUPTICS-maketic-1; - for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged - D_Clearticcmd(tictoclear); // clear the maketic the new tic + for (i = 0; i < counts; i++) + SV_Maketic(); // create missed tics and increment maketic - SV_SendTics(); + for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged + D_Clearticcmd(tictoclear); // clear the maketic the new tic - neededtic = maketic; // the server is a client too + SV_SendTics(); + + neededtic = maketic; // the server is a client too + } + else + hu_resynching = true; } } Net_AckTicker(); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index d35c5cb3..0086132e 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -53,6 +53,8 @@ typedef enum PT_REQUESTFILE, // Client requests a file transfer PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. // If this ID changes, update masterserver definition. + PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic + PT_RESYNCHGET, // Player got resynch packet // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. @@ -66,7 +68,8 @@ typedef enum PT_TEXTCMD2, // Splitscreen text commands. PT_CLIENTJOIN, // Client wants to join; used in start game. PT_NODETIMEOUT, // Packet sent to self if the connection times out. - PT_CONSISTENCY, // Packet sent to resync players. + PT_RESYNCHING, // Packet sent to resync players. + // Blocks game advance until synched. #ifdef NEWPING PT_PING, // Packet sent to tell clients the other client's latency to server. #endif @@ -110,6 +113,147 @@ typedef struct ticcmd_t cmds[45]; // normally [BACKUPTIC][MAXPLAYERS] but too large } ATTRPACK servertics_pak; +// sent to client when all consistency data +// for players has been restored +typedef struct +{ + UINT32 randomseed; + + //ctf flag stuff + SINT8 flagplayer[2]; + INT32 flagloose[2]; + INT32 flagflags[2]; + fixed_t flagx[2]; + fixed_t flagy[2]; + fixed_t flagz[2]; + + UINT32 ingame; // spectator bit for each player + UINT32 ctfteam; // if not spectator, then which team? + + // Resynch game scores and the like all at once + UINT32 score[MAXPLAYERS]; // Everyone's score. + INT16 numboxes[MAXPLAYERS]; + INT16 totalring[MAXPLAYERS]; + tic_t realtime[MAXPLAYERS]; + UINT8 laps[MAXPLAYERS]; +} ATTRPACK resynchend_pak; + +typedef struct +{ + //player stuff + UINT8 playernum; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + UINT8 playerstate; //playerstate_t + UINT32 pflags; //pflags_t + UINT8 panim; //panim_t + + angle_t aiming; + INT32 currentweapon; + INT32 ringweapons; + UINT16 powers[NUMPOWERS]; + + // Score is resynched in the confirm resync packet + INT32 health; + SINT8 lives; + SINT8 continues; + UINT8 scoreadd; + SINT8 xtralife; + SINT8 pity; + + UINT8 skincolor; + INT32 skin; + // Just in case Lua does something like + // modify these at runtime + fixed_t normalspeed; + fixed_t runspeed; + UINT8 thrustfactor; + UINT8 accelstart; + UINT8 acceleration; + UINT8 charability; + UINT8 charability2; + UINT32 charflags; + UINT32 thokitem; //mobjtype_t + UINT32 spinitem; //mobjtype_t + UINT32 revitem; //mobjtype_t + INT32 actionspd; + INT32 mindash; + INT32 maxdash; + fixed_t jumpfactor; + + fixed_t speed; + UINT8 jumping; + UINT8 secondjump; + UINT8 fly1; + tic_t glidetime; + UINT8 climbing; + INT32 deadtimer; + tic_t exiting; + UINT8 homing; + fixed_t cmomx; + fixed_t cmomy; + fixed_t rmomx; + fixed_t rmomy; + + INT32 weapondelay; + INT32 tossdelay; + + INT16 starpostx; + INT16 starposty; + INT16 starpostz; + INT32 starpostnum; + tic_t starposttime; + angle_t starpostangle; + + INT32 maxlink; + fixed_t dashspeed; + INT32 dashtime; + angle_t angle_pos; + angle_t old_angle_pos; + tic_t bumpertime; + INT32 flyangle; + tic_t drilltimer; + INT32 linkcount; + tic_t linktimer; + INT32 anotherflyangle; + tic_t nightstime; + INT32 drillmeter; + UINT8 drilldelay; + UINT8 bonustime; + UINT8 mare; + INT16 lastsidehit, lastlinehit; + + tic_t losstime; + UINT8 timeshit; + INT32 onconveyor; + + //player->mo stuff + UINT8 hasmo; //boolean + + angle_t angle; + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t momx; + fixed_t momy; + fixed_t momz; + fixed_t friction; + fixed_t movefactor; + + INT16 tics; + statenum_t statenum; + UINT32 flags; + UINT32 flags2; + UINT8 eflags; + + fixed_t radius; + fixed_t height; + fixed_t scale; + fixed_t destscale; + fixed_t scalespeed; +} ATTRPACK resynch_pak; + typedef struct { UINT8 version; // different versions don't work @@ -194,143 +338,6 @@ typedef struct tic_t time; // used for ping evaluation } ATTRPACK msaskinfo_pak; -typedef struct -{ - UINT32 randomseed; - - //ctf flag stuff - UINT8 rflagloose; - UINT8 bflagloose; - INT32 rfuse; - INT32 bfuse; - INT32 rflags2; - INT32 bflags2; - INT16 rflagx; - INT16 rflagy; - INT16 rflagz; - INT16 bflagx; - INT16 bflagy; - INT16 bflagz; - - //player stuff - UINT8 playernum; - - UINT8 playerstate; //playerstate_t - ticcmd_t cmd; - fixed_t viewz; - fixed_t viewheight; - fixed_t deltaviewheight; - fixed_t bob; - angle_t aiming; - angle_t awayviewaiming; - INT32 phealth; - SINT8 pity; - INT32 currentweapon; - INT32 ringweapons; - UINT16 powers[NUMPOWERS]; - UINT32 pflags; //pflags_t - UINT8 panim; //panim_t - INT32 flashcount; - UINT8 skincolor; - INT32 skin; - UINT32 score; - INT32 maxlink; - fixed_t dashspeed; - INT32 dashtime; - fixed_t normalspeed; - fixed_t runspeed; - UINT8 thrustfactor; - UINT8 accelstart; - UINT8 acceleration; - UINT8 charability; - UINT8 charability2; - UINT32 charflags; - UINT32 thokitem; //mobjtype_t - UINT32 spinitem; //mobjtype_t - UINT32 revitem; //mobjtype_t - INT32 actionspd; - INT32 mindash; - INT32 maxdash; - fixed_t jumpfactor; - INT32 lives; - INT32 continues; - INT32 xtralife; - fixed_t speed; - INT32 jumping; - UINT8 secondjump; - UINT8 fly1; - UINT8 scoreadd; - tic_t glidetime; - UINT8 climbing; - INT32 deadtimer; - tic_t exiting; - UINT8 homing; - tic_t skidtime; - fixed_t cmomx; - fixed_t cmomy; - fixed_t rmomx; - fixed_t rmomy; - INT32 numboxes; - INT32 totalring; - tic_t realtime; - UINT32 laps; - INT32 ctfteam; - UINT16 gotflag; - INT32 weapondelay; - INT32 tossdelay; - INT16 starpostx; - INT16 starposty; - INT16 starpostz; - INT32 starpostnum; - tic_t starposttime; - angle_t starpostangle; - angle_t angle_pos; - angle_t old_angle_pos; - tic_t bumpertime; - INT32 flyangle; - tic_t drilltimer; - INT32 linkcount; - tic_t linktimer; - INT32 anotherflyangle; - tic_t nightstime; - INT32 drillmeter; - UINT8 drilldelay; - UINT8 bonustime; - UINT8 mare; - INT16 lastsidehit, lastlinehit; - tic_t losstime; - UINT8 timeshit; - INT32 onconveyor; - UINT8 spectator; //boolean - tic_t jointime; - - //player->mo stuff - UINT8 hasmo; //boolean - - angle_t angle; - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t momx; - fixed_t momy; - fixed_t momz; - fixed_t friction; - fixed_t movefactor; - - INT32 tics; - statenum_t statenum; - UINT32 flags; - UINT32 flags2; - UINT8 eflags; - INT32 health; - - fixed_t radius; - fixed_t height; - fixed_t scale; - fixed_t destscale; - fixed_t scalespeed; -} ATTRPACK cons_pak; - // Shorter player information for external use. typedef struct { @@ -372,6 +379,9 @@ typedef struct client2cmd_pak client2pak; // 200 bytes servertics_pak serverpak; // 132495 bytes serverconfig_pak servercfg; // 773 bytes + resynchend_pak resynchend; // + resynch_pak resynchpak; // + UINT8 resynchgot; // UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 136 bytes @@ -379,7 +389,6 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - cons_pak consistency; // 544 bytes plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes #ifdef NEWPING @@ -437,7 +446,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; #endif -extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_consfailprotect, cv_blamecfail, cv_maxsend; +extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend; // used in d_net, the only dependence tic_t ExpandTics(INT32 low); @@ -492,4 +501,5 @@ void D_ResetTiccmds(void); tic_t GetLag(INT32 node); UINT8 GetFreeXCmdSize(void); +extern UINT8 hu_resynching; #endif diff --git a/src/d_main.c b/src/d_main.c index 2492f622..02590390 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -401,7 +401,10 @@ static void D_Display(void) if (lastdraw) { if (rendermode == render_soft) + { VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + usebuffer = true; + } lastdraw = false; } @@ -1094,7 +1097,7 @@ void D_SRB2Main(void) W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta - W_VerifyFileMD5(4, "12c58561edf3be16a15505f1d5eacee0"); // patch.dta + W_VerifyFileMD5(4, "e868046d2d2da1d8c706c900edfb03f8"); // patch.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. diff --git a/src/d_net.c b/src/d_net.c index 3c2213fc..d93b80c9 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -784,18 +784,6 @@ static void DebugPrintpacket(const char *header) fprintfstring((char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics],(size_t)( &((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics])); break; - case PT_CONSISTENCY: - fprintf(debugfile, " randomseed %d playernum %d hasmo %d\n", - netbuffer->u.consistency.randomseed, netbuffer->u.consistency.playernum, netbuffer->u.consistency.hasmo); - fprintf(debugfile, " x %d y %d z %d momx %d momy %d momz %d\n", - netbuffer->u.consistency.x, netbuffer->u.consistency.y, netbuffer->u.consistency.z, - netbuffer->u.consistency.momx, netbuffer->u.consistency.momy, netbuffer->u.consistency.momz); - fprintf(debugfile, " angle %d health %d eflags %d flags %d flags2 %d\n", - netbuffer->u.consistency.angle, netbuffer->u.consistency.health, netbuffer->u.consistency.eflags, - netbuffer->u.consistency.flags, netbuffer->u.consistency.flags2); - fprintf(debugfile, " friction %d movefactor %d tics %d statenum %d\n", - netbuffer->u.consistency.friction, netbuffer->u.consistency.movefactor, - netbuffer->u.consistency.tics, (INT32)netbuffer->u.consistency.statenum); case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 57445244..06c6fcb0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3138,10 +3138,8 @@ static void Command_Addfile(void) p = fn+strlen(fn); while(--p >= fn) if (*p == '\\' || *p == '/' || *p == ':') - { - ++p; break; - } + ++p; WRITESTRINGN(buf_p,p,240); { @@ -4094,8 +4092,17 @@ static void Command_Isgamemodified_f(void) static void Command_Cheats_f(void) { + if (COM_CheckParm("off")) + { + CV_ResetCheatNetVars(); + return; + } + if (CV_CheatsEnabled()) + { CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n")); + CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.")); + } else CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n")); } diff --git a/src/d_player.h b/src/d_player.h index 3abc6ddf..4b297854 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -147,7 +147,7 @@ typedef enum PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek. PF_TAGIT = 1<<28, // The player is it! For Tag Mode - // free: 1<<29, 1<<31 + // free: 1<<29 through 1<<31 } pflags_t; typedef enum @@ -268,10 +268,9 @@ typedef struct player_s // It is updated with cmd->aiming. angle_t aiming; - angle_t awayviewaiming; // Used for cut-away view - // This is only used between levels, // mo->health is used during levels. + /// \todo Remove this. We don't need a second health definition for players. INT32 health; SINT8 pity; // i pity the fool. @@ -324,15 +323,14 @@ typedef struct player_s fixed_t jumpfactor; // How high can the player jump? - INT32 lives; - INT32 continues; // continues that player has acquired + SINT8 lives; + SINT8 continues; // continues that player has acquired - INT32 xtralife; // Ring Extra Life counter + SINT8 xtralife; // Ring Extra Life counter UINT8 gotcontinue; // Got continue from this stage? fixed_t speed; // Player's speed (distance formula of MOMX and MOMY values) - INT32 jumping; // Jump counter - + UINT8 jumping; // Jump counter UINT8 secondjump; UINT8 fly1; // Tails flying @@ -357,10 +355,10 @@ typedef struct player_s ///////////////////// // Race Mode Stuff // ///////////////////// - INT32 numboxes; // Number of item boxes obtained for Race Mode - INT32 totalring; // Total number of rings obtained for Race Mode + INT16 numboxes; // Number of item boxes obtained for Race Mode + INT16 totalring; // Total number of rings obtained for Race Mode tic_t realtime; // integer replacement for leveltime - UINT32 laps; // Number of laps (optional) + UINT8 laps; // Number of laps (optional) //////////////////// // CTF Mode Stuff // @@ -421,6 +419,7 @@ typedef struct player_s mobj_t *awayviewmobj; INT32 awayviewtics; + angle_t awayviewaiming; // Used for cut-away view boolean spectator; UINT8 bot; diff --git a/src/dehacked.c b/src/dehacked.c index e25f66e7..6eae1ce2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1132,7 +1132,7 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "PALETTE")) mapheaderinfo[num-1]->palette = (UINT16)i; else if (fastcmp(word, "NUMLAPS")) - mapheaderinfo[num-1]->numlaps = (UINT32)i; + mapheaderinfo[num-1]->numlaps = (UINT8)i; else if (fastcmp(word, "UNLOCKABLE")) { if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something @@ -7325,24 +7325,29 @@ static const char *const HUDITEMS_LIST[] = { "LIVESPIC", "LIVESNUM", "LIVESX", - "RINGSSPLIT", - "RINGSNUMSPLIT", + "RINGS", + "RINGSSPLIT", "RINGSNUM", + "RINGSNUMSPLIT", + "SCORE", "SCORENUM", - "TIMESPLIT", - "SECONDSSPLIT", - "MINUTESSPLIT", - "TIMECOLONSPLIT", + "TIME", - "TICS", - "SECONDS", + "TIMESPLIT", "MINUTES", + "MINUTESSPLIT", "TIMECOLON", + "TIMECOLONSPLIT", + "SECONDS", + "SECONDSSPLIT", "TIMETICCOLON", - "SS_TOTALRINGS_SPLIT", + "TICS", + "SS_TOTALRINGS", + "SS_TOTALRINGS_SPLIT", + "GETRINGS", "GETRINGSNUM", "TIMELEFT", @@ -7683,6 +7688,9 @@ struct { {"V_70TRANS",V_70TRANS}, {"V_80TRANS",V_80TRANS}, {"V_90TRANS",V_90TRANS}, + {"V_HUDTRANSHALF",V_HUDTRANSHALF}, + {"V_HUDTRANS",V_HUDTRANS}, + {"V_HUDTRANSDOUBLE",V_HUDTRANSDOUBLE}, {"V_AUTOFADEOUT",V_AUTOFADEOUT}, {"V_RETURN8",V_RETURN8}, {"V_OFFSET",V_OFFSET}, diff --git a/src/doomdata.h b/src/doomdata.h index 4023c497..371decc2 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -131,6 +131,7 @@ typedef struct #define ML_NOSONIC 2048 #define ML_NOTAILS 4096 #define ML_NOKNUX 8192 +#define ML_NETONLY 14336 // all of the above // Bounce off walls! #define ML_BOUNCY 16384 diff --git a/src/doomdef.h b/src/doomdef.h index d4ad4a68..a5454851 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -144,8 +144,8 @@ extern FILE *logstream; #define VERSIONSTRING "Trunk" #else #define VERSION 201 // Game version -#define SUBVERSION 3 // more precise version number -#define VERSIONSTRING "v2.1.3" +#define SUBVERSION 4 // more precise version number +#define VERSIONSTRING "v2.1.4" #endif // Modification options @@ -201,7 +201,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 7 +#define MODVERSION 9 diff --git a/src/doomstat.h b/src/doomstat.h index 576b7009..642e9bfc 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -227,7 +227,7 @@ typedef struct UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. INT16 countdown; ///< Countdown until level end? UINT16 palette; ///< PAL lump to use on this map - UINT32 numlaps; ///< Number of laps in circuit mode, unless overridden. + UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) diff --git a/src/g_game.c b/src/g_game.c index e3f2a281..dfd9aacd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1467,10 +1467,12 @@ static void Analog_OnChange(void) { if (!cv_cam_dist.string) return; + + // cameras are not initialized at this point + if (leveltime > 1) CV_SetValue(&cv_cam_dist, 128); - - if (netgame || !camera.chase) + if (netgame) CV_StealthSetValue(&cv_analog, 0); else if (cv_analog.value || demoplayback) CV_SetValue(&cv_cam_dist, 192); @@ -1480,9 +1482,12 @@ static void Analog2_OnChange(void) { if (!splitscreen || !cv_cam2_dist.string) return; + + // cameras are not initialized at this point + if (leveltime > 1) CV_SetValue(&cv_cam2_dist, 128); - if (netgame || !camera2.chase) + if (netgame) CV_StealthSetValue(&cv_analog2, 0); else if (cv_analog2.value) CV_SetValue(&cv_cam2_dist, 192); @@ -1927,7 +1932,6 @@ void G_PlayerReborn(INT32 player) INT32 score; INT32 lives; INT32 continues; - INT32 xtralife; UINT8 charability; UINT8 charability2; fixed_t normalspeed; @@ -1952,9 +1956,9 @@ void G_PlayerReborn(INT32 player) INT32 starpostangle; fixed_t jumpfactor; INT32 exiting; - INT32 numboxes; - INT32 laps; - INT32 totalring; + INT16 numboxes; + INT16 totalring; + UINT8 laps; UINT8 mare; UINT8 skincolor; INT32 skin; @@ -1966,7 +1970,6 @@ void G_PlayerReborn(INT32 player) score = players[player].score; lives = players[player].lives; continues = players[player].continues; - xtralife = players[player].xtralife; ctfteam = players[player].ctfteam; exiting = players[player].exiting; jointime = players[player].jointime; @@ -2017,7 +2020,6 @@ void G_PlayerReborn(INT32 player) p->lives = lives; p->continues = continues; p->pflags = pflags; - p->xtralife = xtralife; p->ctfteam = ctfteam; p->jointime = jointime; p->spectator = spectator; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 43d4537f..168761a0 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -67,6 +67,10 @@ typedef UINT8 GLRGB[3]; #define BLENDMODE PF_Translucent +static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; +static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; +static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; + // // -----------------+ // HWR_DrawPatch : Draw a 'tile' graphic @@ -128,24 +132,16 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale) +void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); + UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); // 3--2 // | /| @@ -153,11 +149,17 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, // 0--1 float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(scale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(scale); + float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); + float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + + if (alphalevel >= 10 && alphalevel < 13) + return; // make patch ready in hardware cache - HWR_GetPatch(gpatch); + if (!colormap) + HWR_GetPatch(gpatch); + else + HWR_GetMappedPatch(gpatch, colormap); switch (option & V_SCALEPATCHMASK) { @@ -197,11 +199,14 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) + if (alphalevel) { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -209,13 +214,13 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { FOutVector v[4]; FBITFIELD flags; - float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); + UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); // 3--2 // | /| @@ -223,8 +228,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix // 0--1 float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(scale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(scale); + float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); + float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + + if (alphalevel >= 10 && alphalevel < 13) + return; // make patch ready in hardware cache HWR_GetPatch(gpatch); @@ -247,17 +255,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix if (option & V_NOSCALESTART) sdupx = sdupy = 2.0f; - v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = ((cx-sx)*sdupx+(w-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-((cy-sy)*sdupy+(h-gpatch->topoffset)*pdupy)/vid.height; + v[0].x = v[3].x = (cx*sdupx - gpatch->leftoffset * pdupx) / vid.width - 1; + v[2].x = v[1].x = (cx*sdupx + ((w-sx) - gpatch->leftoffset) * pdupx) / vid.width - 1; + v[0].y = v[1].y = 1 - (cy*sdupy - gpatch->topoffset * pdupy) / vid.height; + v[2].y = v[3].y = 1 - (cy*sdupy + ((h-sy) - gpatch->topoffset) * pdupy) / vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = ((float)sx/(float)gpatch->height); - v[2].sow = v[1].sow = gpatch->max_s*((float)w/(float)gpatch->width); - v[0].tow = v[1].tow = ((float)sy/(float)gpatch->height); - v[2].tow = v[3].tow = gpatch->max_t*((float)h/(float)gpatch->height); + v[0].sow = v[3].sow = ((sx)/(float)gpatch->width )*gpatch->max_s; + v[2].sow = v[1].sow = ((w )/(float)gpatch->width )*gpatch->max_s; + v[0].tow = v[1].tow = ((sy)/(float)gpatch->height)*gpatch->max_t; + v[2].tow = v[3].tow = ((h )/(float)gpatch->height)*gpatch->max_t; flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; @@ -267,217 +275,14 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) + if (alphalevel) { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); -} - -void HWR_DrawClippedPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - // hardware clips the patch quite nicely anyway :) - HWR_DrawPatch(gpatch, x, y, option); /// \todo do real cliping -} - -// Only supports one kind of translucent for now. Tails 06-12-2003 -// Boked -// Alam_GBC: Why? you could not get a FSurfaceInfo to set the alpha channel? -void HWR_DrawTranslucentPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - FSurfaceInfo Surf; - - // make patch ready in hardware cache - HWR_GetPatch (gpatch); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = PF_Modulated | BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - // Alam_GBC: There, you have translucent HW Draw, OK? - if ((option & V_TRANSLUCENT) && cv_grtranslucenthud.value != 255) - { - Surf.FlatColor.s.alpha = (UINT8)(cv_grtranslucenthud.value/2); - } - else - Surf.FlatColor.s.alpha = 127; - - HWD.pfnDrawPolygon(&Surf, v, 4, flags); -} - -// Draws a patch 2x as small SSNTails 06-10-2003 -void HWR_DrawSmallPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap) -{ - FOutVector v[4]; - FBITFIELD flags; - - float sdupx = FIXED_TO_FLOAT(vid.fdupx); - float sdupy = FIXED_TO_FLOAT(vid.fdupy); - float pdupx = FIXED_TO_FLOAT(vid.fdupx); - float pdupy = FIXED_TO_FLOAT(vid.fdupy); - - // make patch ready in hardware cache - HWR_GetMappedPatch (gpatch, colormap); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); -} - -// -// HWR_DrawMappedPatch(): Like HWR_DrawPatch but with translated color -// -void HWR_DrawMappedPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap) -{ - FOutVector v[4]; - FBITFIELD flags; - - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - - // make patch ready in hardware cache - HWR_GetMappedPatch (gpatch, colormap); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -517,15 +322,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // But then, the question is: why not 0 instead of PF_Masked ? // or maybe PF_Environment ??? (like what I said above) // BP: PF_Environment don't change anything ! and 0 is undifined - if (cv_grtranslucenthud.value != 255) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated | BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); + HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); } // ========================================================================== diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index a6cf3fb7..c93d4ea6 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -44,12 +44,9 @@ boolean HWR_Screenshot(const char *lbmname); void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawClippedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale); +void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap); +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); -void HWR_DrawTranslucentPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawSmallPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); -void HWR_DrawMappedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c8f452a6..14f6d54a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -903,7 +903,7 @@ static inline void HU_DrawCrosshair(void) #endif y = viewwindowy + (viewheight>>1); - V_DrawTranslucentPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET, crosshair[i - 1]); + V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); } static inline void HU_DrawCrosshair2(void) @@ -933,7 +933,7 @@ static inline void HU_DrawCrosshair2(void) #endif y += viewheight; - V_DrawTranslucentPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET, crosshair[i - 1]); + V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); } } @@ -1086,6 +1086,10 @@ void HU_Drawer(void) if (!automapactive && cv_crosshair2.value && !demoplayback && !camera2.chase && !players[secondarydisplayplayer].spectator) HU_DrawCrosshair2(); + + // draw desynch text + if (hu_resynching) + V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP, "Resynching..."); } //====================================================================== @@ -1619,7 +1623,7 @@ static void HU_DrawRankings(void) { if (circuitmap) { - if (players[i].laps+1 >= tab[scorelines].count && completed[i] == false) + if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false) { tab[scorelines].count = players[i].laps+1; tab[scorelines].num = i; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index f80d9809..47bd4370 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -222,21 +222,7 @@ static int libd_draw(lua_State *L) flags &= ~V_PARAMMASK; // Don't let crashes happen. - if (colormap) - { - if (flags & V_ALPHAMASK) - V_DrawTranslucentMappedPatch(x, y, flags, patch, colormap); - else - V_DrawMappedPatch(x, y, flags, patch, colormap); - } - else - { - if (flags & V_ALPHAMASK) - V_DrawTranslucentPatch(x, y, flags, patch); - else - V_DrawScaledPatch(x, y, flags, patch); - } - + V_DrawFixedPatch(x<bob); else if (fastcmp(field,"aiming")) lua_pushinteger(L, plr->aiming); - else if (fastcmp(field,"awayviewaiming")) - lua_pushinteger(L, plr->awayviewaiming); else if (fastcmp(field,"health")) lua_pushinteger(L, plr->health); else if (fastcmp(field,"pity")) @@ -187,7 +185,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"speed")) lua_pushinteger(L, plr->speed); else if (fastcmp(field,"jumping")) - lua_pushinteger(L, plr->jumping); + lua_pushboolean(L, plr->jumping); else if (fastcmp(field,"secondjump")) lua_pushinteger(L, plr->secondjump); else if (fastcmp(field,"fly1")) @@ -306,6 +304,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->awayviewmobj, META_MOBJ); else if (fastcmp(field,"awayviewtics")) lua_pushinteger(L, plr->awayviewtics); + else if (fastcmp(field,"awayviewaiming")) + lua_pushinteger(L, plr->awayviewaiming); else if (fastcmp(field,"spectator")) lua_pushinteger(L, plr->spectator); else if (fastcmp(field,"bot")) @@ -365,8 +365,6 @@ static int player_set(lua_State *L) else if (plr == &players[secondarydisplayplayer]) localaiming2 = plr->aiming; } - else if (fastcmp(field,"awayviewaiming")) - plr->awayviewaiming = (angle_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"health")) plr->health = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"pity")) @@ -424,17 +422,17 @@ static int player_set(lua_State *L) else if (fastcmp(field,"jumpfactor")) plr->jumpfactor = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lives")) - plr->lives = (INT32)luaL_checkinteger(L, 3); + plr->lives = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"continues")) - plr->continues = (INT32)luaL_checkinteger(L, 3); + plr->continues = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"xtralife")) - plr->xtralife = (INT32)luaL_checkinteger(L, 3); + plr->xtralife = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"gotcontinue")) plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"speed")) plr->speed = (fixed_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"jumping")) - plr->jumping = (INT32)luaL_checkinteger(L, 3); + plr->jumping = luaL_checkboolean(L, 3); else if (fastcmp(field,"secondjump")) plr->secondjump = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"fly1")) @@ -462,13 +460,13 @@ static int player_set(lua_State *L) else if (fastcmp(field,"rmomy")) plr->rmomy = (fixed_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"numboxes")) - plr->numboxes = (INT32)luaL_checkinteger(L, 3); + plr->numboxes = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"totalring")) - plr->totalring = (INT32)luaL_checkinteger(L, 3); + plr->totalring = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"realtime")) plr->realtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"laps")) - plr->laps = (UINT32)luaL_checkinteger(L, 3); + plr->laps = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"ctfteam")) plr->ctfteam = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"gotflag")) @@ -567,6 +565,8 @@ static int player_set(lua_State *L) if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. } + else if (fastcmp(field,"awayviewaiming")) + plr->awayviewaiming = (angle_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"spectator")) plr->spectator = lua_toboolean(L, 3); else if (fastcmp(field,"bot")) diff --git a/src/m_cheat.c b/src/m_cheat.c index 44c6f03e..16bd88ad 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -464,9 +464,9 @@ void Command_Savecheckpoint_f(void) // Like M_GetAllEmeralds() but for console devmode junkies. void Command_Getallemeralds_f(void) { - REQUIRE_PANDORA; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; emeralds = ((EMERALD7)*2)-1; @@ -475,8 +475,8 @@ void Command_Getallemeralds_f(void) void Command_Resetemeralds_f(void) { - REQUIRE_PANDORA; REQUIRE_SINGLEPLAYER; + REQUIRE_PANDORA; emeralds = 0; @@ -511,10 +511,10 @@ void Command_Devmode_f(void) void Command_Setrings_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -530,10 +530,10 @@ void Command_Setrings_f(void) void Command_Setlives_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -547,10 +547,10 @@ void Command_Setlives_f(void) void Command_Setcontinues_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { diff --git a/src/m_menu.c b/src/m_menu.c index 5aad4e77..0676bb52 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1137,8 +1137,6 @@ static menuitem_t OP_OpenGLOptionsMenu[] = #ifdef _WINDOWS {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, #endif - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "Translucent HUD", &cv_grtranslucenthud, 60}, #ifdef ALAM_LIGHTING {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70}, #endif @@ -1245,17 +1243,19 @@ static menuitem_t OP_GameOptionsMenu[] = NULL, "Master server", &cv_masterserver, 10}, #endif {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40}, - {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 50}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "HUD Visibility", &cv_translucenthud, 50}, + {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60}, #ifdef SEENAMES - {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 60}, + {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80}, #endif - {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 70}, + {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90}, - {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 90}, - {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,100}, - {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 110}, + {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100}, + {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110}, + {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120}, - {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 130}, + {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140}, }; static menuitem_t OP_ServerOptionsMenu[] = @@ -1276,7 +1276,7 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 110}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 120}, {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 130}, - {IT_STRING | IT_CVAR, NULL, "Consistency Protection", &cv_consfailprotect, 140}, + {IT_STRING | IT_CVAR, NULL, "Attempts to Resynch", &cv_resynchattempts, 140}, #endif }; @@ -4681,9 +4681,9 @@ static void M_DrawSetupChoosePlayerMenu(void) } patch = W_CachePatchName(picname, PU_CACHE); if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<height) - 64 + o*2, SHORT(patch->width), SHORT(patch->height)); + V_DrawCroppedPatch(8<height) - 64 + o*2, SHORT(patch->width), SHORT(patch->height)); else - V_DrawCroppedPatch(8<height) - 32 + o, SHORT(patch->width), SHORT(patch->height)); + V_DrawCroppedPatch(8<height) - 32 + o, SHORT(patch->width), SHORT(patch->height)); W_UnlockCachedPatch(patch); } @@ -4707,9 +4707,9 @@ static void M_DrawSetupChoosePlayerMenu(void) } patch = W_CachePatchName(picname, PU_CACHE); if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), o*2); + V_DrawCroppedPatch(8<width), o*2); else - V_DrawCroppedPatch(8<width), o); + V_DrawCroppedPatch(8<width), o); W_UnlockCachedPatch(patch); } @@ -4741,9 +4741,9 @@ static void M_DrawSetupChoosePlayerMenu(void) else { if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), SHORT(patch->height)); + V_DrawCroppedPatch(8<width), SHORT(patch->height)); else - V_DrawCroppedPatch(8<width), SHORT(patch->height)); + V_DrawCroppedPatch(8<width), SHORT(patch->height)); } W_UnlockCachedPatch(patch); } diff --git a/src/p_map.c b/src/p_map.c index 8b7869b8..eb7c6ad7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2552,7 +2552,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) // one-sided linedef if (!li->backsector) { - if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, li)) + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) return true; // don't hit the back side goto isblocking; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 17db0062..baa04211 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -120,6 +120,13 @@ static inline void P_NetArchivePlayers(void) flags = 0; + // ticcmd write + WRITESINT8(save_p, players[i].cmd.forwardmove); + WRITESINT8(save_p, players[i].cmd.sidemove); + WRITEINT16(save_p, players[i].cmd.angleturn); + WRITEINT16(save_p, players[i].cmd.aiming); + WRITEUINT16(save_p, players[i].cmd.buttons); + WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME); WRITEANGLE(save_p, players[i].aiming); WRITEANGLE(save_p, players[i].awayviewaiming); @@ -146,12 +153,12 @@ static inline void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].score); WRITEINT32(save_p, players[i].dashspeed); WRITEINT32(save_p, players[i].dashtime); - WRITEINT32(save_p, players[i].lives); - WRITEINT32(save_p, players[i].continues); - WRITEINT32(save_p, players[i].xtralife); + WRITESINT8(save_p, players[i].lives); + WRITESINT8(save_p, players[i].continues); + WRITESINT8(save_p, players[i].xtralife); WRITEUINT8(save_p, players[i].gotcontinue); WRITEINT32(save_p, players[i].speed); - WRITEINT32(save_p, players[i].jumping); + WRITEUINT8(save_p, players[i].jumping); WRITEUINT8(save_p, players[i].secondjump); WRITEUINT8(save_p, players[i].fly1); WRITEUINT8(save_p, players[i].scoreadd); @@ -176,7 +183,7 @@ static inline void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].numboxes); WRITEINT32(save_p, players[i].totalring); WRITEUINT32(save_p, players[i].realtime); - WRITEUINT32(save_p, players[i].laps); + WRITEUINT8(save_p, players[i].laps); //////////////////// // CTF Mode Stuff // @@ -282,6 +289,7 @@ static inline void P_NetUnArchivePlayers(void) { INT32 i, j; UINT16 flags; + ticcmd_t tmptic; if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) I_Error("Bad $$$.sav at archive block Players"); @@ -292,6 +300,14 @@ static inline void P_NetUnArchivePlayers(void) if (!playeringame[i]) continue; + memset(&tmptic, 0, sizeof(ticcmd_t)); + tmptic.forwardmove = READSINT8(save_p); + tmptic.sidemove = READSINT8(save_p); + tmptic.angleturn = READINT16(save_p); + tmptic.aiming = READINT16(save_p); + tmptic.buttons = READUINT16(save_p); + G_CopyTiccmd(&players[i].cmd, &tmptic, 1); + READSTRINGN(save_p, player_names[i], MAXPLAYERNAME); players[i].aiming = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p); @@ -318,12 +334,12 @@ static inline void P_NetUnArchivePlayers(void) players[i].score = READUINT32(save_p); players[i].dashspeed = READINT32(save_p); // dashing speed players[i].dashtime = READINT32(save_p); // dashing speed - players[i].lives = READINT32(save_p); - players[i].continues = READINT32(save_p); // continues that player has acquired - players[i].xtralife = READINT32(save_p); // Ring Extra Life counter + players[i].lives = READSINT8(save_p); + players[i].continues = READSINT8(save_p); // continues that player has acquired + players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter players[i].gotcontinue = READUINT8(save_p); // got continue from stage players[i].speed = READINT32(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].jumping = READINT32(save_p); // Jump counter + players[i].jumping = READUINT8(save_p); // Jump counter players[i].secondjump = READUINT8(save_p); players[i].fly1 = READUINT8(save_p); // Tails flying players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus @@ -348,7 +364,7 @@ static inline void P_NetUnArchivePlayers(void) players[i].numboxes = READINT32(save_p); // Number of item boxes obtained for Race Mode players[i].totalring = READINT32(save_p); // Total number of rings obtained for Race Mode players[i].realtime = READUINT32(save_p); // integer replacement for leveltime - players[i].laps = READUINT32(save_p); // Number of laps (optional) + players[i].laps = READUINT8(save_p); // Number of laps (optional) //////////////////// // CTF Mode Stuff // diff --git a/src/p_spec.c b/src/p_spec.c index 20d86176..fa6200cd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3854,10 +3854,10 @@ DoneSection2: if (player->pflags & PF_NIGHTSMODE) player->drillmeter += 48*20; - if (player->laps >= (unsigned)cv_numlaps.value) + if (player->laps >= (UINT8)cv_numlaps.value) CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); else - CONS_Printf(M_GetText("%s started lap %d\n"), player_names[player-players],player->laps+1); + CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); // Reset starposts (checkpoints) info player->starpostangle = player->starposttime = player->starpostnum = 0; @@ -5342,10 +5342,14 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].special == 6) { // Ability flags can disable disable linedefs now, lol - if ((netgame || multiplayer) - || (!(players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - && !(players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - && !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)))) + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if (((lines[i].flags & ML_NETONLY) != ML_NETONLY) + && !(players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) + && !(players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) + && !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX ))) { for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) { @@ -5404,7 +5408,16 @@ void P_SpawnSpecials(INT32 fromnetsave) for (i = 0; i < numlines; i++) { // set line specials to 0 here too, same reason as above - if (!(netgame || multiplayer)) + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) + { + lines[i].special = 0; + continue; + } + else { if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) { diff --git a/src/p_user.c b/src/p_user.c index 5aa0d50a..ac026a11 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8113,19 +8113,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall + ((*rover->topheight - *rover->bottomheight)/2)); delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)) - { + if (*rover->topheight > myfloorz && abs(delta1) < abs(delta2)) myfloorz = *rover->topheight; - } - if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)) - { + if (*rover->bottomheight < myceilingz && abs(delta1) >= abs(delta2)) myceilingz = *rover->bottomheight; - } } } #ifdef POLYOBJECTS - // Check polyobjects and see if tmfloorz/tmceilingz need to be altered + // Check polyobjects and see if floorz/ceilingz need to be altered { INT32 xl, xh, yl, yh, bx, by; validcount++; @@ -8191,10 +8187,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall delta1 = midz - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) + if (polytop > myfloorz && abs(delta1) < abs(delta2)) myfloorz = polytop; - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < myceilingz && abs(delta1) >= abs(delta2)) myceilingz = polybottom; } plink = (polymaplink_t *)(plink->link.next); @@ -8204,7 +8200,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall #endif // crushed camera - if (myceilingz <= myfloorz && !resetcalled && !cameranoclip) + if (myceilingz <= myfloorz + thiscam->height && !resetcalled && !cameranoclip) { P_ResetCamera(player, thiscam); return true; @@ -8645,7 +8641,7 @@ void P_PlayerThink(player_t *player) if (players[i].lives <= 0) continue; - if (!players[i].exiting) + if (!players[i].exiting || players[i].exiting > 3) break; } diff --git a/src/r_main.c b/src/r_main.c index c55de394..6af1bf46 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -122,7 +122,7 @@ static CV_PossibleValue_t drawdist_cons_t[] = { {3072, "3072"}, {4096, "4096"}, {6144, "6144"}, {8192, "8192"}, {0, "Infinite"}, {0, NULL}}; static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; -static CV_PossibleValue_t grtranslucenthud_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; static void ChaseCam_OnChange(void); @@ -141,7 +141,7 @@ consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0 consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grtranslucenthud = {"gr_translucenthud", "255", CV_SAVE|CV_CALL, grtranslucenthud_cons_t, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1237,11 +1237,11 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_rotspeed); CV_RegisterVar(&cv_showhud); + CV_RegisterVar(&cv_translucenthud); // Default viewheight is changeable, // initialized to standard viewheight CV_RegisterVar(&cv_viewheight); - CV_RegisterVar(&cv_grtranslucenthud); #ifdef HWRENDER // GL-specific Commands diff --git a/src/r_main.h b/src/r_main.h index 8a39b7d3..a367960c 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -81,9 +81,8 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); // REFRESH - the actual rendering functions. // -extern consvar_t cv_showhud; +extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; -extern consvar_t cv_grtranslucenthud; extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow, cv_shadowoffs; diff --git a/src/st_stuff.c b/src/st_stuff.c index 56ce8e4e..9f5a691e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -129,27 +129,29 @@ hudinfo_t hudinfo[NUMHUDITEMS] = { 16, 176}, // HUD_LIVESPIC { 74, 184}, // HUD_LIVESNUM { 38, 186}, // HUD_LIVESX - { 220, 10}, // HUD_RINGSSPLIT - { 288, 10}, // HUD_RINGSNUMSPLIT + { 16, 42}, // HUD_RINGS + { 220, 10}, // HUD_RINGSSPLIT { 112, 42}, // HUD_RINGSNUM + { 288, 10}, // HUD_RINGSNUMSPLIT + { 16, 10}, // HUD_SCORE { 128, 10}, // HUD_SCORENUM - { 136, 10}, // HUD_TIMESPLIT - { 212, 10}, // HUD_SECONDSSPLIT - { 188, 10}, // HUD_MINUTESSPLIT - { 188, 10}, // HUD_TIMECOLONSPLIT { 17, 26}, // HUD_TIME - + { 136, 10}, // HUD_TIMESPLIT + { 88, 26}, // HUD_MINUTES + { 188, 10}, // HUD_MINUTESSPLIT + { 88, 26}, // HUD_TIMECOLON + { 188, 10}, // HUD_TIMECOLONSPLIT + { 112, 26}, // HUD_SECONDS + { 212, 10}, // HUD_SECONDSSPLIT + { 112, 26}, // HUD_TIMETICCOLON { 136, 26}, // HUD_TICS - { 112, 26}, // HUD_SECONDS - { 88, 26}, // HUD_MINUTES - { 88, 26}, // HUD_TIMECOLON - { 112, 26}, // HUD_TIMETICCOLON - { 288, 40}, // HUD_SS_TOTALRINGS_SPLIT { 112, 56}, // HUD_SS_TOTALRINGS + { 288, 40}, // HUD_SS_TOTALRINGS_SPLIT + { 110, 93}, // HUD_GETRINGS { 160, 93}, // HUD_GETRINGSNUM { 124, 160}, // HUD_TIMELEFT @@ -160,9 +162,6 @@ hudinfo_t hudinfo[NUMHUDITEMS] = { 240, 160}, // HUD_LAP }; -#define ST_DrawOverlayNum(x,y,f,n) V_DrawTallNum(x, y, f|V_TRANSLUCENT, n) -#define ST_DrawPaddedOverlayNum(x,y,n,d) V_DrawPaddedTallNum(x, y, V_NOSCALESTART|V_TRANSLUCENT, n, d) - // // STATUS BAR CODE // @@ -463,6 +462,7 @@ static INT32 SCX(INT32 x) return FixedInt(FixedMul(x<width); - const UINT8 *colormap; - - if (colornum == 0) - colormap = colormaps; - else // Uses the player colors. - colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); - - I_Assert(num >= 0); // this function does not draw negative numbers - - // draw the number - do - { - x -= (w * vid.dupx); - V_DrawMappedPatch(x, y, V_NOSCALESTART|V_TRANSLUCENT, numpat[num % 10], colormap); - num /= 10; - } while (num); - - // Sorry chum, this function only draws UNSIGNED values! -} - -// Draw a number, scaled, over the view, with set translucency -// Always draw the number completely since it's overlay -// -// Supports different colors! woo! -static void ST_DrawTranslucentNightsOverlayNum(INT32 x /* right border */, INT32 y, INT32 a, +static void ST_DrawNightsOverlayNum(INT32 x /* right border */, INT32 y, INT32 a, INT32 num, patch_t **numpat, skincolors_t colornum) { INT32 w = SHORT(numpat[0]->width); @@ -603,16 +590,16 @@ static void ST_drawDebugInfo(void) static void ST_drawScore(void) { // SCORE: - V_DrawScaledPatch(SCX(hudinfo[HUD_SCORE].x), SCY(hudinfo[HUD_SCORE].y), V_NOSCALESTART|V_TRANSLUCENT, sboscore); + ST_DrawPatchFromHud(HUD_SCORE, sboscore); if (objectplacing) { if (op_displayflags > UINT16_MAX) - V_DrawScaledPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, tallminus); + ST_DrawOverlayPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), tallminus); else - ST_DrawOverlayNum(SCX(hudinfo[HUD_SCORENUM].x), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, op_displayflags); + ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags); } else - ST_DrawOverlayNum(SCX(hudinfo[HUD_SCORENUM].x), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, stplyr->score); + ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score); } static void ST_drawTime(void) @@ -620,8 +607,7 @@ static void ST_drawTime(void) INT32 seconds, minutes, tictrn, tics; // TIME: - V_DrawScaledPatch(SCX(hudinfo[(splitscreen) ? HUD_TIMESPLIT : HUD_TIME].x), - SCY(hudinfo[(splitscreen) ? HUD_TIMESPLIT : HUD_TIME].y), V_NOSCALESTART|V_TRANSLUCENT, sbotime); + ST_DrawPatchFromHudWS(HUD_TIME, sbotime); if (objectplacing) { @@ -633,61 +619,45 @@ static void ST_drawTime(void) else { tics = stplyr->realtime; - seconds = tics/TICRATE % 60; - minutes = tics/(60*TICRATE); + seconds = G_TicsToSeconds(tics); + minutes = G_TicsToMinutes(tics, true); tictrn = G_TicsToCentiseconds(tics); } if (cv_timetic.value == 1) // Tics only -- how simple is this? - ST_DrawOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].x), - SCY(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].y), V_NOSCALESTART, tics); + ST_DrawNumFromHudWS(HUD_SECONDS, tics); else { - // Minutes - ST_DrawOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_MINUTESSPLIT : HUD_MINUTES].x), - SCY(hudinfo[(splitscreen) ? HUD_MINUTESSPLIT : HUD_MINUTES].y), V_NOSCALESTART, minutes); - // Colon - V_DrawScaledPatch(SCX(hudinfo[(splitscreen) ? HUD_TIMECOLONSPLIT : HUD_TIMECOLON].x), - SCY(hudinfo[(splitscreen) ? HUD_TIMECOLONSPLIT : HUD_TIMECOLON].y), V_NOSCALESTART|V_TRANSLUCENT, sbocolon); - // Seconds - ST_DrawPaddedOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].x), - SCY(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].y), seconds, 2); + ST_DrawNumFromHudWS(HUD_MINUTES, minutes); // Minutes + ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon + ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! { - // Colon - V_DrawScaledPatch(SCX(hudinfo[HUD_TIMETICCOLON].x), SCY(hudinfo[HUD_TIMETICCOLON].y), V_NOSCALESTART|V_TRANSLUCENT, sbocolon); - // Tics - ST_DrawPaddedOverlayNum(SCX(hudinfo[HUD_TICS].x), SCY(hudinfo[HUD_TICS].y), tictrn, 2); + ST_DrawPatchFromHud(HUD_TIMETICCOLON, sbocolon); // Colon + ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics } } } static inline void ST_drawRings(void) { - hudnum_t ringHUD = (splitscreen) ? HUD_RINGSSPLIT : HUD_RINGS; - hudnum_t ringnumHUD = (splitscreen) ? HUD_RINGSNUMSPLIT : HUD_RINGSNUM; + INT32 ringnum = max(stplyr->health-1, 0); - V_DrawScaledPatch(SCX(hudinfo[ringHUD].x), SCY(hudinfo[ringHUD].y), V_NOSCALESTART|V_TRANSLUCENT, - (stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings); + ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings)); if (objectplacing) - { - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, op_currentdoomednum); - } + ringnum = op_currentdoomednum; else if (!useNightsSS && G_IsSpecialStage(gamemap)) { - INT32 ringscollected = 0; // Total # everyone has collected INT32 i; - + ringnum = 0; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && players[i].mo->health > 1) - ringscollected += players[i].mo->health - 1; - - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, ringscollected); + ringnum += players[i].mo->health - 1; } - else - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, stplyr->health > 0 ? stplyr->health-1 : 0); + + ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum); } static void ST_drawLives(void) @@ -699,7 +669,7 @@ static void ST_drawLives(void) // face background V_DrawSmallScaledPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag, livesback); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, livesback); // face if (stplyr->mo && stplyr->mo->color) @@ -710,25 +680,29 @@ static void ST_drawLives(void) if (stplyr->powers[pw_super] || stplyr->pflags & PF_NIGHTSMODE) face = superprefix[stplyr->skin]; V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag,face, colormap); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,face, colormap); } else if (stplyr->skincolor) { // skincolor face UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag,faceprefix[stplyr->skin], colormap); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,faceprefix[stplyr->skin], colormap); } // name if (strlen(skins[stplyr->skin].hudname) > 8) - V_DrawThinString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); + V_DrawThinString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), + V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); else - V_DrawString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); + V_DrawString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), + V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); // x - V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag, stlivex); + V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, stlivex); // lives - V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|v_splitflag, va("%d",stplyr->lives)); + V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, va("%d",stplyr->lives)); } static void ST_drawLevelTitle(void) @@ -820,9 +794,9 @@ static void ST_drawFirstPersonHUD(void) if (p) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); else - V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); } // pw_flashing just sets the icon to flash no matter what. @@ -830,17 +804,17 @@ static void ST_drawFirstPersonHUD(void) if (invulntime > 3*TICRATE || (invulntime && leveltime & 1)) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility); + V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); else - V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility); + V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); } if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] && leveltime & 1)) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers); + V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); else - V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers); + V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); } p = NULL; @@ -890,8 +864,8 @@ static void ST_drawFirstPersonHUD(void) } if (p) - V_DrawTranslucentPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), - V_NOSCALESTART|V_OFFSET, p); + V_DrawScaledPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), + V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, p); } // [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold @@ -946,11 +920,7 @@ static void ST_drawNightsRecords(void) V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:"); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings)); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); - - if (aflag) - ST_DrawTranslucentNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); - else - ST_DrawNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); // If new record, say so! if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) @@ -1012,15 +982,13 @@ static void ST_drawNiGHTSHUD(void) if (splitscreen) { - ST_DrawTranslucentNightsOverlayNum(SCX(256), SCY(160), linktrans, (stplyr->linkcount-1), - nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(256), SCY(160), linktrans, (stplyr->linkcount-1), nightsnum, colornum); V_DrawTranslucentMappedPatch(SCX(264), SCY(160), V_NOSCALESTART|linktrans, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } else { - ST_DrawTranslucentNightsOverlayNum(SCX(160), SCY(160), linktrans, (stplyr->linkcount-1), - nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(160), SCY(160), linktrans, (stplyr->linkcount-1), nightsnum, colornum); V_DrawTranslucentMappedPatch(SCX(168), SCY(160), V_NOSCALESTART|linktrans, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } @@ -1032,20 +1000,20 @@ static void ST_drawNiGHTSHUD(void) { INT32 offs = 10 - (stplyr->linktimer - (2*TICRATE - 9)); INT32 ghosttrans = offs << V_ALPHASHIFT; - ST_DrawTranslucentNightsOverlayNum(SCX(160), SCY(160)+(offs*2), ghosttrans, (stplyr->linkcount-2), + ST_DrawNightsOverlayNum(SCX(160), SCY(160)+(offs*2), ghosttrans, (stplyr->linkcount-2), nightsnum, colornum); } #endif if (splitscreen) { - ST_DrawNightsOverlayNum(SCX(256), SCY(160), (stplyr->linkcount-1), nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(256), SCY(160), 0, (stplyr->linkcount-1), nightsnum, colornum); V_DrawMappedPatch(SCX(264), SCY(160), V_NOSCALESTART, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } else { - ST_DrawNightsOverlayNum(SCX(160), SCY(160), (stplyr->linkcount-1), nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(160), SCY(160), 0, (stplyr->linkcount-1), nightsnum, colornum); V_DrawMappedPatch(SCX(168), SCY(160), V_NOSCALESTART, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } @@ -1086,32 +1054,32 @@ static void ST_drawNiGHTSHUD(void) if (splitscreen) { // Dirty hack because V_SNAPTOBOTTOM doesn't have a way to account for splitscreen, but better than overlapping bars. - V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_HUDTRANS, drillfill[fillpatch]); } else if (nosshack) { // Even dirtier hack-of-a-hack to draw seperate drill meters in splitscreen special stages but nothing else. splitscreen = true; - V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_HUDTRANS, drillfill[fillpatch]); stplyr = &players[secondarydisplayplayer]; if (stplyr->pflags & PF_DRILLING) fillpatch = (stplyr->drillmeter & 1) + 1; else fillpatch = 0; - V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); stplyr = &players[displayplayer]; splitscreen = false; } else { // Draw normally. <:3 - V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); } // Display actual drill amount and bumper time @@ -1136,11 +1104,11 @@ static void ST_drawNiGHTSHUD(void) if (LUA_HudEnabled(hud_nightsrings)) { #endif - V_DrawScaledPatch(SCX(16), SCY(8), V_NOSCALESTART|V_TRANSLUCENT, nbracket); + ST_DrawOverlayPatch(SCX(16), SCY(8), nbracket); if (G_IsSpecialStage(gamemap)) - V_DrawScaledPatch(SCX(24), SCY(8) + SCZ(8), V_NOSCALESTART|V_TRANSLUCENT, nsshud); + ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nsshud); else - V_DrawScaledPatch(SCX(24), SCY(8) + SCZ(8), V_NOSCALESTART|V_TRANSLUCENT, nhud[(leveltime/2)%12]); + ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nhud[(leveltime/2)%12]); if (G_IsSpecialStage(gamemap)) { @@ -1161,8 +1129,8 @@ static void ST_drawNiGHTSHUD(void) origamount = stplyr->capsule->spawnpoint->angle; I_Assert(origamount > 0); // should not happen now - V_DrawScaledPatch(SCX(72), SCY(8), V_NOSCALESTART|V_TRANSLUCENT, nbracket); - V_DrawScaledPatch(SCX(74), SCY(8) + SCZ(4), V_NOSCALESTART|V_TRANSLUCENT, minicaps); + ST_DrawOverlayPatch(SCX(72), SCY(8), nbracket); + ST_DrawOverlayPatch(SCX(74), SCY(8) + SCZ(4), minicaps); if (stplyr->capsule->reactiontime != 0) { @@ -1171,10 +1139,10 @@ static void ST_drawNiGHTSHUD(void) for (r = 0; r < 5; r++) { - V_DrawScaledPatch(SCX(230 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, redstat); - V_DrawScaledPatch(SCX(188 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, orngstat); - V_DrawScaledPatch(SCX(146 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, yelstat); - V_DrawScaledPatch(SCX(104 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, byelstat); + ST_DrawOverlayPatch(SCX(230 - (7*r)), SCY(144), redstat); + ST_DrawOverlayPatch(SCX(188 - (7*r)), SCY(144), orngstat); + ST_DrawOverlayPatch(SCX(146 - (7*r)), SCY(144), yelstat); + ST_DrawOverlayPatch(SCX(104 - (7*r)), SCY(144), byelstat); } amount = (origamount - stplyr->capsule->health); @@ -1193,7 +1161,7 @@ static void ST_drawNiGHTSHUD(void) if (r > 10) ++t; if (r > 5) ++t; - V_DrawScaledPatch(SCX(69 + (7*t)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, bluestat); + ST_DrawOverlayPatch(SCX(69 + (7*t)), SCY(144), bluestat); } } } @@ -1202,27 +1170,27 @@ static void ST_drawNiGHTSHUD(void) INT32 cfill; // Lil' white box! - V_DrawScaledPatch(15, STRINGY(8) + 34, V_SNAPTOLEFT|V_SNAPTOTOP|V_TRANSLUCENT, capsulebar); + V_DrawScaledPatch(15, STRINGY(8) + 34, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulebar); amount = (origamount - stplyr->capsule->health); amount = (amount * length)/origamount; for (cfill = 0; cfill < amount && cfill < 88; ++cfill) - V_DrawScaledPatch(15 + cfill + 1, STRINGY(8) + 35, V_SNAPTOLEFT|V_SNAPTOTOP|V_TRANSLUCENT, capsulefill); + V_DrawScaledPatch(15 + cfill + 1, STRINGY(8) + 35, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill); } if (total_ringcount >= stplyr->capsule->health) - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, nredar[leveltime%8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), nredar[leveltime%8]); else - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, narrow[(leveltime/2)%8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[(leveltime/2)%8]); } else - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, narrow[8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[8]); if (total_ringcount >= 100) - ST_DrawOverlayNum((total_ringcount >= 1000) ? SCX(76) : SCX(72), SCY(8) + SCZ(11), V_NOSCALESTART, total_ringcount); + ST_DrawOverlayNum((total_ringcount >= 1000) ? SCX(76) : SCX(72), SCY(8) + SCZ(11), total_ringcount); else - ST_DrawOverlayNum(SCX(68), SCY(8) + SCZ(11), V_NOSCALESTART, total_ringcount); + ST_DrawOverlayNum(SCX(68), SCY(8) + SCZ(11), total_ringcount); #ifdef HAVE_BLUA } #endif @@ -1233,7 +1201,7 @@ static void ST_drawNiGHTSHUD(void) && LUA_HudEnabled(hud_nightsscore) #endif ) - ST_DrawNightsOverlayNum(SCX(304), SCY(16), stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(SCX(304), SCY(16), 0, stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE); // Ideya time remaining if (!stplyr->exiting && stplyr->nightstime > 0 @@ -1275,10 +1243,10 @@ static void ST_drawNiGHTSHUD(void) numbersize = SCX(48)/2; if (realnightstime < 10) - ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), realnightstime, + ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), 0, realnightstime, nightsnum, SKINCOLOR_RED); else - ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), realnightstime, + ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), 0, realnightstime, nightsnum, SKINCOLOR_SUPER4); // Show exact time in debug @@ -1325,31 +1293,34 @@ static void ST_drawNiGHTSHUD(void) static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, INT32 xoffs, patch_t *pat) { - INT32 yelflag = 0; + INT32 txtflags = 0, patflags = 0; if (stplyr->powers[weapon]) { if (stplyr->powers[weapon] >= rw_maximums[wepflag]) - yelflag = V_YELLOWMAP; + txtflags |= V_YELLOWMAP; if (weapon == pw_infinityring || (stplyr->ringweapons & rwflag && stplyr->health > 1)) - V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT, pat); + txtflags |= V_20TRANS; else - V_DrawTranslucentPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|V_80TRANS, pat); + { + txtflags |= V_TRANSLUCENT; + patflags = V_80TRANS; + } + + V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|patflags, pat); if (stplyr->powers[weapon] > 99) - V_DrawThinString(8 + xoffs + 1, STRINGY(162), V_TRANSLUCENT | V_SNAPTOLEFT | yelflag, - va("%d", stplyr->powers[weapon])); + V_DrawThinString(8 + xoffs + 1, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); else - V_DrawString(8 + xoffs, STRINGY(162), V_TRANSLUCENT | V_SNAPTOLEFT | yelflag, - va("%d", stplyr->powers[weapon])); + V_DrawString(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); if (stplyr->currentweapon == wepflag) V_DrawScaledPatch(6 + xoffs, STRINGY(162 - (splitscreen ? 4 : 2)), V_SNAPTOLEFT, curweapon); } else if (stplyr->ringweapons & rwflag) - V_DrawTranslucentPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT, pat); + V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|V_TRANSLUCENT, pat); } static void ST_drawMatchHUD(void) @@ -1503,15 +1474,15 @@ static void ST_drawCTFHUD(void) UINT16 whichflag = 0; // Draw the flags - V_DrawSmallScaledPatch(256, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, rflagico); - V_DrawSmallScaledPatch(288, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, bflagico); + V_DrawSmallScaledPatch(256, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, rflagico); + V_DrawSmallScaledPatch(288, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, bflagico); for (i = 0; i < MAXPLAYERS; i++) { if (players[i].gotflag & GF_REDFLAG) // Red flag isn't at base - V_DrawScaledPatch(256, (splitscreen) ? STRINGY(156) : STRINGY(174), 0, nonicon); + V_DrawScaledPatch(256, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); else if (players[i].gotflag & GF_BLUEFLAG) // Blue flag isn't at base - V_DrawScaledPatch(288, (splitscreen) ? STRINGY(156) : STRINGY(174), 0, nonicon); + V_DrawScaledPatch(288, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); whichflag |= players[i].gotflag; if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG)) @@ -1524,9 +1495,9 @@ static void ST_drawCTFHUD(void) patch_t *p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag; if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); else - V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); } // Display a countdown timer showing how much time left until the flag your team dropped returns to base. @@ -1535,13 +1506,13 @@ static void ST_drawCTFHUD(void) if (redflag && redflag->fuse > 1) { sprintf(timeleft, "%u", (redflag->fuse / TICRATE)); - V_DrawCenteredString(268, STRINGY(184), V_YELLOWMAP, timeleft); + V_DrawCenteredString(268, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); } if (blueflag && blueflag->fuse > 1) { sprintf(timeleft, "%u", (blueflag->fuse / TICRATE)); - V_DrawCenteredString(300, STRINGY(184), V_YELLOWMAP, timeleft); + V_DrawCenteredString(300, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); } } } @@ -1550,11 +1521,11 @@ static void ST_drawCTFHUD(void) static inline void ST_drawTeamName(void) { if (stplyr->ctfteam == 1) - V_DrawString(256, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "RED TEAM"); + V_DrawString(256, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM"); else if (stplyr->ctfteam == 2) - V_DrawString(248, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "BLUE TEAM"); + V_DrawString(248, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "BLUE TEAM"); else - V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "SPECTATOR"); + V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); } #ifdef CHAOSISNOTDEADYET @@ -1562,33 +1533,28 @@ static inline void ST_drawChaosHUD(void) { char chains[33]; sprintf(chains, "CHAINS: %u", stplyr->scoreadd); - V_DrawString(8, STRINGY(184), V_TRANSLUCENT, chains); + V_DrawString(8, STRINGY(184), V_HUDTRANSHALF, chains); } #endif static void ST_drawSpecialStageHUD(void) { if (totalrings > 0) - { - if (splitscreen) - ST_DrawOverlayNum(hudinfo[HUD_SS_TOTALRINGS_SPLIT].x, hudinfo[HUD_SS_TOTALRINGS_SPLIT].y, V_SNAPTOTOP, totalrings); - else - ST_DrawOverlayNum(hudinfo[HUD_SS_TOTALRINGS].x, hudinfo[HUD_SS_TOTALRINGS].y, V_SNAPTOTOP, totalrings); - } + ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings); if (leveltime < 5*TICRATE && totalrings > 0) { - V_DrawScaledPatch(hudinfo[HUD_GETRINGS].x, SCR(hudinfo[HUD_GETRINGS].y), V_TRANSLUCENT, getall); - ST_DrawOverlayNum(hudinfo[HUD_GETRINGSNUM].x, SCR(hudinfo[HUD_GETRINGSNUM].y), 0, totalrings); + ST_DrawPatchFromHud(HUD_GETRINGS, getall); + ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings); } if (sstimer) { - V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), 0, M_GetText("TIME LEFT")); - ST_DrawNightsOverlayNum(SCX(hudinfo[HUD_TIMELEFTNUM].x), SCY(hudinfo[HUD_TIMELEFTNUM].y), sstimer/TICRATE, tallnum, SKINCOLOR_WHITE); + V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), V_HUDTRANS, M_GetText("TIME LEFT")); + ST_DrawNightsOverlayNum(SCX(hudinfo[HUD_TIMELEFTNUM].x), SCY(hudinfo[HUD_TIMELEFTNUM].y), V_HUDTRANS, sstimer/TICRATE, tallnum, SKINCOLOR_WHITE); } else - V_DrawScaledPatch(hudinfo[HUD_TIMEUP].x, hudinfo[HUD_TIMEUP].y, V_TRANSLUCENT, timeup); + ST_DrawPatchFromHud(HUD_TIMEUP, timeup); } static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) @@ -1627,7 +1593,7 @@ static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offse interval = 0; } - V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, STRINGY(hudinfo[HUD_HUNTPICS].y), V_TRANSLUCENT, patches[i]); + V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, STRINGY(hudinfo[HUD_HUNTPICS].y), V_HUDTRANS, patches[i]); return interval; } @@ -1895,9 +1861,9 @@ static void ST_overlayDrawer(void) { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; if (respawntime > 0 && !stplyr->spectator) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Jump to respawn.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); } else if (stplyr->spectator #ifdef HAVE_BLUA @@ -1905,13 +1871,13 @@ static void ST_overlayDrawer(void) #endif ) { - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), V_TRANSLUCENT, M_GetText("You are a spectator.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), V_HUDTRANSHALF, M_GetText("You are a spectator.")); if (G_GametypeHasTeams()) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Fire to be assigned to a team.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team.")); else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Fire to enter the game.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_TRANSLUCENT, M_GetText("Press F12 to watch another player.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_TRANSLUCENT, M_GetText("Press Jump to float and Spin to sink.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink.")); } } @@ -1924,12 +1890,12 @@ void ST_Drawer(boolean refresh) if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { if (cv_seenames.value == 1) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, player_names[seenplayer-players]); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); else if (cv_seenames.value == 2) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, va("%s%s", G_GametypeHasTeams() ? ((seenplayer->ctfteam == 1) ? "\x85" : "\x84") : "", player_names[seenplayer-players])); else //if (cv_seenames.value == 3) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, va("%s%s", !G_RingSlingerGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam) ? "\x83" : "\x85", player_names[seenplayer-players])); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 5b5df5c1..d303bc80 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -83,24 +83,29 @@ typedef enum HUD_LIVESPIC, HUD_LIVESNUM, HUD_LIVESX, - HUD_RINGSSPLIT, - HUD_RINGSNUMSPLIT, + HUD_RINGS, + HUD_RINGSSPLIT, HUD_RINGSNUM, + HUD_RINGSNUMSPLIT, + HUD_SCORE, HUD_SCORENUM, - HUD_TIMESPLIT, - HUD_SECONDSSPLIT, - HUD_MINUTESSPLIT, - HUD_TIMECOLONSPLIT, + HUD_TIME, - HUD_TICS, - HUD_SECONDS, + HUD_TIMESPLIT, HUD_MINUTES, + HUD_MINUTESSPLIT, HUD_TIMECOLON, + HUD_TIMECOLONSPLIT, + HUD_SECONDS, + HUD_SECONDSSPLIT, HUD_TIMETICCOLON, - HUD_SS_TOTALRINGS_SPLIT, + HUD_TICS, + HUD_SS_TOTALRINGS, + HUD_SS_TOTALRINGS_SPLIT, + HUD_GETRINGS, HUD_GETRINGSNUM, HUD_TIMELEFT, diff --git a/src/v_video.c b/src/v_video.c index 76728a35..032a4ec9 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -297,657 +297,127 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #endif } -// -// V_DrawTranslucentMappedPatch: like V_DrawMappedPatch, but with translucency. -// -void V_DrawTranslucentMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) +static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; +static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; + +static const UINT8 *v_colormap = NULL; +static const UINT8 *v_translevel = NULL; + +static inline UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *translevel, *deststop; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - // draw a hardware converted patch - else if (rendermode != render_soft) - { - HWR_DrawMappedPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset); - x -= SHORT(patch->leftoffset); - - if (scrn & V_NOSCALESTART) - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.width) + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - } - else - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.dupy*vid.width) + (x*vid.dupx); - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - scrn &= V_PARAMMASK; - - col = 0; - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(translevel + (((*(colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + (void)dest; return source[ofs>>FRACBITS]; } - -// -// V_DrawMappedPatch: like V_DrawScaledPatch, but with a colormap. -// -void V_DrawMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) +static inline UINT8 mappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawMappedPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - if (scrn & V_FLIP) - { - flip = true; - x -= SHORT(patch->width) - SHORT(patch->leftoffset); - } - else - x -= SHORT(patch->leftoffset); - - if (scrn & V_SPLITSCREEN) - y /= 2; - - if (scrn & V_NOSCALESTART) - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.width) + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - } - else - { - desttop = screens[scrn&V_PARAMMASK] + (y*dupy*vid.width) + (x*dupx); - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - scrn &= V_PARAMMASK; - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx; - - col = 0; - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(colormap + source[ofs>>FRACBITS]); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + (void)dest; return *(v_colormap + source[ofs>>FRACBITS]); } - -// -// V_DrawScaledPatch -// -// Like V_DrawPatch, but scaled 2, 3, 4 times the original size and position. -// This is used for menu and title screens, with high resolutions. -// -void V_DrawScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) +static inline UINT8 translucentpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef PARANOIA - if (!patch) - CONS_Alert(CONS_ERROR, "NULL patch passed to V_DrawScaledPatch?! Crashing!\n"); -#endif - - if (rendermode == render_none) - return; -#ifdef HWRENDER - // draw a hardware converted patch - else if (rendermode != render_soft && !con_startup) - { - HWR_DrawPatch((GLPatch_t *)patch, x, y, scrn); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - if (scrn & V_FLIP) - { - flip = true; - x -= SHORT(patch->width) - SHORT(patch->leftoffset); - } - else - x -= SHORT(patch->leftoffset); - - if (scrn & V_SPLITSCREEN) - y /= 2; - - colfrac = FixedDiv(FRACUNIT, dupx<width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx; - - if (destend + (SHORT(patch->height) * dupy) * vid.width < screens[scrn&V_PARAMMASK]) - return; - - for (col = 0; desttop < destend; col += colfrac, desttop++) - { - register INT32 heightmask; - INT32 topdelta, prevdelta = -1; - - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - - heightmask = column->length - 1; - - while (dest < screens[scrn&V_PARAMMASK] && count) - { - dest += vid.width; - ofs += rowfrac; - --count; - } - - if (count && column->length & heightmask) - { - heightmask++; - heightmask <<= FRACBITS; - - if (rowfrac < 0) - while ((rowfrac += heightmask) < 0) - ; - else - while (rowfrac >= heightmask) - rowfrac -= heightmask; - - do - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - if ((ofs + rowfrac) > heightmask) - goto donedrawing; - } while (count--); - } - else - { - while (count--) - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - } -donedrawing: - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + return *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); } - -/** Draws a patch to the screen, being careful not to go off the right - * side or bottom of the screen. This is slower than a normal draw, so - * it gets a separate function. - * - * With hardware rendering, the patch is clipped anyway, so this is - * just the same as V_DrawScaledPatch(). - * - * \param x X coordinate for left side, based on 320x200 screen. - * \param y Y coordinate for top, based on 320x200 screen. - * \param scrn Any of several flags to change the drawing behavior. - * \param patch Patch to draw. - * \sa V_DrawScaledPatch - * \author Graue - */ -static void V_DrawClippedScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) +static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *destend; - const UINT8 *source, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - // V_NOSCALESTART might be impled for software, but not for hardware! - HWR_DrawClippedPatch((GLPatch_t *)patch, x, y, V_NOSCALESTART); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); - - if (x < 0 || y < 0 || x >= vid.width || y >= vid.height) - return; - - colfrac = FixedDiv(FRACUNIT, dupx<width)*dupx <= vid.width) - destend = desttop + SHORT(patch->width) * dupx; - else - destend = desttop + vid.width - x; - - for (col = 0; desttop < destend; col += colfrac, desttop++) - { - register INT32 heightmask; - INT32 topdelta, prevdelta = -1; - - column = (const column_t *)((const UINT8 *)patch + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - if ((dest-screens[scrn&V_PARAMMASK])/vid.width + count > (unsigned)vid.height - 1) - count = vid.height - 1 - (dest-screens[scrn&V_PARAMMASK])/vid.width; - if (count <= 0) - break; - - ofs = 0; - - heightmask = column->length - 1; - - if (column->length & heightmask) - { - // length is not a power of two - heightmask++; - heightmask <<= FRACBITS; - - if (rowfrac < 0) - while ((rowfrac += heightmask) < 0) - ; - else - while (rowfrac >= heightmask) - rowfrac -= heightmask; - - do - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - if ((ofs + rowfrac) > heightmask) - goto doneclipping; - } while (count--); - } - else - { - // length is a power of two - while (count--) - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - } -doneclipping: - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); } // Draws a patch scaled to arbitrary size. -void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_t science) +void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { + UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); + UINT32 alphalevel = 0; + boolean flip = false; + fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; const column_t *column; - UINT8 *desttop, *dest; + UINT8 *desttop, *dest, *deststart, *destend; const UINT8 *source, *deststop; + if (rendermode == render_none) + return; + #ifdef HWRENDER // oh please - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && !con_startup) { - HWR_DrawSciencePatch((GLPatch_t *)patch, x, y, scrn, science); + HWR_DrawFixedPatch((GLPatch_t *)patch, x, y, pscale, scrn, colormap); return; } #endif + patchdrawfunc = standardpdraw; + + v_translevel = NULL; + if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[cv_translucenthud.value]; + else if (alphalevel == 14) + alphalevel = 10 - cv_translucenthud.value; + else if (alphalevel == 15) + alphalevel = hudplusalpha[cv_translucenthud.value]; + + if (alphalevel >= 10) + return; // invis + } + if (alphalevel) + { + v_translevel = ((alphalevel)<> V_SCALEPATCHSHIFT) + { + case 1: // V_NOSCALEPATCH + dupx = dupy = 1; + break; + case 2: // V_SMALLSCALEPATCH + dupx = vid.smalldupx; + dupy = vid.smalldupy; + break; + case 3: // V_MEDSCALEPATCH + dupx = vid.meddupx; + dupy = vid.meddupy; + break; + default: + break; + } + // only use one dup, to avoid stretching (har har) - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset)<leftoffset)<topoffset)*dupy)<leftoffset)*dupx)<topoffset)<width) - SHORT(patch->leftoffset))<leftoffset)<>=1; desttop = screens[scrn&V_PARAMMASK]; @@ -956,11 +426,13 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ deststop = desttop + vid.rowbytes * vid.height; - if (scrn & V_NOSCALESTART) { + if (scrn & V_NOSCALESTART) + { x >>= FRACBITS; y >>= FRACBITS; desttop += (y*vid.width) + x; - } else + } + else { x = FixedMul(x,dupx<width) * dupx; + for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) { INT32 topdelta, prevdelta = -1; - if (x < 0) { // don't draw off the left of the screen (WRAP PREVENTION) + if (x < 0) + { // don't draw off the left of the screen (WRAP PREVENTION) x++; continue; } @@ -1017,12 +495,14 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; + if (flip) + dest = deststart + (destend - desttop); dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = source[ofs>>FRACBITS]; + *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } column = (const column_t *)((const UINT8 *)column + column->length + 4); @@ -1031,7 +511,7 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ } // Draws a patch cropped and scaled to arbitrary size. -void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_t science, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; @@ -1039,23 +519,26 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ UINT8 *desttop, *dest; const UINT8 *source, *deststop; + if (rendermode == render_none) + return; + #ifdef HWRENDER // Done - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && !con_startup) { - HWR_DrawCroppedPatch((GLPatch_t *)patch, x, y, scrn, science, sx, sy, w, h); + HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); return; } #endif // only use one dup, to avoid stretching (har har) dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset)<leftoffset)<topoffset)<leftoffset)<>= FRACBITS; y >>= FRACBITS; desttop += (y*vid.width) + x; - } else + } + else { x = FixedMul(x,dupx<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - if (scrn & V_SPLITSCREEN) - y /= 2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - x = x*dupx; - y = y*dupy; - desttop += (y*vid.width) + x; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - if (x < 0) { // don't draw off the left of the screen (WRAP PREVENTION) - x++; - continue; - } - if (x > vid.width) // don't draw off the right of the screen (WRAP PREVENTION) - break; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = source[ofs>>FRACBITS]; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, translucent, and colormapped. -void V_DrawSmallTranslucentMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - UINT8 *translevel; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(translevel + (colormap[source[ofs>>FRACBITS]]<<8) + (*dest)); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, and translucent. -void V_DrawSmallTranslucentPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - UINT8 *translevel; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormaps); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, and colormapped. -void V_DrawSmallMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - // only use one dup, to avoid stretching. - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = dupx<<(FRACBITS-1); - colfrac = FixedDiv(FRACUNIT, fdup); - rowfrac = FixedDiv(FRACUNIT, fdup); - - y -= SHORT(patch->topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - if (scrn & V_SPLITSCREEN) - y /= 2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(colormap + source[ofs>>FRACBITS]); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 4x as small. -void V_DrawTinyScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // No. - if (rendermode != render_soft && rendermode != render_none) - return; -#endif - - // only use one dup, to avoid stretching. - fdup = (vid.dupx < vid.dupy ? vid.dupx<topoffset)/4; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/4; - } - else - x -= SHORT(patch->leftoffset)/4; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 4; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = source[ofs>>FRACBITS]; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 4x as small, and colormapped. -void V_DrawTinyMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // No. - if (rendermode != render_soft && rendermode != render_none) - return; -#endif - - // only use one dup, to avoid stretching. - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = dupx<<(FRACBITS-2); - colfrac = FixedDiv(FRACUNIT, fdup); - rowfrac = FixedDiv(FRACUNIT, fdup); - - y -= SHORT(patch->topoffset)/4; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/4; - } - else - x -= SHORT(patch->leftoffset)/4; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 4; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(colormap + source[ofs>>FRACBITS]); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// This draws a patch over a background with translucency...SCALED. -// SCALE THE STARTING COORDS! -// Used for crosshair. -// -void V_DrawTranslucentPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *translevel, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawTranslucentPatch((GLPatch_t *)patch, x, y, scrn); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)*dupy; - x -= SHORT(patch->leftoffset)*dupx; - } - else - { - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); - } - - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// -// V_DrawPatch -// Masks a column based masked pic to the screen. NO SCALING! -// -void V_DrawPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - size_t count; - INT32 col, w; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawPatch((GLPatch_t *)patch, x, y, V_NOSCALESTART|V_NOSCALEPATCH); - return; - } -#endif - - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); -#ifdef RANGECHECK - if (x < 0 || x + SHORT(patch->width) > vid.width || y < 0 - || y + SHORT(patch->height) > vid.height || (unsigned)scrn > 4) - { - fprintf(stderr, "Patch at %d, %d exceeds LFB\n", x, y); - // No I_Error abort - what is up with TNT.WAD? - fprintf(stderr, "V_DrawPatch: bad patch (ignored)\n"); - return; - } -#endif - - desttop = screens[scrn] + y*vid.width + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - w = SHORT(patch->width); - - for (col = 0; col < w; x++, col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)patch + LONG(patch->columnofs[col])); - - // step through the posts in a column - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*vid.width; - count = column->length; - - while (count--) - { - if (dest < deststop) - *dest = *source++; - else - count = 0; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - // // V_DrawContinueIcon // Draw a mini player! If we can, that is. Otherwise we draw a star. @@ -2035,7 +630,7 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin { if (skins[skinnum].flags & SF_HIRES #ifdef HWRENDER - || (rendermode != render_soft && rendermode != render_none) +// || (rendermode != render_soft && rendermode != render_none) #endif ) V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); @@ -2313,12 +908,7 @@ void V_DrawPatchFill(patch_t *pat) for (x = 0; x < vid.width; x += pw) { for (y = 0; y < vid.height; y += ph) - { - if (x + pw >= vid.width || y + ph >= vid.height) - V_DrawClippedScaledPatch(x, y, 0, pat); // V_NOSCALESTART is implied - else - V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); - } + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); } } @@ -2681,15 +1271,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) } colormap = V_GetStringColormap(charflags); - - if (colormap != NULL && (option & V_ALPHAMASK)) - V_DrawTranslucentMappedPatch(cx + center, cy, option, hu_font[c], colormap); - else if (colormap != NULL) - V_DrawMappedPatch(cx + center, cy, option, hu_font[c], colormap); - else if (option & V_ALPHAMASK) - V_DrawTranslucentPatch(cx + center, cy, option, hu_font[c]); - else - V_DrawScaledPatch(cx + center, cy, option, hu_font[c]); + V_DrawFixedPatch((cx + center)< Date: Fri, 21 Mar 2014 14:42:55 -0400 Subject: [PATCH 08/19] SRB2 2.1.4 release --- src/d_clisrv.c | 1135 ++++++++++++++++----------- src/d_clisrv.h | 290 +++---- src/d_main.c | 5 +- src/d_net.c | 12 - src/d_netcmd.c | 13 +- src/d_player.h | 21 +- src/dehacked.c | 28 +- src/doomdata.h | 1 + src/doomdef.h | 6 +- src/doomstat.h | 2 +- src/g_game.c | 20 +- src/hardware/hw_draw.c | 287 +------ src/hardware/hw_main.h | 7 +- src/hu_stuff.c | 10 +- src/lua_hudlib.c | 61 +- src/lua_infolib.c | 2 +- src/lua_playerlib.c | 24 +- src/m_cheat.c | 10 +- src/m_menu.c | 32 +- src/p_map.c | 2 +- src/p_saveg.c | 36 +- src/p_spec.c | 27 +- src/p_user.c | 18 +- src/r_main.c | 6 +- src/r_main.h | 3 +- src/st_stuff.c | 326 ++++---- src/st_stuff.h | 23 +- src/v_video.c | 1684 +++------------------------------------- src/v_video.h | 43 +- src/y_inter.c | 4 +- src/y_inter.h | 2 + 31 files changed, 1383 insertions(+), 2757 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f4b262ba..46a711aa 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -95,10 +95,21 @@ static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet static UINT8 nodewaiting[MAXNETNODES]; static tic_t firstticstosend; // min of the nettics -static INT16 consistancy[BACKUPTICS]; static tic_t tictoclear = 0; // optimize d_clearticcmd static tic_t maketic; +static INT16 consistancy[BACKUPTICS]; + +// Resynching shit! +static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick +static UINT16 resynch_delay[MAXNETNODES]; // delay time before the player can be considered to have desynched +static UINT32 resynch_status[MAXNETNODES]; // 0 bit means synched for that player, 1 means possibly desynched +static UINT8 resynch_sent[MAXNETNODES][MAXNETNODES]; // what synch packets have we attempted to send to the player +static UINT8 resynch_inprogress[MAXNETNODES]; +static UINT8 resynch_local_inprogress = false; // WE are desynched and getting packets to fix it. +static UINT8 player_joining = false; +UINT8 hu_resynching = 0; + // client specific static ticcmd_t localcmds; static ticcmd_t localcmds2; @@ -463,6 +474,541 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) // end extra data function for lmps // ----------------------------------------------------------------- +// ----------------------------------------------------------------- +// resynch player data +// ----------------------------------------------------------------- +static inline void resynch_write_player(resynch_pak *rsp, const size_t i) +{ + size_t j; + + rsp->playernum = (UINT8)i; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + rsp->playerstate = (UINT8)players[i].playerstate; //playerstate_t + rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t + rsp->panim = (UINT8)players[i].panim; //panim_t + + rsp->aiming = (angle_t)LONG(players[i].aiming); + rsp->currentweapon = LONG(players[i].currentweapon); + rsp->ringweapons = LONG(players[i].ringweapons); + + for (j = 0; j < NUMPOWERS; ++j) + rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); + + // Score is resynched in the rspfirm resync packet + rsp->health = 0; // resynched with mo health + rsp->lives = players[i].lives; + rsp->continues = players[i].continues; + rsp->scoreadd = players[i].scoreadd; + rsp->xtralife = players[i].xtralife; + rsp->pity = players[i].pity; + + rsp->skincolor = players[i].skincolor; + rsp->skin = LONG(players[i].skin); + // Just in case Lua does something like + // modify these at runtime + rsp->normalspeed = (fixed_t)LONG(players[i].normalspeed); + rsp->runspeed = (fixed_t)LONG(players[i].runspeed); + rsp->thrustfactor = players[i].thrustfactor; + rsp->accelstart = players[i].accelstart; + rsp->acceleration = players[i].acceleration; + rsp->charability = players[i].charability; + rsp->charability2 = players[i].charability2; + rsp->charflags = (UINT32)LONG(players[i].charflags); + rsp->thokitem = (UINT32)LONG(players[i].thokitem); //mobjtype_t + rsp->spinitem = (UINT32)LONG(players[i].spinitem); //mobjtype_t + rsp->revitem = (UINT32)LONG(players[i].revitem); //mobjtype_t + rsp->actionspd = LONG(players[i].actionspd); + rsp->mindash = LONG(players[i].mindash); + rsp->maxdash = LONG(players[i].maxdash); + rsp->jumpfactor = (fixed_t)LONG(players[i].jumpfactor); + + rsp->speed = (fixed_t)LONG(players[i].speed); + rsp->jumping = players[i].jumping; + rsp->secondjump = players[i].secondjump; + rsp->fly1 = players[i].fly1; + rsp->glidetime = (tic_t)LONG(players[i].glidetime); + rsp->climbing = players[i].climbing; + rsp->deadtimer = players[i].deadtimer; + rsp->exiting = (tic_t)LONG(players[i].exiting); + rsp->homing = players[i].homing; + rsp->cmomx = (fixed_t)LONG(players[i].cmomx); + rsp->cmomy = (fixed_t)LONG(players[i].cmomy); + rsp->rmomx = (fixed_t)LONG(players[i].rmomx); + rsp->rmomy = (fixed_t)LONG(players[i].rmomy); + + rsp->weapondelay = LONG(players[i].weapondelay); + rsp->tossdelay = LONG(players[i].tossdelay); + + rsp->starpostx = SHORT(players[i].starpostx); + rsp->starposty = SHORT(players[i].starposty); + rsp->starpostz = SHORT(players[i].starpostz); + rsp->starpostnum = LONG(players[i].starpostnum); + rsp->starposttime = (tic_t)LONG(players[i].starposttime); + rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); + + rsp->maxlink = LONG(players[i].maxlink); + rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed); + rsp->dashtime = LONG(players[i].dashtime); + rsp->angle_pos = (angle_t)LONG(players[i].angle_pos); + rsp->old_angle_pos = (angle_t)LONG(players[i].old_angle_pos); + rsp->bumpertime = (tic_t)LONG(players[i].bumpertime); + rsp->flyangle = LONG(players[i].flyangle); + rsp->drilltimer = (tic_t)LONG(players[i].drilltimer); + rsp->linkcount = LONG(players[i].linkcount); + rsp->linktimer = (tic_t)LONG(players[i].linktimer); + rsp->anotherflyangle = LONG(players[i].anotherflyangle); + rsp->nightstime = (tic_t)LONG(players[i].nightstime); + rsp->drillmeter = LONG(players[i].drillmeter); + rsp->drilldelay = players[i].drilldelay; + rsp->bonustime = players[i].bonustime; + rsp->mare = players[i].mare; + rsp->lastsidehit = SHORT(players[i].lastsidehit); + rsp->lastlinehit = SHORT(players[i].lastlinehit); + + rsp->losstime = (tic_t)LONG(players[i].losstime); + rsp->timeshit = players[i].timeshit; + rsp->onconveyor = LONG(players[i].onconveyor); + + rsp->hasmo = false; + //Transfer important mo information if the player has a body. + //This lets us resync players even if they are dead. + if (!players[i].mo) + return; + rsp->hasmo = true; + + rsp->health = LONG(players[i].mo->health); + + rsp->angle = (angle_t)LONG(players[i].mo->angle); + rsp->x = LONG(players[i].mo->x); + rsp->y = LONG(players[i].mo->y); + rsp->z = LONG(players[i].mo->z); + rsp->momx = LONG(players[i].mo->momx); + rsp->momy = LONG(players[i].mo->momy); + rsp->momz = LONG(players[i].mo->momz); + rsp->friction = LONG(players[i].mo->friction); + rsp->movefactor = LONG(players[i].mo->movefactor); + + rsp->tics = LONG(players[i].mo->tics); + rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( + rsp->eflags = (UINT32)LONG(players[i].mo->eflags); + rsp->flags = LONG(players[i].mo->flags); + rsp->flags2 = LONG(players[i].mo->flags2); + + rsp->radius = LONG(players[i].mo->radius); + rsp->height = LONG(players[i].mo->height); + rsp->scale = LONG(players[i].mo->scale); + rsp->destscale = LONG(players[i].mo->destscale); + rsp->scalespeed = LONG(players[i].mo->scalespeed); +} + +static void resynch_read_player(resynch_pak *rsp) +{ + INT32 i = rsp->playernum, j; + mobj_t *savedmo = players[i].mo; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + players[i].playerstate = (UINT8)rsp->playerstate; //playerstate_t + players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t + players[i].panim = (UINT8)rsp->panim; //panim_t + + players[i].aiming = (angle_t)LONG(rsp->aiming); + players[i].currentweapon = LONG(rsp->currentweapon); + players[i].ringweapons = LONG(rsp->ringweapons); + + for (j = 0; j < NUMPOWERS; ++j) + players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); + + // Score is resynched in the rspfirm resync packet + players[i].health = rsp->health; + players[i].lives = rsp->lives; + players[i].continues = rsp->continues; + players[i].scoreadd = rsp->scoreadd; + players[i].xtralife = rsp->xtralife; + players[i].pity = rsp->pity; + + players[i].skincolor = rsp->skincolor; + players[i].skin = LONG(rsp->skin); + // Just in case Lua does something like + // modify these at runtime + players[i].normalspeed = (fixed_t)LONG(rsp->normalspeed); + players[i].runspeed = (fixed_t)LONG(rsp->runspeed); + players[i].thrustfactor = rsp->thrustfactor; + players[i].accelstart = rsp->accelstart; + players[i].acceleration = rsp->acceleration; + players[i].charability = rsp->charability; + players[i].charability2 = rsp->charability2; + players[i].charflags = (UINT32)LONG(rsp->charflags); + players[i].thokitem = (UINT32)LONG(rsp->thokitem); //mobjtype_t + players[i].spinitem = (UINT32)LONG(rsp->spinitem); //mobjtype_t + players[i].revitem = (UINT32)LONG(rsp->revitem); //mobjtype_t + players[i].actionspd = LONG(rsp->actionspd); + players[i].mindash = LONG(rsp->mindash); + players[i].maxdash = LONG(rsp->maxdash); + players[i].jumpfactor = (fixed_t)LONG(rsp->jumpfactor); + + players[i].speed = (fixed_t)LONG(rsp->speed); + players[i].jumping = rsp->jumping; + players[i].secondjump = rsp->secondjump; + players[i].fly1 = rsp->fly1; + players[i].glidetime = (tic_t)LONG(rsp->glidetime); + players[i].climbing = rsp->climbing; + players[i].deadtimer = rsp->deadtimer; + players[i].exiting = (tic_t)LONG(rsp->exiting); + players[i].homing = rsp->homing; + players[i].cmomx = (fixed_t)LONG(rsp->cmomx); + players[i].cmomy = (fixed_t)LONG(rsp->cmomy); + players[i].rmomx = (fixed_t)LONG(rsp->rmomx); + players[i].rmomy = (fixed_t)LONG(rsp->rmomy); + + players[i].weapondelay = LONG(rsp->weapondelay); + players[i].tossdelay = LONG(rsp->tossdelay); + + players[i].starpostx = SHORT(rsp->starpostx); + players[i].starposty = SHORT(rsp->starposty); + players[i].starpostz = SHORT(rsp->starpostz); + players[i].starpostnum = LONG(rsp->starpostnum); + players[i].starposttime = (tic_t)LONG(rsp->starposttime); + players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); + + players[i].maxlink = LONG(rsp->maxlink); + players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed); + players[i].dashtime = LONG(rsp->dashtime); + players[i].angle_pos = (angle_t)LONG(rsp->angle_pos); + players[i].old_angle_pos = (angle_t)LONG(rsp->old_angle_pos); + players[i].bumpertime = (tic_t)LONG(rsp->bumpertime); + players[i].flyangle = LONG(rsp->flyangle); + players[i].drilltimer = (tic_t)LONG(rsp->drilltimer); + players[i].linkcount = LONG(rsp->linkcount); + players[i].linktimer = (tic_t)LONG(rsp->linktimer); + players[i].anotherflyangle = LONG(rsp->anotherflyangle); + players[i].nightstime = (tic_t)LONG(rsp->nightstime); + players[i].drillmeter = LONG(rsp->drillmeter); + players[i].drilldelay = rsp->drilldelay; + players[i].bonustime = rsp->bonustime; + players[i].mare = rsp->mare; + players[i].lastsidehit = SHORT(rsp->lastsidehit); + players[i].lastlinehit = SHORT(rsp->lastlinehit); + + players[i].losstime = (tic_t)LONG(rsp->losstime); + players[i].timeshit = rsp->timeshit; + players[i].onconveyor = LONG(rsp->onconveyor); + + //We get a packet for each player in game. + if (!playeringame[i]) + return; + + //...but keep old mo even if it is corrupt or null! + players[i].mo = savedmo; + + //Transfer important mo information if they have a valid mo. + if (!rsp->hasmo) + return; + + //server thinks player has a body. + //Give them a new body that can be then manipulated by the server's info. + if (!players[i].mo) //client thinks it has no body. + P_SpawnPlayer(i); + + //At this point, the player should have a body, whether they were respawned or not. + P_UnsetThingPosition(players[i].mo); + players[i].mo->angle = (angle_t)LONG(rsp->angle); + players[i].mo->eflags = (UINT32)LONG(rsp->eflags); + players[i].mo->flags = LONG(rsp->flags); + players[i].mo->flags2 = LONG(rsp->flags2); + players[i].mo->friction = LONG(rsp->friction); + players[i].mo->health = LONG(rsp->health); + players[i].mo->momx = LONG(rsp->momx); + players[i].mo->momy = LONG(rsp->momy); + players[i].mo->momz = LONG(rsp->momz); + players[i].mo->movefactor = LONG(rsp->movefactor); + players[i].mo->tics = LONG(rsp->tics); + P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum)); + players[i].mo->x = LONG(rsp->x); + players[i].mo->y = LONG(rsp->y); + players[i].mo->z = LONG(rsp->z); + players[i].mo->radius = LONG(rsp->radius); + players[i].mo->height = LONG(rsp->height); + // P_SetScale is redundant for this, as all related variables are already restored properly. + players[i].mo->scale = LONG(rsp->scale); + players[i].mo->destscale = LONG(rsp->destscale); + players[i].mo->scalespeed = LONG(rsp->scalespeed); + + // And finally, SET THE MOBJ SKIN damn it. + players[i].mo->skin = &skins[players[i].skin]; + players[i].mo->color = players[i].skincolor; + + P_SetThingPosition(players[i].mo); +} + +static inline void resynch_write_ctf(resynchend_pak *rst) +{ + mobj_t *mflag; + UINT8 i, j; + + for (i = 0, mflag = redflag; i < 2; ++i, mflag = blueflag) + { + rst->flagx[i] = rst->flagy[i] = rst->flagz[i] = 0; + rst->flagloose[i] = rst->flagflags[i] = 0; + rst->flagplayer[i] = -1; + + if (!mflag) + { + // Should be held by a player + for (j = 0; j < MAXPLAYERS; ++j) + { + if (!playeringame[j] || players[j].gotflag != i) + continue; + rst->flagplayer[i] = (SINT8)j; + break; + } + if (j == MAXPLAYERS) + I_Error("One of the flags has gone completely missing!"); + + continue; + } + + rst->flagx[i] = (fixed_t)LONG(mflag->x); + rst->flagy[i] = (fixed_t)LONG(mflag->y); + rst->flagz[i] = (fixed_t)LONG(mflag->z); + rst->flagflags[i] = LONG(mflag->flags2); + rst->flagloose[i] = LONG(mflag->fuse); // Dropped or not? + } +} + +static inline void resynch_read_ctf(resynchend_pak *p) +{ + UINT8 i; + + for (i = 0; i < MAXPLAYERS; ++i) + players[i].gotflag = 0; + + // Red flag + if (p->flagplayer[0] != -1) // Held by a player + { + if (!playeringame[p->flagplayer[0]]) + I_Error("Invalid red flag player %d who isn't in the game!", (INT32)p->flagplayer[0]); + players[p->flagplayer[0]].gotflag = GF_REDFLAG; + if (redflag) + { + P_RemoveMobj(redflag); + redflag = NULL; + } + } + else + { + if (!redflag) + redflag = P_SpawnMobj(0,0,0,MT_REDFLAG); + + P_UnsetThingPosition(redflag); + redflag->x = (fixed_t)LONG(p->flagx[0]); + redflag->y = (fixed_t)LONG(p->flagy[0]); + redflag->z = (fixed_t)LONG(p->flagz[0]); + redflag->flags2 = LONG(p->flagflags[0]); + redflag->fuse = LONG(p->flagloose[0]); + P_SetThingPosition(redflag); + } + + // Blue flag + if (p->flagplayer[1] != -1) // Held by a player + { + if (!playeringame[p->flagplayer[1]]) + I_Error("Invalid blue flag player %d who isn't in the game!", (INT32)p->flagplayer[1]); + players[p->flagplayer[1]].gotflag = GF_REDFLAG; + if (blueflag) + { + P_RemoveMobj(blueflag); + blueflag = NULL; + } + } + else + { + if (!blueflag) + blueflag = P_SpawnMobj(0,0,0,MT_BLUEFLAG); + + P_UnsetThingPosition(blueflag); + blueflag->x = (fixed_t)LONG(p->flagx[0]); + blueflag->y = (fixed_t)LONG(p->flagy[0]); + blueflag->z = (fixed_t)LONG(p->flagz[0]); + blueflag->flags2 = LONG(p->flagflags[0]); + blueflag->fuse = LONG(p->flagloose[0]); + P_SetThingPosition(blueflag); + } +} + +static inline void resynch_write_others(resynchend_pak *rst) +{ + UINT8 i; + + rst->ingame = rst->ctfteam = 0; + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!playeringame[i]) + { + rst->score[i] = 0; + rst->numboxes[i] = 0; + rst->totalring[i] = 0; + rst->realtime[i] = 0; + rst->laps[i] = 0; + continue; + } + + if (!players[i].spectator) + { + rst->ingame |= (1< 1) + rst->ctfteam |= (1<score[i] = (UINT32)LONG(players[i].score); + rst->numboxes[i] = SHORT(players[i].numboxes); + rst->totalring[i] = SHORT(players[i].totalring); + rst->realtime[i] = (tic_t)LONG(players[i].realtime); + rst->laps[i] = players[i].laps; + } + + // endian safeness + rst->ingame = (UINT32)LONG(rst->ingame); + rst->ctfteam = (UINT32)LONG(rst->ctfteam); +} + +static inline void resynch_read_others(resynchend_pak *p) +{ + UINT8 i; + UINT32 loc_ingame = (UINT32)LONG(p->ingame); + UINT32 loc_ctfteam = (UINT32)LONG(p->ctfteam); + + for (i = 0; i < MAXPLAYERS; ++i) + { + // We don't care if they're in the game or not, just write all the data. + if (loc_ingame & (1<score[i]); + players[i].numboxes = SHORT(p->numboxes[i]); + players[i].totalring = SHORT(p->totalring[i]); + players[i].realtime = (tic_t)LONG(p->realtime[i]); + players[i].laps = p->laps[i]; + } +} + +static void SV_InitResynchVars(INT32 node) +{ + resynch_delay[node] = TICRATE; // initial one second delay + resynch_score[node] = 0; // clean slate + resynch_status[node] = 0x00; + resynch_inprogress[node] = false; + memset(resynch_sent[node], 0, MAXNETNODES); +} + +static void SV_RequireResynch(INT32 node) +{ + INT32 i; + + resynch_delay[node] = 10; // Delay before you can fail sync again + resynch_score[node] += 200; // Add score for initial desynch + resynch_status[node] = 0xFF; // No players assumed synched + resynch_inprogress[node] = true; // so we know to send a PT_RESYNCHEND after sync + + // Initial setup + memset(resynch_sent[node], 0, MAXNETNODES); + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!playeringame[i]) // Player not in game so just drop it from required synch + resynch_status[node] &= ~(1<>1)+1; + } +} + +static void SV_SendResynch(INT32 node) +{ + INT32 i, j; + + // resynched? + if (!resynch_status[node]) + { + // you are now synched + resynch_inprogress[node] = false; + + netbuffer->packettype = PT_RESYNCHEND; + + netbuffer->u.resynchend.randomseed = P_GetRandSeed(); + if (gametype == GT_CTF) + resynch_write_ctf(&netbuffer->u.resynchend); + resynch_write_others(&netbuffer->u.resynchend); + + HSendPacket(node, true, 0, (sizeof(resynchend_pak))); + return; + } + + netbuffer->packettype = PT_RESYNCHING; + for (i = 0, j = 0; i < MAXPLAYERS; ++i) + { + // if already synched don't bother + if (!(resynch_status[node] & 1<u.resynchpak, i); + HSendPacket(node, false, 0, (sizeof(resynch_pak))); + + resynch_sent[node][i] = TICRATE; + resynch_score[node] += 2; // penalty for send + + if (++j > 3) + break; + } + + if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)nodetoplayer[node]; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + resynch_score[node] = 0; + } +} + +static void CL_AcknowledgeResynch(resynch_pak *rsp) +{ + resynch_read_player(rsp); + + netbuffer->packettype = PT_RESYNCHGET; + netbuffer->u.resynchgot = rsp->playernum; + HSendPacket(servernode, true, 0, sizeof(UINT8)); +} + +static void SV_AcknowledgeResynchAck(INT32 node, UINT8 rsg) +{ + if (rsg >= MAXPLAYERS) + resynch_score[node] += 16384; // lol. + else + { + resynch_status[node] &= ~(1<playernum = (UINT8)i; - - con->playerstate = (UINT8)players[i].playerstate; - G_MoveTiccmd(&con->cmd, &players[i].cmd, 1); - con->viewz = LONG(players[i].viewz); - con->viewheight = LONG(players[i].viewheight); - con->deltaviewheight = LONG(players[i].deltaviewheight); - con->bob = LONG(players[i].bob); - con->aiming = (angle_t)LONG(players[i].aiming); - con->awayviewaiming = (angle_t)LONG(players[i].awayviewaiming); - con->phealth = LONG(players[i].health); - con->pity = players[i].pity; - con->currentweapon = LONG(players[i].currentweapon); - con->ringweapons = LONG(players[i].ringweapons); - - for (j = 0; j < NUMPOWERS; j++) - con->powers[j] = (UINT16)SHORT(players[i].powers[j]); - - con->pflags = (UINT32)LONG(players[i].pflags); - con->panim = (UINT8)players[i].panim; - con->flashcount = LONG(players[i].flashcount); - con->skincolor = players[i].skincolor; - con->skin = LONG(players[i].skin); - con->score = (UINT32)LONG(players[i].score); - con->maxlink = LONG(players[i].maxlink); - con->dashspeed = LONG(players[i].dashspeed); - con->dashtime = LONG(players[i].dashtime); - con->normalspeed = LONG(players[i].normalspeed); - con->runspeed = LONG(players[i].runspeed); - con->thrustfactor = players[i].thrustfactor; - con->accelstart = players[i].accelstart; - con->acceleration = players[i].acceleration; - con->charability = players[i].charability; - con->charability2 = players[i].charability2; - con->charflags = (UINT32)LONG(players[i].charflags); - con->thokitem = (UINT32)LONG(players[i].thokitem); - con->spinitem = (UINT32)LONG(players[i].spinitem); - con->revitem = (UINT32)LONG(players[i].revitem); - con->actionspd = LONG(players[i].actionspd); - con->mindash = LONG(players[i].mindash); - con->maxdash = LONG(players[i].maxdash); - con->jumpfactor = LONG(players[i].jumpfactor); - con->lives = LONG(players[i].lives); - con->continues = LONG(players[i].continues); - con->xtralife = LONG(players[i].xtralife); - con->speed = LONG(players[i].speed); - con->jumping = LONG(players[i].jumping); - con->secondjump =players[i].secondjump; - con->fly1 = players[i].fly1; - con->scoreadd = (UINT32)LONG(players[i].scoreadd); - con->glidetime = (tic_t)LONG(players[i].glidetime); - con->climbing = players[i].climbing; - con->deadtimer = LONG(players[i].deadtimer); - con->exiting = (tic_t)LONG(players[i].exiting); - con->homing = players[i].homing; - con->skidtime = (tic_t)LONG(players[i].skidtime); - con->cmomx = LONG(players[i].cmomx); - con->cmomy = LONG(players[i].cmomy); - con->rmomx = LONG(players[i].rmomx); - con->rmomy = LONG(players[i].rmomy); - con->numboxes = LONG(players[i].numboxes); - con->totalring = LONG(players[i].totalring); - con->realtime = (tic_t)LONG(players[i].realtime); - con->laps = (UINT32)LONG(players[i].laps); - con->ctfteam = LONG(players[i].ctfteam); - con->gotflag = (UINT16)SHORT(players[i].gotflag); - con->weapondelay = LONG(players[i].weapondelay); - con->tossdelay = LONG(players[i].tossdelay); - con->starpostx = SHORT(players[i].starpostx); - con->starposty = SHORT(players[i].starposty); - con->starpostz = SHORT(players[i].starpostz); - con->starpostnum = LONG(players[i].starpostnum); - con->starposttime = (tic_t)LONG(players[i].starposttime); - con->starpostangle = (angle_t)LONG(players[i].starpostangle); - con->angle_pos = (angle_t)LONG(players[i].angle_pos); - con->old_angle_pos = (angle_t)LONG(players[i].old_angle_pos); - con->bumpertime = (tic_t)LONG(players[i].bumpertime); - con->flyangle = LONG(players[i].flyangle); - con->drilltimer = (tic_t)LONG(players[i].drilltimer); - con->linkcount = LONG(players[i].linkcount); - con->linktimer = (tic_t)LONG(players[i].linktimer); - con->anotherflyangle = LONG(players[i].anotherflyangle); - con->nightstime = (tic_t)LONG(players[i].nightstime); - con->drillmeter = LONG(players[i].drillmeter); - con->drilldelay = players[i].drilldelay; - con->bonustime = (UINT8)players[i].bonustime; - con->mare = players[i].mare; - con->lastsidehit = SHORT(players[i].lastsidehit); - con->lastlinehit = SHORT(players[i].lastlinehit); - con->losstime = (tic_t)LONG(players[i].losstime); - con->timeshit = (UINT8)players[i].timeshit; - con->onconveyor = LONG(players[i].onconveyor); - con->spectator = (UINT8)players[i].spectator; - con->jointime = (tic_t)LONG(players[i].jointime); - - con->hasmo = false; - //Transfer important mo information if the player has a body. - //This lets us resync players even if they are dead. - if (!players[i].mo) - return; - - con->hasmo = true; - con->angle = (angle_t)LONG(players[i].mo->angle); - con->eflags = (UINT32)LONG(players[i].mo->eflags); - con->flags = LONG(players[i].mo->flags); - con->flags2 = LONG(players[i].mo->flags2); - con->friction = LONG(players[i].mo->friction); - con->health = LONG(players[i].mo->health); - con->momx = LONG(players[i].mo->momx); - con->momy = LONG(players[i].mo->momy); - con->momz = LONG(players[i].mo->momz); - con->movefactor = LONG(players[i].mo->movefactor); - con->tics = LONG(players[i].mo->tics); - con->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( - con->x = LONG(players[i].mo->x); - con->y = LONG(players[i].mo->y); - con->z = LONG(players[i].mo->z); - con->radius = LONG(players[i].mo->radius); - con->height = LONG(players[i].mo->height); - con->scale = LONG(players[i].mo->scale); - con->destscale = LONG(players[i].mo->destscale); - con->scalespeed = LONG(players[i].mo->scalespeed); -} - -static void readconplayer(cons_pak *con, const INT32 playernum) -{ - size_t i; - mobj_t *savedmo = players[playernum].mo; - - //We get a packet for each player in game. - - //Restore CTF information - if (gametype == GT_CTF) - { - // Remove old flags. - if (redflag) - { - P_RemoveMobj(redflag); - redflag = NULL; - } - if (blueflag) - { - P_RemoveMobj(blueflag); - blueflag = NULL; - } - - // Spawn the flags if players aren't carrying them. - if (con->rflagloose != 2) - { - mobj_t *newflag = P_SpawnMobj(con->rflagx << FRACBITS, con->rflagy << FRACBITS, con->rflagz << FRACBITS, MT_REDFLAG); - newflag->flags |= MF_SPECIAL; - newflag->flags2 = con->rflags2; - newflag->fuse = con->rfuse; - newflag->spawnpoint = rflagpoint; - redflag = newflag; - } - - if (con->bflagloose != 2) - { - mobj_t *newflag = P_SpawnMobj(con->bflagx << FRACBITS, con->bflagy << FRACBITS, con->bflagz << FRACBITS, MT_BLUEFLAG); - newflag->flags |= MF_SPECIAL; - newflag->flags2 = con->bflags2; - newflag->fuse = con->bfuse; - newflag->spawnpoint = bflagpoint; - blueflag = newflag; - } - } - - if (!playeringame[playernum]) - return; - - //Tranfer player information. - players[playernum].playerstate = (playerstate_t)con->playerstate; - G_MoveTiccmd(&players[playernum].cmd, &con->cmd, 1); - players[playernum].viewz = LONG(con->viewz); - players[playernum].viewheight = LONG(con->viewheight); - players[playernum].deltaviewheight = LONG(con->deltaviewheight); - players[playernum].bob = LONG(con->bob); - players[playernum].aiming = (angle_t)LONG(con->aiming); - players[playernum].awayviewaiming = (angle_t)LONG(con->awayviewaiming); - players[playernum].health = LONG(con->phealth); - players[playernum].pity = con->pity; - players[playernum].currentweapon = LONG(con->currentweapon); - players[playernum].ringweapons = LONG(con->ringweapons); - - for (i = 0; i < NUMPOWERS; i++) - players[playernum].powers[i] = (UINT16)SHORT(con->powers[i]); - - players[playernum].pflags = (pflags_t)LONG(con->pflags); - players[playernum].panim = (panim_t)con->panim; - players[playernum].flashcount = LONG(con->flashcount); - players[playernum].skincolor = con->skincolor; - players[playernum].skin = LONG(con->skin); - players[playernum].score = (UINT32)LONG(con->score); - players[playernum].maxlink = LONG(con->maxlink); - players[playernum].dashspeed = LONG(con->dashspeed); - players[playernum].dashtime = LONG(con->dashtime); - players[playernum].normalspeed = LONG(con->normalspeed); - players[playernum].runspeed = LONG(con->runspeed); - players[playernum].thrustfactor = con->thrustfactor; - players[playernum].accelstart = con->accelstart; - players[playernum].acceleration = con->acceleration; - players[playernum].charability = con->charability; - players[playernum].charability2 = con->charability2; - players[playernum].charflags = (UINT32)LONG(con->charflags); - players[playernum].thokitem = (mobjtype_t)LONG(con->thokitem); - players[playernum].spinitem = (mobjtype_t)LONG(con->spinitem); - players[playernum].revitem = (mobjtype_t)LONG(con->revitem); - players[playernum].actionspd = LONG(con->actionspd); - players[playernum].mindash = LONG(con->mindash); - players[playernum].maxdash = LONG(con->maxdash); - players[playernum].jumpfactor = LONG(con->jumpfactor); - players[playernum].lives = LONG(con->lives); - players[playernum].continues = LONG(con->continues); - players[playernum].xtralife = LONG(con->xtralife); - players[playernum].speed = LONG(con->speed); - players[playernum].jumping = LONG(con->jumping); - players[playernum].secondjump = con->secondjump; - players[playernum].fly1 = con->fly1; - players[playernum].scoreadd = (UINT32)LONG(con->scoreadd); - players[playernum].glidetime = (tic_t)LONG(con->glidetime); - players[playernum].climbing = con->climbing; - players[playernum].deadtimer = LONG(con->deadtimer); - players[playernum].exiting = (tic_t)LONG(con->exiting); - players[playernum].homing = con->homing; - players[playernum].skidtime = (tic_t)LONG(con->skidtime); - players[playernum].cmomx = LONG(con->cmomx); - players[playernum].cmomy = LONG(con->cmomy); - players[playernum].rmomx = LONG(con->rmomx); - players[playernum].rmomy = LONG(con->rmomy); - players[playernum].numboxes = LONG(con->numboxes); - players[playernum].totalring = LONG(con->totalring); - players[playernum].realtime = (tic_t)LONG(con->realtime); - players[playernum].laps = (UINT32)LONG(con->laps); - players[playernum].ctfteam = LONG(con->ctfteam); - players[playernum].gotflag = (UINT16)SHORT(con->gotflag); - players[playernum].weapondelay = LONG(con->weapondelay); - players[playernum].tossdelay = LONG(con->tossdelay); - players[playernum].starpostx = LONG(con->starpostx); - players[playernum].starposty = LONG(con->starposty); - players[playernum].starpostz = LONG(con->starpostz); - players[playernum].starpostnum = LONG(con->starpostnum); - players[playernum].starposttime = (tic_t)LONG(con->starposttime); - players[playernum].starpostangle = (angle_t)LONG(con->starpostangle); - players[playernum].angle_pos = (angle_t)LONG(con->angle_pos); - players[playernum].old_angle_pos = (angle_t)LONG(con->old_angle_pos); - players[playernum].bumpertime = (tic_t)LONG(con->bumpertime); - players[playernum].flyangle = LONG(con->flyangle); - players[playernum].drilltimer = (tic_t)LONG(con->drilltimer); - players[playernum].linkcount = LONG(con->linkcount); - players[playernum].linktimer = (tic_t)LONG(con->linktimer); - players[playernum].anotherflyangle = LONG(con->anotherflyangle); - players[playernum].nightstime = (tic_t)LONG(con->nightstime); - players[playernum].drillmeter = LONG(con->drillmeter); - players[playernum].drilldelay = con->drilldelay; - players[playernum].bonustime = (boolean)con->bonustime; - players[playernum].mare = con->mare; - players[playernum].lastsidehit = SHORT(con->lastsidehit); - players[playernum].lastlinehit = SHORT(con->lastlinehit); - players[playernum].losstime = (tic_t)LONG(con->losstime); - players[playernum].timeshit = (UINT8)con->timeshit; - players[playernum].onconveyor = LONG(con->onconveyor); - players[playernum].spectator = (boolean)con->spectator; - players[playernum].jointime = (tic_t)LONG(con->jointime); - - //...but keep old mo even if it is corrupt or null! - players[playernum].mo = savedmo; - - //Transfer important mo information if they have a valid mo. - if (!con->hasmo) - return; - //server thinks player has a body. - //Give them a new body that can be then manipulated by the server's info. - if (!players[playernum].mo) //client thinks it has no body. - P_SpawnPlayer(playernum); - - //At this point, the player should have a body, whether they were respawned or not. - P_UnsetThingPosition(players[playernum].mo); - players[playernum].mo->angle = (angle_t)LONG(con->angle); - players[playernum].mo->eflags = (UINT32)LONG(con->eflags); - players[playernum].mo->flags = LONG(con->flags); - players[playernum].mo->flags2 = LONG(con->flags2); - players[playernum].mo->friction = LONG(con->friction); - players[playernum].mo->health = LONG(con->health); - players[playernum].mo->momx = LONG(con->momx); - players[playernum].mo->momy = LONG(con->momy); - players[playernum].mo->momz = LONG(con->momz); - players[playernum].mo->movefactor = LONG(con->movefactor); - players[playernum].mo->tics = LONG(con->tics); - P_SetPlayerMobjState(players[playernum].mo, LONG(con->statenum)); - players[playernum].mo->x = LONG(con->x); - players[playernum].mo->y = LONG(con->y); - players[playernum].mo->z = LONG(con->z); - players[playernum].mo->radius = LONG(con->radius); - players[playernum].mo->height = LONG(con->height); - // P_SetScale is redundant for this, as all related variables are already restored properly. - players[playernum].mo->scale = LONG(con->scale); - players[playernum].mo->destscale = LONG(con->destscale); - players[playernum].mo->scalespeed = LONG(con->scalespeed); - - // And finally, SET THE MOBJ SKIN damn it. - players[playernum].mo->skin = &skins[players[playernum].skin]; - players[playernum].mo->color = players[playernum].skincolor; - - P_SetThingPosition(players[playernum].mo); -} - -static inline void handlectfconstuff(cons_pak *con) -{ - if (redflag) - { - // Flag is loose - if (redflag->fuse) - { - con->rflagloose = 1; - con->rflagx = SHORT(redflag->x >> FRACBITS); - con->rflagy = SHORT(redflag->y >> FRACBITS); - con->rflagz = SHORT(redflag->z >> FRACBITS); - con->rflags2 = LONG(redflag->flags2); - con->rfuse = LONG(redflag->fuse); - } - else // flag is at base - { - con->rflagloose = 0; - con->rflagx = SHORT(rflagpoint->x); - con->rflagy = SHORT(rflagpoint->y); - con->rflagz = SHORT(rflagpoint->z); - con->rflags2 = 0; - con->rfuse = 0; - } - } - else // player has flag - con->rflagloose = 2; - - if (blueflag) - { - // Flag is loose - if (blueflag->fuse) - { - con->bflagloose = 1; - con->bflagx = SHORT(blueflag->x >> FRACBITS); - con->bflagy = SHORT(blueflag->y >> FRACBITS); - con->bflagz = SHORT(blueflag->z >> FRACBITS); - con->bflags2 = LONG(blueflag->flags2); - con->bfuse = LONG(blueflag->fuse); - } - else // flag is at base - { - con->bflagloose = 0; - con->bflagx = SHORT(bflagpoint->x); - con->bflagy = SHORT(bflagpoint->y); - con->bflagz = SHORT(bflagpoint->z); - con->bflags2 = 0; - con->bfuse = 0; - } - } - else // player has flag - con->bflagloose = 2; -} - -/// \todo Remove this AWFUL consistency fixing packet and replace it with re-sending $$$.sav, or at least pause the game until it gets acked! -static void SV_SendConsistency(INT32 node) -{ - INT32 i; - - netbuffer->packettype = PT_CONSISTENCY; - - if (gametype == GT_CTF) - handlectfconstuff(&netbuffer->u.consistency); - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - writeconplayer(&netbuffer->u.consistency, i); - HSendPacket(node, true, 0, (sizeof(cons_pak))); - } -} - // used at txtcmds received to check packetsize bound static size_t TotalTextCmdPerTic(tic_t tic) { @@ -2910,6 +3071,10 @@ static void HandleConnect(SINT8 node) newnode = true; #endif SV_AddNode(node); + + // you get a free second before desynch checks. use it wisely. + SV_InitResynchVars(node); + if (cv_joinnextround.value && gameaction == ga_nothing) G_SetGamestate(GS_WAITINGPLAYERS); if (!SV_SendServerConfig(node)) @@ -2934,6 +3099,7 @@ static void HandleConnect(SINT8 node) DEBFILE("send savegame\n"); } SV_AddWaitingPlayers(); + player_joining = true; } #endif } @@ -2982,6 +3148,9 @@ static void GetPackets(void) XBOXSTATIC tic_t realend,realstart; XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak; FILESTAMP + + player_joining = false; + while (HGetPacket()) { node = (SINT8)doomcom->remotenode; @@ -3153,9 +3322,14 @@ FILESTAMP I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); #endif + txtpak = NULL; + switch (netbuffer->packettype) { // -------------------------------------------- SERVER RECEIVE ---------- + case PT_RESYNCHGET: + SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); + break; case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: @@ -3165,6 +3339,10 @@ FILESTAMP if (!server) break; + // ignore tics from those not synched + if (resynch_inprogress[node]) + break; + // to save bytes, only the low byte of tic numbers are sent // Figure out what the rest of the bytes are realstart = ExpandTics(netbuffer->u.clientpak.client_tic); @@ -3213,42 +3391,30 @@ FILESTAMP G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); + // a delay before we check resynching + // used on join or just after a synch fail + if (resynch_delay[node]) + { + --resynch_delay[node]; + break; + } // check player consistancy during the level - // Careful: When a consistency packet is sent, it overwrites the incoming packet containing the ticcmd. - // Keep this in mind when changing the code that responds to these packets. - if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 - && gamestate == GS_LEVEL && playeringame[netconsole] - && players[netconsole].playerstate == PST_LIVE - && !players[netconsole].spectator - && players[netconsole].jointime > 10 + if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) { - if (cv_consfailprotect.value && consfailcount[netconsole] < cv_consfailprotect.value) + SV_RequireResynch(node); + + if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) { - if (!consfailstatus[netconsole]) - { - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Consistency failure for player %d (%s), restoring...\n"), netconsole+1, player_names[netconsole]); - - DEBFILE(va("Restoring player %d (consistency failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - - SV_SendConsistency(netconsole); - consfailstatus[netconsole] = 1; - consfailcount[netconsole]++; - break; // ticcmd packet is gone. - } - else - { - //We don't want to send any more packets than we have to. - //If the client doesn't resync in a certain time, - //assume they didn't get the packet. Send another. - if (consfailstatus[netconsole] < 10) - consfailstatus[netconsole]++; - else - consfailstatus[netconsole] = 0; - } + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; } else { @@ -3257,19 +3423,14 @@ FILESTAMP buf[0] = (UINT8)netconsole; buf[1] = KICK_MSG_CON_FAIL; SendNetXCmd(XD_KICK, &buf, 2); - DEBFILE(va("player %d kicked (consistency failure) [%u] %d!=%d\n", + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", netconsole, realstart, consistancy[realstart%BACKUPTICS], SHORT(netbuffer->u.clientpak.consistancy))); - consfailstatus[netconsole] = 0; - consfailcount[netconsole] = 0; break; } } - else - { - consfailstatus[netconsole] = 0; - consfailcount[netconsole] = 0; - } + else if (resynch_score[node]) + --resynch_score[node]; break; case PT_TEXTCMD2: // splitscreen special netconsole = nodetoplayer2[node]; @@ -3346,6 +3507,31 @@ FILESTAMP nodeingame[node] = false; break; // -------------------------------------------- CLIENT RECEIVE ---------- + case PT_RESYNCHEND: + // Only accept PT_RESYNCHEND from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node); + + if (server) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + resynch_local_inprogress = false; + + P_SetRandSeed(netbuffer->u.resynchend.randomseed); + + if (gametype == GT_CTF) + resynch_read_ctf(&netbuffer->u.resynchend); + resynch_read_others(&netbuffer->u.resynchend); + + break; case PT_SERVERTICS: // Only accept PT_SERVERTICS from the server. if (node != servernode) @@ -3366,8 +3552,9 @@ FILESTAMP realstart = ExpandTics(netbuffer->u.serverpak.starttic); realend = realstart + netbuffer->u.serverpak.numtics; - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; + if (!txtpak) + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; if (realend > gametic + BACKUPTICS) realend = gametic + BACKUPTICS; @@ -3404,11 +3591,11 @@ FILESTAMP else DEBFILE(va("frame not in bound: %u\n", neededtic)); break; - case PT_CONSISTENCY: - // Only accept PT_CONSISTENCY from the server. + case PT_RESYNCHING: + // Only accept PT_RESYNCHING from the server. if (node != servernode) { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_CONSISTENCY", node); + CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node); if (server) { @@ -3420,8 +3607,8 @@ FILESTAMP break; } - - readconplayer(&netbuffer->u.consistency, netbuffer->u.consistency.playernum); + resynch_local_inprogress = true; + CL_AcknowledgeResynch(&netbuffer->u.resynchpak); break; #ifdef NEWPING case PT_PING: @@ -3470,25 +3657,35 @@ FILESTAMP // Builds ticcmds for console player, // sends out a packet // +// no more use random generator, because at very first tic isn't yet synchronized // Note: It is called consistAncy on purpose. // static INT16 Consistancy(void) { - INT16 ret = 0; INT32 i; + UINT32 ret = 0; DEBFILE(va("TIC %u ", gametic)); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].playerstate == PST_LIVE && !players[i].spectator) - { - //DEBFILE(va("p[%d].x = %f ", i, (double)FIXED_TO_FLOAT(players[i].mo->x))); - ret = (INT16)((ret + (players[i].mo->x>>8)) & 0xFFFF); - ret = (INT16)((ret + players[i].powers[pw_shield]) & 0xFFFF); - } - DEBFILE(va("players = %d, rnd %d\n", ret, P_GetRandSeed())); - ret = (INT16)(ret + P_GetRandSeed()); - return ret; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + ret ^= 0xCCCC; + else if (!players[i].mo); + else + { + ret += players[i].mo->x; + ret -= players[i].mo->y; + ret += players[i].powers[pw_shield]; + ret *= i+1; + } + } + // I give up + // Coop desynching enemies is painful + if (!G_PlatformGametype()) + ret += P_GetRandSeed(); + + return (INT16)(ret & 0xFFFF); } // send the client packet to the server @@ -3776,6 +3973,9 @@ void TryRunTics(tic_t realtics) } #endif + if (player_joining) + return; + if (neededtic > gametic) { if (advancedemo) @@ -3911,13 +4111,19 @@ FILESTAMP MasterClient_Ticker(); // acking the master server if (!server) - CL_SendClientCmd(); // send tic cmd + { + if (!resynch_local_inprogress) + CL_SendClientCmd(); // send tic cmd + hu_resynching = resynch_local_inprogress; + } else { if (!demoplayback) { INT32 counts; + hu_resynching = false; + firstticstosend = gametic; for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i] && nettics[i] < firstticstosend) @@ -3926,18 +4132,31 @@ FILESTAMP // Don't erase tics not acknowledged counts = realtics; - if (maketic + counts >= firstticstosend + BACKUPTICS) - counts = firstticstosend+BACKUPTICS-maketic-1; + for (i = 0; i < MAXNETNODES; ++i) + if (resynch_inprogress[i]) + { + SV_SendResynch(i); + counts = -666; + } - for (i = 0; i < counts; i++) - SV_Maketic(); // create missed tics and increment maketic + // do not make tics while resynching + if (counts != -666) + { + if (maketic + counts >= firstticstosend + BACKUPTICS) + counts = firstticstosend+BACKUPTICS-maketic-1; - for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged - D_Clearticcmd(tictoclear); // clear the maketic the new tic + for (i = 0; i < counts; i++) + SV_Maketic(); // create missed tics and increment maketic - SV_SendTics(); + for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged + D_Clearticcmd(tictoclear); // clear the maketic the new tic - neededtic = maketic; // the server is a client too + SV_SendTics(); + + neededtic = maketic; // the server is a client too + } + else + hu_resynching = true; } } Net_AckTicker(); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index d35c5cb3..0086132e 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -53,6 +53,8 @@ typedef enum PT_REQUESTFILE, // Client requests a file transfer PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. // If this ID changes, update masterserver definition. + PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic + PT_RESYNCHGET, // Player got resynch packet // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. @@ -66,7 +68,8 @@ typedef enum PT_TEXTCMD2, // Splitscreen text commands. PT_CLIENTJOIN, // Client wants to join; used in start game. PT_NODETIMEOUT, // Packet sent to self if the connection times out. - PT_CONSISTENCY, // Packet sent to resync players. + PT_RESYNCHING, // Packet sent to resync players. + // Blocks game advance until synched. #ifdef NEWPING PT_PING, // Packet sent to tell clients the other client's latency to server. #endif @@ -110,6 +113,147 @@ typedef struct ticcmd_t cmds[45]; // normally [BACKUPTIC][MAXPLAYERS] but too large } ATTRPACK servertics_pak; +// sent to client when all consistency data +// for players has been restored +typedef struct +{ + UINT32 randomseed; + + //ctf flag stuff + SINT8 flagplayer[2]; + INT32 flagloose[2]; + INT32 flagflags[2]; + fixed_t flagx[2]; + fixed_t flagy[2]; + fixed_t flagz[2]; + + UINT32 ingame; // spectator bit for each player + UINT32 ctfteam; // if not spectator, then which team? + + // Resynch game scores and the like all at once + UINT32 score[MAXPLAYERS]; // Everyone's score. + INT16 numboxes[MAXPLAYERS]; + INT16 totalring[MAXPLAYERS]; + tic_t realtime[MAXPLAYERS]; + UINT8 laps[MAXPLAYERS]; +} ATTRPACK resynchend_pak; + +typedef struct +{ + //player stuff + UINT8 playernum; + + // Do not send anything visual related. + // Only send data that we need to know for physics. + UINT8 playerstate; //playerstate_t + UINT32 pflags; //pflags_t + UINT8 panim; //panim_t + + angle_t aiming; + INT32 currentweapon; + INT32 ringweapons; + UINT16 powers[NUMPOWERS]; + + // Score is resynched in the confirm resync packet + INT32 health; + SINT8 lives; + SINT8 continues; + UINT8 scoreadd; + SINT8 xtralife; + SINT8 pity; + + UINT8 skincolor; + INT32 skin; + // Just in case Lua does something like + // modify these at runtime + fixed_t normalspeed; + fixed_t runspeed; + UINT8 thrustfactor; + UINT8 accelstart; + UINT8 acceleration; + UINT8 charability; + UINT8 charability2; + UINT32 charflags; + UINT32 thokitem; //mobjtype_t + UINT32 spinitem; //mobjtype_t + UINT32 revitem; //mobjtype_t + INT32 actionspd; + INT32 mindash; + INT32 maxdash; + fixed_t jumpfactor; + + fixed_t speed; + UINT8 jumping; + UINT8 secondjump; + UINT8 fly1; + tic_t glidetime; + UINT8 climbing; + INT32 deadtimer; + tic_t exiting; + UINT8 homing; + fixed_t cmomx; + fixed_t cmomy; + fixed_t rmomx; + fixed_t rmomy; + + INT32 weapondelay; + INT32 tossdelay; + + INT16 starpostx; + INT16 starposty; + INT16 starpostz; + INT32 starpostnum; + tic_t starposttime; + angle_t starpostangle; + + INT32 maxlink; + fixed_t dashspeed; + INT32 dashtime; + angle_t angle_pos; + angle_t old_angle_pos; + tic_t bumpertime; + INT32 flyangle; + tic_t drilltimer; + INT32 linkcount; + tic_t linktimer; + INT32 anotherflyangle; + tic_t nightstime; + INT32 drillmeter; + UINT8 drilldelay; + UINT8 bonustime; + UINT8 mare; + INT16 lastsidehit, lastlinehit; + + tic_t losstime; + UINT8 timeshit; + INT32 onconveyor; + + //player->mo stuff + UINT8 hasmo; //boolean + + angle_t angle; + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t momx; + fixed_t momy; + fixed_t momz; + fixed_t friction; + fixed_t movefactor; + + INT16 tics; + statenum_t statenum; + UINT32 flags; + UINT32 flags2; + UINT8 eflags; + + fixed_t radius; + fixed_t height; + fixed_t scale; + fixed_t destscale; + fixed_t scalespeed; +} ATTRPACK resynch_pak; + typedef struct { UINT8 version; // different versions don't work @@ -194,143 +338,6 @@ typedef struct tic_t time; // used for ping evaluation } ATTRPACK msaskinfo_pak; -typedef struct -{ - UINT32 randomseed; - - //ctf flag stuff - UINT8 rflagloose; - UINT8 bflagloose; - INT32 rfuse; - INT32 bfuse; - INT32 rflags2; - INT32 bflags2; - INT16 rflagx; - INT16 rflagy; - INT16 rflagz; - INT16 bflagx; - INT16 bflagy; - INT16 bflagz; - - //player stuff - UINT8 playernum; - - UINT8 playerstate; //playerstate_t - ticcmd_t cmd; - fixed_t viewz; - fixed_t viewheight; - fixed_t deltaviewheight; - fixed_t bob; - angle_t aiming; - angle_t awayviewaiming; - INT32 phealth; - SINT8 pity; - INT32 currentweapon; - INT32 ringweapons; - UINT16 powers[NUMPOWERS]; - UINT32 pflags; //pflags_t - UINT8 panim; //panim_t - INT32 flashcount; - UINT8 skincolor; - INT32 skin; - UINT32 score; - INT32 maxlink; - fixed_t dashspeed; - INT32 dashtime; - fixed_t normalspeed; - fixed_t runspeed; - UINT8 thrustfactor; - UINT8 accelstart; - UINT8 acceleration; - UINT8 charability; - UINT8 charability2; - UINT32 charflags; - UINT32 thokitem; //mobjtype_t - UINT32 spinitem; //mobjtype_t - UINT32 revitem; //mobjtype_t - INT32 actionspd; - INT32 mindash; - INT32 maxdash; - fixed_t jumpfactor; - INT32 lives; - INT32 continues; - INT32 xtralife; - fixed_t speed; - INT32 jumping; - UINT8 secondjump; - UINT8 fly1; - UINT8 scoreadd; - tic_t glidetime; - UINT8 climbing; - INT32 deadtimer; - tic_t exiting; - UINT8 homing; - tic_t skidtime; - fixed_t cmomx; - fixed_t cmomy; - fixed_t rmomx; - fixed_t rmomy; - INT32 numboxes; - INT32 totalring; - tic_t realtime; - UINT32 laps; - INT32 ctfteam; - UINT16 gotflag; - INT32 weapondelay; - INT32 tossdelay; - INT16 starpostx; - INT16 starposty; - INT16 starpostz; - INT32 starpostnum; - tic_t starposttime; - angle_t starpostangle; - angle_t angle_pos; - angle_t old_angle_pos; - tic_t bumpertime; - INT32 flyangle; - tic_t drilltimer; - INT32 linkcount; - tic_t linktimer; - INT32 anotherflyangle; - tic_t nightstime; - INT32 drillmeter; - UINT8 drilldelay; - UINT8 bonustime; - UINT8 mare; - INT16 lastsidehit, lastlinehit; - tic_t losstime; - UINT8 timeshit; - INT32 onconveyor; - UINT8 spectator; //boolean - tic_t jointime; - - //player->mo stuff - UINT8 hasmo; //boolean - - angle_t angle; - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t momx; - fixed_t momy; - fixed_t momz; - fixed_t friction; - fixed_t movefactor; - - INT32 tics; - statenum_t statenum; - UINT32 flags; - UINT32 flags2; - UINT8 eflags; - INT32 health; - - fixed_t radius; - fixed_t height; - fixed_t scale; - fixed_t destscale; - fixed_t scalespeed; -} ATTRPACK cons_pak; - // Shorter player information for external use. typedef struct { @@ -372,6 +379,9 @@ typedef struct client2cmd_pak client2pak; // 200 bytes servertics_pak serverpak; // 132495 bytes serverconfig_pak servercfg; // 773 bytes + resynchend_pak resynchend; // + resynch_pak resynchpak; // + UINT8 resynchgot; // UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 136 bytes @@ -379,7 +389,6 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - cons_pak consistency; // 544 bytes plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes #ifdef NEWPING @@ -437,7 +446,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; #endif -extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_consfailprotect, cv_blamecfail, cv_maxsend; +extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend; // used in d_net, the only dependence tic_t ExpandTics(INT32 low); @@ -492,4 +501,5 @@ void D_ResetTiccmds(void); tic_t GetLag(INT32 node); UINT8 GetFreeXCmdSize(void); +extern UINT8 hu_resynching; #endif diff --git a/src/d_main.c b/src/d_main.c index 2492f622..02590390 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -401,7 +401,10 @@ static void D_Display(void) if (lastdraw) { if (rendermode == render_soft) + { VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + usebuffer = true; + } lastdraw = false; } @@ -1094,7 +1097,7 @@ void D_SRB2Main(void) W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta - W_VerifyFileMD5(4, "12c58561edf3be16a15505f1d5eacee0"); // patch.dta + W_VerifyFileMD5(4, "e868046d2d2da1d8c706c900edfb03f8"); // patch.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. diff --git a/src/d_net.c b/src/d_net.c index 3c2213fc..d93b80c9 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -784,18 +784,6 @@ static void DebugPrintpacket(const char *header) fprintfstring((char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics],(size_t)( &((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics])); break; - case PT_CONSISTENCY: - fprintf(debugfile, " randomseed %d playernum %d hasmo %d\n", - netbuffer->u.consistency.randomseed, netbuffer->u.consistency.playernum, netbuffer->u.consistency.hasmo); - fprintf(debugfile, " x %d y %d z %d momx %d momy %d momz %d\n", - netbuffer->u.consistency.x, netbuffer->u.consistency.y, netbuffer->u.consistency.z, - netbuffer->u.consistency.momx, netbuffer->u.consistency.momy, netbuffer->u.consistency.momz); - fprintf(debugfile, " angle %d health %d eflags %d flags %d flags2 %d\n", - netbuffer->u.consistency.angle, netbuffer->u.consistency.health, netbuffer->u.consistency.eflags, - netbuffer->u.consistency.flags, netbuffer->u.consistency.flags2); - fprintf(debugfile, " friction %d movefactor %d tics %d statenum %d\n", - netbuffer->u.consistency.friction, netbuffer->u.consistency.movefactor, - netbuffer->u.consistency.tics, (INT32)netbuffer->u.consistency.statenum); case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 57445244..06c6fcb0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3138,10 +3138,8 @@ static void Command_Addfile(void) p = fn+strlen(fn); while(--p >= fn) if (*p == '\\' || *p == '/' || *p == ':') - { - ++p; break; - } + ++p; WRITESTRINGN(buf_p,p,240); { @@ -4094,8 +4092,17 @@ static void Command_Isgamemodified_f(void) static void Command_Cheats_f(void) { + if (COM_CheckParm("off")) + { + CV_ResetCheatNetVars(); + return; + } + if (CV_CheatsEnabled()) + { CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n")); + CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.")); + } else CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n")); } diff --git a/src/d_player.h b/src/d_player.h index 3abc6ddf..4b297854 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -147,7 +147,7 @@ typedef enum PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek. PF_TAGIT = 1<<28, // The player is it! For Tag Mode - // free: 1<<29, 1<<31 + // free: 1<<29 through 1<<31 } pflags_t; typedef enum @@ -268,10 +268,9 @@ typedef struct player_s // It is updated with cmd->aiming. angle_t aiming; - angle_t awayviewaiming; // Used for cut-away view - // This is only used between levels, // mo->health is used during levels. + /// \todo Remove this. We don't need a second health definition for players. INT32 health; SINT8 pity; // i pity the fool. @@ -324,15 +323,14 @@ typedef struct player_s fixed_t jumpfactor; // How high can the player jump? - INT32 lives; - INT32 continues; // continues that player has acquired + SINT8 lives; + SINT8 continues; // continues that player has acquired - INT32 xtralife; // Ring Extra Life counter + SINT8 xtralife; // Ring Extra Life counter UINT8 gotcontinue; // Got continue from this stage? fixed_t speed; // Player's speed (distance formula of MOMX and MOMY values) - INT32 jumping; // Jump counter - + UINT8 jumping; // Jump counter UINT8 secondjump; UINT8 fly1; // Tails flying @@ -357,10 +355,10 @@ typedef struct player_s ///////////////////// // Race Mode Stuff // ///////////////////// - INT32 numboxes; // Number of item boxes obtained for Race Mode - INT32 totalring; // Total number of rings obtained for Race Mode + INT16 numboxes; // Number of item boxes obtained for Race Mode + INT16 totalring; // Total number of rings obtained for Race Mode tic_t realtime; // integer replacement for leveltime - UINT32 laps; // Number of laps (optional) + UINT8 laps; // Number of laps (optional) //////////////////// // CTF Mode Stuff // @@ -421,6 +419,7 @@ typedef struct player_s mobj_t *awayviewmobj; INT32 awayviewtics; + angle_t awayviewaiming; // Used for cut-away view boolean spectator; UINT8 bot; diff --git a/src/dehacked.c b/src/dehacked.c index e25f66e7..6eae1ce2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1132,7 +1132,7 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "PALETTE")) mapheaderinfo[num-1]->palette = (UINT16)i; else if (fastcmp(word, "NUMLAPS")) - mapheaderinfo[num-1]->numlaps = (UINT32)i; + mapheaderinfo[num-1]->numlaps = (UINT8)i; else if (fastcmp(word, "UNLOCKABLE")) { if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something @@ -7325,24 +7325,29 @@ static const char *const HUDITEMS_LIST[] = { "LIVESPIC", "LIVESNUM", "LIVESX", - "RINGSSPLIT", - "RINGSNUMSPLIT", + "RINGS", + "RINGSSPLIT", "RINGSNUM", + "RINGSNUMSPLIT", + "SCORE", "SCORENUM", - "TIMESPLIT", - "SECONDSSPLIT", - "MINUTESSPLIT", - "TIMECOLONSPLIT", + "TIME", - "TICS", - "SECONDS", + "TIMESPLIT", "MINUTES", + "MINUTESSPLIT", "TIMECOLON", + "TIMECOLONSPLIT", + "SECONDS", + "SECONDSSPLIT", "TIMETICCOLON", - "SS_TOTALRINGS_SPLIT", + "TICS", + "SS_TOTALRINGS", + "SS_TOTALRINGS_SPLIT", + "GETRINGS", "GETRINGSNUM", "TIMELEFT", @@ -7683,6 +7688,9 @@ struct { {"V_70TRANS",V_70TRANS}, {"V_80TRANS",V_80TRANS}, {"V_90TRANS",V_90TRANS}, + {"V_HUDTRANSHALF",V_HUDTRANSHALF}, + {"V_HUDTRANS",V_HUDTRANS}, + {"V_HUDTRANSDOUBLE",V_HUDTRANSDOUBLE}, {"V_AUTOFADEOUT",V_AUTOFADEOUT}, {"V_RETURN8",V_RETURN8}, {"V_OFFSET",V_OFFSET}, diff --git a/src/doomdata.h b/src/doomdata.h index 4023c497..371decc2 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -131,6 +131,7 @@ typedef struct #define ML_NOSONIC 2048 #define ML_NOTAILS 4096 #define ML_NOKNUX 8192 +#define ML_NETONLY 14336 // all of the above // Bounce off walls! #define ML_BOUNCY 16384 diff --git a/src/doomdef.h b/src/doomdef.h index d4ad4a68..a5454851 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -144,8 +144,8 @@ extern FILE *logstream; #define VERSIONSTRING "Trunk" #else #define VERSION 201 // Game version -#define SUBVERSION 3 // more precise version number -#define VERSIONSTRING "v2.1.3" +#define SUBVERSION 4 // more precise version number +#define VERSIONSTRING "v2.1.4" #endif // Modification options @@ -201,7 +201,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 7 +#define MODVERSION 9 diff --git a/src/doomstat.h b/src/doomstat.h index 576b7009..642e9bfc 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -227,7 +227,7 @@ typedef struct UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. INT16 countdown; ///< Countdown until level end? UINT16 palette; ///< PAL lump to use on this map - UINT32 numlaps; ///< Number of laps in circuit mode, unless overridden. + UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) diff --git a/src/g_game.c b/src/g_game.c index e3f2a281..dfd9aacd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1467,10 +1467,12 @@ static void Analog_OnChange(void) { if (!cv_cam_dist.string) return; + + // cameras are not initialized at this point + if (leveltime > 1) CV_SetValue(&cv_cam_dist, 128); - - if (netgame || !camera.chase) + if (netgame) CV_StealthSetValue(&cv_analog, 0); else if (cv_analog.value || demoplayback) CV_SetValue(&cv_cam_dist, 192); @@ -1480,9 +1482,12 @@ static void Analog2_OnChange(void) { if (!splitscreen || !cv_cam2_dist.string) return; + + // cameras are not initialized at this point + if (leveltime > 1) CV_SetValue(&cv_cam2_dist, 128); - if (netgame || !camera2.chase) + if (netgame) CV_StealthSetValue(&cv_analog2, 0); else if (cv_analog2.value) CV_SetValue(&cv_cam2_dist, 192); @@ -1927,7 +1932,6 @@ void G_PlayerReborn(INT32 player) INT32 score; INT32 lives; INT32 continues; - INT32 xtralife; UINT8 charability; UINT8 charability2; fixed_t normalspeed; @@ -1952,9 +1956,9 @@ void G_PlayerReborn(INT32 player) INT32 starpostangle; fixed_t jumpfactor; INT32 exiting; - INT32 numboxes; - INT32 laps; - INT32 totalring; + INT16 numboxes; + INT16 totalring; + UINT8 laps; UINT8 mare; UINT8 skincolor; INT32 skin; @@ -1966,7 +1970,6 @@ void G_PlayerReborn(INT32 player) score = players[player].score; lives = players[player].lives; continues = players[player].continues; - xtralife = players[player].xtralife; ctfteam = players[player].ctfteam; exiting = players[player].exiting; jointime = players[player].jointime; @@ -2017,7 +2020,6 @@ void G_PlayerReborn(INT32 player) p->lives = lives; p->continues = continues; p->pflags = pflags; - p->xtralife = xtralife; p->ctfteam = ctfteam; p->jointime = jointime; p->spectator = spectator; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 43d4537f..168761a0 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -67,6 +67,10 @@ typedef UINT8 GLRGB[3]; #define BLENDMODE PF_Translucent +static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; +static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; +static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; + // // -----------------+ // HWR_DrawPatch : Draw a 'tile' graphic @@ -128,24 +132,16 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale) +void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); + UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); // 3--2 // | /| @@ -153,11 +149,17 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, // 0--1 float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(scale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(scale); + float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); + float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + + if (alphalevel >= 10 && alphalevel < 13) + return; // make patch ready in hardware cache - HWR_GetPatch(gpatch); + if (!colormap) + HWR_GetPatch(gpatch); + else + HWR_GetMappedPatch(gpatch, colormap); switch (option & V_SCALEPATCHMASK) { @@ -197,11 +199,14 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) + if (alphalevel) { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -209,13 +214,13 @@ void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { FOutVector v[4]; FBITFIELD flags; - float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); + UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); // 3--2 // | /| @@ -223,8 +228,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix // 0--1 float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(scale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(scale); + float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); + float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + + if (alphalevel >= 10 && alphalevel < 13) + return; // make patch ready in hardware cache HWR_GetPatch(gpatch); @@ -247,17 +255,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix if (option & V_NOSCALESTART) sdupx = sdupy = 2.0f; - v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = ((cx-sx)*sdupx+(w-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-((cy-sy)*sdupy+(h-gpatch->topoffset)*pdupy)/vid.height; + v[0].x = v[3].x = (cx*sdupx - gpatch->leftoffset * pdupx) / vid.width - 1; + v[2].x = v[1].x = (cx*sdupx + ((w-sx) - gpatch->leftoffset) * pdupx) / vid.width - 1; + v[0].y = v[1].y = 1 - (cy*sdupy - gpatch->topoffset * pdupy) / vid.height; + v[2].y = v[3].y = 1 - (cy*sdupy + ((h-sy) - gpatch->topoffset) * pdupy) / vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = ((float)sx/(float)gpatch->height); - v[2].sow = v[1].sow = gpatch->max_s*((float)w/(float)gpatch->width); - v[0].tow = v[1].tow = ((float)sy/(float)gpatch->height); - v[2].tow = v[3].tow = gpatch->max_t*((float)h/(float)gpatch->height); + v[0].sow = v[3].sow = ((sx)/(float)gpatch->width )*gpatch->max_s; + v[2].sow = v[1].sow = ((w )/(float)gpatch->width )*gpatch->max_s; + v[0].tow = v[1].tow = ((sy)/(float)gpatch->height)*gpatch->max_t; + v[2].tow = v[3].tow = ((h )/(float)gpatch->height)*gpatch->max_t; flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; @@ -267,217 +275,14 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, fix flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) + if (alphalevel) { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); -} - -void HWR_DrawClippedPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - // hardware clips the patch quite nicely anyway :) - HWR_DrawPatch(gpatch, x, y, option); /// \todo do real cliping -} - -// Only supports one kind of translucent for now. Tails 06-12-2003 -// Boked -// Alam_GBC: Why? you could not get a FSurfaceInfo to set the alpha channel? -void HWR_DrawTranslucentPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - FSurfaceInfo Surf; - - // make patch ready in hardware cache - HWR_GetPatch (gpatch); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = PF_Modulated | BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - // Alam_GBC: There, you have translucent HW Draw, OK? - if ((option & V_TRANSLUCENT) && cv_grtranslucenthud.value != 255) - { - Surf.FlatColor.s.alpha = (UINT8)(cv_grtranslucenthud.value/2); - } - else - Surf.FlatColor.s.alpha = 127; - - HWD.pfnDrawPolygon(&Surf, v, 4, flags); -} - -// Draws a patch 2x as small SSNTails 06-10-2003 -void HWR_DrawSmallPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap) -{ - FOutVector v[4]; - FBITFIELD flags; - - float sdupx = FIXED_TO_FLOAT(vid.fdupx); - float sdupy = FIXED_TO_FLOAT(vid.fdupy); - float pdupx = FIXED_TO_FLOAT(vid.fdupx); - float pdupy = FIXED_TO_FLOAT(vid.fdupy); - - // make patch ready in hardware cache - HWR_GetMappedPatch (gpatch, colormap); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, flags); -} - -// -// HWR_DrawMappedPatch(): Like HWR_DrawPatch but with translated color -// -void HWR_DrawMappedPatch (GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap) -{ - FOutVector v[4]; - FBITFIELD flags; - - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - - // make patch ready in hardware cache - HWR_GetMappedPatch (gpatch, colormap); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); - break; - case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); - break; - } - - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; - - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; - - flags = BLENDMODE | PF_Clip | PF_NoZClip | PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - if (option & V_TRANSLUCENT) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -517,15 +322,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // But then, the question is: why not 0 instead of PF_Masked ? // or maybe PF_Environment ??? (like what I said above) // BP: PF_Environment don't change anything ! and 0 is undifined - if (cv_grtranslucenthud.value != 255) - { - FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = (UINT8)cv_grtranslucenthud.value; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated | BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); - } - else - HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); + HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); } // ========================================================================== diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index a6cf3fb7..c93d4ea6 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -44,12 +44,9 @@ boolean HWR_Screenshot(const char *lbmname); void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawClippedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawSciencePatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale); +void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap); +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); -void HWR_DrawTranslucentPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawSmallPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); -void HWR_DrawMappedPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option, const UINT8 *colormap); void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c8f452a6..14f6d54a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -903,7 +903,7 @@ static inline void HU_DrawCrosshair(void) #endif y = viewwindowy + (viewheight>>1); - V_DrawTranslucentPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET, crosshair[i - 1]); + V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); } static inline void HU_DrawCrosshair2(void) @@ -933,7 +933,7 @@ static inline void HU_DrawCrosshair2(void) #endif y += viewheight; - V_DrawTranslucentPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET, crosshair[i - 1]); + V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); } } @@ -1086,6 +1086,10 @@ void HU_Drawer(void) if (!automapactive && cv_crosshair2.value && !demoplayback && !camera2.chase && !players[secondarydisplayplayer].spectator) HU_DrawCrosshair2(); + + // draw desynch text + if (hu_resynching) + V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP, "Resynching..."); } //====================================================================== @@ -1619,7 +1623,7 @@ static void HU_DrawRankings(void) { if (circuitmap) { - if (players[i].laps+1 >= tab[scorelines].count && completed[i] == false) + if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false) { tab[scorelines].count = players[i].laps+1; tab[scorelines].num = i; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index f80d9809..47bd4370 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -222,21 +222,7 @@ static int libd_draw(lua_State *L) flags &= ~V_PARAMMASK; // Don't let crashes happen. - if (colormap) - { - if (flags & V_ALPHAMASK) - V_DrawTranslucentMappedPatch(x, y, flags, patch, colormap); - else - V_DrawMappedPatch(x, y, flags, patch, colormap); - } - else - { - if (flags & V_ALPHAMASK) - V_DrawTranslucentPatch(x, y, flags, patch); - else - V_DrawScaledPatch(x, y, flags, patch); - } - + V_DrawFixedPatch(x<bob); else if (fastcmp(field,"aiming")) lua_pushinteger(L, plr->aiming); - else if (fastcmp(field,"awayviewaiming")) - lua_pushinteger(L, plr->awayviewaiming); else if (fastcmp(field,"health")) lua_pushinteger(L, plr->health); else if (fastcmp(field,"pity")) @@ -187,7 +185,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"speed")) lua_pushinteger(L, plr->speed); else if (fastcmp(field,"jumping")) - lua_pushinteger(L, plr->jumping); + lua_pushboolean(L, plr->jumping); else if (fastcmp(field,"secondjump")) lua_pushinteger(L, plr->secondjump); else if (fastcmp(field,"fly1")) @@ -306,6 +304,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->awayviewmobj, META_MOBJ); else if (fastcmp(field,"awayviewtics")) lua_pushinteger(L, plr->awayviewtics); + else if (fastcmp(field,"awayviewaiming")) + lua_pushinteger(L, plr->awayviewaiming); else if (fastcmp(field,"spectator")) lua_pushinteger(L, plr->spectator); else if (fastcmp(field,"bot")) @@ -365,8 +365,6 @@ static int player_set(lua_State *L) else if (plr == &players[secondarydisplayplayer]) localaiming2 = plr->aiming; } - else if (fastcmp(field,"awayviewaiming")) - plr->awayviewaiming = (angle_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"health")) plr->health = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"pity")) @@ -424,17 +422,17 @@ static int player_set(lua_State *L) else if (fastcmp(field,"jumpfactor")) plr->jumpfactor = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lives")) - plr->lives = (INT32)luaL_checkinteger(L, 3); + plr->lives = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"continues")) - plr->continues = (INT32)luaL_checkinteger(L, 3); + plr->continues = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"xtralife")) - plr->xtralife = (INT32)luaL_checkinteger(L, 3); + plr->xtralife = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"gotcontinue")) plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"speed")) plr->speed = (fixed_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"jumping")) - plr->jumping = (INT32)luaL_checkinteger(L, 3); + plr->jumping = luaL_checkboolean(L, 3); else if (fastcmp(field,"secondjump")) plr->secondjump = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"fly1")) @@ -462,13 +460,13 @@ static int player_set(lua_State *L) else if (fastcmp(field,"rmomy")) plr->rmomy = (fixed_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"numboxes")) - plr->numboxes = (INT32)luaL_checkinteger(L, 3); + plr->numboxes = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"totalring")) - plr->totalring = (INT32)luaL_checkinteger(L, 3); + plr->totalring = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"realtime")) plr->realtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"laps")) - plr->laps = (UINT32)luaL_checkinteger(L, 3); + plr->laps = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"ctfteam")) plr->ctfteam = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"gotflag")) @@ -567,6 +565,8 @@ static int player_set(lua_State *L) if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. } + else if (fastcmp(field,"awayviewaiming")) + plr->awayviewaiming = (angle_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"spectator")) plr->spectator = lua_toboolean(L, 3); else if (fastcmp(field,"bot")) diff --git a/src/m_cheat.c b/src/m_cheat.c index 44c6f03e..16bd88ad 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -464,9 +464,9 @@ void Command_Savecheckpoint_f(void) // Like M_GetAllEmeralds() but for console devmode junkies. void Command_Getallemeralds_f(void) { - REQUIRE_PANDORA; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; emeralds = ((EMERALD7)*2)-1; @@ -475,8 +475,8 @@ void Command_Getallemeralds_f(void) void Command_Resetemeralds_f(void) { - REQUIRE_PANDORA; REQUIRE_SINGLEPLAYER; + REQUIRE_PANDORA; emeralds = 0; @@ -511,10 +511,10 @@ void Command_Devmode_f(void) void Command_Setrings_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -530,10 +530,10 @@ void Command_Setrings_f(void) void Command_Setlives_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -547,10 +547,10 @@ void Command_Setlives_f(void) void Command_Setcontinues_f(void) { - REQUIRE_PANDORA; REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; + REQUIRE_PANDORA; if (COM_Argc() > 1) { diff --git a/src/m_menu.c b/src/m_menu.c index 5aad4e77..0676bb52 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1137,8 +1137,6 @@ static menuitem_t OP_OpenGLOptionsMenu[] = #ifdef _WINDOWS {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, #endif - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "Translucent HUD", &cv_grtranslucenthud, 60}, #ifdef ALAM_LIGHTING {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70}, #endif @@ -1245,17 +1243,19 @@ static menuitem_t OP_GameOptionsMenu[] = NULL, "Master server", &cv_masterserver, 10}, #endif {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40}, - {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 50}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "HUD Visibility", &cv_translucenthud, 50}, + {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60}, #ifdef SEENAMES - {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 60}, + {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80}, #endif - {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 70}, + {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90}, - {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 90}, - {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,100}, - {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 110}, + {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100}, + {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110}, + {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120}, - {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 130}, + {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140}, }; static menuitem_t OP_ServerOptionsMenu[] = @@ -1276,7 +1276,7 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 110}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 120}, {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 130}, - {IT_STRING | IT_CVAR, NULL, "Consistency Protection", &cv_consfailprotect, 140}, + {IT_STRING | IT_CVAR, NULL, "Attempts to Resynch", &cv_resynchattempts, 140}, #endif }; @@ -4681,9 +4681,9 @@ static void M_DrawSetupChoosePlayerMenu(void) } patch = W_CachePatchName(picname, PU_CACHE); if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<height) - 64 + o*2, SHORT(patch->width), SHORT(patch->height)); + V_DrawCroppedPatch(8<height) - 64 + o*2, SHORT(patch->width), SHORT(patch->height)); else - V_DrawCroppedPatch(8<height) - 32 + o, SHORT(patch->width), SHORT(patch->height)); + V_DrawCroppedPatch(8<height) - 32 + o, SHORT(patch->width), SHORT(patch->height)); W_UnlockCachedPatch(patch); } @@ -4707,9 +4707,9 @@ static void M_DrawSetupChoosePlayerMenu(void) } patch = W_CachePatchName(picname, PU_CACHE); if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), o*2); + V_DrawCroppedPatch(8<width), o*2); else - V_DrawCroppedPatch(8<width), o); + V_DrawCroppedPatch(8<width), o); W_UnlockCachedPatch(patch); } @@ -4741,9 +4741,9 @@ static void M_DrawSetupChoosePlayerMenu(void) else { if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), SHORT(patch->height)); + V_DrawCroppedPatch(8<width), SHORT(patch->height)); else - V_DrawCroppedPatch(8<width), SHORT(patch->height)); + V_DrawCroppedPatch(8<width), SHORT(patch->height)); } W_UnlockCachedPatch(patch); } diff --git a/src/p_map.c b/src/p_map.c index 8b7869b8..eb7c6ad7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2552,7 +2552,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) // one-sided linedef if (!li->backsector) { - if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, li)) + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) return true; // don't hit the back side goto isblocking; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 17db0062..baa04211 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -120,6 +120,13 @@ static inline void P_NetArchivePlayers(void) flags = 0; + // ticcmd write + WRITESINT8(save_p, players[i].cmd.forwardmove); + WRITESINT8(save_p, players[i].cmd.sidemove); + WRITEINT16(save_p, players[i].cmd.angleturn); + WRITEINT16(save_p, players[i].cmd.aiming); + WRITEUINT16(save_p, players[i].cmd.buttons); + WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME); WRITEANGLE(save_p, players[i].aiming); WRITEANGLE(save_p, players[i].awayviewaiming); @@ -146,12 +153,12 @@ static inline void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].score); WRITEINT32(save_p, players[i].dashspeed); WRITEINT32(save_p, players[i].dashtime); - WRITEINT32(save_p, players[i].lives); - WRITEINT32(save_p, players[i].continues); - WRITEINT32(save_p, players[i].xtralife); + WRITESINT8(save_p, players[i].lives); + WRITESINT8(save_p, players[i].continues); + WRITESINT8(save_p, players[i].xtralife); WRITEUINT8(save_p, players[i].gotcontinue); WRITEINT32(save_p, players[i].speed); - WRITEINT32(save_p, players[i].jumping); + WRITEUINT8(save_p, players[i].jumping); WRITEUINT8(save_p, players[i].secondjump); WRITEUINT8(save_p, players[i].fly1); WRITEUINT8(save_p, players[i].scoreadd); @@ -176,7 +183,7 @@ static inline void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].numboxes); WRITEINT32(save_p, players[i].totalring); WRITEUINT32(save_p, players[i].realtime); - WRITEUINT32(save_p, players[i].laps); + WRITEUINT8(save_p, players[i].laps); //////////////////// // CTF Mode Stuff // @@ -282,6 +289,7 @@ static inline void P_NetUnArchivePlayers(void) { INT32 i, j; UINT16 flags; + ticcmd_t tmptic; if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) I_Error("Bad $$$.sav at archive block Players"); @@ -292,6 +300,14 @@ static inline void P_NetUnArchivePlayers(void) if (!playeringame[i]) continue; + memset(&tmptic, 0, sizeof(ticcmd_t)); + tmptic.forwardmove = READSINT8(save_p); + tmptic.sidemove = READSINT8(save_p); + tmptic.angleturn = READINT16(save_p); + tmptic.aiming = READINT16(save_p); + tmptic.buttons = READUINT16(save_p); + G_CopyTiccmd(&players[i].cmd, &tmptic, 1); + READSTRINGN(save_p, player_names[i], MAXPLAYERNAME); players[i].aiming = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p); @@ -318,12 +334,12 @@ static inline void P_NetUnArchivePlayers(void) players[i].score = READUINT32(save_p); players[i].dashspeed = READINT32(save_p); // dashing speed players[i].dashtime = READINT32(save_p); // dashing speed - players[i].lives = READINT32(save_p); - players[i].continues = READINT32(save_p); // continues that player has acquired - players[i].xtralife = READINT32(save_p); // Ring Extra Life counter + players[i].lives = READSINT8(save_p); + players[i].continues = READSINT8(save_p); // continues that player has acquired + players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter players[i].gotcontinue = READUINT8(save_p); // got continue from stage players[i].speed = READINT32(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].jumping = READINT32(save_p); // Jump counter + players[i].jumping = READUINT8(save_p); // Jump counter players[i].secondjump = READUINT8(save_p); players[i].fly1 = READUINT8(save_p); // Tails flying players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus @@ -348,7 +364,7 @@ static inline void P_NetUnArchivePlayers(void) players[i].numboxes = READINT32(save_p); // Number of item boxes obtained for Race Mode players[i].totalring = READINT32(save_p); // Total number of rings obtained for Race Mode players[i].realtime = READUINT32(save_p); // integer replacement for leveltime - players[i].laps = READUINT32(save_p); // Number of laps (optional) + players[i].laps = READUINT8(save_p); // Number of laps (optional) //////////////////// // CTF Mode Stuff // diff --git a/src/p_spec.c b/src/p_spec.c index 20d86176..fa6200cd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3854,10 +3854,10 @@ DoneSection2: if (player->pflags & PF_NIGHTSMODE) player->drillmeter += 48*20; - if (player->laps >= (unsigned)cv_numlaps.value) + if (player->laps >= (UINT8)cv_numlaps.value) CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); else - CONS_Printf(M_GetText("%s started lap %d\n"), player_names[player-players],player->laps+1); + CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); // Reset starposts (checkpoints) info player->starpostangle = player->starposttime = player->starpostnum = 0; @@ -5342,10 +5342,14 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].special == 6) { // Ability flags can disable disable linedefs now, lol - if ((netgame || multiplayer) - || (!(players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - && !(players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - && !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)))) + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if (((lines[i].flags & ML_NETONLY) != ML_NETONLY) + && !(players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) + && !(players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) + && !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX ))) { for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) { @@ -5404,7 +5408,16 @@ void P_SpawnSpecials(INT32 fromnetsave) for (i = 0; i < numlines; i++) { // set line specials to 0 here too, same reason as above - if (!(netgame || multiplayer)) + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) + { + lines[i].special = 0; + continue; + } + else { if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) { diff --git a/src/p_user.c b/src/p_user.c index 5aa0d50a..ac026a11 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8113,19 +8113,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall + ((*rover->topheight - *rover->bottomheight)/2)); delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)) - { + if (*rover->topheight > myfloorz && abs(delta1) < abs(delta2)) myfloorz = *rover->topheight; - } - if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)) - { + if (*rover->bottomheight < myceilingz && abs(delta1) >= abs(delta2)) myceilingz = *rover->bottomheight; - } } } #ifdef POLYOBJECTS - // Check polyobjects and see if tmfloorz/tmceilingz need to be altered + // Check polyobjects and see if floorz/ceilingz need to be altered { INT32 xl, xh, yl, yh, bx, by; validcount++; @@ -8191,10 +8187,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall delta1 = midz - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) + if (polytop > myfloorz && abs(delta1) < abs(delta2)) myfloorz = polytop; - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < myceilingz && abs(delta1) >= abs(delta2)) myceilingz = polybottom; } plink = (polymaplink_t *)(plink->link.next); @@ -8204,7 +8200,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall #endif // crushed camera - if (myceilingz <= myfloorz && !resetcalled && !cameranoclip) + if (myceilingz <= myfloorz + thiscam->height && !resetcalled && !cameranoclip) { P_ResetCamera(player, thiscam); return true; @@ -8645,7 +8641,7 @@ void P_PlayerThink(player_t *player) if (players[i].lives <= 0) continue; - if (!players[i].exiting) + if (!players[i].exiting || players[i].exiting > 3) break; } diff --git a/src/r_main.c b/src/r_main.c index c55de394..6af1bf46 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -122,7 +122,7 @@ static CV_PossibleValue_t drawdist_cons_t[] = { {3072, "3072"}, {4096, "4096"}, {6144, "6144"}, {8192, "8192"}, {0, "Infinite"}, {0, NULL}}; static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; -static CV_PossibleValue_t grtranslucenthud_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; static void ChaseCam_OnChange(void); @@ -141,7 +141,7 @@ consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0 consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grtranslucenthud = {"gr_translucenthud", "255", CV_SAVE|CV_CALL, grtranslucenthud_cons_t, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1237,11 +1237,11 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_rotspeed); CV_RegisterVar(&cv_showhud); + CV_RegisterVar(&cv_translucenthud); // Default viewheight is changeable, // initialized to standard viewheight CV_RegisterVar(&cv_viewheight); - CV_RegisterVar(&cv_grtranslucenthud); #ifdef HWRENDER // GL-specific Commands diff --git a/src/r_main.h b/src/r_main.h index 8a39b7d3..a367960c 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -81,9 +81,8 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); // REFRESH - the actual rendering functions. // -extern consvar_t cv_showhud; +extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; -extern consvar_t cv_grtranslucenthud; extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow, cv_shadowoffs; diff --git a/src/st_stuff.c b/src/st_stuff.c index 56ce8e4e..9f5a691e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -129,27 +129,29 @@ hudinfo_t hudinfo[NUMHUDITEMS] = { 16, 176}, // HUD_LIVESPIC { 74, 184}, // HUD_LIVESNUM { 38, 186}, // HUD_LIVESX - { 220, 10}, // HUD_RINGSSPLIT - { 288, 10}, // HUD_RINGSNUMSPLIT + { 16, 42}, // HUD_RINGS + { 220, 10}, // HUD_RINGSSPLIT { 112, 42}, // HUD_RINGSNUM + { 288, 10}, // HUD_RINGSNUMSPLIT + { 16, 10}, // HUD_SCORE { 128, 10}, // HUD_SCORENUM - { 136, 10}, // HUD_TIMESPLIT - { 212, 10}, // HUD_SECONDSSPLIT - { 188, 10}, // HUD_MINUTESSPLIT - { 188, 10}, // HUD_TIMECOLONSPLIT { 17, 26}, // HUD_TIME - + { 136, 10}, // HUD_TIMESPLIT + { 88, 26}, // HUD_MINUTES + { 188, 10}, // HUD_MINUTESSPLIT + { 88, 26}, // HUD_TIMECOLON + { 188, 10}, // HUD_TIMECOLONSPLIT + { 112, 26}, // HUD_SECONDS + { 212, 10}, // HUD_SECONDSSPLIT + { 112, 26}, // HUD_TIMETICCOLON { 136, 26}, // HUD_TICS - { 112, 26}, // HUD_SECONDS - { 88, 26}, // HUD_MINUTES - { 88, 26}, // HUD_TIMECOLON - { 112, 26}, // HUD_TIMETICCOLON - { 288, 40}, // HUD_SS_TOTALRINGS_SPLIT { 112, 56}, // HUD_SS_TOTALRINGS + { 288, 40}, // HUD_SS_TOTALRINGS_SPLIT + { 110, 93}, // HUD_GETRINGS { 160, 93}, // HUD_GETRINGSNUM { 124, 160}, // HUD_TIMELEFT @@ -160,9 +162,6 @@ hudinfo_t hudinfo[NUMHUDITEMS] = { 240, 160}, // HUD_LAP }; -#define ST_DrawOverlayNum(x,y,f,n) V_DrawTallNum(x, y, f|V_TRANSLUCENT, n) -#define ST_DrawPaddedOverlayNum(x,y,n,d) V_DrawPaddedTallNum(x, y, V_NOSCALESTART|V_TRANSLUCENT, n, d) - // // STATUS BAR CODE // @@ -463,6 +462,7 @@ static INT32 SCX(INT32 x) return FixedInt(FixedMul(x<width); - const UINT8 *colormap; - - if (colornum == 0) - colormap = colormaps; - else // Uses the player colors. - colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); - - I_Assert(num >= 0); // this function does not draw negative numbers - - // draw the number - do - { - x -= (w * vid.dupx); - V_DrawMappedPatch(x, y, V_NOSCALESTART|V_TRANSLUCENT, numpat[num % 10], colormap); - num /= 10; - } while (num); - - // Sorry chum, this function only draws UNSIGNED values! -} - -// Draw a number, scaled, over the view, with set translucency -// Always draw the number completely since it's overlay -// -// Supports different colors! woo! -static void ST_DrawTranslucentNightsOverlayNum(INT32 x /* right border */, INT32 y, INT32 a, +static void ST_DrawNightsOverlayNum(INT32 x /* right border */, INT32 y, INT32 a, INT32 num, patch_t **numpat, skincolors_t colornum) { INT32 w = SHORT(numpat[0]->width); @@ -603,16 +590,16 @@ static void ST_drawDebugInfo(void) static void ST_drawScore(void) { // SCORE: - V_DrawScaledPatch(SCX(hudinfo[HUD_SCORE].x), SCY(hudinfo[HUD_SCORE].y), V_NOSCALESTART|V_TRANSLUCENT, sboscore); + ST_DrawPatchFromHud(HUD_SCORE, sboscore); if (objectplacing) { if (op_displayflags > UINT16_MAX) - V_DrawScaledPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, tallminus); + ST_DrawOverlayPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), tallminus); else - ST_DrawOverlayNum(SCX(hudinfo[HUD_SCORENUM].x), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, op_displayflags); + ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags); } else - ST_DrawOverlayNum(SCX(hudinfo[HUD_SCORENUM].x), SCY(hudinfo[HUD_SCORENUM].y), V_NOSCALESTART, stplyr->score); + ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score); } static void ST_drawTime(void) @@ -620,8 +607,7 @@ static void ST_drawTime(void) INT32 seconds, minutes, tictrn, tics; // TIME: - V_DrawScaledPatch(SCX(hudinfo[(splitscreen) ? HUD_TIMESPLIT : HUD_TIME].x), - SCY(hudinfo[(splitscreen) ? HUD_TIMESPLIT : HUD_TIME].y), V_NOSCALESTART|V_TRANSLUCENT, sbotime); + ST_DrawPatchFromHudWS(HUD_TIME, sbotime); if (objectplacing) { @@ -633,61 +619,45 @@ static void ST_drawTime(void) else { tics = stplyr->realtime; - seconds = tics/TICRATE % 60; - minutes = tics/(60*TICRATE); + seconds = G_TicsToSeconds(tics); + minutes = G_TicsToMinutes(tics, true); tictrn = G_TicsToCentiseconds(tics); } if (cv_timetic.value == 1) // Tics only -- how simple is this? - ST_DrawOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].x), - SCY(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].y), V_NOSCALESTART, tics); + ST_DrawNumFromHudWS(HUD_SECONDS, tics); else { - // Minutes - ST_DrawOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_MINUTESSPLIT : HUD_MINUTES].x), - SCY(hudinfo[(splitscreen) ? HUD_MINUTESSPLIT : HUD_MINUTES].y), V_NOSCALESTART, minutes); - // Colon - V_DrawScaledPatch(SCX(hudinfo[(splitscreen) ? HUD_TIMECOLONSPLIT : HUD_TIMECOLON].x), - SCY(hudinfo[(splitscreen) ? HUD_TIMECOLONSPLIT : HUD_TIMECOLON].y), V_NOSCALESTART|V_TRANSLUCENT, sbocolon); - // Seconds - ST_DrawPaddedOverlayNum(SCX(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].x), - SCY(hudinfo[(splitscreen) ? HUD_SECONDSSPLIT : HUD_SECONDS].y), seconds, 2); + ST_DrawNumFromHudWS(HUD_MINUTES, minutes); // Minutes + ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon + ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! { - // Colon - V_DrawScaledPatch(SCX(hudinfo[HUD_TIMETICCOLON].x), SCY(hudinfo[HUD_TIMETICCOLON].y), V_NOSCALESTART|V_TRANSLUCENT, sbocolon); - // Tics - ST_DrawPaddedOverlayNum(SCX(hudinfo[HUD_TICS].x), SCY(hudinfo[HUD_TICS].y), tictrn, 2); + ST_DrawPatchFromHud(HUD_TIMETICCOLON, sbocolon); // Colon + ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics } } } static inline void ST_drawRings(void) { - hudnum_t ringHUD = (splitscreen) ? HUD_RINGSSPLIT : HUD_RINGS; - hudnum_t ringnumHUD = (splitscreen) ? HUD_RINGSNUMSPLIT : HUD_RINGSNUM; + INT32 ringnum = max(stplyr->health-1, 0); - V_DrawScaledPatch(SCX(hudinfo[ringHUD].x), SCY(hudinfo[ringHUD].y), V_NOSCALESTART|V_TRANSLUCENT, - (stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings); + ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings)); if (objectplacing) - { - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, op_currentdoomednum); - } + ringnum = op_currentdoomednum; else if (!useNightsSS && G_IsSpecialStage(gamemap)) { - INT32 ringscollected = 0; // Total # everyone has collected INT32 i; - + ringnum = 0; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && players[i].mo->health > 1) - ringscollected += players[i].mo->health - 1; - - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, ringscollected); + ringnum += players[i].mo->health - 1; } - else - ST_DrawOverlayNum(SCX(hudinfo[ringnumHUD].x), SCY(hudinfo[ringnumHUD].y), V_NOSCALESTART, stplyr->health > 0 ? stplyr->health-1 : 0); + + ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum); } static void ST_drawLives(void) @@ -699,7 +669,7 @@ static void ST_drawLives(void) // face background V_DrawSmallScaledPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag, livesback); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, livesback); // face if (stplyr->mo && stplyr->mo->color) @@ -710,25 +680,29 @@ static void ST_drawLives(void) if (stplyr->powers[pw_super] || stplyr->pflags & PF_NIGHTSMODE) face = superprefix[stplyr->skin]; V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag,face, colormap); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,face, colormap); } else if (stplyr->skincolor) { // skincolor face UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag,faceprefix[stplyr->skin], colormap); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,faceprefix[stplyr->skin], colormap); } // name if (strlen(skins[stplyr->skin].hudname) > 8) - V_DrawThinString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); + V_DrawThinString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), + V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); else - V_DrawString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); + V_DrawString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), + V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); // x - V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|v_splitflag, stlivex); + V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, stlivex); // lives - V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|v_splitflag, va("%d",stplyr->lives)); + V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, va("%d",stplyr->lives)); } static void ST_drawLevelTitle(void) @@ -820,9 +794,9 @@ static void ST_drawFirstPersonHUD(void) if (p) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); else - V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); } // pw_flashing just sets the icon to flash no matter what. @@ -830,17 +804,17 @@ static void ST_drawFirstPersonHUD(void) if (invulntime > 3*TICRATE || (invulntime && leveltime & 1)) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility); + V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); else - V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility); + V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); } if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] && leveltime & 1)) { if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers); + V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); else - V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers); + V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); } p = NULL; @@ -890,8 +864,8 @@ static void ST_drawFirstPersonHUD(void) } if (p) - V_DrawTranslucentPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), - V_NOSCALESTART|V_OFFSET, p); + V_DrawScaledPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), + V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, p); } // [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold @@ -946,11 +920,7 @@ static void ST_drawNightsRecords(void) V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:"); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings)); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); - - if (aflag) - ST_DrawTranslucentNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); - else - ST_DrawNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(SCX(BASEVIDWIDTH/2 + 48), SCY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); // If new record, say so! if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) @@ -1012,15 +982,13 @@ static void ST_drawNiGHTSHUD(void) if (splitscreen) { - ST_DrawTranslucentNightsOverlayNum(SCX(256), SCY(160), linktrans, (stplyr->linkcount-1), - nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(256), SCY(160), linktrans, (stplyr->linkcount-1), nightsnum, colornum); V_DrawTranslucentMappedPatch(SCX(264), SCY(160), V_NOSCALESTART|linktrans, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } else { - ST_DrawTranslucentNightsOverlayNum(SCX(160), SCY(160), linktrans, (stplyr->linkcount-1), - nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(160), SCY(160), linktrans, (stplyr->linkcount-1), nightsnum, colornum); V_DrawTranslucentMappedPatch(SCX(168), SCY(160), V_NOSCALESTART|linktrans, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } @@ -1032,20 +1000,20 @@ static void ST_drawNiGHTSHUD(void) { INT32 offs = 10 - (stplyr->linktimer - (2*TICRATE - 9)); INT32 ghosttrans = offs << V_ALPHASHIFT; - ST_DrawTranslucentNightsOverlayNum(SCX(160), SCY(160)+(offs*2), ghosttrans, (stplyr->linkcount-2), + ST_DrawNightsOverlayNum(SCX(160), SCY(160)+(offs*2), ghosttrans, (stplyr->linkcount-2), nightsnum, colornum); } #endif if (splitscreen) { - ST_DrawNightsOverlayNum(SCX(256), SCY(160), (stplyr->linkcount-1), nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(256), SCY(160), 0, (stplyr->linkcount-1), nightsnum, colornum); V_DrawMappedPatch(SCX(264), SCY(160), V_NOSCALESTART, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } else { - ST_DrawNightsOverlayNum(SCX(160), SCY(160), (stplyr->linkcount-1), nightsnum, colornum); + ST_DrawNightsOverlayNum(SCX(160), SCY(160), 0, (stplyr->linkcount-1), nightsnum, colornum); V_DrawMappedPatch(SCX(168), SCY(160), V_NOSCALESTART, nightslink, colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); } @@ -1086,32 +1054,32 @@ static void ST_drawNiGHTSHUD(void) if (splitscreen) { // Dirty hack because V_SNAPTOBOTTOM doesn't have a way to account for splitscreen, but better than overlapping bars. - V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_HUDTRANS, drillfill[fillpatch]); } else if (nosshack) { // Even dirtier hack-of-a-hack to draw seperate drill meters in splitscreen special stages but nothing else. splitscreen = true; - V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(SCX(locx), SCY(locy), V_NOSCALESTART|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(SCX(locx + 2 + dfill), SCY(locy + 3), V_NOSCALESTART|V_HUDTRANS, drillfill[fillpatch]); stplyr = &players[secondarydisplayplayer]; if (stplyr->pflags & PF_DRILLING) fillpatch = (stplyr->drillmeter & 1) + 1; else fillpatch = 0; - V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); stplyr = &players[displayplayer]; splitscreen = false; } else { // Draw normally. <:3 - V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillbar); + V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT, drillfill[fillpatch]); + V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); } // Display actual drill amount and bumper time @@ -1136,11 +1104,11 @@ static void ST_drawNiGHTSHUD(void) if (LUA_HudEnabled(hud_nightsrings)) { #endif - V_DrawScaledPatch(SCX(16), SCY(8), V_NOSCALESTART|V_TRANSLUCENT, nbracket); + ST_DrawOverlayPatch(SCX(16), SCY(8), nbracket); if (G_IsSpecialStage(gamemap)) - V_DrawScaledPatch(SCX(24), SCY(8) + SCZ(8), V_NOSCALESTART|V_TRANSLUCENT, nsshud); + ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nsshud); else - V_DrawScaledPatch(SCX(24), SCY(8) + SCZ(8), V_NOSCALESTART|V_TRANSLUCENT, nhud[(leveltime/2)%12]); + ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nhud[(leveltime/2)%12]); if (G_IsSpecialStage(gamemap)) { @@ -1161,8 +1129,8 @@ static void ST_drawNiGHTSHUD(void) origamount = stplyr->capsule->spawnpoint->angle; I_Assert(origamount > 0); // should not happen now - V_DrawScaledPatch(SCX(72), SCY(8), V_NOSCALESTART|V_TRANSLUCENT, nbracket); - V_DrawScaledPatch(SCX(74), SCY(8) + SCZ(4), V_NOSCALESTART|V_TRANSLUCENT, minicaps); + ST_DrawOverlayPatch(SCX(72), SCY(8), nbracket); + ST_DrawOverlayPatch(SCX(74), SCY(8) + SCZ(4), minicaps); if (stplyr->capsule->reactiontime != 0) { @@ -1171,10 +1139,10 @@ static void ST_drawNiGHTSHUD(void) for (r = 0; r < 5; r++) { - V_DrawScaledPatch(SCX(230 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, redstat); - V_DrawScaledPatch(SCX(188 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, orngstat); - V_DrawScaledPatch(SCX(146 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, yelstat); - V_DrawScaledPatch(SCX(104 - (7*r)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, byelstat); + ST_DrawOverlayPatch(SCX(230 - (7*r)), SCY(144), redstat); + ST_DrawOverlayPatch(SCX(188 - (7*r)), SCY(144), orngstat); + ST_DrawOverlayPatch(SCX(146 - (7*r)), SCY(144), yelstat); + ST_DrawOverlayPatch(SCX(104 - (7*r)), SCY(144), byelstat); } amount = (origamount - stplyr->capsule->health); @@ -1193,7 +1161,7 @@ static void ST_drawNiGHTSHUD(void) if (r > 10) ++t; if (r > 5) ++t; - V_DrawScaledPatch(SCX(69 + (7*t)), SCY(144), V_NOSCALESTART|V_TRANSLUCENT, bluestat); + ST_DrawOverlayPatch(SCX(69 + (7*t)), SCY(144), bluestat); } } } @@ -1202,27 +1170,27 @@ static void ST_drawNiGHTSHUD(void) INT32 cfill; // Lil' white box! - V_DrawScaledPatch(15, STRINGY(8) + 34, V_SNAPTOLEFT|V_SNAPTOTOP|V_TRANSLUCENT, capsulebar); + V_DrawScaledPatch(15, STRINGY(8) + 34, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulebar); amount = (origamount - stplyr->capsule->health); amount = (amount * length)/origamount; for (cfill = 0; cfill < amount && cfill < 88; ++cfill) - V_DrawScaledPatch(15 + cfill + 1, STRINGY(8) + 35, V_SNAPTOLEFT|V_SNAPTOTOP|V_TRANSLUCENT, capsulefill); + V_DrawScaledPatch(15 + cfill + 1, STRINGY(8) + 35, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill); } if (total_ringcount >= stplyr->capsule->health) - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, nredar[leveltime%8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), nredar[leveltime%8]); else - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, narrow[(leveltime/2)%8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[(leveltime/2)%8]); } else - V_DrawScaledPatch(SCX(40), SCY(8) + SCZ(5), V_NOSCALESTART|V_TRANSLUCENT, narrow[8]); + ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[8]); if (total_ringcount >= 100) - ST_DrawOverlayNum((total_ringcount >= 1000) ? SCX(76) : SCX(72), SCY(8) + SCZ(11), V_NOSCALESTART, total_ringcount); + ST_DrawOverlayNum((total_ringcount >= 1000) ? SCX(76) : SCX(72), SCY(8) + SCZ(11), total_ringcount); else - ST_DrawOverlayNum(SCX(68), SCY(8) + SCZ(11), V_NOSCALESTART, total_ringcount); + ST_DrawOverlayNum(SCX(68), SCY(8) + SCZ(11), total_ringcount); #ifdef HAVE_BLUA } #endif @@ -1233,7 +1201,7 @@ static void ST_drawNiGHTSHUD(void) && LUA_HudEnabled(hud_nightsscore) #endif ) - ST_DrawNightsOverlayNum(SCX(304), SCY(16), stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(SCX(304), SCY(16), 0, stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE); // Ideya time remaining if (!stplyr->exiting && stplyr->nightstime > 0 @@ -1275,10 +1243,10 @@ static void ST_drawNiGHTSHUD(void) numbersize = SCX(48)/2; if (realnightstime < 10) - ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), realnightstime, + ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), 0, realnightstime, nightsnum, SKINCOLOR_RED); else - ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), realnightstime, + ST_DrawNightsOverlayNum(SCX(160) + numbersize, SCY(12), 0, realnightstime, nightsnum, SKINCOLOR_SUPER4); // Show exact time in debug @@ -1325,31 +1293,34 @@ static void ST_drawNiGHTSHUD(void) static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, INT32 xoffs, patch_t *pat) { - INT32 yelflag = 0; + INT32 txtflags = 0, patflags = 0; if (stplyr->powers[weapon]) { if (stplyr->powers[weapon] >= rw_maximums[wepflag]) - yelflag = V_YELLOWMAP; + txtflags |= V_YELLOWMAP; if (weapon == pw_infinityring || (stplyr->ringweapons & rwflag && stplyr->health > 1)) - V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT, pat); + txtflags |= V_20TRANS; else - V_DrawTranslucentPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|V_80TRANS, pat); + { + txtflags |= V_TRANSLUCENT; + patflags = V_80TRANS; + } + + V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|patflags, pat); if (stplyr->powers[weapon] > 99) - V_DrawThinString(8 + xoffs + 1, STRINGY(162), V_TRANSLUCENT | V_SNAPTOLEFT | yelflag, - va("%d", stplyr->powers[weapon])); + V_DrawThinString(8 + xoffs + 1, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); else - V_DrawString(8 + xoffs, STRINGY(162), V_TRANSLUCENT | V_SNAPTOLEFT | yelflag, - va("%d", stplyr->powers[weapon])); + V_DrawString(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); if (stplyr->currentweapon == wepflag) V_DrawScaledPatch(6 + xoffs, STRINGY(162 - (splitscreen ? 4 : 2)), V_SNAPTOLEFT, curweapon); } else if (stplyr->ringweapons & rwflag) - V_DrawTranslucentPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT, pat); + V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|V_TRANSLUCENT, pat); } static void ST_drawMatchHUD(void) @@ -1503,15 +1474,15 @@ static void ST_drawCTFHUD(void) UINT16 whichflag = 0; // Draw the flags - V_DrawSmallScaledPatch(256, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, rflagico); - V_DrawSmallScaledPatch(288, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, bflagico); + V_DrawSmallScaledPatch(256, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, rflagico); + V_DrawSmallScaledPatch(288, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, bflagico); for (i = 0; i < MAXPLAYERS; i++) { if (players[i].gotflag & GF_REDFLAG) // Red flag isn't at base - V_DrawScaledPatch(256, (splitscreen) ? STRINGY(156) : STRINGY(174), 0, nonicon); + V_DrawScaledPatch(256, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); else if (players[i].gotflag & GF_BLUEFLAG) // Blue flag isn't at base - V_DrawScaledPatch(288, (splitscreen) ? STRINGY(156) : STRINGY(174), 0, nonicon); + V_DrawScaledPatch(288, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); whichflag |= players[i].gotflag; if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG)) @@ -1524,9 +1495,9 @@ static void ST_drawCTFHUD(void) patch_t *p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag; if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); else - V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p); + V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); } // Display a countdown timer showing how much time left until the flag your team dropped returns to base. @@ -1535,13 +1506,13 @@ static void ST_drawCTFHUD(void) if (redflag && redflag->fuse > 1) { sprintf(timeleft, "%u", (redflag->fuse / TICRATE)); - V_DrawCenteredString(268, STRINGY(184), V_YELLOWMAP, timeleft); + V_DrawCenteredString(268, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); } if (blueflag && blueflag->fuse > 1) { sprintf(timeleft, "%u", (blueflag->fuse / TICRATE)); - V_DrawCenteredString(300, STRINGY(184), V_YELLOWMAP, timeleft); + V_DrawCenteredString(300, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); } } } @@ -1550,11 +1521,11 @@ static void ST_drawCTFHUD(void) static inline void ST_drawTeamName(void) { if (stplyr->ctfteam == 1) - V_DrawString(256, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "RED TEAM"); + V_DrawString(256, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM"); else if (stplyr->ctfteam == 2) - V_DrawString(248, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "BLUE TEAM"); + V_DrawString(248, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "BLUE TEAM"); else - V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_TRANSLUCENT, "SPECTATOR"); + V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); } #ifdef CHAOSISNOTDEADYET @@ -1562,33 +1533,28 @@ static inline void ST_drawChaosHUD(void) { char chains[33]; sprintf(chains, "CHAINS: %u", stplyr->scoreadd); - V_DrawString(8, STRINGY(184), V_TRANSLUCENT, chains); + V_DrawString(8, STRINGY(184), V_HUDTRANSHALF, chains); } #endif static void ST_drawSpecialStageHUD(void) { if (totalrings > 0) - { - if (splitscreen) - ST_DrawOverlayNum(hudinfo[HUD_SS_TOTALRINGS_SPLIT].x, hudinfo[HUD_SS_TOTALRINGS_SPLIT].y, V_SNAPTOTOP, totalrings); - else - ST_DrawOverlayNum(hudinfo[HUD_SS_TOTALRINGS].x, hudinfo[HUD_SS_TOTALRINGS].y, V_SNAPTOTOP, totalrings); - } + ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings); if (leveltime < 5*TICRATE && totalrings > 0) { - V_DrawScaledPatch(hudinfo[HUD_GETRINGS].x, SCR(hudinfo[HUD_GETRINGS].y), V_TRANSLUCENT, getall); - ST_DrawOverlayNum(hudinfo[HUD_GETRINGSNUM].x, SCR(hudinfo[HUD_GETRINGSNUM].y), 0, totalrings); + ST_DrawPatchFromHud(HUD_GETRINGS, getall); + ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings); } if (sstimer) { - V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), 0, M_GetText("TIME LEFT")); - ST_DrawNightsOverlayNum(SCX(hudinfo[HUD_TIMELEFTNUM].x), SCY(hudinfo[HUD_TIMELEFTNUM].y), sstimer/TICRATE, tallnum, SKINCOLOR_WHITE); + V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), V_HUDTRANS, M_GetText("TIME LEFT")); + ST_DrawNightsOverlayNum(SCX(hudinfo[HUD_TIMELEFTNUM].x), SCY(hudinfo[HUD_TIMELEFTNUM].y), V_HUDTRANS, sstimer/TICRATE, tallnum, SKINCOLOR_WHITE); } else - V_DrawScaledPatch(hudinfo[HUD_TIMEUP].x, hudinfo[HUD_TIMEUP].y, V_TRANSLUCENT, timeup); + ST_DrawPatchFromHud(HUD_TIMEUP, timeup); } static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) @@ -1627,7 +1593,7 @@ static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offse interval = 0; } - V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, STRINGY(hudinfo[HUD_HUNTPICS].y), V_TRANSLUCENT, patches[i]); + V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, STRINGY(hudinfo[HUD_HUNTPICS].y), V_HUDTRANS, patches[i]); return interval; } @@ -1895,9 +1861,9 @@ static void ST_overlayDrawer(void) { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; if (respawntime > 0 && !stplyr->spectator) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Jump to respawn.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); } else if (stplyr->spectator #ifdef HAVE_BLUA @@ -1905,13 +1871,13 @@ static void ST_overlayDrawer(void) #endif ) { - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), V_TRANSLUCENT, M_GetText("You are a spectator.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), V_HUDTRANSHALF, M_GetText("You are a spectator.")); if (G_GametypeHasTeams()) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Fire to be assigned to a team.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team.")); else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_TRANSLUCENT, M_GetText("Press Fire to enter the game.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_TRANSLUCENT, M_GetText("Press F12 to watch another player.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_TRANSLUCENT, M_GetText("Press Jump to float and Spin to sink.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player.")); + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink.")); } } @@ -1924,12 +1890,12 @@ void ST_Drawer(boolean refresh) if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { if (cv_seenames.value == 1) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, player_names[seenplayer-players]); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); else if (cv_seenames.value == 2) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, va("%s%s", G_GametypeHasTeams() ? ((seenplayer->ctfteam == 1) ? "\x85" : "\x84") : "", player_names[seenplayer-players])); else //if (cv_seenames.value == 3) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_TRANSLUCENT, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, va("%s%s", !G_RingSlingerGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam) ? "\x83" : "\x85", player_names[seenplayer-players])); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 5b5df5c1..d303bc80 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -83,24 +83,29 @@ typedef enum HUD_LIVESPIC, HUD_LIVESNUM, HUD_LIVESX, - HUD_RINGSSPLIT, - HUD_RINGSNUMSPLIT, + HUD_RINGS, + HUD_RINGSSPLIT, HUD_RINGSNUM, + HUD_RINGSNUMSPLIT, + HUD_SCORE, HUD_SCORENUM, - HUD_TIMESPLIT, - HUD_SECONDSSPLIT, - HUD_MINUTESSPLIT, - HUD_TIMECOLONSPLIT, + HUD_TIME, - HUD_TICS, - HUD_SECONDS, + HUD_TIMESPLIT, HUD_MINUTES, + HUD_MINUTESSPLIT, HUD_TIMECOLON, + HUD_TIMECOLONSPLIT, + HUD_SECONDS, + HUD_SECONDSSPLIT, HUD_TIMETICCOLON, - HUD_SS_TOTALRINGS_SPLIT, + HUD_TICS, + HUD_SS_TOTALRINGS, + HUD_SS_TOTALRINGS_SPLIT, + HUD_GETRINGS, HUD_GETRINGSNUM, HUD_TIMELEFT, diff --git a/src/v_video.c b/src/v_video.c index 76728a35..032a4ec9 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -297,657 +297,127 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #endif } -// -// V_DrawTranslucentMappedPatch: like V_DrawMappedPatch, but with translucency. -// -void V_DrawTranslucentMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) +static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; +static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; + +static const UINT8 *v_colormap = NULL; +static const UINT8 *v_translevel = NULL; + +static inline UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *translevel, *deststop; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - // draw a hardware converted patch - else if (rendermode != render_soft) - { - HWR_DrawMappedPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset); - x -= SHORT(patch->leftoffset); - - if (scrn & V_NOSCALESTART) - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.width) + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - } - else - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.dupy*vid.width) + (x*vid.dupx); - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - scrn &= V_PARAMMASK; - - col = 0; - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(translevel + (((*(colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + (void)dest; return source[ofs>>FRACBITS]; } - -// -// V_DrawMappedPatch: like V_DrawScaledPatch, but with a colormap. -// -void V_DrawMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) +static inline UINT8 mappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawMappedPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - if (scrn & V_FLIP) - { - flip = true; - x -= SHORT(patch->width) - SHORT(patch->leftoffset); - } - else - x -= SHORT(patch->leftoffset); - - if (scrn & V_SPLITSCREEN) - y /= 2; - - if (scrn & V_NOSCALESTART) - { - desttop = screens[scrn&V_PARAMMASK] + (y*vid.width) + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - } - else - { - desttop = screens[scrn&V_PARAMMASK] + (y*dupy*vid.width) + (x*dupx); - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - scrn &= V_PARAMMASK; - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx; - - col = 0; - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(colormap + source[ofs>>FRACBITS]); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + (void)dest; return *(v_colormap + source[ofs>>FRACBITS]); } - -// -// V_DrawScaledPatch -// -// Like V_DrawPatch, but scaled 2, 3, 4 times the original size and position. -// This is used for menu and title screens, with high resolutions. -// -void V_DrawScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) +static inline UINT8 translucentpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef PARANOIA - if (!patch) - CONS_Alert(CONS_ERROR, "NULL patch passed to V_DrawScaledPatch?! Crashing!\n"); -#endif - - if (rendermode == render_none) - return; -#ifdef HWRENDER - // draw a hardware converted patch - else if (rendermode != render_soft && !con_startup) - { - HWR_DrawPatch((GLPatch_t *)patch, x, y, scrn); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - if (scrn & V_FLIP) - { - flip = true; - x -= SHORT(patch->width) - SHORT(patch->leftoffset); - } - else - x -= SHORT(patch->leftoffset); - - if (scrn & V_SPLITSCREEN) - y /= 2; - - colfrac = FixedDiv(FRACUNIT, dupx<width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx; - - if (destend + (SHORT(patch->height) * dupy) * vid.width < screens[scrn&V_PARAMMASK]) - return; - - for (col = 0; desttop < destend; col += colfrac, desttop++) - { - register INT32 heightmask; - INT32 topdelta, prevdelta = -1; - - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - - heightmask = column->length - 1; - - while (dest < screens[scrn&V_PARAMMASK] && count) - { - dest += vid.width; - ofs += rowfrac; - --count; - } - - if (count && column->length & heightmask) - { - heightmask++; - heightmask <<= FRACBITS; - - if (rowfrac < 0) - while ((rowfrac += heightmask) < 0) - ; - else - while (rowfrac >= heightmask) - rowfrac -= heightmask; - - do - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - if ((ofs + rowfrac) > heightmask) - goto donedrawing; - } while (count--); - } - else - { - while (count--) - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - } -donedrawing: - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + return *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); } - -/** Draws a patch to the screen, being careful not to go off the right - * side or bottom of the screen. This is slower than a normal draw, so - * it gets a separate function. - * - * With hardware rendering, the patch is clipped anyway, so this is - * just the same as V_DrawScaledPatch(). - * - * \param x X coordinate for left side, based on 320x200 screen. - * \param y Y coordinate for top, based on 320x200 screen. - * \param scrn Any of several flags to change the drawing behavior. - * \param patch Patch to draw. - * \sa V_DrawScaledPatch - * \author Graue - */ -static void V_DrawClippedScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) +static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) { - size_t count; - INT32 col, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest, *destend; - const UINT8 *source, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - // V_NOSCALESTART might be impled for software, but not for hardware! - HWR_DrawClippedPatch((GLPatch_t *)patch, x, y, V_NOSCALESTART); - return; - } -#endif - - switch (scrn & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - dupx = dupy = 1; - break; - case V_SMALLSCALEPATCH: - dupx = vid.smalldupx; - dupy = vid.smalldupy; - break; - case V_MEDSCALEPATCH: - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: - dupx = vid.dupx; - dupy = vid.dupy; - break; - } - - // Only use one dup, to avoid stretching. - if (dupx < dupy) - dupy = dupx; - else - dupx = dupy; - - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); - - if (x < 0 || y < 0 || x >= vid.width || y >= vid.height) - return; - - colfrac = FixedDiv(FRACUNIT, dupx<width)*dupx <= vid.width) - destend = desttop + SHORT(patch->width) * dupx; - else - destend = desttop + vid.width - x; - - for (col = 0; desttop < destend; col += colfrac, desttop++) - { - register INT32 heightmask; - INT32 topdelta, prevdelta = -1; - - column = (const column_t *)((const UINT8 *)patch + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - if ((dest-screens[scrn&V_PARAMMASK])/vid.width + count > (unsigned)vid.height - 1) - count = vid.height - 1 - (dest-screens[scrn&V_PARAMMASK])/vid.width; - if (count <= 0) - break; - - ofs = 0; - - heightmask = column->length - 1; - - if (column->length & heightmask) - { - // length is not a power of two - heightmask++; - heightmask <<= FRACBITS; - - if (rowfrac < 0) - while ((rowfrac += heightmask) < 0) - ; - else - while (rowfrac >= heightmask) - rowfrac -= heightmask; - - do - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - if ((ofs + rowfrac) > heightmask) - goto doneclipping; - } while (count--); - } - else - { - // length is a power of two - while (count--) - { - if (dest < deststop) - *dest = source[ofs>>FRACBITS]; - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - } -doneclipping: - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); } // Draws a patch scaled to arbitrary size. -void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_t science) +void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { + UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); + UINT32 alphalevel = 0; + boolean flip = false; + fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; const column_t *column; - UINT8 *desttop, *dest; + UINT8 *desttop, *dest, *deststart, *destend; const UINT8 *source, *deststop; + if (rendermode == render_none) + return; + #ifdef HWRENDER // oh please - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && !con_startup) { - HWR_DrawSciencePatch((GLPatch_t *)patch, x, y, scrn, science); + HWR_DrawFixedPatch((GLPatch_t *)patch, x, y, pscale, scrn, colormap); return; } #endif + patchdrawfunc = standardpdraw; + + v_translevel = NULL; + if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[cv_translucenthud.value]; + else if (alphalevel == 14) + alphalevel = 10 - cv_translucenthud.value; + else if (alphalevel == 15) + alphalevel = hudplusalpha[cv_translucenthud.value]; + + if (alphalevel >= 10) + return; // invis + } + if (alphalevel) + { + v_translevel = ((alphalevel)<> V_SCALEPATCHSHIFT) + { + case 1: // V_NOSCALEPATCH + dupx = dupy = 1; + break; + case 2: // V_SMALLSCALEPATCH + dupx = vid.smalldupx; + dupy = vid.smalldupy; + break; + case 3: // V_MEDSCALEPATCH + dupx = vid.meddupx; + dupy = vid.meddupy; + break; + default: + break; + } + // only use one dup, to avoid stretching (har har) - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset)<leftoffset)<topoffset)*dupy)<leftoffset)*dupx)<topoffset)<width) - SHORT(patch->leftoffset))<leftoffset)<>=1; desttop = screens[scrn&V_PARAMMASK]; @@ -956,11 +426,13 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ deststop = desttop + vid.rowbytes * vid.height; - if (scrn & V_NOSCALESTART) { + if (scrn & V_NOSCALESTART) + { x >>= FRACBITS; y >>= FRACBITS; desttop += (y*vid.width) + x; - } else + } + else { x = FixedMul(x,dupx<width) * dupx; + for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) { INT32 topdelta, prevdelta = -1; - if (x < 0) { // don't draw off the left of the screen (WRAP PREVENTION) + if (x < 0) + { // don't draw off the left of the screen (WRAP PREVENTION) x++; continue; } @@ -1017,12 +495,14 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; + if (flip) + dest = deststart + (destend - desttop); dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = source[ofs>>FRACBITS]; + *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } column = (const column_t *)((const UINT8 *)column + column->length + 4); @@ -1031,7 +511,7 @@ void V_DrawSciencePatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ } // Draws a patch cropped and scaled to arbitrary size. -void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_t science, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; @@ -1039,23 +519,26 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, INT32 scrn, patch_t *patch, fixed_ UINT8 *desttop, *dest; const UINT8 *source, *deststop; + if (rendermode == render_none) + return; + #ifdef HWRENDER // Done - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && !con_startup) { - HWR_DrawCroppedPatch((GLPatch_t *)patch, x, y, scrn, science, sx, sy, w, h); + HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); return; } #endif // only use one dup, to avoid stretching (har har) dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset)<leftoffset)<topoffset)<leftoffset)<>= FRACBITS; y >>= FRACBITS; desttop += (y*vid.width) + x; - } else + } + else { x = FixedMul(x,dupx<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - if (scrn & V_SPLITSCREEN) - y /= 2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - x = x*dupx; - y = y*dupy; - desttop += (y*vid.width) + x; - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - if (x < 0) { // don't draw off the left of the screen (WRAP PREVENTION) - x++; - continue; - } - if (x > vid.width) // don't draw off the right of the screen (WRAP PREVENTION) - break; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = source[ofs>>FRACBITS]; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, translucent, and colormapped. -void V_DrawSmallTranslucentMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - UINT8 *translevel; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(translevel + (colormap[source[ofs>>FRACBITS]]<<8) + (*dest)); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, and translucent. -void V_DrawSmallTranslucentPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - UINT8 *translevel; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormaps); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - } - } - - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 2x as small, and colormapped. -void V_DrawSmallMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - if (!(scrn & V_NOSCALESTART)) // Graue 07-08-2004: I have no idea why this works - { - x = FixedInt(FixedMul(vid.fdupx, x*FRACUNIT)); - y = FixedInt(FixedMul(vid.fdupy, y*FRACUNIT)); - scrn |= V_NOSCALESTART; - } - HWR_DrawSmallPatch((GLPatch_t *)patch, x, y, scrn, colormap); - return; - } -#endif - - // only use one dup, to avoid stretching. - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = dupx<<(FRACBITS-1); - colfrac = FixedDiv(FRACUNIT, fdup); - rowfrac = FixedDiv(FRACUNIT, fdup); - - y -= SHORT(patch->topoffset)/2; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/2; - } - else - x -= SHORT(patch->leftoffset)/2; - - if (scrn & V_SPLITSCREEN) - y /= 2; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SPLITSCREEN && scrn & V_SNAPTOBOTTOM) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 2; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(colormap + source[ofs>>FRACBITS]); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 4x as small. -void V_DrawTinyScaledPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // No. - if (rendermode != render_soft && rendermode != render_none) - return; -#endif - - // only use one dup, to avoid stretching. - fdup = (vid.dupx < vid.dupy ? vid.dupx<topoffset)/4; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/4; - } - else - x -= SHORT(patch->leftoffset)/4; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 4; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = source[ofs>>FRACBITS]; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// Draws a patch 4x as small, and colormapped. -void V_DrawTinyMappedPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch, const UINT8 *colormap) -{ - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest, *deststart, *destend; - const UINT8 *source, *deststop; - boolean flip = false; - -#ifdef HWRENDER - // No. - if (rendermode != render_soft && rendermode != render_none) - return; -#endif - - // only use one dup, to avoid stretching. - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = dupx<<(FRACBITS-2); - colfrac = FixedDiv(FRACUNIT, fdup); - rowfrac = FixedDiv(FRACUNIT, fdup); - - y -= SHORT(patch->topoffset)/4; - if (scrn & V_FLIP) - { - flip = true; - x -= (SHORT(patch->width) - SHORT(patch->leftoffset))/4; - } - else - x -= SHORT(patch->leftoffset)/4; - - desttop = screens[scrn&V_PARAMMASK]; - - if (!desttop) - return; - - deststop = desttop + vid.rowbytes * vid.height; - - if (scrn & V_NOSCALESTART) - desttop += (y*vid.width) + x; - else - { - desttop += (y*dupy*vid.width) + (x*dupx); - - // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : *(colormap + source[0]))); - } - } - } - deststart = desttop; - destend = desttop + SHORT(patch->width) * dupx / 4; - - for (col = 0; (col>>FRACBITS) < SHORT(patch->width); col += colfrac, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (flip) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - *dest = *(colormap + source[ofs>>FRACBITS]); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// This draws a patch over a background with translucency...SCALED. -// SCALE THE STARTING COORDS! -// Used for crosshair. -// -void V_DrawTranslucentPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - size_t count; - INT32 col, w, dupx, dupy, ofs, colfrac, rowfrac; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *translevel, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawTranslucentPatch((GLPatch_t *)patch, x, y, scrn); - return; - } -#endif - - if (scrn & V_ALPHAMASK) - { - INT32 alphalevel = (scrn & V_ALPHAMASK) >> V_ALPHASHIFT; - if (alphalevel >= NUMTRANSMAPS) - return; // fully translucent - translevel = ((alphalevel)<topoffset)*dupy; - x -= SHORT(patch->leftoffset)*dupx; - } - else - { - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); - } - - colfrac = FixedDiv(FRACUNIT, dupx<width)<columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*dupy*vid.width; - count = column->length*dupy; - - ofs = 0; - while (count--) - { - if (dest < deststop) - *dest = *(translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); - else - count = 0; - dest += vid.width; - ofs += rowfrac; - } - - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - -// -// V_DrawPatch -// Masks a column based masked pic to the screen. NO SCALING! -// -void V_DrawPatch(INT32 x, INT32 y, INT32 scrn, patch_t *patch) -{ - size_t count; - INT32 col, w; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *deststop; - -#ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) - { - HWR_DrawPatch((GLPatch_t *)patch, x, y, V_NOSCALESTART|V_NOSCALEPATCH); - return; - } -#endif - - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); -#ifdef RANGECHECK - if (x < 0 || x + SHORT(patch->width) > vid.width || y < 0 - || y + SHORT(patch->height) > vid.height || (unsigned)scrn > 4) - { - fprintf(stderr, "Patch at %d, %d exceeds LFB\n", x, y); - // No I_Error abort - what is up with TNT.WAD? - fprintf(stderr, "V_DrawPatch: bad patch (ignored)\n"); - return; - } -#endif - - desttop = screens[scrn] + y*vid.width + x; - deststop = screens[scrn&V_PARAMMASK] + vid.rowbytes * vid.height; - w = SHORT(patch->width); - - for (col = 0; col < w; x++, col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (const column_t *)((const UINT8 *)patch + LONG(patch->columnofs[col])); - - // step through the posts in a column - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)column + 3; - dest = desttop + topdelta*vid.width; - count = column->length; - - while (count--) - { - if (dest < deststop) - *dest = *source++; - else - count = 0; - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } -} - // // V_DrawContinueIcon // Draw a mini player! If we can, that is. Otherwise we draw a star. @@ -2035,7 +630,7 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin { if (skins[skinnum].flags & SF_HIRES #ifdef HWRENDER - || (rendermode != render_soft && rendermode != render_none) +// || (rendermode != render_soft && rendermode != render_none) #endif ) V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); @@ -2313,12 +908,7 @@ void V_DrawPatchFill(patch_t *pat) for (x = 0; x < vid.width; x += pw) { for (y = 0; y < vid.height; y += ph) - { - if (x + pw >= vid.width || y + ph >= vid.height) - V_DrawClippedScaledPatch(x, y, 0, pat); // V_NOSCALESTART is implied - else - V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); - } + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); } } @@ -2681,15 +1271,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) } colormap = V_GetStringColormap(charflags); - - if (colormap != NULL && (option & V_ALPHAMASK)) - V_DrawTranslucentMappedPatch(cx + center, cy, option, hu_font[c], colormap); - else if (colormap != NULL) - V_DrawMappedPatch(cx + center, cy, option, hu_font[c], colormap); - else if (option & V_ALPHAMASK) - V_DrawTranslucentPatch(cx + center, cy, option, hu_font[c]); - else - V_DrawScaledPatch(cx + center, cy, option, hu_font[c]); + V_DrawFixedPatch((cx + center)< Date: Fri, 21 Mar 2014 16:05:12 -0400 Subject: [PATCH 09/19] bump SRB2Mac version --- src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index f898a993..44d660e0 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1212,7 +1212,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.2; + CURRENT_PROJECT_VERSION = 2.1.4; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1224,7 +1224,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.2; + CURRENT_PROJECT_VERSION = 2.1.4; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( From ec902fed52dc6ba6125610101b003ac46bf2bada Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Fri, 21 Mar 2014 20:28:41 +0000 Subject: [PATCH 10/19] OpenGL Intermission picture fix Fixes intermission pictures being taken in OpenGL. --- src/y_inter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/y_inter.c b/src/y_inter.c index 49bac308..def5bbb1 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -990,6 +990,10 @@ void Y_StartIntermission(void) else { useinterpic = false; +#ifdef HWRENDER + if (rendermode == render_opengl) + usebuffer = true; // This needs to be here for OpenGL, otherwise usebuffer is never set to true for it, and thus there's no screenshot in the intermission +#endif } usetile = false; From 037b15dbf72d2e14c484c0cde84a5dad818b611b Mon Sep 17 00:00:00 2001 From: "Tobias \"ToBeFree\" Frei" Date: Fri, 21 Mar 2014 22:03:20 +0100 Subject: [PATCH 11/19] change version number to 2.1.4, add linux64 info Huge thanks to Alam_Squeeze from #srb2fun. :D --- readme.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 7a33a55d..aa25ef0f 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Here it is! SRB2 v2.1.2 source code! +Here it is! SRB2 v2.1.4 source code! Win32 with Visual C (6SP6+Processor Pack OR 7) @@ -58,6 +58,10 @@ Build instructions: make -C src LINUX=1 +Build instructions (64 bit): + +make -C src LINUX64=1 + Build instructions to build for Wii Linux/SRB2Wii on a PowerPC system, follow cross-compiling instructions for cross-compiling on a x86 system: From 1f452953b67c8fe8b5d588212fd05ce65358b544 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 22 Mar 2014 14:52:32 +0000 Subject: [PATCH 12/19] Post processor skybox Post processing no longer done in the skybox. --- src/hardware/hw_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 14b15561..23374500 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4592,8 +4592,6 @@ if (0) if (cv_grfog.value) HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); - HWR_DoPostProcessor(player); - // Check for new console commands. NetUpdate(); From 9386b3900b74c842717d03b0532819751bdd88f0 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 22 Mar 2014 17:17:40 +0000 Subject: [PATCH 13/19] OpenGL remove HOMs Removes HOMs from OpenGL. This also seems to have made skyboxes not draw ontop of everything else on Intel GPU's. --- src/hardware/hw_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 23374500..16987b88 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4610,6 +4610,15 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on + FRGBAFloat ClearColor; + + ClearColor.red = 0.0f; + ClearColor.green = 0.0f; + ClearColor.blue = 0.0f; + ClearColor.alpha = 1.0f; + + HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. + if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind @@ -4685,7 +4694,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); //------------------------------------------------------------------------ - HWR_ClearView(); + HWR_ClearView(); // Clears the depth buffer and resets the view I believe if (0) { // I don't think this is ever used. From 2b781d82d5d10b586754e9fb6428f5b872355bff Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 22 Mar 2014 15:54:46 -0400 Subject: [PATCH 14/19] Quartz is evil, we need to ask for a new modeList --- src/sdl/i_video.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 71c81364..1a2305fe 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1577,6 +1577,7 @@ const char *VID_GetModeName(INT32 modeNum) INT32 VID_GetModeForSize(INT32 w, INT32 h) { INT32 matchMode = -1, i; + VID_PrepareModeList(); if (USE_FULLSCREEN && numVidModes != -1) { for (i=firstEntry; i Date: Sat, 22 Mar 2014 16:09:41 -0400 Subject: [PATCH 15/19] Fixup Srb2Mac to exclude srb2.srb from Lite pack --- src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index 44d660e0..dfe755af 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -976,11 +976,11 @@ buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Srb2mac" */; buildPhases = ( 8D1107290486CEB800E47090 /* Resources */, - 677E4CB30E1765500034519D /* ShellScript */, + 677E4CB30E1765500034519D /* Get SCM Info */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, 002F39FD09D0883400EBEB88 /* Copy Frameworks into .app bundle */, - 679B708A102B872300AA9E4C /* ShellScript */, + 679B708A102B872300AA9E4C /* Make DMG */, ); buildRules = ( ); @@ -1028,7 +1028,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 677E4CB30E1765500034519D /* ShellScript */ = { + 677E4CB30E1765500034519D /* Get SCM Info */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; comments = "update the time and date stamps in src/comptime.c"; @@ -1036,13 +1036,14 @@ ); inputPaths = ( ); + name = "Get SCM Info"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "PATH=\"/usr/local/bin:$PATH\" $SRCROOT/../../../comptime.sh $SRCROOT/../../"; }; - 679B708A102B872300AA9E4C /* ShellScript */ = { + 679B708A102B872300AA9E4C /* Make DMG */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; comments = "make DMG file for Release builds"; @@ -1051,13 +1052,14 @@ inputPaths = ( $BUILT_PRODUCTS_DIR/$WRAPPER_NAME, ); + name = "Make DMG"; outputPaths = ( $BUILT_PRODUCTS_DIR/$TARGET_NAME.nodata.dmg, $BUILT_PRODUCTS_DIR/$TARGET_NAME.dmg, ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -ex\n\n[ \"$ACTION\" = build ] || exit 0\n[ \"$CURRENT_VARIANT\" = \"normal\" ] || exit 0\n[ \"$BUILD_STYLE\" = \"Release\" ] || exit 0\n\ndir=\"$TEMP_FILES_DIR/$TARGET_NAME.disk\"\ndmg=\"$BUILT_PRODUCTS_DIR/$TARGET_NAME.dmg\"\ndmg_nodata=\"$BUILT_PRODUCTS_DIR/$TARGET_NAME.nodata.dmg\"\n\nrm -rf -- \"$dir\"\nmkdir \"$dir\"\ncp -R \"$BUILT_PRODUCTS_DIR/$WRAPPER_NAME\" \"$dir\"\nrm -f -- \"$dmg\"\nhdiutil create -ov -fs HFS+ -srcfolder \"$dir\" -volname \"$TARGET_NAME\" \"$dmg\"\nhdiutil internet-enable -yes \"$dmg\"\ncd \"$dir/$WRAPPER_NAME/Contents/Resources\"\nrm -f -- *.wad\nrm -f -- *.dta\nrm -f -- *.plr\nrm -f -- *.wpn\ncd \"$OLDPWD\"\nrm -f -- \"$dmg_nodata\"\nhdiutil create -ov -fs HFS+ -srcfolder \"$dir\" -volname \"$TARGET_NAME Lite\" \"$dmg_nodata\"\nhdiutil internet-enable -yes \"$dmg_nodata\"\nrm -rf -- \"$dir\""; + shellScript = "set -ex\n\n[ \"$ACTION\" = build ] || exit 0\n[ \"$CURRENT_VARIANT\" = \"normal\" ] || exit 0\n[ \"$BUILD_STYLE\" = \"Release\" ] || exit 0\n\ndir=\"$TEMP_FILES_DIR/$TARGET_NAME.disk\"\ndmg=\"$BUILT_PRODUCTS_DIR/$TARGET_NAME.dmg\"\ndmg_nodata=\"$BUILT_PRODUCTS_DIR/$TARGET_NAME.nodata.dmg\"\n\nrm -rf -- \"$dir\"\nmkdir \"$dir\"\ncp -R \"$BUILT_PRODUCTS_DIR/$WRAPPER_NAME\" \"$dir\"\nrm -f -- \"$dmg\"\nhdiutil create -ov -fs HFS+ -srcfolder \"$dir\" -volname \"$TARGET_NAME\" \"$dmg\"\nhdiutil internet-enable -yes \"$dmg\"\ncd \"$dir/$WRAPPER_NAME/Contents/Resources\"\nrm -f -- *.wad\nrm -f -- *.dta\nrm -f -- *.plr\nrm -f -- *.wpn\nrm -f -- *.srb2\ncd \"$OLDPWD\"\nrm -f -- \"$dmg_nodata\"\nhdiutil create -ov -fs HFS+ -srcfolder \"$dir\" -volname \"$TARGET_NAME Lite\" \"$dmg_nodata\"\nhdiutil internet-enable -yes \"$dmg_nodata\"\nrm -rf -- \"$dir\""; }; /* End PBXShellScriptBuildPhase section */ From 734d6b56f08349fdfc69dfcba75f807a85642561 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sun, 23 Mar 2014 00:04:35 +0000 Subject: [PATCH 16/19] OpenGL Flashpal Flashes Fixed flashes for OpenGL Nukes/Teleports etc. --- src/hardware/hw_main.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 16987b88..0e356269 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5231,11 +5231,19 @@ void HWR_DoPostProcessor(player_t *player) FOutVector v[4]; FSurfaceInfo Surf; - v[0].x = v[2].y = v[3].x = v[3].y = -1.0f; - v[0].y = v[1].x = v[1].y = v[2].x = 1.0f; - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + v[0].x = v[2].y = v[3].x = v[3].y = -4.0f; + v[0].y = v[1].x = v[1].y = v[2].x = 4.0f; + v[0].z = v[1].z = v[2].z = v[3].z = 4.0f; // 4.0 because of the same reason as with the sky, just after the screen is cleared so near clipping plane is 3.99 + + // This won't change if the flash palettes are changed unfortunately, but it works for its purpose + if (player->flashpal == PAL_NUKE) + { + Surf.FlatColor.s.red = 0xff; + Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish + } + else + Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; Surf.FlatColor.s.alpha = 0xc0; // match software mode HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); From 15bd266cac107f879509f70a168530c6add08195 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 23 Mar 2014 12:00:29 -0400 Subject: [PATCH 17/19] SRB2 2.1.5 release --- src/am_map.c | 146 ++++++++++++++++++++++++++++++++++++-------- src/d_clisrv.c | 15 ++++- src/d_main.c | 4 +- src/d_net.c | 8 +-- src/d_netcmd.c | 19 ++++-- src/d_ticcmd.h | 7 ++- src/dehacked.c | 4 ++ src/doomdef.h | 6 +- src/g_game.c | 118 ++++++++++++++++++++--------------- src/g_game.h | 6 +- src/g_input.c | 3 + src/g_input.h | 3 + src/hu_stuff.c | 16 ++--- src/info.c | 6 +- src/lua_hudlib.c | 10 +++ src/m_menu.c | 26 +++++--- src/p_inter.c | 2 +- src/p_mobj.c | 36 +++++++---- src/p_mobj.h | 6 +- src/p_setup.c | 2 +- src/p_user.c | 23 ++++--- src/sdl/i_system.c | 10 ++- src/win32/win_sys.c | 8 ++- 23 files changed, 344 insertions(+), 140 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 9c2aee2c..70714fac 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -25,36 +25,64 @@ #endif // For use if I do walls with outsides/insides -static const UINT8 GREENS = (10*16); -static const UINT8 GREENRANGE = 16; -static const UINT8 GRAYS = (0*16); -static const UINT8 GRAYSRANGE = 16; -static const UINT8 DBLACK = 31; -static const UINT8 DWHITE = 0; +static const UINT8 REDS = (8*16); +static const UINT8 REDRANGE = 16; +static const UINT8 GRAYS = (1*16); +static const UINT8 GRAYSRANGE = 16; +static const UINT8 BROWNS = (3*16); +static const UINT8 BROWNRANGE = 16; +static const UINT8 YELLOWS = (7*16); +static const UINT8 YELLOWRANGE = 8; +static const UINT8 GREENS = (10*16); +static const UINT8 GREENRANGE = 16; +static const UINT8 DBLACK = 31; +static const UINT8 DWHITE = 0; + +static const UINT8 NOCLIMBREDS = 248; +static const UINT8 NOCLIMBREDRANGE = 8; +static const UINT8 NOCLIMBGRAYS = 204; +static const UINT8 NOCLIMBGRAYSRANGE = 4; +static const UINT8 NOCLIMBBROWNS = (2*16); +static const UINT8 NOCLIMBBROWNRANGE = 16; +static const UINT8 NOCLIMBYELLOWS = (11*16); +static const UINT8 NOCLIMBYELLOWRANGE = 8; + #ifdef _NDS #undef BACKGROUND #endif // Automap colors -#define BACKGROUND DBLACK -#define YOURCOLORS DWHITE -#define YOURRANGE 0 -#define WALLCOLORS REDS -#define WALLRANGE REDRANGE -#define TSWALLCOLORS GRAYS -#define TSWALLRANGE GRAYSRANGE -#define FDWALLCOLORS BROWNS -#define FDWALLRANGE BROWNRANGE -#define CDWALLCOLORS YELLOWS -#define CDWALLRANGE YELLOWRANGE -#define THINGCOLORS GREENS -#define THINGRANGE GREENRANGE -#define SECRETWALLCOLORS WALLCOLORS -#define SECRETWALLRANGE WALLRANGE -#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define GRIDRANGE 0 -#define XHAIRCOLORS GRAYS +#define BACKGROUND DBLACK +#define YOURCOLORS DWHITE +#define YOURRANGE 0 +#define WALLCOLORS (REDS + REDRANGE/2) +#define WALLRANGE (REDRANGE/2) +#define NOCLIMBWALLCOLORS (NOCLIMBREDS + NOCLIMBREDRANGE/2) +#define NOCLIMBWALLRANGE (NOCLIMBREDRANGE/2) +#define THOKWALLCOLORS REDS +#define THOKWALLRANGE REDRANGE +#define NOCLIMBTHOKWALLCOLORS NOCLIMBREDS +#define NOCLIMBTHOKWALLRANGE NOCLIMBREDRANGE +#define TSWALLCOLORS GRAYS +#define TSWALLRANGE GRAYSRANGE +#define NOCLIMBTSWALLCOLORS NOCLIMBGRAYS +#define NOCLIMBTSWALLRANGE NOCLIMBGRAYSRANGE +#define FDWALLCOLORS BROWNS +#define FDWALLRANGE BROWNRANGE +#define NOCLIMBFDWALLCOLORS NOCLIMBBROWNS +#define NOCLIMBFDWALLRANGE NOCLIMBBROWNRANGE +#define CDWALLCOLORS YELLOWS +#define CDWALLRANGE YELLOWRANGE +#define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS +#define NOCLIMBCDWALLRANGE NOCLIMBYELLOWRANGE +#define THINGCOLORS GREENS +#define THINGRANGE GREENRANGE +#define SECRETWALLCOLORS WALLCOLORS +#define SECRETWALLRANGE WALLRANGE +#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) +#define GRIDRANGE 0 +#define XHAIRCOLORS GRAYS // drawing stuff #define FB 0 @@ -1009,7 +1037,75 @@ static inline void AM_drawWalls(void) l.b.x = lines[i].v2->x; l.b.y = lines[i].v2->y; - AM_drawMline(&l, GRAYS + 3); +// AM_drawMline(&l, GRAYS + 3); // Old, everything-is-gray automap + if (!lines[i].backsector) // 1-sided + { + if (lines[i].flags & ML_NOCLIMB) + { + AM_drawMline(&l, NOCLIMBWALLCOLORS+lightlev); + } + else + { + AM_drawMline(&l, WALLCOLORS+lightlev); + } + } + else if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight // Back is thok barrier + || lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // Front is thok barrier + { + if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight + && lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // BOTH are thok barriers + { + if (lines[i].flags & ML_NOCLIMB) + { + AM_drawMline(&l, NOCLIMBTSWALLCOLORS+lightlev); + } + else + { + AM_drawMline(&l, TSWALLCOLORS+lightlev); + } + } + else + { + if (lines[i].flags & ML_NOCLIMB) + { + AM_drawMline(&l, NOCLIMBTHOKWALLCOLORS+lightlev); + } + else + { + AM_drawMline(&l, THOKWALLCOLORS+lightlev); + } + } + } + else + { + if (lines[i].flags & ML_NOCLIMB) { + if (lines[i].backsector->floorheight + != lines[i].frontsector->floorheight) { + AM_drawMline(&l, NOCLIMBFDWALLCOLORS + lightlev); // floor level change + } + else if (lines[i].backsector->ceilingheight + != lines[i].frontsector->ceilingheight) { + AM_drawMline(&l, NOCLIMBCDWALLCOLORS+lightlev); // ceiling level change + } + else { + AM_drawMline(&l, NOCLIMBTSWALLCOLORS+lightlev); + } + } + else + { + if (lines[i].backsector->floorheight + != lines[i].frontsector->floorheight) { + AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change + } + else if (lines[i].backsector->ceilingheight + != lines[i].frontsector->ceilingheight) { + AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change + } + else { + AM_drawMline(&l, TSWALLCOLORS+lightlev); + } + } + } } } diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 46a711aa..c6008e86 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -759,7 +759,10 @@ static inline void resynch_write_ctf(resynchend_pak *rst) // Should be held by a player for (j = 0; j < MAXPLAYERS; ++j) { - if (!playeringame[j] || players[j].gotflag != i) + // GF_REDFLAG is 1, GF_BLUEFLAG is 2 + // redflag handling is i=0, blueflag is i=1 + // so check for gotflag == (i+1) + if (!playeringame[j] || players[j].gotflag != (i+1)) continue; rst->flagplayer[i] = (SINT8)j; break; @@ -2229,7 +2232,11 @@ static void CL_RemovePlayer(INT32 playernum) void CL_Reset(void) { - if (demorecording || metalrecording) + if (metalrecording) + G_StopMetalRecording(); + if (metalplayback) + G_StopMetalDemo(); + if (demorecording) G_CheckDemoStatus(); // reset client/server code @@ -2954,8 +2961,10 @@ boolean Playing(void) boolean SV_SpawnServer(void) { - if (demoplayback || metalplayback) + if (demoplayback) G_StopDemo(); // reset engine parameter + if (metalplayback) + G_StopMetalDemo(); if (!serverrunning) { diff --git a/src/d_main.c b/src/d_main.c index 02590390..bd8e12f2 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1090,14 +1090,14 @@ void D_SRB2Main(void) #endif D_CleanFile(); -#if 1 // md5s last updated 3/18/14 +#if 1 // md5s last updated 3/22/14 // Check MD5s of autoloaded files W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta - W_VerifyFileMD5(4, "e868046d2d2da1d8c706c900edfb03f8"); // patch.dta + W_VerifyFileMD5(4, "4d56695e194a6fd3bc5c87610a215186"); // patch.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. diff --git a/src/d_net.c b/src/d_net.c index d93b80c9..906c5389 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -129,10 +129,10 @@ boolean Net_GetNetStat(void) // ----------------------------------------------------------------- // Some structs and functions for acknowledgement of packets // ----------------------------------------------------------------- -#define MAXACKPACKETS 64 // minimum number of nodes -#define MAXACKTOSEND 64 -#define URGENTFREESLOTENUM 6 -#define ACKTOSENDTIMEOUT (TICRATE/17) +#define MAXACKPACKETS 96 // minimum number of nodes +#define MAXACKTOSEND 96 +#define URGENTFREESLOTENUM 10 +#define ACKTOSENDTIMEOUT (TICRATE/11) #ifndef NONET typedef struct diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 06c6fcb0..6b74e602 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1575,15 +1575,18 @@ static void Command_Playdemo_f(void) return; } - // disconnect from server here? - if (demoplayback || metalplayback) - G_StopDemo(); if (netgame) { CONS_Printf(M_GetText("You can't play a demo while in a netgame.\n")); return; } + // disconnect from server here? + if (demoplayback) + G_StopDemo(); + if (metalplayback) + G_StopMetalDemo(); + // open the demo file strcpy(name, COM_Argv(1)); // dont add .lmp so internal game demos can be played @@ -1603,15 +1606,18 @@ static void Command_Timedemo_f(void) return; } - // disconnect from server here? - if (demoplayback || metalplayback) - G_StopDemo(); if (netgame) { CONS_Printf(M_GetText("You can't play a demo while in a netgame.\n")); return; } + // disconnect from server here? + if (demoplayback) + G_StopDemo(); + if (metalplayback) + G_StopMetalDemo(); + // open the demo file strcpy (name, COM_Argv(1)); // dont add .lmp so internal game demos can be played @@ -1970,6 +1976,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (demorecording) // Okay, level loaded, character spawned and skinned, G_BeginRecording(); // I AM NOW READY TO RECORD. demo_start = true; + metal_start = true; } static void Command_Pause(void) diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 41d25f2e..edbba552 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -36,8 +36,11 @@ typedef enum BT_CAMRIGHT = 1<<9, // turn camera right BT_TOSSFLAG = 1<<10, BT_JUMP = 1<<11, - BT_FIRENORMAL = 1<<12 // Fire a normal ring no matter what - // free: up to and including 1<<15 + BT_FIRENORMAL = 1<<12, // Fire a normal ring no matter what + + BT_CUSTOM1 = 1<<13, + BT_CUSTOM2 = 1<<14, + BT_CUSTOM3 = 1<<15, } buttoncode_t; // The data sampled per tick (single player) diff --git a/src/dehacked.c b/src/dehacked.c index 6eae1ce2..35e672eb 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7101,6 +7101,7 @@ static const char *const MOBJFLAG_LIST[] = { "STICKY", "NIGHTSITEM", "NOCLIPTHING", + "GRENADEBOUNCE", "RUNSPAWNFUNC", NULL }; @@ -7648,6 +7649,9 @@ struct { {"BT_TOSSFLAG",BT_TOSSFLAG}, {"BT_JUMP",BT_JUMP}, {"BT_FIRENORMAL",BT_FIRENORMAL}, // Fire a normal ring no matter what + {"BT_CUSTOM1",BT_CUSTOM1}, // Lua customizable + {"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable + {"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable // cvflags_t {"CV_SAVE",CV_SAVE}, diff --git a/src/doomdef.h b/src/doomdef.h index a5454851..6c9d7ebe 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -144,8 +144,8 @@ extern FILE *logstream; #define VERSIONSTRING "Trunk" #else #define VERSION 201 // Game version -#define SUBVERSION 4 // more precise version number -#define VERSIONSTRING "v2.1.4" +#define SUBVERSION 5 // more precise version number +#define VERSIONSTRING "v2.1.5" #endif // Modification options @@ -201,7 +201,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 9 +#define MODVERSION 10 diff --git a/src/g_game.c b/src/g_game.c index dfd9aacd..8f0d5b91 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -231,14 +231,17 @@ boolean demorecording; boolean demoplayback; boolean titledemo; // Title Screen demo can be cancelled by any key static UINT8 *demobuffer = NULL; -static UINT8 *metalbuffer = NULL; -static UINT8 *demo_p, *metal_p, *demotime_p; +static UINT8 *demo_p, *demotime_p; static UINT8 *demoend; static UINT8 demoflags; boolean singledemo; // quit after playing a demo from cmdline +boolean demo_start; // don't start playing demo right away + boolean metalrecording; // recording as metal sonic mobj_t *metalplayback; -boolean demo_start; // don't start playing demo right away +static UINT8 *metalbuffer = NULL; +static UINT8 *metal_p; +boolean metal_start; // extra data stuff (events registered this frame while recording) static struct { @@ -1046,8 +1049,16 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) if (PLAYER1INPUTDOWN(gc_tossflag)) cmd->buttons |= BT_TOSSFLAG; + // Lua scriptable buttons + if (PLAYER1INPUTDOWN(gc_custom1)) + cmd->buttons |= BT_CUSTOM1; + if (PLAYER1INPUTDOWN(gc_custom2)) + cmd->buttons |= BT_CUSTOM2; + if (PLAYER1INPUTDOWN(gc_custom3)) + cmd->buttons |= BT_CUSTOM3; + // use with any button/key - if (PLAYER1INPUTDOWN(gc_use) && !(player->pflags & PF_MACESPIN)) + if (PLAYER1INPUTDOWN(gc_use)) cmd->buttons |= BT_USE; // Camera Controls @@ -1315,6 +1326,14 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) if (PLAYER2INPUTDOWN(gc_tossflag)) cmd->buttons |= BT_TOSSFLAG; + // Lua scriptable buttons + if (PLAYER2INPUTDOWN(gc_custom1)) + cmd->buttons |= BT_CUSTOM1; + if (PLAYER2INPUTDOWN(gc_custom2)) + cmd->buttons |= BT_CUSTOM2; + if (PLAYER2INPUTDOWN(gc_custom3)) + cmd->buttons |= BT_CUSTOM3; + // use with any button/key if (PLAYER2INPUTDOWN(gc_use)) cmd->buttons |= BT_USE; @@ -2645,8 +2664,10 @@ static void G_DoCompleted(void) gameaction = ga_nothing; - if (metalrecording || metalplayback) - G_CheckDemoStatus(); + if (metalplayback) + G_StopMetalDemo(); + if (metalrecording) + G_StopMetalRecording(); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -4200,7 +4221,7 @@ void G_ReadMetalTic(mobj_t *metal) UINT16 speed; UINT8 statetype; - if (!metal_p || !demo_start) + if (!metal_p || !metal_start) return; ziptic = READUINT8(metal_p); @@ -4289,7 +4310,7 @@ void G_ReadMetalTic(mobj_t *metal) if (*metal_p == DEMOMARKER) { // end of demo data stream - G_CheckDemoStatus(); + G_StopMetalDemo(); return; } } @@ -4396,7 +4417,7 @@ void G_WriteMetalTic(mobj_t *metal) // latest demos with mouse aiming byte in ticcmd if (demo_p >= demoend - 32) { - G_CheckDemoStatus(); // no more space + G_StopMetalRecording(); // no more space return; } } @@ -4871,6 +4892,7 @@ void G_DoPlayDemo(char *defdemoname) // didn't start recording right away. demo_start = false; + metal_start = false; #ifdef HAVE_BLUA LUAh_MapChange(); @@ -4916,6 +4938,7 @@ void G_DoPlayDemo(char *defdemoname) players[0].jumpfactor = jumpfactor; demo_start = true; + metal_start = true; } void G_AddGhost(char *defdemoname) @@ -5168,6 +5191,7 @@ void G_DoPlayMetal(void) if (!mo) { CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); + Z_Free(metalbuffer); return; } @@ -5215,18 +5239,46 @@ void G_DoneLevelLoad(void) =================== */ +// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist +void G_StopMetalDemo(void) +{ + + // Metal Sonic finishing doesn't end the game, dammit. + Z_Free(metalbuffer); + metalbuffer = NULL; + metalplayback = NULL; + metal_p = NULL; +} + +// Stops metal sonic recording. +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void) +{ + boolean saved = false; + if (demo_p) + { + UINT8 *p = demobuffer+16; // checksum position +#ifdef NOMD5 + UINT8 i; + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + for (i = 0; i < 16; i++, p++) + *p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. +#else + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file. +#endif + saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. + } + free(demobuffer); + metalrecording = false; + if (saved) + I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); + I_Error("Failed to save demo!"); +} + // reset engine variable set for the demos // called from stopdemo command, map command, and g_checkdemoStatus. void G_StopDemo(void) { - if (metalplayback) - { // Metal Sonic finishing doesn't end the game, dammit. - Z_Free(metalbuffer); - metalbuffer = NULL; - metalplayback = NULL; - if (!demoplayback) - return; - } Z_Free(demobuffer); demobuffer = NULL; demoplayback = false; @@ -5250,31 +5302,7 @@ boolean G_CheckDemoStatus(void) if(ghosts) // ... ... ... ghosts = NULL; // :) - if (metalrecording) - { - saved = false; - if (demo_p) - { - UINT8 *p = demobuffer+16; // checksum position -#ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. -#else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file. -#endif - saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. - } - free(demobuffer); - metalrecording = false; - if (saved) - I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); - else - I_Error("Failed to save demo!"); - return true; - } + // DO NOT end metal sonic demos here if (timingdemo) { @@ -5334,12 +5362,6 @@ boolean G_CheckDemoStatus(void) return true; } - if (metalplayback) - { - G_StopDemo(); - return false; - } - return false; } diff --git a/src/g_game.h b/src/g_game.h index d57b6ebd..af37fc8a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -37,12 +37,14 @@ extern boolean playeringame[MAXPLAYERS]; // demoplaying back and demo recording extern boolean demoplayback, titledemo, demorecording, timingdemo; -extern mobj_t *metalplayback; // Quit after playing a demo from cmdline. extern boolean singledemo; extern boolean demo_start; +extern mobj_t *metalplayback; +extern boolean metal_start; + // gametic at level start extern tic_t levelstarttic; @@ -150,6 +152,8 @@ void G_TimeDemo(const char *name); void G_AddGhost(char *defdemoname); void G_DoPlayMetal(void); void G_DoneLevelLoad(void); +void G_StopMetalDemo(void); +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); diff --git a/src/g_input.c b/src/g_input.c index 29d13dce..f8170dd3 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -989,6 +989,9 @@ static const char *gamecontrolname[num_gamecontrols] = "jump", "console", "pause", + "custom1", + "custom2", + "custom3", }; #define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t)) diff --git a/src/g_input.h b/src/g_input.h index 334b7ad9..699542a8 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -118,6 +118,9 @@ typedef enum gc_jump, gc_console, gc_pause, + gc_custom1, // Lua scriptable + gc_custom2, // Lua scriptable + gc_custom3, // Lua scriptable num_gamecontrols } gamecontrols_e; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 14f6d54a..96902c73 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1714,19 +1714,19 @@ static void HU_DrawCoopOverlay(void) #endif if (emeralds & EMERALD1) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)-32, V_TRANSLUCENT, emeraldpics[0]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)-32, 0, emeraldpics[0]); if (emeralds & EMERALD2) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)-16, V_TRANSLUCENT, emeraldpics[1]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[1]); if (emeralds & EMERALD3) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)+16, V_TRANSLUCENT, emeraldpics[2]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[2]); if (emeralds & EMERALD4) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)+32, V_TRANSLUCENT, emeraldpics[3]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)+32, 0, emeraldpics[3]); if (emeralds & EMERALD5) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)+16, V_TRANSLUCENT, emeraldpics[4]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[4]); if (emeralds & EMERALD6) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)-16, V_TRANSLUCENT, emeraldpics[5]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[5]); if (emeralds & EMERALD7) - V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3) , V_TRANSLUCENT, emeraldpics[6]); + V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3) , 0, emeraldpics[6]); } static void HU_DrawNetplayCoopOverlay(void) @@ -1741,7 +1741,7 @@ static void HU_DrawNetplayCoopOverlay(void) for (i = 0; i < 7; ++i) { if (emeralds & (1 << i)) - V_DrawScaledPatch(20 + (i * 20), 6, V_TRANSLUCENT, emeraldpics[i]); + V_DrawScaledPatch(20 + (i * 20), 6, 0, emeraldpics[i]); } } diff --git a/src/info.c b/src/info.c index e69d84f0..d0ba598b 100644 --- a/src/info.c +++ b/src/info.c @@ -4817,10 +4817,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset - 100, // mass + 20*TICRATE, // mass 48*FRACUNIT, // damage sfx_s3k5d, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_BOUNCE, // flags + MF_NOBLOCKMAP|MF_MISSILE|MF_BOUNCE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -11936,7 +11936,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 6*TICRATE, // mass (<-- Looking for the Grenade Ring's fuse? It's right here!) 1, // damage sfx_s3k5d, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_BOUNCE, // flags + MF_NOBLOCKMAP|MF_MISSILE|MF_BOUNCE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 47bd4370..38b06961 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -195,6 +195,15 @@ static int patch_set(lua_State *L) // lib_draw // +static int libd_patchExists(lua_State *L) +{ + if (!hud_running) + return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!"); + + lua_pushboolean(L, W_CheckNumForName(luaL_checkstring(L, 1)) != LUMPERROR); + return 1; +} + static int libd_cachePatch(lua_State *L) { if (!hud_running) @@ -342,6 +351,7 @@ static int libd_stringWidth(lua_State *L) } static luaL_Reg lib_draw[] = { + {"patchExists", libd_patchExists}, {"cachePatch", libd_cachePatch}, {"draw", libd_draw}, {"drawScaled", libd_drawScaled}, diff --git a/src/m_menu.c b/src/m_menu.c index 0676bb52..30876cbc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1037,6 +1037,10 @@ static menuitem_t OP_CameraControlsMenu[] = static menuitem_t OP_MiscControlsMenu[] = { + {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 }, + {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 }, + {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 }, + {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause }, {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console }, }; @@ -3764,8 +3768,8 @@ static void M_Options(INT32 choice) // if the player is not admin or server, disable server options OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); - // if the player is playing _at all_, disable data options - OP_MainMenu[3].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + // if the player is playing _at all_, disable the erase data options + OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); @@ -5709,7 +5713,7 @@ static void M_DrawConnectMenu(void) // Room name if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, ""); + V_YELLOWMAP, (itemOn == mp_connect_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); @@ -6560,8 +6566,9 @@ static void M_Setup1PControlsMenu(INT32 choice) OP_MPControlsMenu[0].status = IT_CALL|IT_STRING2; OP_MPControlsMenu[1].status = IT_CALL|IT_STRING2; OP_MPControlsMenu[2].status = IT_CALL|IT_STRING2; - // Unhide the entire misc menu - OP_ControlListMenu[3].status = IT_SUBMENU | IT_STRING; + // Unide the pause/console controls too + OP_MiscControlsMenu[3].status = IT_CALL|IT_STRING2; + OP_MiscControlsMenu[4].status = IT_CALL|IT_STRING2; OP_ControlListDef.prevMenu = &OP_P1ControlsDef; M_SetupNextMenu(&OP_ControlListDef); @@ -6578,8 +6585,9 @@ static void M_Setup2PControlsMenu(INT32 choice) OP_MPControlsMenu[0].status = IT_GRAYEDOUT2; OP_MPControlsMenu[1].status = IT_GRAYEDOUT2; OP_MPControlsMenu[2].status = IT_GRAYEDOUT2; - // Hide the entire misc menu - OP_ControlListMenu[3].status = IT_GRAYEDOUT; + // Hide the pause/console controls too + OP_MiscControlsMenu[3].status = IT_GRAYEDOUT2; + OP_MiscControlsMenu[4].status = IT_GRAYEDOUT2; OP_ControlListDef.prevMenu = &OP_P2ControlsDef; M_SetupNextMenu(&OP_ControlListDef); diff --git a/src/p_inter.c b/src/p_inter.c index 03ad7c46..398ad493 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1861,7 +1861,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if (target->player && !target->player->spectator) { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! - G_CheckDemoStatus(); + G_StopMetalRecording(); #ifdef CHAOSISNOTDEADYET if (gametype == GT_CHAOS) target->player->score /= 2; // Halve the player's score in Chaos Mode diff --git a/src/p_mobj.c b/src/p_mobj.c index b973c6cc..a7dc363f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1669,16 +1669,21 @@ static boolean P_ZMovement(mobj_t *mo) // another to prevent them from turning into hockey pucks. // I'm sorry in advance. -SH // PS: Oh, and Brak's napalm bombs too, now. - if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) + if (mo->flags & MF_GRENADEBOUNCE) { - if (mo->momz <= 0) + // Going down? (Or up in reverse gravity?) + if (mo->momz*P_MobjFlip(mo) < 0) { - if (mo->momz >= -FixedMul(FRACUNIT, mo->scale)) + // If going slower than a fracunit, just stop. + if (abs(mo->momz) < FixedMul(FRACUNIT, mo->scale)) { mo->momx = mo->momy = mo->momz = 0; - if (mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) - P_SetMobjState(mo, mo->info->deathstate); + + // Napalm hack + if (mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE && mo->fuse) + mo->fuse = 1; } + // Otherwise bounce up at half speed. else mo->momz = -FixedMul(mo->momz, FRACUNIT/2); S_StartSound(mo, mo->info->activesound); @@ -4595,7 +4600,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // This is below threshold because we don't want to bob while zipping around // Ohh you're in for it now.. - if (mobj->flags2 & MF2_FRET && mobj->health <= 3) + if (mobj->flags2 & MF2_FRET && mobj->health <= mobj->info->damage) mobj->fuse = 0; // reactiontime is used for delays. @@ -4657,11 +4662,13 @@ static void P_Boss9Thinker(mobj_t *mobj) case 1: { // Okay, we're up? Good, time to gather energy... - if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) + if (mobj->health > mobj->info->damage) + { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); - } else + } + else P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); mobj->fuse = 4*TICRATE; mobj->flags |= MF_PAIN; @@ -4673,8 +4680,12 @@ static void P_Boss9Thinker(mobj_t *mobj) case 2: // We're all charged and ready now! Unleash the fury!! - P_RemoveMobj(mobj->tracer); - P_SetTarget(&mobj->tracer, mobj->hnext); + if (mobj->health > mobj->info->damage) + { + mobj_t *removemobj = mobj->tracer; + P_SetTarget(&mobj->tracer, mobj->hnext); + P_RemoveMobj(removemobj); + } if (mobj->health <= mobj->info->damage) { // Attack 1: Pinball dash! if (mobj->health == 1) @@ -6483,6 +6494,7 @@ void P_MobjThinker(mobj_t *mobj) { // gargoyle and snowman handled in P_PushableThinker, not here case MT_THROWNGRENADE: + case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: P_SetMobjState(mobj, mobj->info->deathstate); break; case MT_BLUEFLAG: @@ -7231,6 +7243,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) #endif switch (mobj->type) { + case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: + mobj->fuse = mobj->info->mass; case MT_BLACKEGGMAN: { mobj_t *spawn = P_SpawnMobj(mobj->x, mobj->z, mobj->z+mobj->height-16*FRACUNIT, MT_BLACKEGGMAN_HELPER); @@ -9445,7 +9459,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) boolean P_CheckMissileSpawn(mobj_t *th) { // move a little forward so an angle can be computed if it immediately explodes - if (th->type != MT_THROWNGRENADE) // hack: bad! should be a flag. + if (th->flags & MF_GRENADEBOUNCE) // hack: bad! should be a flag. { th->x += th->momx>>1; th->y += th->momy>>1; diff --git a/src/p_mobj.h b/src/p_mobj.h index 84d22301..6d120c47 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -156,9 +156,11 @@ typedef enum // for chase camera, don't be blocked by things (partial clipping) // (need comma at end of this for SOC editor) MF_NOCLIPTHING = 1<<27, + // Missile bounces like a grenade. + MF_GRENADEBOUNCE = 1<<28, // Run the action thinker on spawn. - MF_RUNSPAWNFUNC = 1<<28, - // free: to and including 1<<31 + MF_RUNSPAWNFUNC = 1<<29, + // free: 1<<30 and 1<<31 } mobjflag_t; typedef enum diff --git a/src/p_setup.c b/src/p_setup.c index 25bcd0d5..9b32d4a0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2315,7 +2315,7 @@ boolean P_SetupLevel(boolean skipprecip) cv_debug = botskin = 0; if (metalplayback) - G_StopDemo(); + G_StopMetalDemo(); // Clear CECHO messages HU_ClearCEcho(); diff --git a/src/p_user.c b/src/p_user.c index ac026a11..d5c17e00 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3178,12 +3178,26 @@ static void P_DoSuperStuff(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_STND); P_RestoreMusic(player); P_SpawnShieldOrb(player); + + // Restore color + if (player->powers[pw_shield] & SH_FIREFLOWER) + { + player->mo->color = SKINCOLOR_WHITE; + G_GhostAddColor(GHC_FIREFLOWER); + } + else + { + player->mo->color = player->skincolor; + G_GhostAddColor(GHC_NORMAL); + } + if (gametype != GT_COOP) { HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); } + return; } // Deplete one ring every second while super @@ -3200,7 +3214,7 @@ static void P_DoSuperStuff(player_t *player) G_GhostAddColor(GHC_SUPER); // Ran out of rings while super! - if ((player->powers[pw_super]) && (player->health <= 1 || player->exiting)) + if (player->powers[pw_super] && (player->health <= 1 || player->exiting)) { player->powers[pw_emeralds] = 0; // lost the power stones P_SpawnGhostMobj(player->mo); @@ -9194,7 +9208,7 @@ void P_PlayerAfterThink(player_t *player) } } } - else if ((player->pflags & PF_MACESPIN) && player->mo->tracer) + else if ((player->pflags & PF_MACESPIN) && player->mo->tracer && player->mo->tracer->target) { player->mo->height = P_GetPlayerSpinHeight(player); // tracer is what you're hanging onto.... @@ -9214,11 +9228,6 @@ void P_PlayerAfterThink(player_t *player) if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? { - if (cmd->buttons & BT_USE) // do we actually still want this? - { - player->mo->tracer->target->health += 50; - player->mo->angle += 50< ANGLE_MAX - } player->mo->tracer->target->health += cmd->sidemove; player->mo->angle += cmd->sidemove< ANGLE_MAX diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 9c0f521f..1e03edd8 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2278,8 +2278,12 @@ void I_Quit(void) G_SaveGameData(); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. - if (demorecording || metalrecording) + + if (demorecording) G_CheckDemoStatus(); + if (metalrecording) + G_StopMetalRecording(); + D_QuitNetGame(); I_ShutdownMusic(); I_ShutdownSound(); @@ -2431,8 +2435,10 @@ void I_Error(const char *error, ...) G_SaveGameData(); // Tails 12-08-2002 // Shutdown. Here might be other errors. - if (demorecording || metalrecording) + if (demorecording) G_CheckDemoStatus(); + if (metalrecording) + G_StopMetalRecording(); D_QuitNetGame(); I_ShutdownMusic(); diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index f31b8b1c..efb0be46 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -665,8 +665,10 @@ void I_Error(const char *error, ...) // save demo, could be useful for debug // NOTE: demos are normally not saved here. - if (demorecording || metalrecording) + if (demorecording) G_CheckDemoStatus(); + if (metalrecording) + G_StopMetalRecording(); D_QuitNetGame(); @@ -749,8 +751,10 @@ void I_Quit(void) DWORD mode; // when recording a demo, should exit using 'q', // but sometimes we forget and use Alt+F4, so save here too. - if (demorecording || metalrecording) + if (demorecording) G_CheckDemoStatus(); + if (metalrecording) + G_StopMetalRecording(); M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET From fdc27ca720ea2f18ac2c7b778341203baeacbb06 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 23 Mar 2014 12:05:33 -0400 Subject: [PATCH 18/19] bump readme.txt --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index aa25ef0f..14d9c92e 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Here it is! SRB2 v2.1.4 source code! +Here it is! SRB2 v2.1.5 source code! Win32 with Visual C (6SP6+Processor Pack OR 7) From bb6688107b4e8e0ffee9a5491377415bd84cac0c Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 23 Mar 2014 12:06:07 -0400 Subject: [PATCH 19/19] bump Srb2mac project --- src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index dfe755af..fdda1c58 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.4; + CURRENT_PROJECT_VERSION = 2.1.5; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.4; + CURRENT_PROJECT_VERSION = 2.1.5; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = (