From ba3e6765eff380b0f06ff8360c945abc0b1dac00 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 00:39:30 +0100 Subject: [PATCH 01/13] K_DrawKartMinimap: Bugfixes to NO CONTEST X - Fix Race NO CONTEST X not being colormapped - Fix non-local players not being NO CONTEST X-ified --- src/k_hud.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index cd8f77af6..dd141cde7 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3781,7 +3781,7 @@ static void K_drawKartMinimap(void) if (mobj->health <= 0 && (players[i].pflags & PF_NOCONTEST)) { workingPic = kp_nocontestminimap; - R_GetTranslationColormap(0, mobj->color, GTC_CACHE); + colormap = R_GetTranslationColormap(0, mobj->color, GTC_CACHE); if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) mobj = mobj->tracer; @@ -3806,7 +3806,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); // Target reticule if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace) @@ -3912,7 +3912,7 @@ static void K_drawKartMinimap(void) if (mobj->health <= 0 && (players[localplayers[i]].pflags & PF_NOCONTEST)) { workingPic = kp_nocontestminimap; - R_GetTranslationColormap(0, mobj->color, GTC_CACHE); + colormap = R_GetTranslationColormap(0, mobj->color, GTC_CACHE); if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) mobj = mobj->tracer; From 0ac2541eb922ea2d02729fcac2e2993a45be3d4d Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 00:49:06 +0100 Subject: [PATCH 02/13] k_drawKartTImestamp: Clean up SPB Attack distance bar - Use a minimap-like graphic for the background area - The goofy name comes from a delightfully awful development conversation - Make the entire thing snap to the screen's bottom and slide in - Fix a potential sqrt of a negative/zero value --- src/k_hud.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index dd141cde7..284ca4149 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -77,6 +77,7 @@ patch_t *kp_facehighlight[8]; static patch_t *kp_nocontestminimap; static patch_t *kp_spbminimap; +static patch_t *kp_wouldyoustillcatchmeifiwereaworm; static patch_t *kp_capsuleminimap[3]; static patch_t *kp_ringsticker[2]; @@ -348,7 +349,11 @@ void K_LoadKartHUDGraphics(void) // Special minimap icons HU_UpdatePatch(&kp_nocontestminimap, "MINIDEAD"); + HU_UpdatePatch(&kp_spbminimap, "SPBMMAP"); + + HU_UpdatePatch(&kp_wouldyoustillcatchmeifiwereaworm, "MINIPROG"); + HU_UpdatePatch(&kp_capsuleminimap[0], "MINICAP1"); HU_UpdatePatch(&kp_capsuleminimap[1], "MINICAP2"); HU_UpdatePatch(&kp_capsuleminimap[2], "MINICAP3"); @@ -1662,17 +1667,27 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U if (modeattacking & ATTACKING_SPB && stplyr->SPBdistance > 0) { UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - int ybar = 180; - int widthbar = 120; + INT32 ybar = 180; + INT32 widthbar = 120, xbar = 160 - widthbar/2, currentx; + INT32 barflags = V_SNAPTOBOTTOM|V_SLIDEIN; - V_DrawFill(160 - widthbar / 2, ybar, widthbar, 1, 6); - V_DrawMappedPatch(160 + widthbar/2 - 7, ybar - 7, FRACUNIT, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); + V_DrawScaledPatch(xbar, ybar - 2, barflags|minimaptrans, kp_wouldyoustillcatchmeifiwereaworm); + + V_DrawMappedPatch(160 + widthbar/2 - 7, ybar - 7, barflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); // vibes-based math - int bombxoff = (stplyr->SPBdistance/mapobjectscale - mobjinfo[MT_SPB].radius/FRACUNIT - mobjinfo[MT_PLAYER].radius/FRACUNIT) * 8; - bombxoff = sqrt(bombxoff) - 5; - bombxoff = max(0, min(bombxoff, widthbar)); - V_DrawScaledPatch(160 + widthbar/2 - bombxoff, ybar - 7, FRACUNIT, W_CachePatchName("SPBMMAP", PU_CACHE)); + currentx = (stplyr->SPBdistance/mapobjectscale - mobjinfo[MT_SPB].radius/FRACUNIT - mobjinfo[MT_PLAYER].radius/FRACUNIT) * 8; + if (currentx > 0) + { + currentx = sqrt(currentx); + if (currentx > widthbar) + currentx = widthbar; + } + else + { + currentx = 0; + } + V_DrawScaledPatch(xbar - currentx - 5, ybar - 7, barflags, kp_spbminimap); } } From e82082fd066d56fd917d6e9a471e4207d1da1304 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 00:51:28 +0100 Subject: [PATCH 03/13] K_UpdateDistanceFromFinishLine: Do not destroy distancetofinish value if the player NO CONTESTed --- src/k_hud.c | 2 +- src/k_kart.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 284ca4149..1b17024fa 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1671,7 +1671,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U INT32 widthbar = 120, xbar = 160 - widthbar/2, currentx; INT32 barflags = V_SNAPTOBOTTOM|V_SLIDEIN; - V_DrawScaledPatch(xbar, ybar - 2, barflags|minimaptrans, kp_wouldyoustillcatchmeifiwereaworm); + V_DrawScaledPatch(xbar, ybar - 2, barflags, kp_wouldyoustillcatchmeifiwereaworm); V_DrawMappedPatch(160 + widthbar/2 - 7, ybar - 7, barflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); diff --git a/src/k_kart.c b/src/k_kart.c index 48f1afaa8..571d1587b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8592,11 +8592,16 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) } // nextwaypoint is now the waypoint that is in front of us - if (player->exiting || player->spectator) + if ((player->exiting && !(player->pflags & PF_NOCONTEST)) || player->spectator) { // Player has finished, we don't need to calculate this player->distancetofinish = 0U; } + else if (player->pflags & PF_NOCONTEST) + { + // We also don't need to calculate this, but there's also no need to destroy the data... + ; + } else if ((player->currentwaypoint != NULL) && (player->nextwaypoint != NULL) && (finishline != NULL)) { const boolean useshortcuts = false; From 7abb2ce162c17ab0ff33707f529fed6eb320e5fa Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 00:59:40 +0100 Subject: [PATCH 04/13] K_drawKartMinimap: Add progression meter variation - Uses a lot of existing apparatus, just leveraged to draw horizontally instead of a full map. - Currently only functional in Sealed Star contexts, due to K_GetCircuitLength having no clean alternative for sprint tracks. - Tracks Catcher/Emerald. - K_drawKartProgressionMinimapIcon and K_getKartProgressionMinimapDistance - Abstracts the progress of converting distance to finish into a position on the bar. - Sibling function of K_drawKartMinimapIcon - The author of this commit wanted to make it an alternate outcome of this function, which it shares a lot of similarity with, but doing waypoint traversal in HUD for objects that don't independently track their distance would absolutely tank performance. - Tidying up in the main function permitted less minimap state to be used in these. --- src/k_hud.c | 262 ++++++++++++++++++++++++++++++++++--------- src/k_specialstage.h | 4 +- src/objects/ufo.c | 2 + 3 files changed, 214 insertions(+), 54 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 1b17024fa..ea84a3528 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -13,6 +13,8 @@ #include "k_kart.h" #include "k_battle.h" #include "k_grandprix.h" +#include "k_specialstage.h" +#include "k_objects.h" #include "k_boss.h" #include "k_color.h" #include "k_director.h" @@ -78,6 +80,8 @@ patch_t *kp_facehighlight[8]; static patch_t *kp_nocontestminimap; static patch_t *kp_spbminimap; static patch_t *kp_wouldyoustillcatchmeifiwereaworm; +static patch_t *kp_catcherminimap; +static patch_t *kp_emeraldminimap; static patch_t *kp_capsuleminimap[3]; static patch_t *kp_ringsticker[2]; @@ -353,6 +357,8 @@ void K_LoadKartHUDGraphics(void) HU_UpdatePatch(&kp_spbminimap, "SPBMMAP"); HU_UpdatePatch(&kp_wouldyoustillcatchmeifiwereaworm, "MINIPROG"); + HU_UpdatePatch(&kp_catcherminimap, "UFOMAP"); + HU_UpdatePatch(&kp_emeraldminimap, "EMEMAP"); HU_UpdatePatch(&kp_capsuleminimap[0], "MINICAP1"); HU_UpdatePatch(&kp_capsuleminimap[1], "MINICAP2"); @@ -3567,6 +3573,47 @@ static void K_drawKartNameTags(void) } } +#define PROGRESSION_BAR_WIDTH 120 + +static INT32 K_getKartProgressionMinimapDistance(UINT32 distancetofinish) +{ + INT32 dist; + + if (specialstageinfo.maxDist == 0U) + { + return 0; + } + + dist = specialstageinfo.maxDist/PROGRESSION_BAR_WIDTH; + + dist = (specialstageinfo.maxDist-distancetofinish)/dist; + + if (dist > PROGRESSION_BAR_WIDTH) + { + return PROGRESSION_BAR_WIDTH; + } + + if (dist < 0) + { + return 0; + } + + return dist; +} + +static void K_drawKartProgressionMinimapIcon(UINT32 distancetofinish, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap) +{ + if (distancetofinish == UINT32_MAX) + return; + + hudx += K_getKartProgressionMinimapDistance(distancetofinish); + + hudx = ((hudx - (SHORT(icon->width)/2))<height)/2))<width)-SHORT(icon->width))/2)<height)-SHORT(icon->height))/2)<width))/2)<height))/2)<width) / 2); - amypos = (amnumypos / FRACUNIT) + (SHORT(minimapinfo.minimap_pic->height) / 2); + amxpos = (amnumxpos / FRACUNIT); + amypos = (amnumypos / FRACUNIT); if (flags & V_NOSCALESTART) { @@ -3649,17 +3696,26 @@ static void K_drawKartMinimapWaypoint(waypoint_t *wp, INT32 hudx, INT32 hudy, IN static void K_drawKartMinimap(void) { patch_t *workingPic; + INT32 i = 0; INT32 x, y; + INT32 minimaptrans = 4; INT32 splitflags = 0; + UINT8 skin = 0; UINT8 *colormap = NULL; + SINT8 localplayers[MAXSPLITSCREENPLAYERS]; SINT8 numlocalplayers = 0; + mobj_t *mobj, *next; // for SPB drawing (or any other item(s) we may wanna draw, I dunno!) + fixed_t interpx, interpy; + boolean doprogressionbar = false; + boolean dofade = false, doencore = false; + // Draw the HUD only when playing in a level. // hu_stuff needs this, unlike st_stuff. if (gamestate != GS_LEVEL) @@ -3670,16 +3726,58 @@ static void K_drawKartMinimap(void) if (stplyr != &players[displayplayers[0]]) return; - if (minimapinfo.minimap_pic == NULL) + if (specialstageinfo.valid == true) { - return; // no pic, just get outta here + // future work: maybe make this a unique gametype rule? + // I would do this now if it were easier to get the + // distancetofinish for an arbitrary object. ~toast 070423 + doprogressionbar = true; } - if (r_splitscreen < 2) // 1/2P right aligned + if (doprogressionbar == false) { - splitflags = (V_SLIDEIN|V_SNAPTORIGHT); + if (minimapinfo.minimap_pic == NULL) + { + return; // no pic, just get outta here + } + + else if (r_splitscreen < 2) // 1/2P right aligned + { + splitflags = (V_SLIDEIN|V_SNAPTORIGHT); + } + else if (r_splitscreen == 3) // 4P splits + { + dofade = true; + } + // 3P lives in the middle of the bottom right + // viewport and shouldn't fade in OR slide + + x = MINI_X; + y = MINI_Y; + + workingPic = minimapinfo.minimap_pic; + + doencore = encoremode; } - else if (r_splitscreen == 3) // 4P centered + else + { + x = BASEVIDWIDTH/2; + + if (r_splitscreen > 0) + { + y = BASEVIDHEIGHT/2; + dofade = true; + } + else + { + y = 180; + splitflags = (V_SLIDEIN|V_SNAPTOBOTTOM); + } + + workingPic = kp_wouldyoustillcatchmeifiwereaworm; + } + + if (dofade) { const tic_t length = TICRATE/2; @@ -3687,34 +3785,49 @@ static void K_drawKartMinimap(void) return; if (lt_exitticker < length) minimaptrans = (((INT32)lt_exitticker)*minimaptrans)/((INT32)length); + + if (!minimaptrans) + return; } - // 3P lives in the middle of the bottom right player and shouldn't fade in OR slide - - if (!minimaptrans) - return; - - x = MINI_X - (SHORT(minimapinfo.minimap_pic->width)/2); - y = MINI_Y - (SHORT(minimapinfo.minimap_pic->height)/2); minimaptrans = ((10-minimaptrans)<width), y, splitflags|minimaptrans|V_FLIP, minimapinfo.minimap_pic); + if (doencore) + { + V_DrawScaledPatch( + x + (SHORT(workingPic->width)/2), + y - (SHORT(workingPic->height)/2), + splitflags|minimaptrans|V_FLIP, + workingPic + ); + } else - V_DrawScaledPatch(x, y, splitflags|minimaptrans, minimapinfo.minimap_pic); + { + V_DrawScaledPatch( + x - (SHORT(workingPic->width)/2), + y - (SHORT(workingPic->height)/2), + splitflags|minimaptrans, + workingPic + ); + } // most icons will be rendered semi-ghostly. splitflags |= V_HUDTRANSHALF; // let offsets transfer to the heads, too! - if (encoremode) - x += SHORT(minimapinfo.minimap_pic->leftoffset); + if (doencore) + x += SHORT(workingPic->leftoffset); else - x -= SHORT(minimapinfo.minimap_pic->leftoffset); - y -= SHORT(minimapinfo.minimap_pic->topoffset); + x -= SHORT(workingPic->leftoffset); + y -= SHORT(workingPic->topoffset); + + if (doprogressionbar == true) + { + x -= PROGRESSION_BAR_WIDTH/2; + } // Draw the super item in Battle - if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled) + if (doprogressionbar == false && (gametyperules & GTR_OVERTIME) && battleovertime.enabled) { if (battleovertime.enabled >= 10*TICRATE || (battleovertime.enabled & 1)) { @@ -3732,7 +3845,7 @@ static void K_drawKartMinimap(void) localplayers[i] = -1; // Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen) - if (ghosts) + if (ghosts && doprogressionbar == true) // future work: show ghosts on progression bar { demoghost *g = ghosts; while (g) @@ -3757,19 +3870,15 @@ static void K_drawKartMinimap(void) K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap); g = g->next; } - - if (!stplyr->mo || stplyr->spectator || stplyr->exiting) - return; - - localplayers[numlocalplayers++] = stplyr-players; } - else + { for (i = MAXPLAYERS-1; i >= 0; i--) { if (!playeringame[i]) continue; - if (!players[i].mo || players[i].spectator || !players[i].mo->skin || players[i].exiting) + if (!players[i].mo || players[i].spectator || !players[i].mo->skin + || (doprogressionbar == false && players[i].exiting)) continue; // This player is out of the game! @@ -3818,22 +3927,33 @@ static void K_drawKartMinimap(void) colormap = NULL; } - interpx = R_InterpolateFixed(mobj->old_x, mobj->x); - interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); - - // Target reticule - if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace) - || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[i]))) + if (doprogressionbar == false) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + interpx = R_InterpolateFixed(mobj->old_x, mobj->x); + interpy = R_InterpolateFixed(mobj->old_y, mobj->y); + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + + // Target reticule + if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace) + || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[i]))) + { + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + } + } + else + { + K_drawKartProgressionMinimapIcon(players[i].distancetofinish, x, y, splitflags, workingPic, colormap); } } } // draw minimap-pertinent objects - for (mobj = trackercap; mobj; mobj = next) + if (doprogressionbar == true) + { + // future work: support these specific objects on this + } + else for (mobj = trackercap; mobj; mobj = next) { next = mobj->itnext; @@ -3887,7 +4007,34 @@ static void K_drawKartMinimap(void) } // ...but first, any boss targets. - if (bossinfo.valid == true) + if (doprogressionbar == true) + { + if (specialstageinfo.valid == true) + { + UINT32 distancetofinish = K_GetSpecialUFODistance(); + if (distancetofinish > 0 && specialstageinfo.ufo != NULL && P_MobjWasRemoved(specialstageinfo.ufo) == false) + { + colormap = NULL; + if (specialstageinfo.ufo->health > 1) + { + workingPic = kp_catcherminimap; + } + else + { + workingPic = kp_emeraldminimap; + if (specialstageinfo.ufo->color) + { + colormap = R_GetTranslationColormap(TC_DEFAULT, specialstageinfo.ufo->color, GTC_CACHE); + } + } + + K_drawKartProgressionMinimapIcon(distancetofinish, x, y, splitflags, workingPic, colormap); + } + } + + // future work: support boss minimap icons on the progression bar + } + else if (bossinfo.valid == true) { for (i = 0; i < NUMWEAKSPOTS; i++) { @@ -3949,20 +4096,27 @@ static void K_drawKartMinimap(void) colormap = NULL; } - interpx = R_InterpolateFixed(mobj->old_x, mobj->x); - interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); - - // Target reticule - if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace) - || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[localplayers[i]]))) + if (doprogressionbar == false) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + interpx = R_InterpolateFixed(mobj->old_x, mobj->x); + interpy = R_InterpolateFixed(mobj->old_y, mobj->y); + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + + // Target reticule + if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace) + || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[localplayers[i]]))) + { + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + } + } + else + { + K_drawKartProgressionMinimapIcon(players[i].distancetofinish, x, y, splitflags, workingPic, colormap); } } - if (cv_kartdebugwaypoints.value != 0) + if (doprogressionbar == false && cv_kartdebugwaypoints.value != 0) { size_t idx; @@ -3983,6 +4137,8 @@ static void K_drawKartMinimap(void) } } +#undef PROGRESSION_BAR_WIDTH + static void K_drawKartFinish(boolean finish) { INT32 timer, minsplitstationary, pnum = 0, splitflags = V_SPLITSCREEN; diff --git a/src/k_specialstage.h b/src/k_specialstage.h index 6b20ca220..329d7f99f 100644 --- a/src/k_specialstage.h +++ b/src/k_specialstage.h @@ -24,8 +24,10 @@ extern struct specialstageinfo { boolean valid; ///< If true, then data in this struct is valid - UINT32 beamDist; ///< Where the exit beam is. mobj_t *ufo; ///< The Chaos Emerald capsule. + UINT32 maxDist; ///< The distance from one end of the track to another. + + UINT32 beamDist; ///< Where the exit beam is. } specialstageinfo; /*-------------------------------------------------- diff --git a/src/objects/ufo.c b/src/objects/ufo.c index a632986d0..9774c5894 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -345,6 +345,7 @@ static void UFOMove(mobj_t *ufo) ufo->momx = 0; ufo->momy = 0; ufo->momz = ufo_speed(ufo); + ufo_distancetofinish(ufo) = 0; return; } @@ -901,6 +902,7 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) ufo = P_SpawnMobj(start->mobj->x, start->mobj->y, start->mobj->z, MT_SPECIAL_UFO); ufo_waypoint(ufo) = (INT32)K_GetWaypointHeapIndex(start); UFOUpdateDistanceToFinish(ufo); + specialstageinfo.maxDist = ufo_distancetofinish(ufo); } ufo_speed(ufo) = FixedMul(UFO_START_SPEED, K_GetKartGameSpeedScalar(gamespeed)); From 1f018f8d274750d2e8fc8d8c6a68e16dfe78f25b Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 18:03:29 +0100 Subject: [PATCH 05/13] k_hud.c: Consistently use TC_DEFAULT instead of 0 for R_GetTranslationColormap --- src/k_hud.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index ea84a3528..f4261f302 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3045,7 +3045,7 @@ static void K_drawKartWanted(void) } if (battlewanted[0] != -1) - colormap = R_GetTranslationColormap(0, players[battlewanted[0]].skincolor, GTC_CACHE); + colormap = R_GetTranslationColormap(TC_DEFAULT, players[battlewanted[0]].skincolor, GTC_CACHE); V_DrawFixedPatch(basex< 1 ? kp_wantedsplit : kp_wanted), colormap); /*if (basey2) V_DrawFixedPatch(basex<health <= 0 && (players[i].pflags & PF_NOCONTEST)) { workingPic = kp_nocontestminimap; - colormap = R_GetTranslationColormap(0, mobj->color, GTC_CACHE); + colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE); if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) mobj = mobj->tracer; @@ -4074,7 +4074,7 @@ static void K_drawKartMinimap(void) if (mobj->health <= 0 && (players[localplayers[i]].pflags & PF_NOCONTEST)) { workingPic = kp_nocontestminimap; - colormap = R_GetTranslationColormap(0, mobj->color, GTC_CACHE); + colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE); if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) mobj = mobj->tracer; @@ -4750,7 +4750,7 @@ static void K_drawInput(void) else { UINT8 *colormap; - colormap = R_GetTranslationColormap(0, stplyr->skincolor, GTC_CACHE); + colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); V_DrawFixedPatch(x< Date: Fri, 7 Apr 2023 19:32:46 +0100 Subject: [PATCH 06/13] UFO Catcher can now carry Emeralds other than the Green Chaos Emerald - Uses P_GetNextEmerald to determine the associated emerald. Earlier work paying dividends! - Color selected matching Cup Select screen - New states which can be used in other contexts - S_SUPEREMERALD1 and S_SUPEREMERALD2 - S_SUPEREMERALD_UNDER --- src/deh_tables.c | 5 +++++ src/info.c | 8 +++++++- src/info.h | 6 ++++++ src/objects/ufo.c | 43 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index cfe834370..764bf9742 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1219,6 +1219,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_CHAOSEMERALD2", "S_CHAOSEMERALD_UNDER", + // Super Emeralds + "S_SUPEREMERALD1", + "S_SUPEREMERALD2", + "S_SUPEREMERALD_UNDER", + "S_EMERALDSPARK1", "S_EMERALDSPARK2", "S_EMERALDSPARK3", diff --git a/src/info.c b/src/info.c index 8cfb54d28..e2c00bd88 100644 --- a/src/info.c +++ b/src/info.c @@ -144,6 +144,7 @@ char sprnames[NUMSPRITES + 1][5] = "NSTR", // NiGHTS star "EMBM", // Emblem "EMRC", // Chaos Emeralds + "SEMR", // Super Emeralds "ESPK", "SHRD", // Emerald Hunt @@ -1775,6 +1776,11 @@ state_t states[NUMSTATES] = {SPR_EMRC, FF_FULLBRIGHT|FF_ADD, 1, {NULL}, 0, 0, S_CHAOSEMERALD1}, // S_CHAOSEMERALD2 {SPR_EMRC, FF_FULLBRIGHT|1, -1, {NULL}, 1, 0, S_NULL}, // S_CHAOSEMERALD_UNDER + // Super Emeralds + {SPR_SEMR, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_SUPEREMERALD2}, // S_SUPEREMERALD1 + {SPR_SEMR, FF_FULLBRIGHT|FF_ADD, 1, {NULL}, 0, 0, S_SUPEREMERALD1}, // S_SUPEREMERALD2 + {SPR_SEMR, FF_FULLBRIGHT|1, -1, {NULL}, 1, 0, S_NULL}, // S_SUPEREMERALD_UNDER + {SPR_ESPK, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EMERALDSPARK2}, // S_EMERALDSPARK1 {SPR_ESPK, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_EMERALDSPARK3}, // S_EMERALDSPARK2 {SPR_ESPK, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_EMERALDSPARK4}, // S_EMERALDSPARK3 @@ -29318,7 +29324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_SPECIAL_UFO -1, // doomednum - S_CHAOSEMERALD1, // spawnstate + S_INVISIBLE, // spawnstate 101, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/info.h b/src/info.h index f7496fc14..47ce02a7e 100644 --- a/src/info.h +++ b/src/info.h @@ -695,6 +695,7 @@ typedef enum sprite SPR_NSTR, // NiGHTS star SPR_EMBM, // Emblem SPR_EMRC, // Chaos Emeralds + SPR_SEMR, // Super Emeralds SPR_ESPK, SPR_SHRD, // Emerald Hunt @@ -2256,6 +2257,11 @@ typedef enum state S_CHAOSEMERALD2, S_CHAOSEMERALD_UNDER, + // Super Emeralds + S_SUPEREMERALD1, + S_SUPEREMERALD2, + S_SUPEREMERALD_UNDER, + S_EMERALDSPARK1, S_EMERALDSPARK2, S_EMERALDSPARK3, diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 9774c5894..4aa9b949f 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -907,15 +907,44 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) ufo_speed(ufo) = FixedMul(UFO_START_SPEED, K_GetKartGameSpeedScalar(gamespeed)); - // TODO: Adjustable Special Stage emerald color - ufo->color = SKINCOLOR_CHAOSEMERALD1; + // Adjustable Special Stage emerald color/shape + { + overlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY); - overlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY); - P_SetTarget(&overlay->target, ufo); - overlay->color = ufo->color; + ufo->color = SKINCOLOR_CHAOSEMERALD1; + i = P_GetNextEmerald(); + if (i > 0) + { + ufo->color += (i - 1) % 7; + if (i > 7) + { + // Super Emeralds + P_SetMobjState(ufo, S_SUPEREMERALD1); + P_SetMobjState(overlay, S_SUPEREMERALD_UNDER); + } + else + { + // Chaos Emerald + P_SetMobjState(ufo, S_CHAOSEMERALD1); + P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER); + } + } + else + { + // Prize -- todo, currently using standard Emerald + P_SetMobjState(ufo, S_CHAOSEMERALD1); + P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER); + } - // TODO: Super Emeralds / Chaos Rings - P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER); + if (P_MobjWasRemoved(ufo)) // uh oh ! + { + // Attempted crash prevention with custom SOC + return NULL; + } + + overlay->color = ufo->color; + P_SetTarget(&overlay->target, ufo); + } // Create UFO pieces. // First: UFO center. From 03049db837c91a0439e5cc7c1ca22ee7a4a0fee1 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 21:01:36 +0100 Subject: [PATCH 07/13] UFO Catchet glass ball Preliminary offset, no effects, but closer to complete visually. --- src/deh_tables.c | 2 ++ src/info.c | 4 ++++ src/info.h | 4 ++++ src/objects/ufo.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 764bf9742..bdb74b55b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4562,6 +4562,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SPECIAL_UFO_POD", "S_SPECIAL_UFO_OVERLAY", + "S_SPECIAL_UFO_GLASS", + "S_SPECIAL_UFO_GLASS_UNDER", "S_SPECIAL_UFO_ARM", "S_SPECIAL_UFO_STEM", diff --git a/src/info.c b/src/info.c index e2c00bd88..253baa581 100644 --- a/src/info.c +++ b/src/info.c @@ -795,6 +795,8 @@ char sprnames[NUMSPRITES + 1][5] = "UFOB", "UFOA", "UFOS", + "SSCA", + "SSCB", "UQMK", @@ -5190,6 +5192,8 @@ state_t states[NUMSTATES] = {SPR_UFOB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_POD {SPR_UFOB, 1|FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_SPECIAL_UFO_OVERLAY + {SPR_SSCA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_GLASS + {SPR_SSCB, FF_SUBTRACT, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_GLASS_UNDER {SPR_UFOA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_ARM {SPR_UFOS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_STEM diff --git a/src/info.h b/src/info.h index 47ce02a7e..6c9d7c773 100644 --- a/src/info.h +++ b/src/info.h @@ -1346,6 +1346,8 @@ typedef enum sprite SPR_UFOB, SPR_UFOA, SPR_UFOS, + SPR_SSCA, + SPR_SSCB, SPR_UQMK, @@ -5616,6 +5618,8 @@ typedef enum state S_SPECIAL_UFO_POD, S_SPECIAL_UFO_OVERLAY, + S_SPECIAL_UFO_GLASS, + S_SPECIAL_UFO_GLASS_UNDER, S_SPECIAL_UFO_ARM, S_SPECIAL_UFO_STEM, diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 4aa9b949f..ef71da4c0 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -54,6 +54,8 @@ enum { UFO_PIECE_TYPE_POD, + UFO_PIECE_TYPE_GLASS, + UFO_PIECE_TYPE_GLASS_UNDER, UFO_PIECE_TYPE_ARM, UFO_PIECE_TYPE_STEM, }; @@ -544,6 +546,8 @@ static void UFOKillPiece(mobj_t *piece) switch (ufo_piece_type(piece)) { + case UFO_PIECE_TYPE_GLASS: + case UFO_PIECE_TYPE_GLASS_UNDER: case UFO_PIECE_TYPE_STEM: { piece->tics = 1; @@ -794,18 +798,25 @@ void Obj_UFOPieceThink(mobj_t *piece) return; } - piece->destscale = 3 * ufo->destscale / 2; piece->scalespeed = ufo->scalespeed; switch (ufo_piece_type(piece)) { case UFO_PIECE_TYPE_POD: { + piece->destscale = 3 * ufo->destscale / 2; UFOMoveTo(piece, ufo->x, ufo->y, ufo->z + (132 * piece->scale)); if (S_SoundPlaying(ufo, sfx_clawzm) && ufo_speed(ufo) > 70*FRACUNIT) SpawnUFOSpeedLines(piece); break; } + case UFO_PIECE_TYPE_GLASS: + case UFO_PIECE_TYPE_GLASS_UNDER: + { + piece->destscale = ufo->destscale; + UFOMoveTo(piece, ufo->x, ufo->y, ufo->z); + break; + } case UFO_PIECE_TYPE_ARM: { fixed_t dis = (88 * piece->scale); @@ -813,6 +824,7 @@ void Obj_UFOPieceThink(mobj_t *piece) fixed_t x = ufo->x - FixedMul(dis, FINECOSINE(piece->angle >> ANGLETOFINESHIFT)); fixed_t y = ufo->y - FixedMul(dis, FINESINE(piece->angle >> ANGLETOFINESHIFT)); + piece->destscale = 3 * ufo->destscale / 2; UFOMoveTo(piece, x, y, ufo->z + (24 * piece->scale)); piece->angle -= FixedMul(ANG2, FixedDiv(ufo_speed(ufo), UFO_BASE_SPEED)); @@ -823,6 +835,7 @@ void Obj_UFOPieceThink(mobj_t *piece) fixed_t stemZ = ufo->z + (294 * piece->scale); fixed_t sc = FixedDiv(FixedDiv(ufo->ceilingz - stemZ, piece->scale), 15 * FRACUNIT); + piece->destscale = 3 * ufo->destscale / 2; UFOMoveTo(piece, ufo->x, ufo->y, stemZ); if (sc > 0) { @@ -961,6 +974,39 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) P_SetTarget(&ufo_pieces(ufo), piece); prevPiece = piece; + // Next, the glass ball. + { + piece = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_SPECIAL_UFO_PIECE); + P_SetTarget(&ufo_piece_owner(piece), ufo); + + P_SetMobjState(piece, S_SPECIAL_UFO_GLASS); + ufo_piece_type(piece) = UFO_PIECE_TYPE_GLASS; + + /*overlay = P_SpawnMobjFromMobj(piece, 0, 0, 0, MT_OVERLAY); + P_SetTarget(&overlay->target, piece); + P_SetMobjState(overlay, S_SPECIAL_UFO_GLASS_UNDER); + overlay->dispoffset = -20;*/ + + P_SetTarget(&ufo_piece_next(prevPiece), piece); + P_SetTarget(&ufo_piece_prev(piece), prevPiece); + prevPiece = piece; + } + + // This SHOULD have been an MT_OVERLAY... but it simply doesn't + // draw-order stack with the Emerald correctly any other way. + { + piece = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_SPECIAL_UFO_PIECE); + P_SetTarget(&ufo_piece_owner(piece), ufo); + + P_SetMobjState(piece, S_SPECIAL_UFO_GLASS_UNDER); + ufo_piece_type(piece) = UFO_PIECE_TYPE_GLASS_UNDER; + piece->dispoffset = -2; + + P_SetTarget(&ufo_piece_next(prevPiece), piece); + P_SetTarget(&ufo_piece_prev(piece), prevPiece); + prevPiece = piece; + } + // Add the catcher arms. for (i = 0; i < UFO_NUMARMS; i++) { From 6108aa3dd6f72d94842d2fddae8c88f75d5cfdab Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 22:36:32 +0100 Subject: [PATCH 08/13] Spawn shards on UFO Catcher glass damage Involves some code adapted from monitor.c ... I couldn't just expose it via k_object.h because the clean entrypoint was JUST too specific to Monitors --- src/objects/ufo.c | 96 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index ef71da4c0..dda10760b 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -517,6 +517,90 @@ void Obj_SpecialUFOThinker(mobj_t *ufo) } } +// The following is adapted from monitor.c for UFO Catcher damage +// I couldn't just exose the relevant things via k_object.h +// because they're *just* too specific to Monitors... ~toast 070423 + +#define shard_can_roll(o) ((o)->extravalue1) + +static inline boolean +can_shard_state_roll (statenum_t state) +{ + switch (state) + { + case S_MONITOR_BIG_SHARD: + case S_MONITOR_SMALL_SHARD: + return true; + + default: + return false; + } +} + +static void +spawn_shard +( mobj_t * part, + statenum_t state) +{ + mobj_t *ufo = ufo_piece_owner(part); + + // These divisions and multiplications are done on the + // offsets to give bigger increments of randomness. + + const fixed_t h = FixedDiv( + ufo->height, ufo->scale); + + const UINT16 rad = (ufo->radius / ufo->scale) / 4; + const UINT16 tall = (h / FRACUNIT); + + mobj_t *p = P_SpawnMobjFromMobj(ufo, + P_RandomRange(PR_ITEM_DEBRIS, -(rad), rad) * 8 * FRACUNIT, + P_RandomRange(PR_ITEM_DEBRIS, -(rad), rad) * 8 * FRACUNIT, + P_RandomKey(PR_ITEM_DEBRIS, tall + 1) * 4 * FRACUNIT, + MT_MONITOR_SHARD); + + P_SetScale(p, (p->destscale = p->destscale * 3)); + + angle_t th = R_PointToAngle2(ufo->x, ufo->y, p->x, p->y); + + th -= P_RandomKey(PR_ITEM_DEBRIS, ANGLE_45) - ANGLE_22h; + + p->hitlag = 0; + + P_Thrust(p, th, 6 * p->scale); + p->momz = P_RandomRange(PR_ITEM_DEBRIS, 3, 10) * p->scale; + + P_SetMobjState(p, state); + + shard_can_roll(p) = can_shard_state_roll(state); + + if (shard_can_roll(p)) + { + p->rollangle = P_Random(PR_ITEM_DEBRIS); + } + + if (P_RandomChance(PR_ITEM_DEBRIS, FRACUNIT/2)) + { + p->renderflags |= RF_DONTDRAW; + } +} + +static void +spawn_debris (mobj_t *part) +{ + mobj_t *ufo = ufo_piece_owner(part); + + INT32 i; + + for (i = ufo->health; + i <= mobjinfo[ufo->type].spawnhealth; i += 5) + { + spawn_shard(part, S_MONITOR_BIG_SHARD); + spawn_shard(part, S_MONITOR_SMALL_SHARD); + spawn_shard(part, S_MONITOR_TWINKLE); + } +} + static void UFOCopyHitlagToPieces(mobj_t *ufo) { mobj_t *piece = NULL; @@ -526,6 +610,12 @@ static void UFOCopyHitlagToPieces(mobj_t *ufo) { piece->hitlag = ufo->hitlag; piece->eflags = (piece->eflags & ~MFE_DAMAGEHITLAG) | (ufo->eflags & MFE_DAMAGEHITLAG); + + if (ufo_piece_type(piece) == UFO_PIECE_TYPE_GLASS) + { + spawn_debris (piece); + } + piece = ufo_piece_next(piece); } } @@ -691,15 +781,16 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN // Speed up on damage! ufo_speed(ufo) += addSpeed; + ufo->health = max(1, ufo->health - damage); + K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true); UFOCopyHitlagToPieces(ufo); - if (damage >= ufo->health - 1) + if (ufo->health == 1) { // Destroy the UFO parts, and make the emerald collectible! UFOKillPieces(ufo); - ufo->health = 1; ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW); ufo->shadowscale = FRACUNIT/3; @@ -716,7 +807,6 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN S_StartSound(ufo, sfx_clawht); S_StopSoundByID(ufo, sfx_clawzm); P_StartQuake(64<health -= damage; return true; } From c7c78bc72b3f7b51a95461c74660922a9ab86d16 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 23:18:08 +0100 Subject: [PATCH 09/13] K_drawTargetHUD: Track at sprite x/y/z offset in 3d space --- src/k_hud_track.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_hud_track.cpp b/src/k_hud_track.cpp index 9d2e23f23..d44f46fbb 100644 --- a/src/k_hud_track.cpp +++ b/src/k_hud_track.cpp @@ -411,9 +411,9 @@ void K_drawTargetHUD(const vector3_t* origin, player_t* player) } vector3_t pos = { - R_InterpolateFixed(mobj->old_x, mobj->x), - R_InterpolateFixed(mobj->old_y, mobj->y), - R_InterpolateFixed(mobj->old_z, mobj->z) + (mobj->height >> 1), + R_InterpolateFixed(mobj->old_x, mobj->x) + mobj->sprxoff, + R_InterpolateFixed(mobj->old_y, mobj->y) + mobj->spryoff, + R_InterpolateFixed(mobj->old_z, mobj->z) + mobj->sprzoff + (mobj->height >> 1), }; targetList.push_back({mobj, pos, R_PointToDist2(origin->x, origin->y, pos.x, pos.y)}); From 2969aabae4d491418ad6d6139e71c143301b6bd7 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 23:36:30 +0100 Subject: [PATCH 10/13] UFO Catcher: Adjust for changed glass graphic --- src/objects/ufo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index dda10760b..f69f43cd9 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -903,7 +903,7 @@ void Obj_UFOPieceThink(mobj_t *piece) case UFO_PIECE_TYPE_GLASS: case UFO_PIECE_TYPE_GLASS_UNDER: { - piece->destscale = ufo->destscale; + piece->destscale = 5 * ufo->destscale / 3; UFOMoveTo(piece, ufo->x, ufo->y, ufo->z); break; } From 307d78130f1a0f9e8ef258f9f0e9f2c0f3f64974 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 23:36:46 +0100 Subject: [PATCH 11/13] UFO Catcher: Adjust sprite z offset of prize inside glass orb --- src/objects/ufo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index f69f43cd9..3e85b59e1 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -1047,6 +1047,8 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) overlay->color = ufo->color; P_SetTarget(&overlay->target, ufo); + + ufo->sprzoff = 32 * mapobjectscale; } // Create UFO pieces. From 6ae455dbfc028eb47579af4864e1bf55af0c4576 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Apr 2023 23:53:00 +0100 Subject: [PATCH 12/13] Add MF_DONTENCOREMAP to Monitor assets (+ Magician Box) --- src/info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 253baa581..1edddcb49 100644 --- a/src/info.c +++ b/src/info.c @@ -22540,7 +22540,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOSQUISH, // flags + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOSQUISH|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -22567,7 +22567,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOSQUISH, // flags + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOSQUISH|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -22594,7 +22594,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, From 4b7aa368b55fa2c49fd6f9b5c85955c37f3cedbb Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Apr 2023 00:05:18 +0100 Subject: [PATCH 13/13] P_GetNextEmerald: Accomodate map reuse in GP - In GP, use struct's cup pointer to get Emerald so the active cup ID is in control - Outside of GP, get cup pointer from map so Emerald is always the "canon" one --- src/p_user.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 71d8eb630..46829d0b7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -313,15 +313,29 @@ boolean P_PlayerMoving(INT32 pnum) // UINT8 P_GetNextEmerald(void) { - INT16 mapnum = gamemap-1; + cupheader_t *cup = NULL; - if (mapnum > nummapheaders || !mapheaderinfo[mapnum]) + if (grandprixinfo.gp == true) + { + cup = grandprixinfo.cup; + } + + if (cup == NULL) + { + INT16 mapnum = gamemap-1; + + if (mapnum < nummapheaders && mapheaderinfo[mapnum]) + { + cup = mapheaderinfo[mapnum]->cup; + } + } + + if (cup == NULL) + { return 0; + } - if (!mapheaderinfo[mapnum]->cup || mapheaderinfo[mapnum]->cup->cachedlevels[CUPCACHE_SPECIAL] != mapnum) - return 0; - - return mapheaderinfo[mapnum]->cup->emeraldnum; + return cup->emeraldnum; } //