From f040523b19b7e20013a66ff8afacb48dfa14fd23 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 25 Jul 2023 18:01:07 +0100 Subject: [PATCH 1/8] Implement the Sunbeam Palm decoration - Randomised tilt - Randomised leaf angles - Technically specifiable number of leaves, but the default of 5 is sane enough --- src/deh_tables.c | 6 +++++ src/info.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/info.h | 9 ++++++++ src/p_mobj.c | 46 +++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index 8e15ef2f1..c7130ecac 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4449,6 +4449,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_LIZARDMAN", "S_LIONMAN", + "S_SUNBEAMPALM_STEM", + "S_SUNBEAMPALM_LEAF", + "S_KARMAFIREWORK1", "S_KARMAFIREWORK2", "S_KARMAFIREWORK3", @@ -5735,6 +5738,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_LIZARDMAN", "MT_LIONMAN", + "MT_SUNBEAMPALM_STEM", + "MT_SUNBEAMPALM_LEAF", + "MT_KARMAFIREWORK", "MT_RINGSPARKS", "MT_GAINAX", diff --git a/src/info.c b/src/info.c index 749b2a6af..99f88652f 100644 --- a/src/info.c +++ b/src/info.c @@ -818,6 +818,9 @@ char sprnames[NUMSPRITES + 1][5] = "WBLZ", "WBLN", + "TUST", + "TULE", + "FWRK", "MXCL", "RGSP", @@ -5155,6 +5158,9 @@ state_t states[NUMSTATES] = {SPR_WBLZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIZARDMAN {SPR_WBLN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIONMAN + {SPR_TUST, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SUNBEAMPALM_STEM + {SPR_TULE, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SUNBEAMPALM_LEAF + {SPR_FWRK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK2}, // S_KARMAFIREWORK1 {SPR_FWRK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK3}, // S_KARMAFIREWORK2 {SPR_FWRK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK4}, // S_KARMAFIREWORK3 @@ -29293,6 +29299,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SUNBEAMPALM_STEM + 2697, // doomednum + S_SUNBEAMPALM_STEM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 90<args[0])+1 % 6) + 4); + + const fixed_t pivot = P_RandomRange(PR_DECORATION, -40, 20) * FRACUNIT; + + mobj->rollangle = FixedAngle(pivot); + + const fixed_t temptop = FixedDiv(mobj->height, mobj->scale); + const fixed_t tempside = mobj->info->radius * 2; + + const fixed_t top = P_ReturnThrustX(mobj, mobj->rollangle, temptop) + P_ReturnThrustY(mobj, mobj->rollangle, tempside); + const fixed_t side = P_ReturnThrustX(mobj, mobj->rollangle, tempside) - P_ReturnThrustY(mobj, mobj->rollangle, temptop); + + const fixed_t basex = P_ReturnThrustX(mobj, mobj->angle, side); + const fixed_t basey = P_ReturnThrustY(mobj, mobj->angle, side); + + const angle_t divideangle = FixedAngle((360*FRACUNIT)/numleaves); + angle_t leafangle = P_RandomKey(PR_DECORATION, 360)*ANG1; + + const fixed_t dist = mobjinfo[MT_SUNBEAMPALM_LEAF].radius; + + // Spawn all of the papersprite leaves + for (i = 0; i < numleaves; i++, leafangle += divideangle) + { + mobj_t *leaf; + + leaf = P_SpawnMobjFromMobj( + mobj, + basex + P_ReturnThrustX(mobj, leafangle, dist), + basey + P_ReturnThrustY(mobj, leafangle, dist), + top, + MT_SUNBEAMPALM_LEAF + ); + + if (P_MobjWasRemoved(leaf)) + continue; + + leaf->angle = leafangle; + + leaf->frame |= P_RandomKey(PR_DECORATION, 5); + } + + break; + } case MT_BATTLECAPSULE: { sector_t *sec = R_PointInSubsector(mobj->x, mobj->y)->sector; From 03f9ff08473099b5a7f9c066bce019bd06167e6a Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 26 Jul 2023 14:20:46 +0100 Subject: [PATCH 2/8] Character Select menu: Put B, D on the right side of the PLAYER/profile name text, to avoid overlapping the player's eyes --- src/k_menudraw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 8324cbada..d15e39d42 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1633,17 +1633,17 @@ static void M_DrawCharSelectPreview(UINT8 num) if (p->showextra == false) { - V_DrawScaledPatch(x+9, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE)); - V_DrawScaledPatch(x, y+2, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE)); + INT32 backx = x + ((num & 1) ? -1 : 11); + V_DrawScaledPatch(backx, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE)); + + V_DrawScaledPatch(x + ((num & 1) ? 44 : 0), y+2, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE)); + + profile_t *pr = NULL; if (p->mdepth > CSSTEP_PROFILE) { - profile_t *pr = PR_GetProfile(p->profilen); - V_DrawCenteredFileString(x+16+18, y+2, 0, pr->profilename); - } - else - { - V_DrawFileString(x+16, y+2, 0, "PLAYER"); + pr = PR_GetProfile(p->profilen); } + V_DrawCenteredFileString(backx+26, y+2, 0, pr ? pr->profilename : "PLAYER"); } if (p->mdepth >= CSSTEP_FOLLOWER) From 23f479f365d24f2a6ec81a2808e9815170a2b2f4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 26 Jul 2023 14:31:50 +0100 Subject: [PATCH 3/8] Intermission - DUEL mode Show players' appearances on intermissions with less than or equal to 2 players, in port priority order, to mimic Sonic 3 Competition. Also shows player letter and profile name in Match Race, to really drive the reference home. --- src/k_menu.h | 1 + src/k_menudraw.c | 2 +- src/y_inter.c | 109 ++++++++++++++++++++++++++++++++++++++++++++--- src/y_inter.h | 1 + 4 files changed, 105 insertions(+), 8 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index ff7876ef8..ab3a26443 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1155,6 +1155,7 @@ void M_DrawMessageMenu(void); void M_DrawImageDef(void); void M_DrawCharacterSelect(void); +boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 rotation, UINT32 frame, INT32 addflags, UINT8 *colormap); void M_DrawCupSelect(void); void M_DrawLevelSelect(void); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index d15e39d42..5821e474c 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1474,7 +1474,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y) } // returns false if the character couldn't be rendered -static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 rotation, UINT32 frame, INT32 addflags, UINT8 *colormap) +boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 rotation, UINT32 frame, INT32 addflags, UINT8 *colormap) { UINT8 spr; spritedef_t *sprdef; diff --git a/src/y_inter.c b/src/y_inter.c index 935691a17..524c84fd9 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -178,6 +178,8 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) data.numplayers = 0; data.roundnum = 0; + data.isduel = (numplayersingame <= 2); + for (j = 0; j < numplayersingame; j++) { for (i = 0; i < MAXPLAYERS; i++) @@ -441,7 +443,7 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) INT32 x, y; INT32 x2, returny, inwardshim = 0; - boolean verticalresults = (standings->numplayers < 4); + boolean verticalresults = (standings->numplayers < 4 && (standings->numplayers == 1 || standings->isduel == false)); boolean datarightofcolumn = false; boolean drawping = (netgame && gamestate == GS_LEVEL); @@ -488,7 +490,11 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) y = 106 - (heightcount * yspacing)/2; - if (y < 70) + if (standings->isduel) + { + y += 38; + } + else if (y < 70) { // One sanity check. y = 70; @@ -502,7 +508,20 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) : P_IsLocalPlayer ); - for (i = 0; i < standings->numplayers; i++) + boolean doreverse = ( + standings->isduel && standings->numplayers == 2 + && standings->num[0] > standings->num[1] + ); + + i = 0; + UINT8 halfway = (standings->numplayers-1)/2; + if (doreverse) + { + i = standings->numplayers-1; + halfway++; + } + + do // don't use "continue" in this loop just for sanity's sake { const UINT8 pnum = standings->num[i]; @@ -512,6 +531,67 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) standings->num[i] = MAXPLAYERS; // this should be the only field setting in this function else { + UINT8 *charcolormap = NULL; + if (standings->color[i] != SKINCOLOR_NONE) + { + charcolormap = R_GetTranslationColormap(standings->character[i], standings->color[i], GTC_CACHE); + } + + if (standings->isduel) + { + INT32 duelx = x + 25 - inwardshim/2, duely = y - 80; + if (datarightofcolumn) + duelx += inwardshim/2; + else + duelx -= inwardshim/2; + + V_DrawScaledPatch(duelx, duely, 0, W_CachePatchName("DUELGRPH", PU_CACHE)); + V_DrawScaledPatch(duelx + 8, duely + 9, V_TRANSLUCENT, W_CachePatchName("PREVBACK", PU_CACHE)); + + UINT8 spr2 = SPR2_STIN; + if (standings->pos[i] == 2) + { + spr2 = (datarightofcolumn ? SPR2_STGR : SPR2_STGL); + } + + M_DrawCharacterSprite( + duelx + 40, duely + 78, + standings->character[i], + spr2, + (datarightofcolumn ? 1 : 7), + 0, + 0, + charcolormap + ); + + if (!netgame) + { + UINT8 j, profilen = 0; + for (j = 0; j <= splitscreen; j++) + { + if (pnum == g_localplayers[j]) + break; + } + + if (j > splitscreen) + continue; + + profilen = cv_lastprofile[j].value; + + duelx += 8; + duely += 5; + + INT32 backx = duelx + (datarightofcolumn ? -1 : 11); + + V_DrawScaledPatch(backx, duely, 0, W_CachePatchName("FILEBACK", PU_CACHE)); + + V_DrawScaledPatch(duelx + (datarightofcolumn ? 44 : 0), duely, 0, W_CachePatchName(va("CHARSEL%c", 'A' + j), PU_CACHE)); + + profile_t *pr = PR_GetProfile(profilen); + V_DrawCenteredFileString(backx+26, duely, 0, pr ? pr->profilename : "PLAYER"); + } + } + // Apply the jitter offset (later reversed) if (standings->jitter[pnum] > 0) y--; @@ -522,12 +602,15 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) if (standings->color[i] != SKINCOLOR_NONE) { - UINT8 *charcolormap; if ((players[pnum].pflags & PF_NOCONTEST) && players[pnum].bot) { // RETIRED !! - charcolormap = R_GetTranslationColormap(TC_DEFAULT, standings->color[i], GTC_CACHE); - V_DrawMappedPatch(x+14, y-5, 0, W_CachePatchName("MINIDEAD", PU_CACHE), charcolormap); + V_DrawMappedPatch( + x+14, y-5, + 0, + W_CachePatchName("MINIDEAD", PU_CACHE), + R_GetTranslationColormap(TC_DEFAULT, standings->color[i], GTC_CACHE) + ); } else { @@ -645,7 +728,7 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) y += yspacing; - if (verticalresults == false && i == (standings->numplayers-1)/2) + if (verticalresults == false && i == halfway) { x = 169 + xoffset - inwardshim; y = returny; @@ -653,7 +736,19 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) datarightofcolumn = true; x2 = x + 118 + 5; } + + if (!doreverse) + { + if (++i < standings->numplayers) + continue; + break; + } + + if (i == 0) + break; + i--; } + while (true); } // diff --git a/src/y_inter.h b/src/y_inter.h index 27a85fa6d..6995023db 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -22,6 +22,7 @@ typedef struct boolean gotthrough; // show "got through" boolean showrank; // show rank-restricted queue entry at the end, if it exists boolean encore; // encore mode + boolean isduel; // duel mode UINT8 roundnum; // round number char headerstring[64]; // holds levelnames up to 64 characters From 8553581d806517f23535caaa100bd21290639f11 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 26 Jul 2023 15:51:39 +0100 Subject: [PATCH 4/8] Improved behaviour for skipping second half of intermission in offline games Instead of tying it directly to the number of players, instead base it on whether the points are important to keep track of. - Match Race or Time Attack - No next map override, since points will persist to that one - No maps queued, so points aren't relevant - OR maps are queued but you haven't started them yet, so the points will be discarded --- src/y_inter.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 524c84fd9..64801bd1c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1786,9 +1786,22 @@ void Y_StartIntermission(void) // Prevent a weird bug timer = 1; } - else if (nump < 2 && !netgame) + else if ( + ( // Match Race or Time Attack + netgame == false + && grandprixinfo.gp == false + ) + && ( + modeattacking != ATTACKING_NONE // Definitely never another map + || ( // Any level sequence? + roundqueue.size == 0 // No maps queued, points aren't relevant + || roundqueue.position == 0 // OR points from this round will be discarded + ) + ) + ) { // No PWR/global score, skip it + // (the above is influenced by G_GetNextMap) timer /= 2; } else From 2b4cd831e1097f1bc666e9a952f05e673fedcf91 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 26 Jul 2023 16:51:05 +0100 Subject: [PATCH 5/8] Fix on-screen alignment of Duel Intermission boxes - Now more consistent between time/score and rankings mode - Symmetrical if you flipped the screen, no slight rightward bias in placement --- src/y_inter.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 64801bd1c..b074c9e4a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -539,11 +539,8 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) if (standings->isduel) { - INT32 duelx = x + 25 - inwardshim/2, duely = y - 80; - if (datarightofcolumn) - duelx += inwardshim/2; - else - duelx -= inwardshim/2; + INT32 duelx = x + 22 + (datarightofcolumn ? inwardshim : -inwardshim); + INT32 duely = y - 80; V_DrawScaledPatch(duelx, duely, 0, W_CachePatchName("DUELGRPH", PU_CACHE)); V_DrawScaledPatch(duelx + 8, duely + 9, V_TRANSLUCENT, W_CachePatchName("PREVBACK", PU_CACHE)); From 3eb356f7b991b03a346ae034a50d63e33074ae6d Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 27 Jul 2023 18:19:14 -0700 Subject: [PATCH 6/8] Comptime.cmake: get rid of CMake < 3.5 compatibility warning --- cmake/Comptime.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Comptime.cmake b/cmake/Comptime.cmake index 8388aed9e..c609efee4 100644 --- a/cmake/Comptime.cmake +++ b/cmake/Comptime.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(CMAKE_BINARY_DIR "${BINARY_DIR}") set(CMAKE_CURRENT_BINARY_DIR "${BINARY_DIR}") From b7d4513fba3d97798428265c946613bdca80ab05 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 27 Jul 2023 18:32:11 -0700 Subject: [PATCH 7/8] CMakeLists.txt: add -fmax-errors=5 for GNU Stops compilation after 5 errors, such as in the case of cascading errors from a missing semicolon. --- src/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bfe87f14..25f966d11 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -513,6 +513,11 @@ target_compile_options(SRB2SDL2 PRIVATE $<$,$>: /Wv:19.20.27004.0 > + + # GNU + $<$: + -fmax-errors=5 + > ) if(SRB2_CONFIG_ERRORMODE) target_compile_options(SRB2SDL2 PRIVATE From 1b5d59746f49fd1c38b733004f579d73700aa2f6 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 28 Jul 2023 22:21:37 +0100 Subject: [PATCH 8/8] Adjustments/fixes to Duel Intermission view - Always show, even in online - Add Egga Channel/CPU icon if not a local player-controlled character - This fixes an infinite loop crash that could previously affect 1v1s VS bots --- src/y_inter.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index b074c9e4a..bfaa71521 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -561,31 +561,38 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) charcolormap ); - if (!netgame) + duelx += 8; + duely += 5; + + UINT8 j; + for (j = 0; j <= splitscreen; j++) { - UINT8 j, profilen = 0; - for (j = 0; j <= splitscreen; j++) - { - if (pnum == g_localplayers[j]) - break; - } + if (pnum == g_localplayers[j]) + break; + } - if (j > splitscreen) - continue; + INT32 letterpos = duelx + (datarightofcolumn ? 44 : 0); - profilen = cv_lastprofile[j].value; + if (j > splitscreen) + { + V_DrawScaledPatch(letterpos, duely, 0, W_CachePatchName(va("CHAR%s", (players[pnum].bot ? "CPU" : "EGGA")), PU_CACHE)); + } + else + { + duelx += (datarightofcolumn ? -1 : 11); - duelx += 8; - duely += 5; + UINT8 profilen = cv_lastprofile[j].value; - INT32 backx = duelx + (datarightofcolumn ? -1 : 11); + V_DrawScaledPatch(duelx, duely, 0, W_CachePatchName("FILEBACK", PU_CACHE)); - V_DrawScaledPatch(backx, duely, 0, W_CachePatchName("FILEBACK", PU_CACHE)); + if (datarightofcolumn && j == 0) + letterpos++; // A is one pixel thinner - V_DrawScaledPatch(duelx + (datarightofcolumn ? 44 : 0), duely, 0, W_CachePatchName(va("CHARSEL%c", 'A' + j), PU_CACHE)); + V_DrawScaledPatch(letterpos, duely, 0, W_CachePatchName(va("CHARSEL%c", 'A' + j), PU_CACHE)); profile_t *pr = PR_GetProfile(profilen); - V_DrawCenteredFileString(backx+26, duely, 0, pr ? pr->profilename : "PLAYER"); + + V_DrawCenteredFileString(duelx+26, duely, 0, pr ? pr->profilename : "PLAYER"); } }