From b6ab552a702dc20a1019ec6a8c34c809cea44944 Mon Sep 17 00:00:00 2001 From: NepDisk <16447892+NepDisk@users.noreply.github.com> Date: Sat, 16 Nov 2024 21:18:06 -0500 Subject: [PATCH 01/21] Fix Spring angle Yes this is duped code but I can't be assed to figure out why the previous broke shit --- src/p_map.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index c5acbf738..2dba4a244 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -289,7 +289,6 @@ P_DoSpringEx // mass = vertical speed // damage = horizontal speed // raisestate = state to change spring to on collision -// painchance = star effect color // boolean P_DoSpring(mobj_t *spring, mobj_t *object) { @@ -348,7 +347,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) P_TryMove(object, spring->x + offx, spring->y + offy, true, NULL); } - P_DoSpringEx(object, mapobjectscale, vertispeed, horizspeed, spring->angle); + if (vertispeed) + object->momz = FixedMul(vertispeed,FixedSqrt(FixedMul(vscale, spring->scale))); + + if (horizspeed) + { + if (!object->player) + P_InstaThrust(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(hscale, spring->scale)))); + else + { + fixed_t finalSpeed = FixedDiv(horizspeed, hscale); + fixed_t pSpeed = object->player->speed; + + if (pSpeed > finalSpeed) + finalSpeed = pSpeed; + + P_InstaThrust(object, spring->angle, FixedMul(finalSpeed,FixedSqrt(FixedMul(hscale, spring->scale)))); + } + } + // Re-solidify spring->flags |= (spring->info->flags & (MF_SPECIAL|MF_SOLID)); @@ -374,7 +391,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) return true; } - static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) { player_t *p = object->player; // will be NULL if not a player From ea3f3a718ca71dc313dd148987e094390a8af1a1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 3 Nov 2022 08:47:44 -0400 Subject: [PATCH 02/21] Add V_VFLIP Ironman can now be shitty --- src/deh_tables.c | 1 + src/hardware/hw_draw.c | 17 ++++++++++++++--- src/v_video.c | 41 +++++++++++++++++++++++++++-------------- src/v_video.h | 9 ++++++--- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5dcef079b..eb2143577 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1252,6 +1252,7 @@ struct int_const_s const INT_CONST[] = { {"V_OVERLAY",V_OVERLAY}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, {"V_FLIP",V_FLIP}, + {"V_VFLIP",V_VFLIP}, {"V_SNAPTOTOP",V_SNAPTOTOP}, {"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM}, {"V_SNAPTOLEFT",V_SNAPTOLEFT}, diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ca2881921..008838178 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -188,7 +188,10 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p offsetx = (float)(gpatch->leftoffset) * fscalew; // top offset - offsety = (float)(gpatch->topoffset) * fscaleh; + if (option & V_VFLIP) + offsety = (float)(gpatch->height - gpatch->topoffset) * fscaleh; + else + offsety = (float)(gpatch->topoffset) * fscaleh; cx -= offsetx; cy -= offsety; @@ -249,8 +252,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p v[2].s = v[1].s = hwrPatch->max_s; } - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; + if (option & V_VFLIP) + { + v[0].t = v[1].t = hwrPatch->max_t; + v[2].t = v[3].t = 0.0f; + } + else + { + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = hwrPatch->max_t; + } flags = PF_NoDepthTest; diff --git a/src/v_video.c b/src/v_video.c index 8b96fa0b6..50979f8d6 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -627,10 +627,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca colfrac = FixedDiv(FRACUNIT, fdup); rowfrac = FixedDiv(FRACUNIT, vdup); - // So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible - // For now let's just at least give V_OFFSET the ability to support V_FLIP - // I'll probably make a better fix for 2.2 where I don't have to worry about breaking existing support for stuff - // -- Monster Iestyn 29/10/18 { fixed_t offsetx = 0, offsety = 0; @@ -641,15 +637,17 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca offsetx = FixedMul(patch->leftoffset<topoffset<height - patch->topoffset)<topoffset<= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); while (column->topdelta != 0xff) @@ -717,17 +716,31 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca topdelta += prevdelta; prevdelta = topdelta; source = (const UINT8 *)(column) + 3; + dest = desttop; if (scrn & V_FLIP) - dest = deststart + (destend - desttop); + dest = deststart + (destend - dest); dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + if (scrn & V_VFLIP) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); } } @@ -786,7 +799,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ y -= FixedMul(patch->topoffset<leftoffset<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } diff --git a/src/v_video.h b/src/v_video.h index 4aad49de2..8dbe029ff 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -85,11 +85,14 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_GetColor(color) (pLocalPalette[color&0xFF]) #define V_GetMasterColor(color) (pMasterPalette[color&0xFF]) -// Bottom 8 bits are used for parameter (screen or character) +// Bottom 8 bits are used for parameter (character) #define V_PARAMMASK 0x000000FF -// strings/characters only -#define V_STRINGDANCE 0x00000002 +// Bottom bit is used for screen (patches) +#define V_SCREENMASK 0x0000000F + +#define V_STRINGDANCE 0x00000002 // (strings/characters only) funny undertale +#define V_VFLIP 0x00000010 // (patches only) Vertical flip // flags hacked in scrn (not supported by all functions (see src)) // patch scaling uses bits 9 and 10 From 11608cd1b7f2bf438d6d88c35688b84a69642d9b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 11 Dec 2022 13:53:51 -0500 Subject: [PATCH 03/21] Clipping rectangle Instead of the absolute insanity that is V_DrawCroppedPatch, which makes you specify the number of pixels to crop off the top/left and then the number of pixels to show after the crop ... you just use V_SetClipRect to create a rectangle for any future draws to be cropped down to, and V_ClearClipRect afterwards to clear it. Currently only supported by V_DrawStretchyFixedPatch. Ideally other drawing functions should also receive clipping rectangle support too. --- src/hardware/hw_draw.c | 6 +- src/k_hud.c | 114 +----------- src/k_hud.h | 2 - src/typedef.h | 1 + src/v_video.c | 381 ++++++++++++++++++++++++++++------------- src/v_video.h | 13 ++ 6 files changed, 286 insertions(+), 231 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 008838178..ff58f05f3 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -207,7 +207,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p INT32 intx, inty; intx = (INT32)cx; inty = (INT32)cy; - K_AdjustXYWithSnap(&intx, &inty, option, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, option, dupx, dupy); cx = (float)intx; cy = (float)inty; } @@ -1011,7 +1011,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 intx = (INT32)fx; inty = (INT32)fy; - K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); fx = (float)intx; fy = (float)inty; } @@ -1103,7 +1103,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) intx = (INT32)fx; inty = (INT32)fy; - K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); fx = (float)intx; fy = (float)inty; } diff --git a/src/k_hud.c b/src/k_hud.c index 5da4c25ed..177b4a9b2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -620,116 +620,6 @@ INT32 ITEM2_X, ITEM2_Y; INT32 LAPS2_X, LAPS2_Y; INT32 POSI2_X, POSI2_Y; -void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy) -{ - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx - INT32 screenwidth = vid.width; - INT32 screenheight = vid.height; - INT32 basewidth = BASEVIDWIDTH * dupx; - INT32 baseheight = BASEVIDHEIGHT * dupy; - SINT8 player = -1; - UINT8 i; - - if (options & V_SPLITSCREEN) - { - if (r_splitscreen > 0) - { - screenheight /= 2; - baseheight /= 2; - } - - if (r_splitscreen > 1) - { - screenwidth /= 2; - basewidth /= 2; - } - } - - for (i = 0; i <= r_splitscreen; i++) - { - if (stplyr == &players[displayplayers[i]]) - { - player = i; - break; - } - } - - if (vid.width != (BASEVIDWIDTH * dupx)) - { - if (options & V_SNAPTORIGHT) - *x += (screenwidth - basewidth); - else if (!(options & V_SNAPTOLEFT)) - *x += (screenwidth - basewidth) / 2; - } - - if (vid.height != (BASEVIDHEIGHT * dupy)) - { - if (options & V_SNAPTOBOTTOM) - *y += (screenheight - baseheight); - else if (!(options & V_SNAPTOTOP)) - *y += (screenheight - baseheight) / 2; - } - - if (options & V_SPLITSCREEN) - { - if (r_splitscreen == 1) - { - if (player == 1) - *y += screenheight; - } - else if (r_splitscreen > 1) - { - if (player == 1 || player == 3) - *x += screenwidth; - - if (player == 2 || player == 3) - *y += screenheight; - } - } - - if (options & V_SLIDEIN) - { - const tic_t length = TICRATE/4; - tic_t timer = lt_exitticker; - if (bossinfo.boss == true) - { - if (leveltime <= 3) - timer = 0; - else - timer = leveltime-3; - } - - if (timer < length) - { - boolean slidefromright = false; - - const INT32 offsetAmount = (screenwidth * FRACUNIT/2) / length; - fixed_t offset = (screenwidth * FRACUNIT/2) - (timer * offsetAmount); - - offset += FixedMul(offsetAmount, renderdeltatics); - offset /= FRACUNIT; - - if (r_splitscreen > 1) - { - if (stplyr == &players[displayplayers[1]] || stplyr == &players[displayplayers[3]]) - slidefromright = true; - } - - if (options & V_SNAPTORIGHT) - slidefromright = true; - else if (options & V_SNAPTOLEFT) - slidefromright = false; - - if (slidefromright == true) - { - offset = -offset; - } - - *x -= offset; - } - } -} - // This version of the function was prototyped in Lua by Nev3r ... a HUGE thank you goes out to them! void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean reverse) { @@ -1269,6 +1159,8 @@ static void K_drawKartItem(void) V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); + V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); + // Then, the numbers: if (stplyr->itemamount >= numberdisplaymin && !stplyr->itemroulette) { @@ -1288,6 +1180,8 @@ static void K_drawKartItem(void) else V_DrawFixedPatch(fx< 0) + { + screenheight /= 2; + baseheight /= 2; + } + + if (r_splitscreen > 1) + { + screenwidth /= 2; + basewidth /= 2; + } + } + + for (i = 0; i <= r_splitscreen; i++) + { + if (stplyr == &players[displayplayers[i]]) + { + player = i; + break; + } + } + + if (vid.width != (BASEVIDWIDTH * dupx)) + { + if (options & V_SNAPTORIGHT) + *x += (screenwidth - basewidth); + else if (!(options & V_SNAPTOLEFT)) + *x += (screenwidth - basewidth) / 2; + } + + if (vid.height != (BASEVIDHEIGHT * dupy)) + { + if (options & V_SNAPTOBOTTOM) + *y += (screenheight - baseheight); + else if (!(options & V_SNAPTOTOP)) + *y += (screenheight - baseheight) / 2; + } + + if (options & V_SPLITSCREEN) + { + if (r_splitscreen == 1) + { + if (player == 1) + *y += screenheight; + } + else if (r_splitscreen > 1) + { + if (player == 1 || player == 3) + *x += screenwidth; + + if (player == 2 || player == 3) + *y += screenheight; + } + } + + if (options & V_SLIDEIN) + { + const tic_t length = TICRATE/4; + tic_t timer = lt_exitticker; + if (bossinfo.boss == true) + { + if (leveltime <= 3) + timer = 0; + else + timer = leveltime-3; + } + + if (timer < length) + { + boolean slidefromright = false; + + const INT32 offsetAmount = (screenwidth * FRACUNIT/2) / length; + fixed_t offset = (screenwidth * FRACUNIT/2) - (timer * offsetAmount); + + offset += FixedMul(offsetAmount, renderdeltatics); + offset /= FRACUNIT; + + if (r_splitscreen > 1) + { + if (stplyr == &players[displayplayers[1]] || stplyr == &players[displayplayers[3]]) + slidefromright = true; + } + + if (options & V_SNAPTORIGHT) + slidefromright = true; + else if (options & V_SNAPTOLEFT) + slidefromright = false; + + if (slidefromright == true) + { + offset = -offset; + } + + *x -= offset; + } + } +} + +static cliprect_t cliprect; + +cliprect_t *V_GetClipRect(void) +{ + if (cliprect.enabled == false) + { + return NULL; + } + + return &cliprect; +} + +void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) +{ + // Adjust position. + if (!(flags & V_NOSCALESTART)) + { + fixed_t dupx = vid.dupx; + fixed_t dupy = vid.dupy; + + if (flags & V_SCALEPATCHMASK) + { + switch ((flags & V_SCALEPATCHMASK) >> 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; + } + } + + dupx = dupy = (dupx < dupy ? dupx : dupy); + + x = FixedMul(x, dupx); + y = FixedMul(y, dupy); + w = FixedMul(w, dupx); + h = FixedMul(h, dupy); + + if (!(flags & V_SCALEPATCHMASK)) + { + V_AdjustXYWithSnap(&x, &y, flags, dupx, dupy); + } + } + + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if (x > vid.width) + { + x = vid.width; + w = 0; + } + + if (y > vid.height) + { + y = vid.height; + h = 0; + } + + cliprect.l = x; + cliprect.t = y; + cliprect.r = x + w; + cliprect.b = y + h; + cliprect.flags = flags; + cliprect.enabled = true; + + /* + V_DrawFill(cliprect.l, cliprect.t, cliprect.r - cliprect.l, cliprect.b - cliprect.t, V_NOSCALESTART); + CONS_Printf("[(%d, %d), (%d, %d)]\n", cliprect.l, cliprect.t, cliprect.r, cliprect.b); + */ +} + +void V_ClearClipRect(void) +{ + cliprect.enabled = false; +} + 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}; @@ -562,6 +768,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t pwidth; // patch width fixed_t offx = 0; // x offset + cliprect_t *const clip = V_GetClipRect(); + if (rendermode == render_none) return; @@ -670,7 +878,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // Center it if necessary if (!(scrn & V_SCALEPATCHMASK)) { - K_AdjustXYWithSnap(&x, &y, scrn, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, scrn, dupx, dupy); } desttop += (y*vid.width) + x; @@ -692,18 +900,19 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++) { INT32 topdelta, prevdelta = -1; + if (scrn & V_FLIP) // offx is measured from right edge instead of left { - if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+pwidth-offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { - if (x+offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) break; } @@ -711,6 +920,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca while (column->topdelta != 0xff) { + fixed_t offy = 0; + topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; @@ -720,23 +931,60 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca dest = desttop; if (scrn & V_FLIP) dest = deststart + (destend - dest); - dest += FixedInt(FixedMul(topdelta<length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac) + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) { + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->t) // don't draw off the top of the clip rect + { + dest += vid.width; + continue; + } + + if (cy > clip->b) // don't draw off the bottom of the clip rect + { + dest += vid.width; + continue; + } + } + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; } } else { - for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac) + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) { + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->t) // don't draw off the top of the clip rect + { + dest += vid.width; + continue; + } + + if (cy > clip->b) // don't draw off the bottom of the clip rect + { + dest += vid.width; + continue; + } + } + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; } } @@ -749,115 +997,16 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // Draws a patch cropped and scaled to arbitrary size. 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) { - UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); - UINT32 alphalevel, blendmode; - // boolean flip = false; + cliprect_t oldClip = cliprect; - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *deststop; + V_SetClipRect(x, y, w, h, scrn); - if (rendermode == render_none) - return; + x -= sx; + y -= sy; -#ifdef HWRENDER - //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode == render_opengl) - { - HWR_DrawCroppedPatch(patch,x,y,pscale,scrn,sx,sy,w,h); - return; - } -#endif + V_DrawStretchyFixedPatch(x, y, pscale, pscale, scrn, patch, NULL); - patchdrawfunc = standardpdraw; - - if ((blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT))) - blendmode++; // realign to constants - if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) - { - if (alphalevel == 10) // V_HUDTRANSHALF - alphalevel = hudminusalpha[st_translucency]; - else if (alphalevel == 11) // V_HUDTRANS - alphalevel = 10 - st_translucency; - else if (alphalevel == 12) // V_HUDTRANSDOUBLE - alphalevel = hudplusalpha[st_translucency]; - - if (alphalevel >= 10) // Still inelegible to render? - return; - } - if ((v_translevel = R_GetBlendTable(blendmode, alphalevel))) - patchdrawfunc = translucentpdraw; - - // only use one dup, to avoid stretching (har har) - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset<leftoffset<>= FRACBITS; - y >>= FRACBITS; - desttop += (y*vid.width) + x; - } - else - { - x = FixedMul(x,dupx<>= FRACBITS; - y >>= FRACBITS; - - // Center it if necessary - // adjustxy - - desttop += (y*vid.width) + x; - } - - for (col = sx<>FRACBITS) < patch->width && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++) - { - INT32 topdelta, prevdelta = -1; - if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) - continue; - if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) - break; - column = (const column_t *)((const UINT8 *)(patch->columns) + (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 (topdelta-sy > 0) - { - dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) - { - if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + cliprect = oldClip; } // @@ -956,7 +1105,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h *= dupy; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) @@ -1083,7 +1232,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h *= dupy; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) @@ -1170,7 +1319,7 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) wh *= dupx; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) diff --git a/src/v_video.h b/src/v_video.h index 8dbe029ff..a88681846 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -171,6 +171,19 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_NOSCALESTART 0x40000000 // don't scale x, y, start coords #define V_SPLITSCREEN 0x80000000 // Add half of screen width or height automatically depending on player number +void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy); + +struct cliprect_t +{ + fixed_t l, r, t, b; + INT32 flags; + boolean enabled; +}; + +cliprect_t *V_GetClipRect(void); +void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags); +void V_ClearClipRect(void); + // defines for old functions #define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)< Date: Sun, 11 Dec 2022 14:02:48 -0500 Subject: [PATCH 04/21] Comment out test case --- src/k_hud.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 177b4a9b2..5804bcc5d 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1159,7 +1159,7 @@ static void K_drawKartItem(void) V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); - V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); + //V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); // Then, the numbers: if (stplyr->itemamount >= numberdisplaymin && !stplyr->itemroulette) @@ -1180,7 +1180,7 @@ static void K_drawKartItem(void) else V_DrawFixedPatch(fx< Date: Sun, 11 Dec 2022 14:14:12 -0500 Subject: [PATCH 05/21] Clear clipping rectangle before each hook call Prevents Lua from being able to make a mess. --- src/d_main.cpp | 3 +++ src/lua_hooklib.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index 1ae89e800..e3a492cf5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -371,6 +371,9 @@ static bool D_Display(void) if (dedicated) //bail out after wipe logic return false; + // Catch runaway clipping rectangles. + V_ClearClipRect(); + // do buffered drawing switch (gamestate) { diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index f186ccabf..f1439c889 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -27,6 +27,8 @@ #include "d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetPreciseTime +#include "v_video.h" // V_ClearClipRect + /* ========================================================================= ABSTRACTION ========================================================================= */ @@ -672,8 +674,13 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) hud_interpcounter = 0; hud_running = true; // local hook + + // Catch runaway clipping rectangles. + V_ClearClipRect(); + init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); + hud_running = false; } } From 34fc4066d7a7845e76051ff6f9be0a96aaf31eac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 11 Dec 2022 16:47:25 -0500 Subject: [PATCH 06/21] Prevent modifying cliprect, wordier vars --- src/v_video.c | 28 ++++++++++++++-------------- src/v_video.h | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 43f524e68..0583a96fa 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -638,7 +638,7 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du static cliprect_t cliprect; -cliprect_t *V_GetClipRect(void) +const cliprect_t *V_GetClipRect(void) { if (cliprect.enabled == false) { @@ -713,10 +713,10 @@ void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) h = 0; } - cliprect.l = x; - cliprect.t = y; - cliprect.r = x + w; - cliprect.b = y + h; + cliprect.left = x; + cliprect.top = y; + cliprect.right = x + w; + cliprect.bottom = y + h; cliprect.flags = flags; cliprect.enabled = true; @@ -768,7 +768,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t pwidth; // patch width fixed_t offx = 0; // x offset - cliprect_t *const clip = V_GetClipRect(); + const cliprect_t *clip = V_GetClipRect(); if (rendermode == render_none) return; @@ -903,16 +903,16 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (scrn & V_FLIP) // offx is measured from right edge instead of left { - if (x+pwidth-offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+pwidth-offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { - if (x+offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) break; } @@ -942,13 +942,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { const INT32 cy = y + topdelta - offy; - if (cy < clip->t) // don't draw off the top of the clip rect + if (cy < clip->top) // don't draw off the top of the clip rect { dest += vid.width; continue; } - if (cy > clip->b) // don't draw off the bottom of the clip rect + if (cy > clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; @@ -969,13 +969,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { const INT32 cy = y + topdelta + offy; - if (cy < clip->t) // don't draw off the top of the clip rect + if (cy < clip->top) // don't draw off the top of the clip rect { dest += vid.width; continue; } - if (cy > clip->b) // don't draw off the bottom of the clip rect + if (cy > clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; diff --git a/src/v_video.h b/src/v_video.h index a88681846..1bd2eb822 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -175,12 +175,12 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du struct cliprect_t { - fixed_t l, r, t, b; + fixed_t left, right, top, bottom; INT32 flags; boolean enabled; }; -cliprect_t *V_GetClipRect(void); +const cliprect_t *V_GetClipRect(void); void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags); void V_ClearClipRect(void); From bdb7d5c6a053c3dc50598e9bacd8839230d2473f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Dec 2022 17:43:11 -0800 Subject: [PATCH 07/21] Fix off-by-one when clipping rectangle bottom --- src/v_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 0583a96fa..709bf489d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -948,7 +948,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca continue; } - if (cy > clip->bottom) // don't draw off the bottom of the clip rect + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; @@ -975,7 +975,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca continue; } - if (cy > clip->bottom) // don't draw off the bottom of the clip rect + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; From 81978cd7f1a4db9a06d2fd7c404ef0b4c4cc3be1 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Dec 2022 17:44:49 -0800 Subject: [PATCH 08/21] OpenGL: clipping support for HWR_DrawStretchyFixedPatch --- src/hardware/hw_draw.c | 56 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ff58f05f3..e79860261 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -145,6 +145,11 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p // 0--1 float dupx, dupy, fscalew, fscaleh, fwidth, fheight; + const cliprect_t *clip = V_GetClipRect(); + + float s_min, s_max; + float t_min, t_max; + // make patch ready in hardware cache if (!colormap) HWR_GetPatch(gpatch); @@ -224,6 +229,41 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p fheight = (float)(gpatch->height) * dupy; } + s_min = t_min = 0.0f; + s_max = hwrPatch->max_s; + t_max = hwrPatch->max_t; + + if (clip) + { + if (cx < clip->left) + { + s_min = ((clip->left - cx) / fwidth) * s_max; + cx = clip->left; + } + + if (cy < clip->top) + { + t_min = ((clip->top - cy) / fheight) * t_max; + cy = clip->top; + } + + if ((cx + fwidth) > clip->right) + { + const float n = (clip->right - clip->left); + + s_max = (s_min + ((n / fwidth) * s_max)); + fwidth = n; + } + + if ((cy + fheight) > clip->bottom) + { + const float n = (clip->bottom - clip->top); + + t_max = (t_min + ((n / fheight) * t_max)); + fheight = n; + } + } + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 cx = -1.0f + (cx / (vid.width / 2.0f)); cy = 1.0f - (cy / (vid.height / 2.0f)); @@ -243,24 +283,24 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if (option & V_FLIP) { - v[0].s = v[3].s = hwrPatch->max_s; - v[2].s = v[1].s = 0.0f; + v[0].s = v[3].s = s_max; + v[2].s = v[1].s = s_min; } else { - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; + v[0].s = v[3].s = s_min; + v[2].s = v[1].s = s_max; } if (option & V_VFLIP) { - v[0].t = v[1].t = hwrPatch->max_t; - v[2].t = v[3].t = 0.0f; + v[0].t = v[1].t = t_max; + v[2].t = v[3].t = t_min; } else { - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; + v[0].t = v[1].t = t_min; + v[2].t = v[3].t = t_max; } flags = PF_NoDepthTest; From c797b3bff5d2b93e10535783417464a52cccdbdb Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Dec 2022 18:38:40 -0800 Subject: [PATCH 09/21] opengl: fix bottom and right edge of clip rect --- src/hardware/hw_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index e79860261..76cc2e289 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -249,7 +249,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if ((cx + fwidth) > clip->right) { - const float n = (clip->right - clip->left); + const float n = (clip->right - cx); s_max = (s_min + ((n / fwidth) * s_max)); fwidth = n; @@ -257,7 +257,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if ((cy + fheight) > clip->bottom) { - const float n = (clip->bottom - clip->top); + const float n = (clip->bottom - cy); t_max = (t_min + ((n / fheight) * t_max)); fheight = n; From d4f54fa28e09cdda4310dbe5b317c4f1f1d01591 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 25 Mar 2024 17:34:53 -0700 Subject: [PATCH 10/21] Legacy GL: fix cliprect in top/left - UV were not adjusted correctly when clipped in the top/left. - Code is more plainly written. --- src/hardware/hw_draw.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 76cc2e289..50655f6aa 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -235,33 +235,39 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if (clip) { - if (cx < clip->left) + float cx1 = cx; + float cy1 = cy; + float cx2 = cx + fwidth; + float cy2 = cy + fheight; + + if (cx1 < clip->left) { - s_min = ((clip->left - cx) / fwidth) * s_max; - cx = clip->left; + s_min = (clip->left - cx1) / fwidth * hwrPatch->max_s; + cx1 = clip->left; } - if (cy < clip->top) + if (cy1 < clip->top) { - t_min = ((clip->top - cy) / fheight) * t_max; - cy = clip->top; + t_min = (clip->top - cy1) / fheight * hwrPatch->max_t; + cy1 = clip->top; } - if ((cx + fwidth) > clip->right) + if (cx2 > clip->right) { - const float n = (clip->right - cx); - - s_max = (s_min + ((n / fwidth) * s_max)); - fwidth = n; + s_max = s_min + (clip->right - cx1) / fwidth * hwrPatch->max_s; + cx2 = clip->right; } - if ((cy + fheight) > clip->bottom) + if (cy2 > clip->bottom) { - const float n = (clip->bottom - cy); - - t_max = (t_min + ((n / fheight) * t_max)); - fheight = n; + t_max = t_min + (clip->bottom - cy1) / fheight * hwrPatch->max_t; + cy2 = clip->bottom; } + + cx = cx1; + cy = cy1; + fwidth = cx2 - cx1; + fheight = cy2 - cy1; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 From 3e1e1245cee19bf54b3cc3655ea20f975da97eed Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Tue, 4 Jun 2024 17:13:35 +0800 Subject: [PATCH 11/21] Expose `V_SetClipRect` and `V_ClearClipRect` to lua Via the `v.setClipRect` and `v.clearClipRect` functions respectively. --- src/lua_hudlib.c | 41 +++++++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.c | 36 ++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.h | 11 +++++++++++ 3 files changed, 88 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 46d5b8a02..e3cf0db32 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -972,6 +972,45 @@ static int libd_drawKartString(lua_State *L) return 0; } +static int libd_setClipRect(lua_State *L) +{ + fixed_t x = luaL_checkinteger(L, 1); + fixed_t y = luaL_checkinteger(L, 2); + fixed_t w = luaL_checkinteger(L, 3); + fixed_t h = luaL_checkinteger(L, 4); + INT32 flags = luaL_optinteger(L, 5, 0); + huddrawlist_h list; + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + HUDONLY + lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + list = (huddrawlist_h) lua_touserdata(L, -1); + lua_pop(L, 1); + + if (LUA_HUD_IsDrawListValid(list)) + LUA_HUD_AddSetClipRect(list, x, y, w, h, flags); + else + V_SetClipRect(x, y, w, h, flags); + return 0; +} + +static int libd_clearClipRect(lua_State *L) +{ + huddrawlist_h list; + + HUDONLY + lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + list = (huddrawlist_h) lua_touserdata(L, -1); + lua_pop(L, 1); + + if (LUA_HUD_IsDrawListValid(list)) + LUA_HUD_AddClearClipRect(list); + else + V_ClearClipRect(); + return 0; +} + static int libd_titleCardStringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); @@ -1263,6 +1302,8 @@ static luaL_Reg lib_draw[] = { {"drawString", libd_drawString}, {"drawTitleCardString", libd_drawTitleCardString}, {"drawKartString", libd_drawKartString}, + {"setClipRect", libd_setClipRect}, + {"clearClipRect", libd_clearClipRect}, // misc {"stringWidth", libd_stringWidth}, {"titleCardStringWidth", libd_titleCardStringWidth}, diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 9a12c7b99..ae62b629b 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -37,6 +37,8 @@ enum drawitem_e { DI_DrawTitleCardString, DI_DrawTitleCardStringBoss, DI_DrawKartString, + DI_SetClipRect, + DI_ClearClipRect, DI_MAX, }; @@ -555,6 +557,34 @@ void LUA_HUD_AddDrawKartString( // CalcStringCoords(item, str); } +void LUA_HUD_AddSetClipRect( + huddrawlist_h list, + fixed_t x, + fixed_t y, + fixed_t w, + fixed_t h, + INT32 flags +) +{ + size_t i = AllocateDrawItem(list); + drawitem_t *item = &list->items[i]; + item->type = DI_SetClipRect; + item->x = x; + item->y = y; + item->w = w; + item->h = h; + item->flags = flags; +} + +void LUA_HUD_AddClearClipRect( + huddrawlist_h list +) +{ + size_t i = AllocateDrawItem(list); + drawitem_t *item = &list->items[i]; + item->type = DI_ClearClipRect; +} + void LUA_HUD_DrawList(huddrawlist_h list) { size_t i; @@ -692,6 +722,12 @@ void LUA_HUD_DrawList(huddrawlist_h list) case DI_DrawKartString: V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr); break; + case DI_SetClipRect: + V_SetClipRect(item->x, item->y, item->w, item->h, item->flags); + break; + case DI_ClearClipRect: + V_ClearClipRect(); + break; default: I_Error("can't draw draw list item: invalid draw list item type"); continue; diff --git a/src/lua_hudlib_drawlist.h b/src/lua_hudlib_drawlist.h index 15249e4f9..1e6bb97d9 100644 --- a/src/lua_hudlib_drawlist.h +++ b/src/lua_hudlib_drawlist.h @@ -120,6 +120,17 @@ void LUA_HUD_AddDrawKartString( const char *str, INT32 flags ); +void LUA_HUD_AddSetClipRect( + huddrawlist_h list, + fixed_t x, + fixed_t y, + fixed_t w, + fixed_t h, + INT32 flags +); +void LUA_HUD_AddClearClipRect( + huddrawlist_h list +); // Draws the given draw list void LUA_HUD_DrawList(huddrawlist_h list); From abc004ddc89d67149ecddee5d3ca98fc9ebaf3c9 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Mon, 26 Aug 2024 10:25:09 +0800 Subject: [PATCH 12/21] Move V_ClearClipRect after call_mapped based on toaster's suggestion --- src/lua_hooklib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index f1439c889..3dca19072 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -675,12 +675,12 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) hud_running = true; // local hook - // Catch runaway clipping rectangles. - V_ClearClipRect(); - init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); + // Catch runaway clipping rectangles. + V_ClearClipRect(); + hud_running = false; } } From 51aeaa7529a54255d41bedb74091883c86d820b8 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 02:25:25 +0100 Subject: [PATCH 13/21] Interop late, fix runaway cliprects, cleanup --- src/lua_hudlib_drawlist.c | 11 ++++++++++- src/st_stuff.c | 17 +++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index ae62b629b..c368d5026 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -203,6 +203,7 @@ static size_t CopyString(huddrawlist_h list, const char* str) } } +/* static void CalcStringCoords(drawitem_t *item, const char *string) { if (!(item->flags & V_NOSCALESTART)) @@ -309,6 +310,7 @@ static void CalcFillCoords(drawitem_t *item) item->y = y; } } +*/ #define INTERP_LATCH 1 #define INTERP_STRING 2 @@ -510,6 +512,8 @@ void LUA_HUD_AddFadeScreen( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + // nothing to interpolate here + item->id = 0; item->type = DI_FadeScreen; item->color = color; item->strength = strength; @@ -568,6 +572,7 @@ void LUA_HUD_AddSetClipRect( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + item->id = GetItemId(); item->type = DI_SetClipRect; item->x = x; item->y = y; @@ -582,6 +587,7 @@ void LUA_HUD_AddClearClipRect( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + item->id = 0; item->type = DI_ClearClipRect; } @@ -723,7 +729,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr); break; case DI_SetClipRect: - V_SetClipRect(item->x, item->y, item->w, item->h, item->flags); + V_SetClipRect(LERPS(x), LERPS(y), LERP(w), LERP(h), item->flags); break; case DI_ClearClipRect: V_ClearClipRect(); @@ -733,4 +739,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) continue; } } + + // who are you running from? + V_ClearClipRect(); } diff --git a/src/st_stuff.c b/src/st_stuff.c index 6e5079962..d108a1c9c 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -724,7 +724,7 @@ void ST_preLevelTitleCardDrawer(void) // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // -static void ST_overlayDrawer(UINT8 playernum) +static void ST_overlayDrawer(void) { // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) @@ -733,9 +733,10 @@ static void ST_overlayDrawer(UINT8 playernum) if (renderisnewtic) { - LUA_HookHUD(luahuddrawlist_game[playernum], HUD_HOOK(game)); + LUA_HUD_ClearDrawList(luahuddrawlist_game[stplyrnum]); + LUA_HookHUD(luahuddrawlist_game[stplyrnum], HUD_HOOK(game)); } - LUA_HUD_DrawList(luahuddrawlist_game[playernum]); + LUA_HUD_DrawList(luahuddrawlist_game[stplyrnum]); } if (!hu_showscores) // hide the following if TAB is held @@ -911,11 +912,6 @@ void ST_Drawer(void) if (st_overlay) { UINT8 i; - if (renderisnewtic) - { - for (i = 0; i <= r_splitscreen; i++) - LUA_HUD_ClearDrawList(luahuddrawlist_game[i]); - } // No deadview! for (i = 0; i <= r_splitscreen; i++) { @@ -923,12 +919,9 @@ void ST_Drawer(void) stplyrnum = i; R_SetViewContext(VIEWCONTEXT_PLAYER1 + i); R_InterpolateView(rendertimefrac); // to assist with object tracking - ST_overlayDrawer(i); + ST_overlayDrawer(); } - for (i = 0; i <= r_splitscreen; i++) - LUA_HUD_DrawList(luahuddrawlist_game[i]); - // draw Midnight Channel's overlay ontop if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. ST_MayonakaStatic(); From 2e1ba3fa44592da337547ae1c77d9bb293f6dfc6 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 15:51:02 +0100 Subject: [PATCH 14/21] Fix patches being turned inside-out by cliprect in GL --- src/hardware/hw_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 50655f6aa..15032cbe2 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -266,8 +266,8 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p cx = cx1; cy = cy1; - fwidth = cx2 - cx1; - fheight = cy2 - cy1; + fwidth = fmaxf(0.0f, cx2 - cx1); + fheight = fmaxf(0.0f, cy2 - cy1); } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 From 3928a98d727664b8daa1313ff12ba7352ffb30b3 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 19:34:53 +0100 Subject: [PATCH 15/21] Properly fix runaway cliprects so they don't interfere with other hooks --- src/lua_hooklib.c | 7 ++++--- src/lua_hud.h | 2 ++ src/lua_hudlib.c | 16 ++++++++++++++++ src/lua_hudlib_drawlist.c | 3 --- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 3dca19072..aebf2185c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -488,8 +488,12 @@ static int call_mapped_hud(Hook_State *hook, const hook_t *map) { hud_interpolate = hud_interpstring = hud_interplatch = false; hud_interpcounter++; + get_hook(hook, map->ids, k); call_single_hook(hook); + + // Catch runaway clipping rectangles. + LUA_ClearClipRect(); } return map->numHooks; @@ -678,9 +682,6 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); - // Catch runaway clipping rectangles. - V_ClearClipRect(); - hud_running = false; } } diff --git a/src/lua_hud.h b/src/lua_hud.h index 0c632b1fa..2d4cb664f 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -59,6 +59,8 @@ boolean LUA_HudEnabled(enum hud option); void LUA_SetHudHook(int hook, huddrawlist_h list); +void LUA_ClearClipRect(void); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index e3cf0db32..fb573b592 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -47,6 +47,8 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 camnum = 1; +static boolean cliprectenabled; + // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -987,6 +989,7 @@ static int libd_setClipRect(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); list = (huddrawlist_h) lua_touserdata(L, -1); lua_pop(L, 1); + cliprectenabled = true; if (LUA_HUD_IsDrawListValid(list)) LUA_HUD_AddSetClipRect(list, x, y, w, h, flags); @@ -1003,6 +1006,7 @@ static int libd_clearClipRect(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); list = (huddrawlist_h) lua_touserdata(L, -1); lua_pop(L, 1); + cliprectenabled = false; if (LUA_HUD_IsDrawListValid(list)) LUA_HUD_AddClearClipRect(list); @@ -1458,6 +1462,8 @@ void LUA_SetHudHook(int hook, huddrawlist_h list) lua_pushlightuserdata(gL, list); lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + cliprectenabled = false; + switch (hook) { case HUD_HOOK(game): @@ -1476,3 +1482,13 @@ void LUA_SetHudHook(int hook, huddrawlist_h list) break; } } + +void LUA_ClearClipRect(void) +{ + // V_ClearClipRect is not enough: we need to insert a clearClipRect + // into the drawlist to protect both hardcode and other HUD hooks. + // thankfully the below function takes zero Lua arguments :^) + if (cliprectenabled) + libd_clearClipRect(gL); + //cliprectenabled = false; +} diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index c368d5026..73edb10cc 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -739,7 +739,4 @@ void LUA_HUD_DrawList(huddrawlist_h list) continue; } } - - // who are you running from? - V_ClearClipRect(); } From 8160267880d1bda7c087725fa07b5ae78910a97e Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 23 Feb 2025 01:45:29 +0100 Subject: [PATCH 16/21] Oops, forgot to resize spritecachedinfo in R_AddKartFaces --- src/r_things.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 205eb7ea9..a4eb35b19 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -249,6 +249,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].flip &= ~(1<= max_spritelumps) + { + max_spritelumps *= 2; + Z_Realloc(spritecachedinfo, max_spritelumps*sizeof(*spritecachedinfo), PU_STATIC, &spritecachedinfo); + } +} + #define NUMFACES 3 static size_t KART_FACES[NUMFACES] = { offsetof(skin_t, facerank), @@ -265,7 +274,8 @@ void R_AddKartFaces(skin_t *skin) lumpnum_t lumpnum = W_CheckNumForName(reinterpret_cast(skin) + KART_FACES[f]); // how do you do, fellow C++ers? if (lumpnum == LUMPERROR) I_Error("R_AddKartFaces: missing patch %s for skin %s", reinterpret_cast(skin) + KART_FACES[f], skin->name); - R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), numspritelumps++, f, 0, 0); + R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), numspritelumps, f, 0, 0); + R_IncrementSpriteLumps(); } sd->numframes = NUMFACES; sd->spriteframes = static_cast(Z_Realloc(sd->spriteframes, sizeof(spriteframe_t)*NUMFACES, PU_STATIC, NULL)); @@ -394,11 +404,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); } - if (++numspritelumps >= max_spritelumps) - { - max_spritelumps *= 2; - Z_Realloc(spritecachedinfo, max_spritelumps*sizeof(*spritecachedinfo), PU_STATIC, &spritecachedinfo); - } + R_IncrementSpriteLumps(); ++numadded; } From e562d838b5807774b327249f0b3348d2e17e307e Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 22 Feb 2025 21:35:07 -0500 Subject: [PATCH 17/21] bumpspark, bumpspring and small code refactoring and cleanup --- src/acs/call-funcs.cpp | 4 +- src/d_netcmd.c | 12 +- src/d_netcmd.h | 3 + src/d_player.h | 2 - src/deh_tables.c | 1 - src/doomstat.h | 4 +- src/g_game.c | 10 +- src/k_collide.c | 30 ----- src/k_hud.c | 284 ++++++++++++++++------------------------- src/k_kart.c | 95 ++++---------- src/k_kart.h | 2 + src/lua_playerlib.c | 8 -- src/p_enemy.c | 9 +- src/p_inter.c | 31 ++--- src/p_local.h | 3 +- src/p_map.c | 13 +- src/p_mobj.c | 18 +-- src/p_mobj.h | 2 +- src/p_saveg.c | 8 +- src/p_setup.c | 6 +- src/p_spec.c | 6 +- src/p_user.c | 27 +--- 22 files changed, 192 insertions(+), 386 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 8dff2e811..f1d25ee7b 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -1358,9 +1358,7 @@ bool CallFunc_PlayerRings(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM: && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) && (info->mo->player != NULL)) { - rings = (gametyperules & GTR_SPHERES) - ? info->mo->player->spheres - : info->mo->player->rings; + rings = info->mo->player->rings; } thread->dataStk.push(rings); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6f29dc633..689d8db2d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -428,7 +428,7 @@ consvar_t cv_kartbot = CVAR_INIT ("kartbot", "0", CV_NETVAR, kartbot_cons_t, NUL consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); // Toggles for new features -consvar_t cv_kartrings = CVAR_INIT ("kartrings", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartRings_OnChange); +consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange); consvar_t cv_kartwalltransfer = CVAR_INIT ("BG_forcewalltransfer", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); @@ -436,6 +436,10 @@ consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR|CV_CHEAT consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartbumpspark = CVAR_INIT ("kartbumpspark", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); + +consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); + static CV_PossibleValue_t kartdebugitem_cons_t[] = { #define FOREACH( name, n ) { n, #name } @@ -6869,13 +6873,13 @@ static void KartRings_OnChange(void) return; } - if (ringsdisabled) + if (cv_kartrings.value) { - CONS_Printf(M_GetText("Rings will be turned %s Next Round .\n"), cv_kartrings.string); + CONS_Printf(M_GetText("Rings will be turned \"On\" Next Round.\n")); } else { - CONS_Printf(M_GetText("Rings will be turned %s Next Round .\n"), cv_kartrings.string); + CONS_Printf(M_GetText("Rings will be turned \"Off\" Next Round.\n")); } } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index abf3dcb6d..78d2dd554 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -93,6 +93,9 @@ extern consvar_t cv_kartusepwrlv; extern consvar_t cv_kartrings; extern consvar_t cv_kartwalltransfer; extern consvar_t cv_kartpurpledrift; +extern consvar_t cv_kartbumpspark; + +extern consvar_t cv_kartbumpspring; extern consvar_t cv_votetime; diff --git a/src/d_player.h b/src/d_player.h index af0252a77..7a4760c9c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -649,8 +649,6 @@ struct player_t INT16 karmadelay; INT16 karmamode; INT16 karmapoints; - INT16 spheres; - tic_t spheredigestion; SINT8 glanceDir; // Direction the player is trying to look backwards in diff --git a/src/deh_tables.c b/src/deh_tables.c index eb2143577..9054e978f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -946,7 +946,6 @@ struct int_const_s const INT_CONST[] = { {"DMG_SQUISH",DMG_SQUISH}, {"DMG_WIPEOUT",DMG_WIPEOUT}, {"DMG_EXPLODE",DMG_EXPLODE}, - {"DMG_STING",DMG_STING}, {"DMG_KARMA",DMG_KARMA}, //// Death types {"DMG_INSTAKILL",DMG_INSTAKILL}, diff --git a/src/doomstat.h b/src/doomstat.h index 377ed086f..e310eb549 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -494,10 +494,10 @@ enum GameTypeRules // Race rules GTR_CIRCUIT = 1, // Enables the finish line, laps, and the waypoint system. GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype. + GTR_RINGS = 1<<3, // Allow Rings in this gametype. // Battle gametype rules - GTR_BUMPERS = 1<<3, // Enables the bumper health system - GTR_SPHERES = 1<<4, // Replaces rings with blue spheres + GTR_BUMPERS = 1<<4, // Enables the bumper health system GTR_PAPERITEMS = 1<<5, // Replaces item boxes with paper item spawners GTR_WANTED = 1<<6, // Enables the wanted anti-camping system GTR_KARMA = 1<<7, // Enables the Karma system if you're out of bumpers diff --git a/src/g_game.c b/src/g_game.c index adc7af2b1..1212ba904 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2260,7 +2260,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 botdifficulty; INT16 rings; - INT16 spheres; angle_t playerangleturn; UINT8 botdiffincrease; @@ -2335,8 +2334,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0); karmapoints = 0; wanted = 0; - rings = ((gametyperules & GTR_SPHERES) ? 0 : 10); - spheres = 0; + rings = 10; kickstartaccel = 0; nocontrol = 0; laps = 0; @@ -2382,7 +2380,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) karmapoints = players[player].karmapoints; wanted = players[player].wanted; rings = players[player].rings; - spheres = players[player].spheres; kickstartaccel = players[player].kickstartaccel; nocontrol = players[player].nocontrol; @@ -2471,7 +2468,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->bot = bot; p->botvars.difficulty = botdifficulty; p->rings = rings; - p->spheres = spheres; p->botvars.diffincrease = botdiffincrease; p->botvars.rival = botrival; p->xtralife = xtralife; @@ -3105,9 +3101,9 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Race - GTR_CIRCUIT|GTR_BOTS, + GTR_CIRCUIT|GTR_BOTS|GTR_RINGS, // Battle - GTR_BUMPERS|GTR_KARMA|GTR_WANTED|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT + GTR_BUMPERS|GTR_RINGS|GTR_KARMA|GTR_WANTED|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT }; // diff --git a/src/k_collide.c b/src/k_collide.c index d98a9893d..83cac0bc3 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -911,36 +911,6 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return true; } } - - /*if (!ringsdisabled) // Ring sting, this is a bit more unique - { - t1Condition = (K_GetShieldFromItem(t2->player->itemtype) == KSHIELD_NONE); - t2Condition = (K_GetShieldFromItem(t1->player->itemtype) == KSHIELD_NONE); - - if (t1Condition == true) - { - if (t2->player->rings <= 0) - { - P_DamageMobj(t2, t1, t1, 1, DMG_STING); - stungT2 = true; - } - - P_PlayerRingBurst(t2->player, 1); - } - - if (t2Condition == true) - { - if (t1->player->rings <= 0) - { - P_DamageMobj(t1, t2, t2, 1, DMG_STING); - stungT1 = true; - } - - P_PlayerRingBurst(t1->player, 1); - } - - return (stungT1 || stungT2); - }*/ return false; } diff --git a/src/k_hud.c b/src/k_hud.c index 5804bcc5d..910595d98 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -62,8 +62,6 @@ static patch_t *kp_splitlapflag; static patch_t *kp_bumpersticker; static patch_t *kp_bumperstickerwide; static patch_t *kp_karmasticker; -static patch_t *kp_spheresticker; -static patch_t *kp_splitspheresticker; static patch_t *kp_splitkarmabomb; static patch_t *kp_timeoutsticker; @@ -185,8 +183,6 @@ void K_LoadKartHUDGraphics(void) HU_UpdatePatch(&kp_bumpersticker, "K_STBALN"); HU_UpdatePatch(&kp_bumperstickerwide, "K_STBALW"); HU_UpdatePatch(&kp_karmasticker, "K_STKARM"); - HU_UpdatePatch(&kp_spheresticker, "K_STBSMT"); - HU_UpdatePatch(&kp_splitspheresticker, "K_SPBSMT"); HU_UpdatePatch(&kp_splitkarmabomb, "K_SPTKRM"); HU_UpdatePatch(&kp_timeoutsticker, "K_STTOUT"); @@ -1979,35 +1975,14 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN } } -static void K_drawKartLapsAndRings(void) +static void K_drawKartLaps(void) { const boolean uselives = G_GametypeUsesLives(); INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANS|V_SPLITSCREEN; - UINT8 rn[2]; - INT32 ringflip = 0; - UINT8 *ringmap = NULL; - boolean colorring = false; - INT32 ringx = 0; - - rn[0] = ((abs(stplyr->rings) / 10) % 10); - rn[1] = (abs(stplyr->rings) % 10); - - if (!ringsdisabled) - { - - if (stplyr->rings <= 0 && (leveltime/5 & 1)) // In debt - { - ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); - colorring = true; - } - else if (stplyr->rings >= 20) // Maxed out - ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); - } if (r_splitscreen > 1) { INT32 fx = 0, fy = 0, fr = 0; - INT32 flipflag = 0; // pain and suffering defined below if (r_splitscreen < 2) // don't change shit for THIS splitscreen. @@ -2028,7 +2003,6 @@ static void K_drawKartLapsAndRings(void) fx = LAPS2_X; fy = LAPS2_Y; splitflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN; - flipflag = V_FLIP; // make the string right aligned and other shit } } @@ -2059,18 +2033,6 @@ static void K_drawKartLapsAndRings(void) V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(numlaps) % 10]); } - if (!ringsdisabled) - { - - V_DrawMappedPatch(fr, fy-10, V_HUDTRANS|splitflags|ringflip, kp_ringsplitscreen, (colorring ? ringmap : NULL)); - - if (stplyr->rings < 0) // Draw the minus for ring debt - V_DrawMappedPatch(fr+7, fy-8, V_HUDTRANS|splitflags, kp_ringdebtminussmall, ringmap); - - V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[rn[0]], ringmap); - V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[rn[1]], ringmap); - } - // Lives if (uselives) { @@ -2090,47 +2052,6 @@ static void K_drawKartLapsAndRings(void) else V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps)); - if (!ringsdisabled) - { - SINT8 i; - V_DrawScaledPatch(LAPS_X, LAPS_Y-14, V_HUDTRANS|splitflags, kp_ringsticker[(stplyr->pflags & PF_RINGLOCK) ? 1 : 0]); - - if (stplyr->rings < 0) // Draw the minus for ring debt - { - V_DrawMappedPatch(LAPS_X-5, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); - } - - V_DrawMappedPatch(LAPS_X+2, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); - V_DrawMappedPatch(LAPS_X+8, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); - - // Draw the fillbars - if (stplyr->rings) - { - SINT8 ringcount = stplyr->rings; - SINT8 barcolors[4] = {66,83,65}; - boolean indebt = false; - - if (stplyr->rings < 0) - { - barcolors[0] = 35; - barcolors[1] = 33; - barcolors[2] = 37; - ringcount = -ringcount; - indebt = true; - } - if (!indebt || (indebt && (leveltime/5 & 1))) - { - for (i = 0; i != ringcount; i++) - { - - V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-10, 1, 3, barcolors[0]|splitflags); - V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-9, 1, 2, barcolors[1]|splitflags); - V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-6, 1, 1, barcolors[2]|splitflags); - } - } - } - } - // Lives if (uselives) { @@ -2241,7 +2162,7 @@ static void K_drawKartSpeedometer(void) if (gametype == GT_BATTLE) battleoffset = -4; - if (!ringsdisabled && !(gametype == GT_BATTLE)) + if (K_RingsActive() == true) ringoffset = -16; if (cv_newspeedometer.value == 0) @@ -2279,101 +2200,117 @@ static void K_drawKartSpeedometer(void) K_drawKartAccessibilityIcons(56); } -static void K_drawBlueSphereMeter(void) +static void K_drawRingMeter(void) { - const UINT8 maxBars = 4; - const UINT8 segColors[] = {73, 64, 52, 54, 55, 35, 34, 33, 202, 180, 181, 182, 164, 165, 166, 153, 152}; - const UINT8 sphere = max(min(stplyr->spheres, 40), 0); + UINT8 rn[2]; + INT32 ringflip = 0; + UINT8 *ringmap = NULL; + boolean colorring = false; + INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANS|V_SPLITSCREEN; - UINT8 numBars = min((sphere / 10), maxBars); - UINT8 colorIndex = (sphere * sizeof(segColors)) / (40 + 1); - INT32 fx, fy; - UINT8 i; - INT32 splitflags = V_HUDTRANS|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN; - INT32 flipflag = 0; - INT32 xstep = 15; + rn[0] = ((abs(stplyr->rings) / 10) % 10); + rn[1] = (abs(stplyr->rings) % 10); - // pain and suffering defined below - if (r_splitscreen < 2) // don't change shit for THIS splitscreen. + + if (stplyr->rings <= 0 && (leveltime/5 & 1)) // In debt { - fx = LAPS_X; - fy = LAPS_Y-22; - V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_spheresticker); + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); + colorring = true; } - else - { - xstep = 8; - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... - { - fx = LAPS_X-2; - fy = LAPS_Y; - } - else // else, that means we're P2 or P4. - { - fx = LAPS2_X+(SHORT(kp_splitspheresticker->width) - 10); - fy = LAPS2_Y; - splitflags ^= V_SNAPTOLEFT|V_SNAPTORIGHT; - flipflag = V_FLIP; // make the string right aligned and other shit - xstep = -xstep; - } - fy -= 16; - V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_splitspheresticker); - } - - if (r_splitscreen < 2) - { - fx += 25; - } - else - { - fx += (flipflag) ? -18 : 13; - } - - for (i = 0; i <= numBars; i++) - { - UINT8 segLen = (r_splitscreen < 2) ? 10 : 5; - - if (i == numBars) - { - segLen = (sphere % 10); - if (r_splitscreen < 2) - ; - else - { - segLen = (segLen+1)/2; // offset so nonzero spheres shows up IMMEDIATELY - if (!segLen) - break; - if (flipflag) - fx += (5-segLen); - } - } - - if (r_splitscreen < 2) - { - V_DrawFill(fx, fy + 6, segLen, 3, segColors[max(colorIndex-1, 0)] | splitflags); - V_DrawFill(fx, fy + 7, segLen, 1, segColors[max(colorIndex-2, 0)] | splitflags); - V_DrawFill(fx, fy + 9, segLen, 3, segColors[colorIndex] | splitflags); - } - else - { - V_DrawFill(fx, fy + 5, segLen, 1, segColors[max(colorIndex-1, 0)] | splitflags); - V_DrawFill(fx, fy + 6, segLen, 1, segColors[max(colorIndex-2, 0)] | splitflags); - V_DrawFill(fx, fy + 7, segLen, 2, segColors[colorIndex] | splitflags); - } - - fx += xstep; - } -} - -static void K_drawKartBumpersOrKarma(void) -{ - UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); - INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN; + else if (stplyr->rings >= 20) // Maxed out + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); if (r_splitscreen > 1) { - INT32 fx = 0, fy = 0; - INT32 flipflag = 0; + INT32 fx = 0, fy = 0, fr = 0; + + // pain and suffering defined below + if (r_splitscreen < 2) // don't change shit for THIS splitscreen. + { + fx = LAPS_X; + fy = LAPS_Y; + } + else + { + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + { + fx = LAPS_X; + fy = LAPS_Y; + splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; + } + else // else, that means we're P2 or P4. + { + fx = LAPS2_X; + fy = LAPS2_Y; + splitflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN; + } + } + + fr = fx; + + V_DrawMappedPatch(fr, fy-10, V_HUDTRANS|splitflags|ringflip, kp_ringsplitscreen, (colorring ? ringmap : NULL)); + + if (stplyr->rings < 0) // Draw the minus for ring debt + V_DrawMappedPatch(fr+7, fy-8, V_HUDTRANS|splitflags, kp_ringdebtminussmall, ringmap); + + V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[rn[0]], ringmap); + V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[rn[1]], ringmap); + } + else + { + SINT8 i; + SINT8 ringoffsety = 0; + + if (gametype == GT_BATTLE) + ringoffsety -= 4; + + V_DrawScaledPatch(LAPS_X, LAPS_Y-14 + ringoffsety, V_HUDTRANS|splitflags, kp_ringsticker[(stplyr->pflags & PF_RINGLOCK) ? 1 : 0]); + + if (stplyr->rings < 0) // Draw the minus for ring debt + { + V_DrawMappedPatch(LAPS_X-5, LAPS_Y-11 + ringoffsety, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); + } + + V_DrawMappedPatch(LAPS_X+2, LAPS_Y-11 + ringoffsety, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); + V_DrawMappedPatch(LAPS_X+8, LAPS_Y-11 + ringoffsety, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); + + // Draw the fillbars + if (stplyr->rings) + { + SINT8 ringcount = stplyr->rings; + SINT8 barcolors[4] = {66,83,65}; + boolean indebt = false; + + if (stplyr->rings < 0) + { + barcolors[0] = 35; + barcolors[1] = 33; + barcolors[2] = 37; + ringcount = -ringcount; + indebt = true; + } + if (!indebt || (indebt && (leveltime/5 & 1))) + { + for (i = 0; i != ringcount; i++) + { + + V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-10 + ringoffsety, 1, 3, barcolors[0]|splitflags); + V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-9 + ringoffsety, 1, 2, barcolors[1]|splitflags); + V_DrawFill(LAPS_X+17+(2*i), LAPS_Y-6 + ringoffsety, 1, 1, barcolors[2]|splitflags); + } + } + } + } +} + +static void K_drawKartBumpersOrKarma(void) +{ + UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); + INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN; + + if (r_splitscreen > 1) + { + INT32 fx = 0, fy = 0; // pain and suffering defined below if (r_splitscreen < 2) // don't change shit for THIS splitscreen. @@ -2394,11 +2331,9 @@ static void K_drawKartBumpersOrKarma(void) fx = LAPS2_X; fy = LAPS2_Y; splitflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN; - flipflag = V_FLIP; // make the string right aligned and other shit } } - //V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); if (itembreaker) @@ -2500,7 +2435,6 @@ static void K_drawKartWanted(void) UINT8 *colormap = NULL; INT32 basex = 0, basey = 0; - for (i = 0; i < 4; i++) { if (battlewanted[i] == -1) @@ -4285,7 +4219,7 @@ static void K_drawDistributionDebugger(void) if (pingame == 1) { - if (stplyr->itemroulette && (stplyr->cmd.buttons & BT_ATTACK) && (cv_superring.value && !ringsdisabled)) + if (stplyr->itemroulette && (stplyr->cmd.buttons & BT_ATTACK) && cv_superring.value && (K_RingsActive() == true)) V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, kp_superring[1]); else V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, items[1]); @@ -4520,7 +4454,7 @@ void K_drawKartHUD(void) { if (gametyperules & GTR_CIRCUIT) { - K_drawKartLapsAndRings(); + K_drawKartLaps(); } else if (gametyperules & GTR_BUMPERS) { @@ -4538,9 +4472,9 @@ void K_drawKartHUD(void) K_drawKartAccessibilityIcons(0); } - if (gametyperules & GTR_SPHERES) + if (K_RingsActive() == true) { - K_drawBlueSphereMeter(); + K_drawRingMeter(); } if (modeattacking && !bossinfo.boss) diff --git a/src/k_kart.c b/src/k_kart.c index 445221c29..12618c2de 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -254,6 +254,10 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartwalltransfer); CV_RegisterVar(&cv_kartpurpledrift); + + CV_RegisterVar(&cv_kartbumpspark); + + CV_RegisterVar(&cv_kartbumpspring); } //} @@ -651,7 +655,7 @@ INT32 K_KartGetItemOdds( case KITEM_SUPERRING: notNearEnd = true; - if (ringsdisabled) // No rings rolled if rings are turned off. + if ((K_RingsActive() == false)) // No rings rolled if rings are turned off. { newodds = 0; } @@ -1429,7 +1433,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { if (gametype == GT_RACE) { - if (mashed && (modeattacking || (cv_superring.value && !ringsdisabled))) // ANY mashed value? You get rings. + if (mashed && (modeattacking || (cv_superring.value && (K_RingsActive() == true)))) // ANY mashed value? You get rings. { K_KartGetItemResult(player, KITEM_SUPERRING); player->karthud[khud_itemblinkmode] = 1; @@ -1502,7 +1506,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) // SPECIAL CASE No. 4: // Being in ring debt occasionally forces Super Ring on you if you mashed - if (!(gametyperules & GTR_SPHERES || ringsdisabled) && mashed && player->rings < 0 && cv_superring.value) + if ((K_RingsActive() == true) && mashed && player->rings < 0 && cv_superring.value) { INT32 debtamount = min(20, abs(player->rings)); if (P_RandomChance((debtamount*FRACUNIT)/20)) @@ -3044,7 +3048,6 @@ void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker) // In a perfect world we could move this here, but there's // a few niche situations where we want a pain sound from // the victim, but no confirm sound from the attacker. - // (ex: DMG_STING) //K_PlayPainSound(victim, attacker); @@ -3391,12 +3394,6 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberb finalspeed = FixedMul(FixedMul(k_speed<<14, g_cc), player->mo->scale); - if (player->spheres > 0) - { - fixed_t sphereAdd = (FRACUNIT/60); // 66% at max - finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres)); - } - if (K_PlayerUsesBotMovement(player)) { // Increase bot speed by 1-10% depending on difficulty @@ -6556,7 +6553,7 @@ void K_KartPlayerHUDUpdate(player_t *player) if (gametype == GT_RACE) { - if (!ringsdisabled) + if ((K_RingsActive() == true)) { if (player->pflags & PF_RINGLOCK) { @@ -6928,7 +6925,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - /*if (gametype == GT_RACE && player->rings <= 0 && !ringsdisabled) // spawn ring debt indicator + /*if (gametype == GT_RACE && player->rings <= 0 && (K_RingsActive() == true)) // spawn ring debt indicator { mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK); @@ -7004,7 +7001,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } - if (ringsdisabled) + if ((K_RingsActive() == false)) { player->rings = 0; } @@ -7016,59 +7013,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->rings = -20; } - if (player->spheres > 40) - player->spheres = 40; - // where's the < 0 check? see below the following block! - - if ((gametyperules & GTR_BUMPERS) && (player->bumper <= 0)) - { - // Deplete 1 every tic when removed from the game. - player->spheres--; - player->spheredigestion = 0; - } - else - { - tic_t spheredigestion = TICRATE; // Base rate of 1 every second when playing. - tic_t digestionpower = ((10 - player->kartspeed) + (10 - player->kartweight))-1; // 1 to 17 - - // currently 0-34 - digestionpower = ((player->spheres*digestionpower)/20); - - if (digestionpower >= spheredigestion) - { - spheredigestion = 1; - } - else - { - spheredigestion -= digestionpower; - } - - if ((player->spheres > 0) && (player->spheredigestion > 0)) - { - // If you got a massive boost in spheres, catch up digestion as necessary. - if (spheredigestion < player->spheredigestion) - { - player->spheredigestion = (spheredigestion + player->spheredigestion)/2; - } - - player->spheredigestion--; - - if (player->spheredigestion == 0) - { - player->spheres--; - player->spheredigestion = spheredigestion; - } - } - else - { - player->spheredigestion = spheredigestion; - } - } - - // where's the > 40 check? see above the previous block! - if (player->spheres < 0) - player->spheres = 0; - if (comeback == false || !(gametyperules & GTR_KARMA) || (player->pflags & PF_ELIMINATED)) { player->karmadelay = comebacktime; @@ -9127,7 +9071,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (!(cmd->buttons & BT_ATTACK)) { if (player->itemtype == KITEM_NONE - && NO_HYUDORO && !ringsdisabled && !(HOLDING_ITEM + && NO_HYUDORO && (K_RingsActive() == true) && !(HOLDING_ITEM || player->itemamount || player->itemroulette || player->rocketsneakertimer @@ -10151,4 +10095,21 @@ boolean K_IsSPBInGame(void) return false; } +boolean K_RingsActive(void) +{ + if (!(gametyperules & GTR_RINGS)) + { + // No Rings in this gametype. + return false; + } + + if (!ringsactive) + { + // Rings aren't enabled. + return false; + } + + return true; +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 39b6ef5bf..5fa08c66d 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -172,6 +172,8 @@ void K_UnsetItemOut(player_t *player); boolean K_SafeRespawnPosition(mobj_t * mo); +boolean K_RingsActive(void); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f06460c31..1da6247b5 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -390,10 +390,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->bumper); else if (fastcmp(field,"karmadelay")) lua_pushinteger(L, plr->karmadelay); - else if (fastcmp(field,"spheres")) - lua_pushinteger(L, plr->spheres); - else if (fastcmp(field,"spheredigestion")) - lua_pushinteger(L, plr->spheredigestion); else if (fastcmp(field,"pflags")) { UINT32 pflags = plr->pflags; @@ -797,10 +793,6 @@ static int player_set(lua_State *L) plr->bumper = luaL_checkinteger(L, 3); else if (fastcmp(field,"karmadelay")) plr->karmadelay = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spheres")) - plr->spheres = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spheredigestion")) - plr->spheredigestion = luaL_checkinteger(L, 3); else if (fastcmp(field,"kartspeed")) plr->kartspeed = luaL_checkinteger(L, 3); else if (fastcmp(field,"kartweight")) diff --git a/src/p_enemy.c b/src/p_enemy.c index 4b2720b5d..22977afcc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3662,10 +3662,7 @@ void A_AttractChase(mobj_t *actor) // Set attraction flag actor->cusval = 1; - if ( - (actor->tracer->player && actor->tracer->health - && (gametyperules & GTR_SPHERES)) - || (actor->tracer->player->itemtype == KITEM_THUNDERSHIELD + if ((actor->tracer->player->itemtype == KITEM_THUNDERSHIELD && RINGTOTAL(actor->tracer->player) < 20 && !(actor->tracer->player->pflags & PF_RINGLOCK)) //&& P_CheckSight(actor, actor->tracer) @@ -13006,7 +13003,7 @@ void A_ItemPop(mobj_t *actor) actor->target->player->itemroulette = 1; // Let Ring-less maps in on the rings fun as well! - if (!ringsdisabled) + if ((K_RingsActive() == true) ) { SINT8 awardamount = 10; if (actor->target->player->position == 1) @@ -13203,7 +13200,7 @@ void A_SPBChase(mobj_t *actor) spbplace = actor->tracer->player->position; } - if (!ringsdisabled) // Spawn rings to make up for the fact first has ring grabbing + if ((K_RingsActive() == true) ) // Spawn rings to make up for the fact first has ring grabbing { if (leveltime % 10 == 0) { diff --git a/src/p_inter.c b/src/p_inter.c index b2166d136..d6c87b723 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -170,7 +170,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) // When you pick up some items in nights, it displays // a score sign, and awards you some drill time. // -void P_DoNightsScore(player_t *player) +static void P_DoNightsScore(player_t *player) { mobj_t *dummymo; @@ -679,13 +679,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; - case MT_BLUESPHERE: - if (!(P_CanPickupItem(player, 0))) - return; - - P_GivePlayerSpheres(player, 1); - break; - // Secret emblem thingy case MT_EMBLEM: { @@ -2047,7 +2040,7 @@ static UINT8 P_ShouldHookDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sourc status = shouldDamage; - if (shouldSpin > 0 && ((type == DMG_NORMAL) || (type == DMG_WIPEOUT) || (type == DMG_STING))) + if (shouldSpin > 0 && ((type == DMG_NORMAL) || (type == DMG_WIPEOUT))) status = shouldSpin; else if (shouldExplode > 0 && ((type == DMG_EXPLODE) || (type == DMG_KARMA))) status = shouldExplode; @@ -2204,12 +2197,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // We successfully damaged them! Give 'em some bumpers! - if (type != DMG_STING && (gametyperules & GTR_BUMPERS)) + if (gametyperules & GTR_BUMPERS) { if (source && source != player->mo && source->player) { - K_TryHurtSoundExchange(target, source); K_BattleAwardHit(source->player, player, inflictor, 1); if (damagetype & DMG_STEAL) @@ -2239,6 +2231,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } } + K_TryHurtSoundExchange(target, source); + if (!((damagetype & DMG_NORMAL) || (damagetype & DMG_WIPEOUT))) player->sneakertimer = 0; player->driftboost = 0; @@ -2248,12 +2242,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da switch (type) { - case DMG_STING: - K_DebtStingPlayer(player, source); - K_KartPainEnergyFling(player); - LUA_HookPlayerSpin(target, inflictor, source, damage, damagetype); - ringburst = 0; - break; case DMG_EXPLODE: case DMG_KARMA: ringburst = K_ExplodePlayer(player, inflictor, source); @@ -2278,10 +2266,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da break; } - if (type != DMG_STING) - { - player->flashing = K_GetKartFlashing(player); - } + player->flashing = K_GetKartFlashing(player); P_PlayRinglossSound(target); @@ -2406,8 +2391,8 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) INT32 i; angle_t fa; - // Rings shouldn't be in Battle! - if (gametyperules & GTR_SPHERES) + // Rings need to be enabled! + if ((K_RingsActive() == false) ) return; // Better safe than sorry. diff --git a/src/p_local.h b/src/p_local.h index c58ff19cf..b70eb7eda 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -191,7 +191,6 @@ void P_RestoreMusic(player_t *player); boolean P_EndingMusic(player_t *player); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); INT32 P_GivePlayerRings(player_t *player, INT32 num_rings); -INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); @@ -552,7 +551,7 @@ struct BasicFF_t #define DMG_WIPEOUT 0x01 // Normal, but with extra flashy effects #define DMG_EXPLODE 0x02 #define DMG_SQUISH 0x03 -#define DMG_STING 0x04 +//#define free 0x04 #define DMG_KARMA 0x05 // Karma Bomb explosion -- works like DMG_EXPLODE, but steals half of their bumpers & deletes the rest //// Death types - cannot be combined with damage types #define DMG_INSTAKILL 0x80 diff --git a/src/p_map.c b/src/p_map.c index caa54063f..14c0cacaa 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3642,9 +3642,16 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) mmomx = mo->player->rmomx; mmomy = mo->player->rmomy; - mo->player->drift = 0; - mo->player->driftcharge = 0; - mo->player->pogospring = 0; + if (!cv_kartbumpspark.value) + { + mo->player->drift = 0; + mo->player->driftcharge = 0; + } + + if (!cv_kartbumpspring.value) + { + mo->player->pogospring = 0; + } slidemo = mo; bestslideline = result->line; diff --git a/src/p_mobj.c b/src/p_mobj.c index f8a564c23..46d519446 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10416,15 +10416,6 @@ void P_RespawnSpecials(void) time = 5*TICRATE; else #endif - if (gametyperules & GTR_SPHERES) - { - if (pcount > 2) - time -= (5*TICRATE) * (pcount-2); - - if (time < 5*TICRATE) - time = 5*TICRATE; - } - else { if (pcount == 1) // No respawn when alone { @@ -10959,7 +10950,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) } case MT_RING: { - if (ringsdisabled) + if ((K_RingsActive() == false) ) return false; break; } @@ -10985,8 +10976,8 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) { boolean isRingCapsule = (mthing->args[0] < 1 || mthing->args[0] == KITEM_SUPERRING || mthing->args[0] >= NUMKARTITEMS); - // don't spawn ring capsules in GTR_SPHERES gametypes - if (isRingCapsule && (gametyperules & GTR_SPHERES)) + // don't spawn ring capsules in ringless gametypes + if (isRingCapsule && !(gametyperules & GTR_RINGS)) return false; // in record attack, only spawn ring capsules @@ -11018,9 +11009,6 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) { (void)mthing; - if ((i == MT_RING) && (gametyperules & GTR_SPHERES)) - return MT_BLUESPHERE; - if ((i == MT_RANDOMITEM) && (gametyperules & (GTR_PAPERITEMS|GTR_CIRCUIT)) == (GTR_PAPERITEMS|GTR_CIRCUIT) && !bossinfo.boss) return MT_PAPERITEMSPOT; diff --git a/src/p_mobj.h b/src/p_mobj.h index 97ca4ff2c..cdd0ba610 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -575,7 +575,7 @@ extern boolean runemeraldmanager; extern UINT16 emeraldspawndelay; extern INT32 numstarposts; extern INT32 numbosswaypoints; -extern boolean ringsdisabled; +extern boolean ringsactive; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index 679c1ab5b..d7879aa6d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -339,8 +339,6 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEINT16(save->p, players[i].karmamode); WRITEINT16(save->p, players[i].karmapoints); WRITEINT16(save->p, players[i].wanted); - WRITEINT16(save->p, players[i].spheres); - WRITEUINT32(save->p, players[i].spheredigestion); WRITESINT8(save->p, players[i].glanceDir); @@ -642,8 +640,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].karmamode = READINT16(save->p); players[i].karmapoints = READINT16(save->p); players[i].wanted = READINT16(save->p); - players[i].spheres = READINT16(save->p); - players[i].spheredigestion = READUINT32(save->p); players[i].glanceDir = READSINT8(save->p); @@ -4985,7 +4981,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT32(save->p, leveltime); WRITEINT16(save->p, lastmap); WRITEUINT16(save->p, bossdisabled); - WRITEUINT8(save->p, ringsdisabled); + WRITEUINT8(save->p, ringsactive); for (i = 0; i < 4; i++) { @@ -5154,7 +5150,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool leveltime = READUINT32(save->p); lastmap = READINT16(save->p); bossdisabled = READUINT16(save->p); - ringsdisabled = READUINT8(save->p); + ringsactive = READUINT8(save->p); for (i = 0; i < 4; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 931f303e5..bad476e4c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -142,7 +142,7 @@ line_t *spawnlines; side_t *spawnsides; INT32 numstarposts; INT32 numbosswaypoints; -boolean ringsdisabled; +boolean ringsactive; UINT16 bossdisabled; boolean stoppedclock; boolean levelloading; @@ -7855,9 +7855,9 @@ static void P_InitLevelSettings(boolean reloadinggamestate) itembreaker = false; if (cv_kartrings.value) - ringsdisabled = false; + ringsactive = true; else - ringsdisabled = true; + ringsactive = false; // emerald hunt hunt1 = hunt2 = hunt3 = NULL; diff --git a/src/p_spec.c b/src/p_spec.c index 676448e0c..7d2ea24b8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1344,10 +1344,10 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor) if (!playeringame[i] || players[i].spectator) continue; - if (!players[i].mo || ((gametyperules & GTR_SPHERES) ? players[i].spheres : players[i].rings) <= 0) + if (!players[i].mo || players[i].rings <= 0) continue; - rings += (gametyperules & GTR_SPHERES) ? players[i].spheres : players[i].rings; + rings += players[i].rings; } } else @@ -1355,7 +1355,7 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor) if (!(actor && actor->player)) return false; // no player to count rings from here, sorry - rings = (gametyperules & GTR_SPHERES) ? actor->player->spheres : actor->player->rings; + rings = actor->player->rings; } switch (triggerline->args[2]) diff --git a/src/p_user.c b/src/p_user.c index 8bdef27cd..aa923b198 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -496,11 +496,8 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings) if (!player->mo) return 0; - - if ((gametyperules & GTR_BUMPERS)) // No rings in Battle Mode - return 0; - if (ringsdisabled) // No rings in when turned off + if ((K_RingsActive() == false)) // No rings when turned off return 0; test = player->rings + num_rings; @@ -514,26 +511,6 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings) return num_rings; } -INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres) -{ - num_spheres += player->spheres; - - // Not alive - if ((gametyperules & GTR_BUMPERS) && (player->bumper <= 0)) - return 0; - - if (num_spheres > 40) // Reached the cap, don't waste 'em! - num_spheres = 40; - else if (num_spheres < 0) - num_spheres = 0; - - num_spheres -= player->spheres; - - player->spheres += num_spheres; - - return num_spheres; -} - // // P_GivePlayerLives // @@ -691,7 +668,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) void P_PlayRinglossSound(mobj_t *source) { - if (ringsdisabled) + if ((K_RingsActive() == false)) return; if (source->player && K_GetShieldFromItem(source->player->itemtype) != KSHIELD_NONE) From 1a42afafa3744d8a4695094698f56debc68eb7d9 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 22 Feb 2025 08:11:23 -0500 Subject: [PATCH 18/21] Adjust player bumping --- src/k_kart.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 12618c2de..fd0e91397 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1630,13 +1630,15 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against) // from causing super crazy bumps. fixed_t spd = K_GetKartSpeed(mobj->player, false, true); - weight = (mobj->player->kartweight) * FRACUNIT; + fixed_t speedfactor = 8 * mapobjectscale; - if (mobj->player->speed > spd) - weight += (mobj->player->speed - spd) / 8; + weight = (mobj->player->kartweight) * FRACUNIT; if (mobj->player->itemtype == KITEM_BUBBLESHIELD) weight += 9*FRACUNIT; + + if (mobj->player->speed > spd) + weight += FixedDiv((mobj->player->speed - spd), speedfactor); } return weight; @@ -1694,7 +1696,7 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) break; } - return FixedMul(weight, mobj->scale); + return weight; } static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2) From 13503bf80beaf37855dd83d1516c2f1d9a00fd96 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 22 Feb 2025 21:51:47 -0500 Subject: [PATCH 19/21] Use Kart calc for bumping --- src/k_kart.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index fd0e91397..c759aa6f7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1630,15 +1630,13 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against) // from causing super crazy bumps. fixed_t spd = K_GetKartSpeed(mobj->player, false, true); - fixed_t speedfactor = 8 * mapobjectscale; - weight = (mobj->player->kartweight) * FRACUNIT; if (mobj->player->itemtype == KITEM_BUBBLESHIELD) weight += 9*FRACUNIT; if (mobj->player->speed > spd) - weight += FixedDiv((mobj->player->speed - spd), speedfactor); + weight += (mobj->player->speed - spd)/8; } return weight; From 894af06eea0f8f362c3d0dfc68ad93d8a9ca4dba Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 22 Feb 2025 21:59:18 -0500 Subject: [PATCH 20/21] Fix HUD for itembreaker with rings enabled --- src/k_hud.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_hud.c b/src/k_hud.c index 910595d98..951c42b05 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2264,6 +2264,9 @@ static void K_drawRingMeter(void) if (gametype == GT_BATTLE) ringoffsety -= 4; + if (itembreaker) + ringoffsety -= 2; + V_DrawScaledPatch(LAPS_X, LAPS_Y-14 + ringoffsety, V_HUDTRANS|splitflags, kp_ringsticker[(stplyr->pflags & PF_RINGLOCK) ? 1 : 0]); if (stplyr->rings < 0) // Draw the minus for ring debt From 3c09716a7873584e272d0ef3a50ed48ad2cd22d2 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 22 Feb 2025 22:07:02 -0500 Subject: [PATCH 21/21] Fix selfhit playing hitem --- src/p_inter.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index d6c87b723..5f1512a80 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2197,10 +2197,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // We successfully damaged them! Give 'em some bumpers! - if (gametyperules & GTR_BUMPERS) + if (source && source != player->mo && source->player) { - - if (source && source != player->mo && source->player) + if (gametyperules & GTR_BUMPERS) { K_BattleAwardHit(source->player, player, inflictor, 1); @@ -2225,13 +2224,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_DestroyBumpers(player, 1); } } - else - { - K_DestroyBumpers(player, 1); - } - } - K_TryHurtSoundExchange(target, source); + K_TryHurtSoundExchange(target, source); + } if (!((damagetype & DMG_NORMAL) || (damagetype & DMG_WIPEOUT))) player->sneakertimer = 0;