From 0974d6d1f47c125f25ca51fee8b4ae55c5d3847f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 00:08:50 -0500 Subject: [PATCH 01/89] Reduced hitlag jitter Makes a little easier to parse. I might have gone overboard but I really wanted to test my hunch if Ivo's issue was mostly the fact it jitters so hard :V --- src/hardware/hw_main.c | 5 +++-- src/hardware/hw_md2.c | 3 ++- src/k_hud.c | 2 +- src/k_kart.h | 1 + src/r_things.c | 7 +++++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3e113bd76..ecb7f7436 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -39,6 +39,7 @@ #include "../f_finale.h" #include "../r_things.h" // R_GetShadowZ #include "../p_slopes.h" +#include "../k_kart.h" // HITLAGJITTERS #include "hw_md2.h" #ifdef NEWCLIP @@ -3645,7 +3646,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) // hitlag vibrating if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { @@ -5064,7 +5065,7 @@ static void HWR_ProjectSprite(mobj_t *thing) // hitlag vibrating if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 4b8d1de6f..69f00d898 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -45,6 +45,7 @@ // SRB2Kart #include "../k_color.h" +#include "../k_kart.h" // HITLAGJITTERS #ifdef HAVE_PNG @@ -1374,7 +1375,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // hitlag vibrating if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = spr->mobj->hitlag * (FRACUNIT / 10); + fixed_t mul = spr->mobj->hitlag * HITLAGJITTERS; if (leveltime & 1) { diff --git a/src/k_hud.c b/src/k_hud.c index 25b437f5c..39ce118e8 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3744,7 +3744,7 @@ static void K_drawKartFirstPerson(void) // hitlag vibrating if (stplyr->mo->hitlag > 0 && (stplyr->mo->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10); + fixed_t mul = stplyr->mo->hitlag * HITLAGJITTERS; if (r_splitscreen && mul > FRACUNIT) mul = FRACUNIT; diff --git a/src/k_kart.h b/src/k_kart.h index 540e6845c..1efc5fb2f 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -20,6 +20,7 @@ Make sure this matches the actual number of states #define KART_NUMINVSPARKLESANIM 12 #define MAXHITLAGTICS 18 //12 +#define HITLAGJITTERS (FRACUNIT / 32) player_t *K_GetItemBoxPlayer(mobj_t *mobj); angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); diff --git a/src/r_things.c b/src/r_things.c index defd02a5f..197100470 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -35,7 +35,6 @@ #include "p_slopes.h" #include "d_netfil.h" // blargh. for nameonly(). #include "m_cheat.h" // objectplace -#include "k_color.h" // SRB2kart #include "p_local.h" // stplyr #ifdef HWRENDER #include "hardware/hw_md2.h" @@ -44,6 +43,10 @@ #include "hardware/hw_drv.h" #endif +// SRB2kart +#include "k_color.h" +#include "k_kart.h" // HITLAGJITTERS + #define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -1438,7 +1441,7 @@ static void R_ProjectSprite(mobj_t *thing) // hitlag vibrating if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { From 15556dce0bcaec8105b5891bb3a6a738cf7ba0bd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 00:25:40 -0500 Subject: [PATCH 02/89] Quakes are scaled with map scale Finally --- src/p_enemy.c | 4 ++-- src/p_spec.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9f5fc86d8..2fdbc6f58 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12205,9 +12205,9 @@ void A_Boss5BombExplode(mobj_t *actor) P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale); P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale); - //P_StartQuake(9*actor->scale, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); + //P_StartQuake(9*FRACUNIT, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); // the above does not exist, so we set the quake values directly instead - quake.intensity = 9*actor->scale; + quake.intensity = 9*FRACUNIT; quake.time = TICRATE/6; // the following quake values have no effect atm? ah well, may as well set them anyway { diff --git a/src/p_spec.c b/src/p_spec.c index 16823916e..764f9c738 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8746,6 +8746,6 @@ static void P_SpawnPushers(void) // epicenter and radius are not yet used. void P_StartQuake(fixed_t intensity, tic_t time) { - quake.intensity = intensity; + quake.intensity = FixedMul(intensity, mapobjectscale); quake.time = time; } From c1b34d4d4ff276826713d619b62630c32a1661db Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 00:32:07 -0500 Subject: [PATCH 03/89] A few more instances --- src/p_enemy.c | 3 +++ src/p_spec.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 2fdbc6f58..7a67fc2af 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -11195,10 +11195,13 @@ void A_MineExplode(mobj_t *actor) A_Scream(actor); actor->flags = MF_NOGRAVITY|MF_NOCLIP; + /* quake.epicenter = NULL; quake.radius = 512*FRACUNIT; quake.intensity = 8*FRACUNIT; quake.time = TICRATE/3; + */ + P_StartQuake(8<tracer, 192*FRACUNIT, 0, true); P_MobjCheckWater(actor); diff --git a/src/p_spec.c b/src/p_spec.c index 764f9c738..d428444a3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2976,9 +2976,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // reasonable defaults. if (!quake.intensity) - quake.intensity = 8< Date: Sun, 28 Nov 2021 13:31:25 -0500 Subject: [PATCH 04/89] Bring back more jitter --- src/k_kart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.h b/src/k_kart.h index 1efc5fb2f..53e0e8bc1 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -20,7 +20,7 @@ Make sure this matches the actual number of states #define KART_NUMINVSPARKLESANIM 12 #define MAXHITLAGTICS 18 //12 -#define HITLAGJITTERS (FRACUNIT / 32) +#define HITLAGJITTERS (FRACUNIT / 20) player_t *K_GetItemBoxPlayer(mobj_t *mobj); angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); From dca887e23e519aec983cbd0bcb63164f084893b9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 14:36:58 -0500 Subject: [PATCH 05/89] Do not adjust friction on bots for tire grease --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 29aa4f177..96c488e0f 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -482,7 +482,7 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) fixed_t rubberband = K_BotRubberband(player) - FRACUNIT; fixed_t origFrict, newFrict; - if (rubberband <= 0) + if (rubberband <= 0 || player->tiregrease > 0) { // Never get weaker than normal friction return frict; From c7caf7ab441424cd216015434295dac764005c7b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 14:37:21 -0500 Subject: [PATCH 06/89] Pull the prediction a lot more forward by default --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 96c488e0f..375b1794d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -571,7 +571,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const fixed_t radreduce = min(distreduce + FRACUNIT/4, FRACUNIT); const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict - const fixed_t speed = max(P_AproxDistance(player->mo->momx, player->mo->momy), K_GetKartSpeed(player, false) / 4); + const fixed_t speed = max(P_AproxDistance(player->rmomx, player->rmomy), K_GetKartSpeed(player, false)); const INT32 startDist = (768 * mapobjectscale) / FRACUNIT; const INT32 distance = ((FixedMul(speed, distreduce) / FRACUNIT) * futuresight) + startDist; From 40958073e39f17a8063b455b1022e2a6e1fa1e6d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 14:42:44 -0500 Subject: [PATCH 07/89] Increase bot max top speed now that everything around it is fixed lol --- src/k_bot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 375b1794d..44269cf58 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -430,8 +430,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player) } else { - // Max at +10% for level 9 bots - rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10); + // Max at +20% for level 9 bots + rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 5); } // Only allow you to go faster than your regular top speed if you're facing the right direction From 6be351a3043c72f38e6dfab5e6b6de5b1ad9fb72 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 14:55:03 -0500 Subject: [PATCH 08/89] Improved item throwing - Bots attempt to do fast item snipes (they will throw more often when above top speed) - They will not waste double jawz anymore (they check for a jawz already targetting who they want to shoot before they decide to shoot it) --- src/k_botitem.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index 212a84929..a7acea642 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -690,17 +690,19 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) const fixed_t topspeed = K_GetKartSpeed(player, false); fixed_t radius = (player->mo->radius * 32); SINT8 throwdir = -1; + UINT8 snipeMul = 2; if (player->speed > topspeed) { radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! } player->botvars.itemconfirm++; if (K_PlayerInCone(player, radius, 10, false)) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + player->botvars.itemconfirm += player->botvars.difficulty * snipeMul; throwdir = 1; } else if (K_PlayerInCone(player, radius, 10, true)) @@ -732,10 +734,13 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) const fixed_t topspeed = K_GetKartSpeed(player, false); fixed_t radius = (player->mo->radius * 32); SINT8 throwdir = 1; + UINT8 snipeMul = 2; + INT32 lastTarg = player->lastjawztarget; if (player->speed > topspeed) { radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! } player->botvars.itemconfirm++; @@ -746,10 +751,33 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) throwdir = -1; } - if (player->lastjawztarget != -1) + if (lastTarg != -1 + && playeringame[lastTarg] == true + && players[lastTarg].spectator == false + && players[lastTarg].mo != NULL + && P_MobjWasRemoved(players[lastTarg].mo) == false) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; - throwdir = 1; + mobj_t *targ = players[lastTarg].mo; + mobj_t *mobj = NULL, *next = NULL; + boolean targettedAlready = false; + + // Make sure no other Jawz are targetting this player. + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + + if (mobj->type == MT_JAWZ && mobj->target == targ) + { + targettedAlready = true; + break; + } + } + + if (targettedAlready == false) + { + player->botvars.itemconfirm += player->botvars.difficulty * snipeMul; + throwdir = 1; + } } if (player->botvars.itemconfirm > 5*TICRATE) From 3536c73b6634d7a66f459c17f32728c9055a9c39 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 15:08:54 -0500 Subject: [PATCH 09/89] Fix eggbox stealth being bugged and never being used... --- src/k_botsearch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 55533d02a..80650030d 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -122,7 +122,7 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y) } } - return (globalsmuggle.randomitems * globalsmuggle.eggboxes); + return (globalsmuggle.randomitems * (globalsmuggle.eggboxes + 1)); } /*-------------------------------------------------- From e4b27933f2e75e8879c2de267584c73deb5632aa Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 15:13:54 -0500 Subject: [PATCH 10/89] Comment the tire grease change --- src/k_bot.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 44269cf58..435eb1c6b 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -482,12 +482,20 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) fixed_t rubberband = K_BotRubberband(player) - FRACUNIT; fixed_t origFrict, newFrict; - if (rubberband <= 0 || player->tiregrease > 0) + if (rubberband <= 0) { // Never get weaker than normal friction return frict; } + if (player->tiregrease > 0) + { + // This isn't great -- it means rubberbanding will slow down when they hit a spring + // But it's better than the opposite where they accelerate into hyperspace :V + // (would appreciate an actual fix though ... could try being additive instead of multiplicative) + return frict; + } + origFrict = FixedDiv(ORIG_FRICTION, FRACUNIT + (rubberband / 2)); if (frict == ORIG_FRICTION) From fbaa57a39c50f3991730523f47951ad426cb0888 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 28 Nov 2021 15:20:57 -0500 Subject: [PATCH 11/89] Give Landmines its own bot usage function Prevents them from attempting to use landmines tossed forward. (Not really notable at all, since there's no one in front of you when you get landmine, at most means they may hold onto it longer, but it was just a weird thing I always meant to fix) --- src/k_botitem.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index a7acea642..67d858ea4 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -546,6 +546,39 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) } } +/*-------------------------------------------------- + static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) + + Item usage for landmine tossing. + + Input Arguments:- + player - Bot to do this for. + cmd - Bot's ticcmd to edit. + turnamt - How hard they currently are turning. + + Return:- + None +--------------------------------------------------*/ +static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) +{ + player->botvars.itemconfirm++; + + if (abs(turnamt) >= KART_FULLTURN/2) + { + player->botvars.itemconfirm += player->botvars.difficulty / 2; + } + + if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + { + player->botvars.itemconfirm += player->botvars.difficulty; + } + + if (player->botvars.itemconfirm > 2*TICRATE) + { + K_BotGenericPressItem(player, cmd, -1); + } +} + /*-------------------------------------------------- static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) @@ -1064,7 +1097,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemSneaker(player, cmd); break; case KITEM_BANANA: - case KITEM_LANDMINE: if (!(player->pflags & PF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); @@ -1109,6 +1141,9 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemMine(player, cmd, turnamt); } break; + case KITEM_LANDMINE: + K_BotItemLandmine(player, cmd, turnamt); + break; case KITEM_THUNDERSHIELD: K_BotItemThunder(player, cmd); break; From f19e8be3a00f55093e036c8added754ab6cd24a6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 30 Nov 2021 14:03:56 -0500 Subject: [PATCH 12/89] Enable lagless cam I left it off because I think Kart intentionally removed it, but the reason we did might not apply anymore...? --- src/d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 52cd7b46c..f185d7430 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -813,7 +813,7 @@ void D_SRB2Loop(void) } else if (rendertimeout < entertic) // in case the server hang or netsplit { -#if 0 +#if 1 // Lagless camera! Yay! if (gamestate == GS_LEVEL && netgame) { From 4a8222d397a41119ffb51e6a835f06be46531d8d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 30 Nov 2021 14:28:27 -0500 Subject: [PATCH 13/89] Just set default renderdelta when paused Supports multiple pause types too --- src/d_main.c | 2 +- src/hardware/hw_main.c | 6 +++--- src/hardware/hw_md2.c | 2 +- src/r_things.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index f185d7430..a220e0c34 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -774,7 +774,7 @@ void D_SRB2Loop(void) // process tics (but maybe not if realtic == 0) TryRunTics(realtics); - if (cv_frameinterpolation.value == 1) + if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause())) { fixed_t entertimefrac = I_GetTimeFrac(); // renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b74bd71ea..e605b6c66 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3645,7 +3645,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) fixed_t interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); @@ -5085,7 +5085,7 @@ static void HWR_ProjectSprite(mobj_t *thing) interpz = thing->z; interpangle = mobjangle; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); @@ -5515,7 +5515,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 70c064081..aadb1b398 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1372,7 +1372,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) fixed_t interpz = spr->mobj->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x); interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y); diff --git a/src/r_things.c b/src/r_things.c index 6d9cca7a4..f383d6d6a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1437,7 +1437,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->player) interpangle = thing->player->drawangle; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); @@ -1777,7 +1777,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t linkscale; thing = thing->tracer; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac); interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac); @@ -2126,7 +2126,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) fixed_t interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); From b716e142a8c715edfc1035a38e8aa3a3aebd7fdf Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Nov 2021 21:24:00 +0000 Subject: [PATCH 14/89] Some fixes for bad player info on joining servers. * Don't overwrite the first player's name when joining with multiple local splitscreen players. (resolves #151) * The defaults for unprovided names are now consistently "Player A/B/C/D" as opposed to some being letter-based and some being number-based. * Send local player info once per local splitscreen player, rather than n^2 times (where n is the number of local splitscreen players). * Since the packet *requires* four names to be sent every time you join a server, send dummy names for local splitscreen players who aren't connecting, instead of your actual cvars (no data leakage you didn't ask for!) --- src/d_clisrv.c | 37 ++++++++++++++-------- src/d_netcmd.c | 86 +++++++++++++++++++++++++++----------------------- src/d_netcmd.h | 3 +- src/g_game.c | 1 - src/r_main.c | 4 --- 5 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2148804df..e6fcb6643 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -795,10 +795,14 @@ static boolean CL_SendJoin(void) sizeof netbuffer->u.clientcfg.application); for (i = 0; i <= splitscreen; i++) - CleanupPlayerName(g_localplayers[i], cv_playername[i].zstring); - - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // the MAXPLAYERS addition is necessary to communicate that g_localplayers is not yet safe to reference + CleanupPlayerName(MAXPLAYERS+i, cv_playername[i].zstring); strncpy(netbuffer->u.clientcfg.names[i], cv_playername[i].zstring, MAXPLAYERNAME); + } + // privacy shield for the local players not joining this session + for (; i < MAXSPLITSCREENPLAYERS; i++) + strncpy(netbuffer->u.clientcfg.names[i], va("Player %c", 'A' + i), MAXPLAYERNAME); return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak)); } @@ -1334,7 +1338,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXPLAYERS; i++) { LUA_InvalidatePlayer(&players[i]); - sprintf(player_names[i], "Player %d", i + 1); + sprintf(player_names[i], "Player %c", 'A' + i); } CL_LoadReceivedSavegame(true); @@ -2401,7 +2405,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) doomcom->numslots--; // Reset the name - sprintf(player_names[playernum], "Player %d", playernum+1); + sprintf(player_names[playernum], "Player %c", 'A' + playernum); player_name_changes[playernum] = 0; @@ -3213,7 +3217,7 @@ void SV_ResetServer(void) playeringame[i] = false; playernode[i] = UINT8_MAX; memset(playeraddress[i], 0, sizeof(*playeraddress)); - sprintf(player_names[i], "Player %d", i + 1); + sprintf(player_names[i], "Player %c", 'A' + i); adminplayers[i] = -1; // Populate the entire adminplayers array with -1. K_ClearClientPowerLevels(); splitscreen_invitations[i] = -1; @@ -3412,7 +3416,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) P_ForceLocalAngle(newplayer, newplayer->angleturn); - D_SendPlayerConfig(); + D_SendPlayerConfig(splitscreenplayer); addedtogame = true; if (rejoined) @@ -3558,14 +3562,13 @@ static void Got_AddBot(UINT8 **p, INT32 playernum) LUAh_PlayerJoin(newplayernum); } -static boolean SV_AddWaitingPlayers(const char *name, const char *name2, const char *name3, const char *name4) +static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *name2, const char *name3, const char *name4) { - INT32 node, n, newplayer = false; + INT32 n, newplayernum; UINT8 buf[4 + MAXPLAYERNAME]; UINT8 *buf_p = buf; - INT32 newplayernum; + boolean newplayer = false; - for (node = 0; node < MAXNETNODES; node++) { // splitscreen can allow 2+ players in one node for (; nodewaiting[node] > 0; nodewaiting[node]--) @@ -3684,6 +3687,7 @@ boolean SV_SpawnServer(void) I_Error("What do you think you're doing?"); return false; #else + boolean result = false; if (demo.playback) G_StopDemo(); // reset engine parameter if (metalplayback) @@ -3710,7 +3714,14 @@ boolean SV_SpawnServer(void) else doomcom->numslots = 1; } - return SV_AddWaitingPlayers(cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring); + // strictly speaking, i'm not convinced the following is necessary + // but I'm not confident enough to remove it entirely in case it breaks something + { + SINT8 node = 0; + for (; node < MAXNETNODES; node++) + result |= SV_AddWaitingPlayers(node, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring); + } + return result; #endif } @@ -3882,7 +3893,7 @@ static void HandleConnect(SINT8 node) SV_SendSaveGame(node, false); // send a complete game state DEBFILE("send savegame\n"); } - SV_AddWaitingPlayers(names[0], names[1], names[2], names[3]); + SV_AddWaitingPlayers(node, names[0], names[1], names[2], names[3]); joindelay += cv_joindelay.value * TICRATE; player_joining = true; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4ed110f35..3524790f6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -222,8 +222,6 @@ static void Command_KartGiveItem_f(void); // CLIENT VARIABLES // ========================================================================= -void SendWeaponPref(UINT8 n); - static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; #ifdef LJOYSTICK @@ -1110,6 +1108,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) * is restored to what it was before. * * We assume that if playernum is in ::g_localplayers + * (unless clientjoin is true, a necessary evil) * the console variable ::cv_playername[n] is * already set to newname. However, the player name table is assumed to * contain the old name. @@ -1128,6 +1127,10 @@ void CleanupPlayerName(INT32 playernum, const char *newname) char *tmpname = NULL; INT32 i; boolean namefailed = true; + boolean clientjoin = !!(playernum >= MAXPLAYERS); + + if (clientjoin) + playernum -= MAXPLAYERS; buf = Z_StrDup(newname); @@ -1185,17 +1188,20 @@ void CleanupPlayerName(INT32 playernum, const char *newname) } // no stealing another player's name - for (i = 0; i < MAXPLAYERS; i++) + if (!clientjoin) { - if (i != playernum && playeringame[i] - && strcasecmp(tmpname, player_names[i]) == 0) + for (i = 0; i < MAXPLAYERS; i++) { - break; + if (i != playernum && playeringame[i] + && strcasecmp(tmpname, player_names[i]) == 0) + { + break; + } } - } - if (i < MAXPLAYERS) - break; + if (i < MAXPLAYERS) + break; + } // name is okay then namefailed = false; @@ -1206,18 +1212,23 @@ void CleanupPlayerName(INT32 playernum, const char *newname) // set consvars whether namefailed or not, because even if it succeeded, // spaces may have been removed - for (i = 0; i <= splitscreen; i++) + if (clientjoin) + CV_StealthSet(&cv_playername[playernum], tmpname); + else { - if (playernum == g_localplayers[i]) + for (i = 0; i <= splitscreen; i++) { - CV_StealthSet(&cv_playername[i], tmpname); - break; + if (playernum == g_localplayers[i]) + { + CV_StealthSet(&cv_playername[i], tmpname); + break; + } } - } - if (i > splitscreen) - { - I_Assert(((void)"CleanupPlayerName used on non-local player", 0)); + if (i > splitscreen) + { + I_Assert(((void)"CleanupPlayerName used on non-local player", 0)); + } } Z_Free(buf); @@ -1811,33 +1822,28 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum) } } -void D_SendPlayerConfig(void) +void D_SendPlayerConfig(UINT8 n) { - UINT8 i; + UINT8 buf[4]; + UINT8 *p = buf; - for (i = 0; i <= splitscreen; i++) + SendNameAndColor(n); + SendWeaponPref(n); + + if (n == 0) { - UINT8 buf[4]; - UINT8 *p = buf; - - SendNameAndColor(i); - SendWeaponPref(i); - - if (i == 0) - { - // Send it over - WRITEUINT16(p, vspowerlevel[PWRLV_RACE]); - WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]); - } - else - { - // Splitscreen players have invalid powerlevel - WRITEUINT16(p, 0); - WRITEUINT16(p, 0); - } - - SendNetXCmdForPlayer(i, XD_POWERLEVEL, buf, p-buf); + // Send it over + WRITEUINT16(p, vspowerlevel[PWRLV_RACE]); + WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]); } + else + { + // Splitscreen players have invalid powerlevel + WRITEUINT16(p, 0); + WRITEUINT16(p, 0); + } + + SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf); } // Only works for displayplayer, sorry! diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 41dc3fdf7..0e8ef25e2 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -207,7 +207,8 @@ void D_RegisterServerCommands(void); void D_RegisterClientCommands(void); void CleanupPlayerName(INT32 playernum, const char *newname); boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); -void D_SendPlayerConfig(void); +void SendWeaponPref(UINT8 n); +void D_SendPlayerConfig(UINT8 n); void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore diff --git a/src/g_game.c b/src/g_game.c index 000be94cd..e4fd7d209 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -346,7 +346,6 @@ static void kickstartaccel_OnChange(void); static void kickstartaccel2_OnChange(void); static void kickstartaccel3_OnChange(void); static void kickstartaccel4_OnChange(void); -void SendWeaponPref(UINT8 n); static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, {1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, diff --git a/src/r_main.c b/src/r_main.c index 231bde280..cd9a6bf22 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -149,10 +149,6 @@ static void ChaseCam_OnChange(void); static void ChaseCam2_OnChange(void); static void ChaseCam3_OnChange(void); static void ChaseCam4_OnChange(void); -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL); consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS] = { From 43356ca73eaf0c4cd49a2e90a41a8537a408eccb Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 30 Nov 2021 18:10:51 -0500 Subject: [PATCH 15/89] Nope, it actually just causes camera hitches even when alone, even if this fixes the problem its not the solution --- src/d_main.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index a220e0c34..425231347 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -813,20 +813,6 @@ void D_SRB2Loop(void) } else if (rendertimeout < entertic) // in case the server hang or netsplit { -#if 1 - // Lagless camera! Yay! - if (gamestate == GS_LEVEL && netgame) - { - INT32 i; - - for (i = 0; i <= r_splitscreen; i++) - { - if (camera[i].chase) - P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false); - } - } -#endif - // (Only display if not already done for frame interp) cv_frameinterpolation.value == 0 ? D_Display() : 0; From 6ecac4159a9f58eae87b1846c104419531a5a143 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Dec 2021 06:45:02 -0500 Subject: [PATCH 16/89] This seems to fix the camera stuttering in netgames when I try it on my own Feel like this might be wrong so TRY IT first!! --- src/d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 425231347..b8fad8ec6 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -774,7 +774,7 @@ void D_SRB2Loop(void) // process tics (but maybe not if realtic == 0) TryRunTics(realtics); - if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause())) + if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause() || hu_stopped)) { fixed_t entertimefrac = I_GetTimeFrac(); // renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based From 7238a1be837ada9b2e55eedccdf8edaca1592a8f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Dec 2021 10:53:15 -0500 Subject: [PATCH 17/89] Interpolate camera roll, fix skybox in opengl --- src/hardware/hw_main.c | 7 +++--- src/r_fps.c | 26 ++++++----------------- src/r_fps.h | 1 + src/r_main.c | 48 ++++++++++++++++++++++++------------------ src/r_state.h | 2 +- 5 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e605b6c66..38fdd0e3c 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5803,8 +5803,7 @@ static void HWR_DrawSkyBackground(player_t *player) dometransform.scalez = 1; dometransform.fovxangle = fpov; // Tails dometransform.fovyangle = fpov; // Tails - HWR_RollTransform(&dometransform, - R_ViewRollAngle(player)); + HWR_RollTransform(&dometransform, viewroll); dometransform.splitscreen = r_splitscreen; HWR_GetTexture(texturetranslation[skytexture]); @@ -6096,7 +6095,7 @@ void HWR_RenderSkyboxView(player_t *player) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - HWR_RollTransform(&atransform, R_ViewRollAngle(player)); + HWR_RollTransform(&atransform, viewroll); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); @@ -6308,7 +6307,7 @@ void HWR_RenderPlayerView(void) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - HWR_RollTransform(&atransform, R_ViewRollAngle(player)); + HWR_RollTransform(&atransform, viewroll); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); diff --git a/src/r_fps.c b/src/r_fps.c index 2d2b4f61e..fe1adb062 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -83,10 +83,7 @@ static void R_SetupFreelook(player_t *player, boolean skybox) void R_InterpolateView(fixed_t frac) { - boolean skybox = false; - INT32 i; - - if (FIXED_TO_FLOAT(frac) < 0) + if (frac < 0) frac = 0; if (frac > FRACUNIT) frac = FRACUNIT; @@ -97,31 +94,20 @@ void R_InterpolateView(fixed_t frac) viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac); aimingangle = oldview->aim + R_LerpAngle(oldview->aim, newview->aim, frac); + viewroll = oldview->roll + R_LerpAngle(oldview->roll, newview->roll, frac); viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - // this is gonna create some interesting visual errors for long distance teleports... - // might want to recalculate the view sector every frame instead... viewplayer = newview->player; viewsector = R_PointInSubsector(viewx, viewy)->sector; - // well, this ain't pretty - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (newview == &skyview_new[i]) - { - skybox = true; - break; - } - } - - R_SetupFreelook(newview->player, skybox); + R_SetupFreelook(newview->player, newview->sky); } void R_UpdateViewInterpolation(void) { - INT32 i; + UINT8 i; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { @@ -132,7 +118,7 @@ void R_UpdateViewInterpolation(void) void R_SetViewContext(enum viewcontext_e _viewcontext) { - INT32 i; + UINT8 i = 0; I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1 && _viewcontext <= VIEWCONTEXT_SKY4); @@ -149,7 +135,7 @@ void R_SetViewContext(enum viewcontext_e _viewcontext) newview = &pview_new[i]; break; case VIEWCONTEXT_SKY1: - case VIEWCONTEXT_SKY2: + case VIEWCONTEXT_SKY2:; case VIEWCONTEXT_SKY3: case VIEWCONTEXT_SKY4: i = viewcontext - VIEWCONTEXT_SKY1; diff --git a/src/r_fps.h b/src/r_fps.h index 2d4dbe874..eb674b142 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -41,6 +41,7 @@ typedef struct { angle_t angle; angle_t aim; + angle_t roll; fixed_t cos; fixed_t sin; mobj_t *mobj; diff --git a/src/r_main.c b/src/r_main.c index 231bde280..ea0d8482d 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -71,7 +71,7 @@ size_t framecount; size_t loopcount; fixed_t viewx, viewy, viewz; -angle_t viewangle, aimingangle; +angle_t viewangle, aimingangle, viewroll; UINT8 viewssnum; fixed_t viewcos, viewsin; sector_t *viewsector; @@ -656,7 +656,7 @@ void R_CheckViewMorph(int s) float fisheyemap[MAXVIDWIDTH/2 + 1]; #endif - angle_t rollangle = R_ViewRollAngle(&players[displayplayers[s]]); + angle_t rollangle = viewroll; #ifdef WOUGHMP_WOUGHMP fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value #endif @@ -1206,8 +1206,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) void R_SetupFrame(player_t *player) { camera_t *thiscam = &camera[0]; - boolean chasecam = false; - UINT8 i; + boolean chasecam = (cv_chasecam[0].value != 0); + UINT8 i = 0; for (i = 0; i <= r_splitscreen; i++) { @@ -1221,12 +1221,17 @@ void R_SetupFrame(player_t *player) } if (i > r_splitscreen) - return; // shouldn't be possible, but just in case + { + i = 0; // Shouldn't be possible, but just in case. + thiscam = &camera[0]; + chasecam = (cv_chasecam[0].value != 0); + R_SetViewContext(VIEWCONTEXT_PLAYER1); + } if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off - if (chasecam && !thiscam->chase) + if (chasecam && (thiscam && !thiscam->chase)) { P_ResetCamera(player, thiscam); thiscam->chase = true; @@ -1270,6 +1275,7 @@ void R_SetupFrame(player_t *player) newview->aim = localaiming[i]; } } + newview->roll = R_ViewRollAngle(player); newview->z += quake.z; newview->player = player; @@ -1302,7 +1308,7 @@ void R_SetupFrame(player_t *player) // newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT); // newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); + R_InterpolateView(rendertimefrac); } void R_SkyboxFrame(player_t *player) @@ -1310,22 +1316,21 @@ void R_SkyboxFrame(player_t *player) camera_t *thiscam = &camera[0]; UINT8 i = 0; - if (r_splitscreen) + for (i = 0; i <= r_splitscreen; i++) { - for (i = 1; i <= r_splitscreen; i++) + if (player == &players[displayplayers[i]]) { - if (player == &players[displayplayers[i]]) - { - thiscam = &camera[i]; - R_SetViewContext(VIEWCONTEXT_SKY1 + i); - break; - } + thiscam = &camera[i]; + R_SetViewContext(VIEWCONTEXT_SKY1 + i); + break; } + } - if (i > r_splitscreen) - { - i = 0; - } + if (i > r_splitscreen) + { + i = 0; // Shouldn't be possible, but just in case. + thiscam = &camera[0]; + R_SetViewContext(VIEWCONTEXT_SKY1); } // cut-away view stuff @@ -1343,7 +1348,7 @@ void R_SkyboxFrame(player_t *player) newview->aim = player->awayviewaiming; newview->angle = player->awayviewmobj->angle; } - else if (thiscam->chase) + else if (thiscam && thiscam->chase) { newview->aim = thiscam->aiming; newview->angle = thiscam->angle; @@ -1359,6 +1364,7 @@ void R_SkyboxFrame(player_t *player) } } newview->angle += r_viewmobj->angle; + newview->roll = R_ViewRollAngle(player); newview->player = player; @@ -1445,7 +1451,7 @@ void R_SkyboxFrame(player_t *player) // newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT); // newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); + R_InterpolateView(rendertimefrac); } boolean R_ViewpointHasChasecam(player_t *player) diff --git a/src/r_state.h b/src/r_state.h index cb55e2c2b..6f9008cc7 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -93,7 +93,7 @@ extern side_t *spawnsides; // POV data. // extern fixed_t viewx, viewy, viewz; -extern angle_t viewangle, aimingangle; +extern angle_t viewangle, aimingangle, viewroll; extern UINT8 viewssnum; // splitscreen view number extern boolean viewsky, skyVisible; extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player From 3e227654c7b5925db5a83ec40a4a34e8927ce2fe Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Dec 2021 12:46:41 -0500 Subject: [PATCH 18/89] Little unneeded semicolon --- src/r_fps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_fps.c b/src/r_fps.c index fe1adb062..7258d3b75 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -135,7 +135,7 @@ void R_SetViewContext(enum viewcontext_e _viewcontext) newview = &pview_new[i]; break; case VIEWCONTEXT_SKY1: - case VIEWCONTEXT_SKY2:; + case VIEWCONTEXT_SKY2: case VIEWCONTEXT_SKY3: case VIEWCONTEXT_SKY4: i = viewcontext - VIEWCONTEXT_SKY1; From 225590b7ba099348a013dcfc306ee5c9e77f4b48 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Dec 2021 13:52:51 -0500 Subject: [PATCH 19/89] Draw framerate counter properly in uncapped --- src/i_system.h | 2 +- src/screen.c | 89 ++++++++++++++++++++++++++++++++++++++++------- src/screen.h | 3 ++ src/sdl/i_video.c | 2 ++ 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/src/i_system.h b/src/i_system.h index 4bc0e73da..789117eaa 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -56,7 +56,7 @@ precise_t I_GetPreciseTime(void); /** \brief Returns the difference between precise times as microseconds. */ -int I_PreciseToMicros(precise_t); +int I_PreciseToMicros(precise_t d); /** \brief The I_Sleep function diff --git a/src/screen.c b/src/screen.c index abc302748..ef5fa7769 100644 --- a/src/screen.c +++ b/src/screen.c @@ -453,9 +453,46 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height) // XMOD FPS display // moved out of os-specific code for consistency -static boolean fpsgraph[TICRATE]; +static boolean ticsgraph[TICRATE]; static tic_t lasttic; +static UINT32 fpstime = 0; +static UINT32 lastupdatetime = 0; + +#define FPSUPDATERATE 1/20 // What fraction of a second to update at. The fraction will not simplify to 0, trust me. +#define FPSMAXSAMPLES 16 + +static UINT32 fpssamples[FPSMAXSAMPLES]; +static UINT32 fpssampleslen = 0; +static UINT32 fpssum = 0; +double aproxfps = 0.0f; + +void SCR_CalcAproxFps(void) +{ + tic_t i = 0; + if (I_PreciseToMicros(fpstime - lastupdatetime) > 1000000 * FPSUPDATERATE) + { + if (fpssampleslen == FPSMAXSAMPLES) + { + fpssum -= fpssamples[0]; + + for (i = 1; i < fpssampleslen; i++) + fpssamples[i-1] = fpssamples[i]; + } + else + fpssampleslen++; + + fpssamples[fpssampleslen-1] = I_GetPreciseTime() - fpstime; + fpssum += fpssamples[fpssampleslen-1]; + + aproxfps = 1000000 / (I_PreciseToMicros(fpssum) / (double)fpssampleslen); + + lastupdatetime = I_GetPreciseTime(); + } + + fpstime = I_GetPreciseTime(); +} + void SCR_DisplayTicRate(void) { tic_t i; @@ -464,25 +501,51 @@ void SCR_DisplayTicRate(void) const UINT8 *ticcntcolor = NULL; for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i) - fpsgraph[i % TICRATE] = false; + ticsgraph[i % TICRATE] = false; - fpsgraph[ontic % TICRATE] = true; + ticsgraph[ontic % TICRATE] = true; for (i = 0;i < TICRATE;++i) - if (fpsgraph[i]) + if (ticsgraph[i]) ++totaltics; - if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); - else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); - // draw "FPS" V_DrawFixedPatch(306<= 60.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); + + /* + if (cv_fpscap.value != 0) + { + // draw total frame: + //V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cv_fpscap.value, ticcntcolor); + // draw "/" + //V_DrawFixedPatch(306<= TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); + + // draw total frame: + V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, TICRATE, ticcntcolor); + // draw "/" + V_DrawFixedPatch(306< Date: Wed, 1 Dec 2021 15:51:57 -0500 Subject: [PATCH 20/89] Enable the thinker of NOTHINK... OK so we kind of need NOTHINK objects to still think because otherwise they can never update their interpolation values. This should probably replaced with some other kind of system, consider this temporary... (MF_NOTHINK is still mostly covered by a very early return in MobjThinker, if you're unaware, just means this might have to waste the extra time iterating through them...) --- src/p_mobj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 533eb8de7..c70c9a2cc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9930,7 +9930,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } } + // OK so we kind of need NOTHINK objects to still think + // because otherwise they can never update their + // interpolation values. They might need some other kind + // of system, so consider this temporary... +#if 0 if (!(mobj->flags & MF_NOTHINK)) +#endif P_AddThinker(THINK_MOBJ, &mobj->thinker); if (mobj->skin) // correct inadequecies above. From 83444ce5d583445c24f774f849e62dad93912080 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Dec 2021 16:50:17 -0500 Subject: [PATCH 21/89] Interpolate angle & nametags --- src/d_player.h | 2 + src/hardware/hw_main.c | 17 +++++--- src/k_hud.c | 96 +++++++++++++++++++++++++++++++++++------- src/p_local.h | 4 ++ src/p_mobj.c | 12 ++++++ src/p_mobj.h | 2 + src/p_user.c | 22 +++++++--- src/r_things.c | 10 ++--- 8 files changed, 134 insertions(+), 31 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 0a406f785..e1ec7f2e8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -312,6 +312,7 @@ typedef struct player_s fixed_t bob; angle_t viewrollangle; + angle_t old_viewrollangle; // camera tilt // TODO: expose to lua angle_t tilt; @@ -325,6 +326,7 @@ typedef struct player_s // fun thing for player sprite angle_t drawangle; + angle_t old_drawangle; // interp // Bit flags. // See pflags_t, above. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 38fdd0e3c..ffb8ef521 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5055,7 +5055,6 @@ static void HWR_ProjectSprite(mobj_t *thing) INT32 heightsec, phs; const boolean splat = R_ThingIsFloorSprite(thing); const boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat); - angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); float z1, z2; fixed_t spr_width, spr_height; @@ -5083,14 +5082,22 @@ static void HWR_ProjectSprite(mobj_t *thing) interpx = thing->x; interpy = thing->y; interpz = thing->z; - interpangle = mobjangle; + interpangle = (thing->player ? thing->player->drawangle : thing->angle); if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - interpangle = mobjangle; + + if (thing->player) + { + interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); + } + else + { + interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); + } } // hitlag vibrating (todo: interp somehow?) @@ -5276,8 +5283,8 @@ static void HWR_ProjectSprite(mobj_t *thing) if (papersprite) { - rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); - rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT)); + rightsin = FIXED_TO_FLOAT(FINESINE((interpangle)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((interpangle)>>ANGLETOFINESHIFT)); } else { diff --git a/src/k_hud.c b/src/k_hud.c index 589467bd6..b4ef2f32a 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -801,7 +801,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu player_t *player; fixed_t viewpointX, viewpointY, viewpointZ; - angle_t viewpointAngle, viewpointAiming; + angle_t viewpointAngle, viewpointAiming, viewpointRoll; INT32 screenWidth, screenHeight; fixed_t screenHalfW, screenHalfH; @@ -829,12 +829,13 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu cam = &camera[cameraNum]; player = &players[displayplayers[cameraNum]]; - if (cam == NULL || player == NULL) + if (cam == NULL || player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo) == true) { // Shouldn't be possible? return; } + // TODO: needs da interp if (cam->chase == true && !player->spectator) { // Use the camera's properties. @@ -843,26 +844,45 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu viewpointZ = cam->z - point->z; viewpointAngle = (INT32)cam->angle; viewpointAiming = (INT32)cam->aiming; + viewpointRoll = (INT32)player->viewrollangle; + + if (cv_frameinterpolation.value == 1) + { + viewpointX = cam->old_x + FixedMul(rendertimefrac, cam->x - cam->old_x); + viewpointY = cam->old_y + FixedMul(rendertimefrac, cam->y - cam->old_y); + viewpointZ = (cam->old_z + FixedMul(rendertimefrac, cam->z - cam->old_z)) - point->z; + + viewpointAngle = (INT32)(cam->old_angle + FixedMul(rendertimefrac, cam->angle - cam->old_angle)); + viewpointAiming = (INT32)(cam->old_aiming + FixedMul(rendertimefrac, cam->aiming - cam->old_aiming)); + viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); + } } else { // Use player properties. - - if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) - { - // This shouldn't happen. - return; - } - viewpointX = player->mo->x; viewpointY = player->mo->y; viewpointZ = player->viewz - point->z; viewpointAngle = (INT32)player->mo->angle; viewpointAiming = (INT32)player->aiming; + viewpointRoll = (INT32)player->viewrollangle; + + if (cv_frameinterpolation.value == 1) + { + viewpointX = player->mo->old_x + FixedMul(rendertimefrac, player->mo->x - player->mo->old_x); + viewpointY = player->mo->old_y + FixedMul(rendertimefrac, player->mo->y - player->mo->old_y); + viewpointZ = (player->mo->old_z + FixedMul(rendertimefrac, player->viewz - player->mo->old_z)) - point->z; //player->old_viewz + + viewpointAngle = (INT32)(player->mo->old_angle + FixedMul(rendertimefrac, player->mo->angle - player->mo->old_angle)); + //viewpointAiming = (INT32)(player->mo->old_aiming + FixedMul(rendertimefrac, player->mo->aiming - player->mo->old_aiming)); + viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); + } } viewpointAngle += (INT32)angleOffset; + (void)viewpointRoll; // will be used later... + // Calculate screen size adjustments. // TODO: Anyone want to make this support non-green resolutions somehow? :V screenWidth = BASEVIDWIDTH; @@ -2590,6 +2610,7 @@ static void K_drawKartPlayerCheck(void) UINT8 *colormap = NULL; UINT8 pnum = 0; vector3_t v; + vector3_t pPos; trackingResult_t result; if (!playeringame[i] || checkplayer->spectator) @@ -2614,7 +2635,22 @@ static void K_drawKartPlayerCheck(void) v.y = checkplayer->mo->y; v.z = checkplayer->mo->z; - distance = R_PointToDist2(stplyr->mo->x, stplyr->mo->y, v.x, v.y); + pPos.x = stplyr->mo->x; + pPos.y = stplyr->mo->y; + pPos.z = stplyr->mo->z; + + if (cv_frameinterpolation.value == 1) + { + v.x = checkplayer->mo->old_x + FixedMul(rendertimefrac, checkplayer->mo->x - checkplayer->mo->old_x); + v.y = checkplayer->mo->old_y + FixedMul(rendertimefrac, checkplayer->mo->y - checkplayer->mo->old_y); + v.z = checkplayer->mo->old_z + FixedMul(rendertimefrac, checkplayer->mo->z - checkplayer->mo->old_z); + + pPos.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); + pPos.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); + pPos.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); + } + + distance = R_PointToDist2(pPos.x, pPos.y, v.x, v.y); if (distance > maxdistance) { @@ -2801,12 +2837,26 @@ static void K_drawKartNameTags(void) c.x = thiscam->x; c.y = thiscam->y; c.z = thiscam->z; + + if (cv_frameinterpolation.value == 1) + { + c.x = thiscam->old_x + FixedMul(rendertimefrac, thiscam->x - thiscam->old_x); + c.y = thiscam->old_y + FixedMul(rendertimefrac, thiscam->y - thiscam->old_y); + c.z = thiscam->old_z + FixedMul(rendertimefrac, thiscam->z - thiscam->old_z); + } } else { c.x = stplyr->mo->x; c.y = stplyr->mo->y; c.z = stplyr->mo->z; + + if (cv_frameinterpolation.value == 1) + { + c.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); + c.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); + c.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); + } } for (i = 0; i < MAXPLAYERS; i++) @@ -2849,6 +2899,13 @@ static void K_drawKartNameTags(void) v.y = ntplayer->mo->y; v.z = ntplayer->mo->z; + if (cv_frameinterpolation.value == 1) + { + v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); + v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); + v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); + } + if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP)) { v.z += ntplayer->mo->height; @@ -2904,7 +2961,16 @@ static void K_drawKartNameTags(void) v.x = ntplayer->mo->x; v.y = ntplayer->mo->y; - v.z = ntplayer->mo->z + (ntplayer->mo->height / 2); + v.z = ntplayer->mo->z; + + if (cv_frameinterpolation.value == 1) + { + v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); + v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); + v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); + } + + v.z += (ntplayer->mo->height / 2); if (stplyr->mo->eflags & MFE_VERTICALFLIP) { @@ -3145,7 +3211,7 @@ static void K_drawKartMinimap(void) interpx = g->mo->x; interpy = g->mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x); interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y); @@ -3210,7 +3276,7 @@ static void K_drawKartMinimap(void) interpx = players[i].mo->x; interpy = players[i].mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x); interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y); @@ -3245,7 +3311,7 @@ static void K_drawKartMinimap(void) interpx = mobj->x; interpy = mobj->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x); interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y); @@ -3282,7 +3348,7 @@ static void K_drawKartMinimap(void) interpx = players[localplayers[i]].mo->x; interpy = players[localplayers[i]].mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x); interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y); diff --git a/src/p_local.h b/src/p_local.h index 631920bb6..61a8cf3a0 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -112,6 +112,10 @@ typedef struct camera_s fixed_t pan; // SRB2Kart: camera pitches on slopes angle_t pitch; + + // Interpolation data + fixed_t old_x, old_y, old_z; + angle_t old_angle, old_aiming; } camera_t; // demo freecam or something before i commit die diff --git a/src/p_mobj.c b/src/p_mobj.c index c70c9a2cc..5a7c4d0d5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3661,6 +3661,9 @@ void P_PrecipThinker(precipmobj_t *mobj) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; P_CycleStateAnimation((mobj_t *)mobj); @@ -8822,6 +8825,9 @@ void P_MobjThinker(mobj_t *mobj) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) @@ -9976,6 +9982,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; return mobj; } @@ -10032,6 +10041,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; return mobj; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 3c7ab4367..2373bdca4 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -285,6 +285,7 @@ typedef struct mobj_s // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation + angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h @@ -424,6 +425,7 @@ typedef struct precipmobj_s // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation + angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h diff --git a/src/p_user.c b/src/p_user.c index c36ef75f0..4b857972d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1145,6 +1145,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_x = mobj->old_x; ghost->old_y = mobj->old_y; ghost->old_z = mobj->old_z; + ghost->old_angle = (mobj->player ? mobj->player->old_drawangle : mobj->old_angle); + ghost->old_pitch = mobj->old_pitch; + ghost->old_roll = mobj->old_roll; return ghost; } @@ -2848,6 +2851,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; #endif + thiscam->old_x = thiscam->x; + thiscam->old_y = thiscam->y; + thiscam->old_z = thiscam->z; + thiscam->old_angle = thiscam->angle; + thiscam->old_aiming = thiscam->aiming; + democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we // We probably shouldn't move the camera if there is no player or player mobj somehow @@ -4160,6 +4169,9 @@ void P_PlayerThink(player_t *player) ticcmd_t *cmd; const size_t playeri = (size_t)(player - players); + player->old_drawangle = player->drawangle; + player->old_viewrollangle = player->viewrollangle; + #ifdef PARANOIA if (!player->mo) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); @@ -4172,11 +4184,6 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->mo->hitlag > 0) - { - return; - } - if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid @@ -4192,6 +4199,11 @@ void P_PlayerThink(player_t *player) if (player->awayviewtics && player->awayviewtics != -1) player->awayviewtics--; + if (player->mo->hitlag > 0) + { + return; + } + // Track airtime if (P_IsObjectOnGround(player->mo)) { diff --git a/src/r_things.c b/src/r_things.c index f383d6d6a..2e50e732c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1431,10 +1431,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t interpx = thing->x; fixed_t interpy = thing->y; fixed_t interpz = thing->z; - angle_t interpangle = thing->angle; - - // use player drawangle if player - if (thing->player) interpangle = thing->player->drawangle; + angle_t interpangle = (thing->player ? thing->player->drawangle : thing->angle); // do interpolation if (cv_frameinterpolation.value == 1) @@ -1442,13 +1439,14 @@ static void R_ProjectSprite(mobj_t *thing) interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + if (thing->player) { - interpangle = thing->player->drawangle; + interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); } else { - interpangle = thing->angle; + interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); } } From 2a74ee07f101e450fb30c6fd09e5524277aa8366 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 Dec 2021 20:10:52 -0800 Subject: [PATCH 22/89] Update underwater physics - Reduce steering effect and remove increased friction. - Strafe into turns and tilt the inside wheels up. --- src/d_player.h | 2 ++ src/k_kart.c | 23 ++++++++++++++++++++--- src/k_kart.h | 1 + src/p_saveg.c | 4 ++++ src/p_user.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/r_patchrotation.c | 6 +++++- 6 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 0a406f785..0578e0301 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -394,6 +394,8 @@ typedef struct player_s INT32 aizdrifttilt; INT32 aizdriftturn; + INT32 underwatertilt; + fixed_t offroad; // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed UINT8 waterskip; // Water skipping counter diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..a516f996b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7565,7 +7565,7 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) basedrift += (basedrift / greasetics) * player->tiregrease; } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + if (player->mo->eflags & (MFE_TOUCHWATER)) { countersteer = FixedMul(countersteer, 3*FRACUNIT/2); } @@ -7672,7 +7672,11 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost); } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + if (player->mo->eflags & MFE_UNDERWATER) + { + turnfixed /= 2; + } + else if (player->mo->eflags & MFE_TOUCHWATER) { turnfixed = FixedMul(turnfixed, 3*FRACUNIT/2); } @@ -7683,6 +7687,19 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return (turnfixed / FRACUNIT); } +INT32 K_GetUnderwaterTurnAdjust(player_t *player) +{ + if (player->mo->eflags & MFE_UNDERWATER) + { + INT32 steer = (K_GetKartTurnValue(player, + player->steering) << TICCMD_REDUCE); + return FixedMul(steer, 8 * FixedDiv(player->speed, + 2 * K_GetKartSpeed(player, false) / 3)); + } + else + return 0; +} + INT32 K_GetKartDriftSparkValue(player_t *player) { return (26*4 + player->kartspeed*2 + (9 - player->kartweight))*8; @@ -8449,7 +8466,7 @@ void K_AdjustPlayerFriction(player_t *player) */ // Water gets ice physics too - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + if (player->mo->eflags & MFE_TOUCHWATER) { player->mo->friction += 614; } diff --git a/src/k_kart.h b/src/k_kart.h index 8b0f755d6..af8751e6a 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -92,6 +92,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); void K_UpdateSteeringValue(player_t *player, INT16 destSteering); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); +INT32 K_GetUnderwaterTurnAdjust(player_t *player); INT32 K_GetKartDriftSparkValue(player_t *player); INT32 K_StairJankFlip(INT32 value); INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage); diff --git a/src/p_saveg.c b/src/p_saveg.c index 83625026d..39a4fec28 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -239,6 +239,8 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].aizdrifttilt); WRITEINT32(save_p, players[i].aizdriftturn); + WRITEINT32(save_p, players[i].underwatertilt); + WRITEFIXED(save_p, players[i].offroad); WRITEUINT8(save_p, players[i].waterskip); @@ -495,6 +497,8 @@ static void P_NetUnArchivePlayers(void) players[i].aizdrifttilt = READINT32(save_p); players[i].aizdriftturn = READINT32(save_p); + players[i].underwatertilt = READINT32(save_p); + players[i].offroad = READFIXED(save_p); players[i].waterskip = READUINT8(save_p); diff --git a/src/p_user.c b/src/p_user.c index c36ef75f0..9c1e87a53 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1769,6 +1769,42 @@ static void P_3dMovement(player_t *player) if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... movepushforward = FixedMul(movepushforward, player->mo->movefactor); + { + INT32 a = K_GetUnderwaterTurnAdjust(player); + INT32 adj = 0; + + if (a) + { + adj = a / 4; + + if (abs(player->underwatertilt + adj) > abs(a)) + adj = (a - player->underwatertilt); + + if (abs(a) < abs(player->underwatertilt)) + adj = 0; + + movepushangle += a; + } + + if (adj) + { + player->underwatertilt += adj; + + if (abs(player->underwatertilt) > ANG30) + { + player->underwatertilt = + player->underwatertilt > 0 ? ANG30 + : -(ANG30); + } + } + else + { + player->underwatertilt = + FixedMul(player->underwatertilt, + 7*FRACUNIT/8); + } + } + totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward); totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward); } @@ -2055,6 +2091,10 @@ void P_MovePlayer(player_t *player) else if (player->drift != 0) { INT32 a = (ANGLE_45 / 5) * player->drift; + + if (player->mo->eflags & MFE_UNDERWATER) + a /= 2; + player->drawangle += a; } } diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 3744dfce2..24c1de5d2 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -42,7 +42,11 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer) angle_t rollAngle = 0; - if (sliptideLift) + if (player->mo->eflags & MFE_UNDERWATER) + { + rollAngle -= player->underwatertilt; + } + else if (sliptideLift) { /* (from side) tilt downward if turning toward camera, upward if away. */ From aebe6dd59ca61b485851c333f639a0dcb6c16876 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 Dec 2021 20:13:20 -0800 Subject: [PATCH 23/89] Don't apply shallow water effects while in offroad --- src/k_kart.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index a516f996b..40ca0ca8f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7676,7 +7676,8 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) { turnfixed /= 2; } - else if (player->mo->eflags & MFE_TOUCHWATER) + else if ((player->mo->eflags & MFE_TOUCHWATER) && + !player->offroad) { turnfixed = FixedMul(turnfixed, 3*FRACUNIT/2); } @@ -8466,7 +8467,8 @@ void K_AdjustPlayerFriction(player_t *player) */ // Water gets ice physics too - if (player->mo->eflags & MFE_TOUCHWATER) + if ((player->mo->eflags & MFE_TOUCHWATER) && + !player->offroad) { player->mo->friction += 614; } From f0c9e49a2baacb3c9032a8582912814e79e4775f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 Dec 2021 22:38:59 -0800 Subject: [PATCH 24/89] Clip watertop and waterbottom between other sector and FOFs --- src/p_mobj.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 491b371b3..96beed530 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2956,6 +2956,8 @@ void P_MobjCheckWater(mobj_t *mobj) player_t *p = mobj->player; // Will just be null if not a player. fixed_t height = mobj->height; boolean wasgroundpounding = false; + fixed_t top2 = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y); + fixed_t bot2 = P_GetSectorFloorZAt(sector, mobj->x, mobj->y); // Default if no water exists. mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; @@ -2966,14 +2968,21 @@ void P_MobjCheckWater(mobj_t *mobj) for (rover = sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) - || (((rover->flags & FF_BLOCKPLAYER) && mobj->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) - continue; topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) + || (((rover->flags & FF_BLOCKPLAYER) && mobj->player) + || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) + { + if (topheight < top2 && topheight > thingtop) + top2 = topheight; + if (bottomheight > bot2 && bottomheight < mobj->z) + bot2 = bottomheight; + continue; + } + if (mobj->eflags & MFE_VERTICALFLIP) { if (topheight < (thingtop - (height>>1)) @@ -3011,6 +3020,12 @@ void P_MobjCheckWater(mobj_t *mobj) } } + if (mobj->watertop > top2) + mobj->watertop = top2; + + if (mobj->waterbottom < bot2) + mobj->waterbottom = bot2; + // Spectators and dead players don't get to do any of the things after this. if (p && (p->spectator || p->playerstate != PST_LIVE)) return; From 9bde266f9f210a82a1a5e6460e5e259436d01ce2 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 Dec 2021 22:41:25 -0800 Subject: [PATCH 25/89] Water running You can run on water in any case where you would have slope resistance AND your speed is over 100%. You may run on water regardless if you're speed is above 200%. --- src/p_local.h | 1 + src/p_map.c | 2 +- src/p_maputl.c | 4 ++-- src/p_mobj.c | 39 ++++++++++++++++++++++++++++++++++----- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 631920bb6..037e9aa50 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -329,6 +329,7 @@ void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); boolean P_CanRunOnWater(player_t *player, ffloor_t *rover); +boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover); void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot); diff --git a/src/p_map.c b/src/p_map.c index d0716790b..f78a0b402 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1848,7 +1848,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && P_CheckSolidLava(rover)) + if (thing->player && P_CheckSolidFFloorSurface(thing->player, rover)) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; diff --git a/src/p_maputl.c b/src/p_maputl.c index 2e21f5ee3..5acddf09c 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -730,7 +730,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidLava(rover)) + if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -772,7 +772,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidLava(rover)) + if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index 96beed530..6853c06f9 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1879,7 +1879,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && P_CheckSolidLava(rover)) // only the player should stand on lava + if (mo->player && P_CheckSolidFFloorSurface(mo->player, rover)) // only the player should stand on lava or run on water ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2940,6 +2940,34 @@ boolean P_SceneryZMovement(mobj_t *mo) return true; } +// P_CanRunOnWater +// +// Returns true if player can waterrun on the 3D floor +// +boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) +{ + boolean flip = player->mo->eflags & MFE_VERTICALFLIP; + fixed_t topspeed = K_GetKartSpeed(player, false); + fixed_t surfaceheight = flip ? player->mo->waterbottom : player->mo->watertop; + fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z; + fixed_t clip = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight); + fixed_t span = player->mo->watertop - player->mo->waterbottom; + + return + clip > -(player->mo->height / 2) && + span > player->mo->height && + player->speed / 3 > abs(player->mo->momz) && + (player->speed > 2 * topspeed || (player->speed > + topspeed && K_SlopeResistance(player))) && + (rover->flags & FF_SWIMMABLE); +} + +boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover) +{ + return P_CheckSolidLava(rover) || + P_CanRunOnWater(player, rover); +} + // // P_MobjCheckWater // @@ -2955,6 +2983,7 @@ void P_MobjCheckWater(mobj_t *mobj) ffloor_t *rover; player_t *p = mobj->player; // Will just be null if not a player. fixed_t height = mobj->height; + fixed_t halfheight = height / 2; boolean wasgroundpounding = false; fixed_t top2 = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y); fixed_t bot2 = P_GetSectorFloorZAt(sector, mobj->x, mobj->y); @@ -2985,14 +3014,14 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & MFE_VERTICALFLIP) { - if (topheight < (thingtop - (height>>1)) - || bottomheight > thingtop) + if (topheight < (thingtop - halfheight) + || bottomheight > (thingtop + halfheight)) continue; } else { - if (topheight < mobj->z - || bottomheight > (mobj->z + (height>>1))) + if (topheight < (mobj->z - halfheight) + || bottomheight > (mobj->z + halfheight)) continue; } From a7a572a7eab280bcafa9f5c11d06bf7d5ddfb157 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 Dec 2021 23:23:43 -0800 Subject: [PATCH 26/89] Water-run if you are above 100% speed and would cross a tripwire --- src/p_mobj.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 6853c06f9..b52522a75 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2947,7 +2947,6 @@ boolean P_SceneryZMovement(mobj_t *mo) boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) { boolean flip = player->mo->eflags & MFE_VERTICALFLIP; - fixed_t topspeed = K_GetKartSpeed(player, false); fixed_t surfaceheight = flip ? player->mo->waterbottom : player->mo->watertop; fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z; fixed_t clip = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight); @@ -2957,8 +2956,8 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) clip > -(player->mo->height / 2) && span > player->mo->height && player->speed / 3 > abs(player->mo->momz) && - (player->speed > 2 * topspeed || (player->speed > - topspeed && K_SlopeResistance(player))) && + player->speed > K_GetKartSpeed(player, false) && + K_TripWirePass(player) && (rover->flags & FF_SWIMMABLE); } From 58446441fe5db01b5720e9687134229c2b442fe7 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Dec 2021 16:14:56 -0800 Subject: [PATCH 27/89] Don't water-run while in grow Also there was a typo lmao --- src/k_kart.c | 13 +++++++++++++ src/k_kart.h | 1 + src/p_mobj.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..a66f34d32 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2700,6 +2700,19 @@ boolean K_TripwirePass(player_t *player) return false; } +boolean K_WaterRun(player_t *player) +{ + if ( + player->invincibilitytimer || + player->sneakertimer || + player->tiregrease || + player->flamedash || + player->speed > 2 * K_GetKartSpeed(player, false) + ) + return true; + return false; +} + static fixed_t K_FlameShieldDashVar(INT32 val) { // 1 second = 75% + 50% top speed diff --git a/src/k_kart.h b/src/k_kart.h index 8b0f755d6..0b60d521a 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -108,6 +108,7 @@ void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); boolean K_TripwirePass(player_t *player); +boolean K_WaterRun(player_t *player); void K_ApplyTripWire(player_t *player, tripwirestate_t state); INT16 K_GetSpindashChargeTime(player_t *player); fixed_t K_GetSpindashChargeSpeed(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index b52522a75..dba88de15 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2957,7 +2957,7 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) span > player->mo->height && player->speed / 3 > abs(player->mo->momz) && player->speed > K_GetKartSpeed(player, false) && - K_TripWirePass(player) && + K_WaterRun(player) && (rover->flags & FF_SWIMMABLE); } From 8484ba929472ec1373a087a7b5c80dd50dc87fe9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 6 Dec 2021 20:38:30 -0500 Subject: [PATCH 28/89] Alpha value for fade colormaps --- src/r_data.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 04b6c232b..46ae0dbd2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -615,6 +615,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright; double maskamt = 0, othermask = 0; + double fmaskamt = 0, fothermask = 0; UINT8 cr = R_GetRgbaR(extra_colormap->rgba), cg = R_GetRgbaG(extra_colormap->rgba), @@ -622,8 +623,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) ca = R_GetRgbaA(extra_colormap->rgba), cfr = R_GetRgbaR(extra_colormap->fadergba), cfg = R_GetRgbaG(extra_colormap->fadergba), - cfb = R_GetRgbaB(extra_colormap->fadergba); -// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software + cfb = R_GetRgbaB(extra_colormap->fadergba), + cfa = R_GetRgbaA(extra_colormap->fadergba); UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -654,14 +655,11 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cdestb = cfb; cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb)); - // fade alpha unused in software - // maskamt = (double)(cfa/24.0l); - // othermask = 1 - maskamt; - // maskamt /= 0xff; + fmaskamt = (double)(cfa/24.0l); + fothermask = 1 - fmaskamt; + //fmaskamt /= 0xff; - // cdestr *= maskamt; - // cdestg *= maskamt; - // cdestb *= maskamt; + (void)fothermask; // unused, but don't feel like commenting it out ///////////////////// // This code creates the colormap array used by software renderer @@ -710,7 +708,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) } // Add/subtract this value during fading. - brightChange[i] = fabs(cbest - cdist) / (double)fadedist; + brightChange[i] = (fabs(cbest - cdist) / (double)fadedist) * fmaskamt; } // Now allocate memory for the actual colormap array itself! From b03cfe302d0850a77e36d6186ad3007eb87dc783 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 6 Dec 2021 20:58:31 -0500 Subject: [PATCH 29/89] OGL fade alpha support --- src/hardware/hw_defs.h | 2 +- src/hardware/r_opengl/r_opengl.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 3f6ad01e5..b4dc1accb 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -284,7 +284,7 @@ struct FSurfaceInfo typedef struct FSurfaceInfo FSurfaceInfo; #define GL_DEFAULTMIX 0x00000000 -#define GL_DEFAULTFOG 0xFF000000 +#define GL_DEFAULTFOG 0x19000000 //Hurdler: added for backward compatibility enum hwdsetspecialstate diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 367ce8331..51a4dd99d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -723,6 +723,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "colorIntensity = abs(colorIntensity - (fogBrightness));\n" \ "}\n" \ "colorIntensity *= darkness;\n" \ + "colorIntensity *= fade_color.a * 10.0;\n" \ "if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \ "final_color.r = fade_color.r;\n" \ "} else if (final_color.r < fade_color.r) {\n" \ From dbefc8fe5810d13f690c0549a1df8df1749e3bf3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 6 Dec 2021 22:47:15 -0500 Subject: [PATCH 30/89] Fix yellow persist fade colormap bug I did the equivalent change to OpenGL and it broke Zoned City, despite it being fine in Software ... not sure what's up with that, since the color math is pretty similar. Just gonna leave that alone for now... --- src/hardware/r_opengl/r_opengl.c | 6 +++--- src/r_data.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 51a4dd99d..84d6ded6e 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -715,12 +715,12 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \ "float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \ "float colorIntensity = 0.0;\n" \ - "if (fogBrightness > colorBrightness) {\n" \ + "if (colorBrightness < fogBrightness) {\n" \ "colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \ - "colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \ + "colorIntensity = abs(colorIntensity - (1.0 - max(fade_color.r, max(fade_color.g, fade_color.b))));\n" \ "} else {\n" \ "colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \ - "colorIntensity = abs(colorIntensity - (fogBrightness));\n" \ + "colorIntensity = abs(colorIntensity - min(fade_color.r, min(fade_color.g, fade_color.b)));\n" \ "}\n" \ "colorIntensity *= darkness;\n" \ "colorIntensity *= fade_color.a * 10.0;\n" \ diff --git a/src/r_data.c b/src/r_data.c index 46ae0dbd2..bb2e508ba 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -699,12 +699,12 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) if (cbrightness < cdestbright) { cbest = 255.0l - min(r, min(g, b)); - cdist = 255.0l - cdestbright; + cdist = 255.0l - max(cdestr, max(cdestg, cdestb)); } else { cbest = max(r, max(g, b)); - cdist = cdestbright; + cdist = min(cdestr, min(cdestg, cdestb)); } // Add/subtract this value during fading. From ab77bceb886ff92afd08ecaaebe33968a452564e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Dec 2021 20:33:41 -0800 Subject: [PATCH 31/89] Adjust underwater strafing - 3/4 steering ability while underwater (not drifting). - A little less friction while underwater. --- src/k_kart.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 40ca0ca8f..e4761ef59 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7694,6 +7694,10 @@ INT32 K_GetUnderwaterTurnAdjust(player_t *player) { INT32 steer = (K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE); + + if (!player->drift) + steer = 3 * steer / 2; + return FixedMul(steer, 8 * FixedDiv(player->speed, 2 * K_GetKartSpeed(player, false) / 3)); } @@ -8472,6 +8476,10 @@ void K_AdjustPlayerFriction(player_t *player) { player->mo->friction += 614; } + else if (player->mo->eflags & MFE_UNDERWATER) + { + player->mo->friction += 312; + } // Wipeout slowdown if (player->spinouttimer && player->wipeoutslow) From 84170a59fa5d09658e554c41b8aeb79fee6f9398 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Dec 2021 20:35:26 -0800 Subject: [PATCH 32/89] Cap underwater steering tilting --- src/p_user.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 9c1e87a53..591bdd8f7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1775,7 +1775,20 @@ static void P_3dMovement(player_t *player) if (a) { - adj = a / 4; + const fixed_t maxadj = ANG10/4; + + adj = a / 4; + + if (adj > 0) + { + if (adj > maxadj) + adj = maxadj; + } + else if (adj < 0) + { + if (adj < -(maxadj)) + adj = -(maxadj); + } if (abs(player->underwatertilt + adj) > abs(a)) adj = (a - player->underwatertilt); From ce366099b008711c8c240155a088d95c3b14db51 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Dec 2021 21:07:34 -0800 Subject: [PATCH 33/89] Make horizontal versus vertical momentum more strict when deciding water-run --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dba88de15..23aa0cb13 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2955,7 +2955,7 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) return clip > -(player->mo->height / 2) && span > player->mo->height && - player->speed / 3 > abs(player->mo->momz) && + player->speed / 5 > abs(player->mo->momz) && player->speed > K_GetKartSpeed(player, false) && K_WaterRun(player) && (rover->flags & FF_SWIMMABLE); From 0cbd24e5891b2ff193453fddb2b6d60747e6f28f Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 6 Dec 2021 21:30:35 -0800 Subject: [PATCH 34/89] 2x vertical speed for downward springs --- src/p_map.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index d0716790b..858eb7600 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -310,6 +310,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (spring->eflags & MFE_VERTICALFLIP) vertispeed *= -1; + if ((spring->eflags ^ object->eflags) & MFE_VERTICALFLIP) + vertispeed *= 2; + // Vertical springs teleport you on TOP of them. if (vertispeed > 0) { From 4a0d0f224f8ef8dafd131c247a3e14675cab1a33 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 7 Dec 2021 01:01:00 -0500 Subject: [PATCH 35/89] Fuck crazy turning --- src/k_kart.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..2887ad32a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7565,10 +7565,12 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) basedrift += (basedrift / greasetics) * player->tiregrease; } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) +#if 0 + if (player->mo->eflags & MFE_UNDERWATER) { countersteer = FixedMul(countersteer, 3*FRACUNIT/2); } +#endif return basedrift + (FixedMul(driftadjust * FRACUNIT, countersteer) / FRACUNIT); } @@ -7672,11 +7674,6 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost); } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) - { - turnfixed = FixedMul(turnfixed, 3*FRACUNIT/2); - } - // Weight has a small effect on turning turnfixed = FixedMul(turnfixed, weightadjust); From 2b3da168cb417f3ae4d33745fe08e91d576889ee Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Tue, 7 Dec 2021 09:54:00 +0100 Subject: [PATCH 36/89] New landmine explosion --- src/deh_tables.c | 1 + src/info.c | 2 +- src/info.h | 3 +++ src/k_kart.c | 21 ++++++++++++------ src/k_kart.h | 1 + src/p_enemy.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index aae6f660c..7e309c33f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -323,6 +323,7 @@ actionpointer_t actionpointers[] = {{A_SPBChase}, "A_SPBCHASE"}, {{A_SSMineSearch}, "A_SSMINESEARCH"}, {{A_SSMineExplode}, "A_SSMINEEXPLODE"}, + {{A_LandMineExplode}, "A_LANDMINEEXPLODE"}, {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, {{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, {{A_FZBoomFlash}, "A_FZBOOMFLASH"}, diff --git a/src/info.c b/src/info.c index 915702380..b4a8a8012 100644 --- a/src/info.c +++ b/src/info.c @@ -4358,7 +4358,7 @@ state_t states[NUMSTATES] = {SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10 {SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE + {SPR_NULL, 0, 1, {A_LandMineExplode}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE {SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1 {SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2 diff --git a/src/info.h b/src/info.h index c9998c498..115948905 100644 --- a/src/info.h +++ b/src/info.h @@ -276,6 +276,7 @@ enum actionnum A_SPBCHASE, A_SSMINESEARCH, A_SSMINEEXPLODE, + A_LANDMINEEXPLODE, A_BALLHOGEXPLODE, A_LIGHTNINGFOLLOWPLAYER, A_FZBOOMFLASH, @@ -546,6 +547,8 @@ void A_JawzExplode(); void A_SPBChase(); void A_SSMineSearch(); void A_SSMineExplode(); +void A_LandMineExplode(); +void A_LandMineExplode(); void A_BallhogExplode(); void A_LightningFollowPlayer(); void A_FZBoomFlash(); diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..71255a8f8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3623,14 +3623,9 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 #define MINEQUAKEDIST 4096 -// Spawns the purely visual explosion -void K_SpawnMineExplosion(mobj_t *source, UINT8 color) +// Does the proximity screen flash and quake for explosions +void K_MineFlashScreen(mobj_t *source) { - INT32 i, radius, height; - mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); - mobj_t *dust; - mobj_t *truc; - INT32 speed, speed2; INT32 pnum; player_t *p; @@ -3653,6 +3648,18 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) break; // we can break right now because quakes are global to all split players somehow. } } +} + +// Spawns the purely visual explosion +void K_SpawnMineExplosion(mobj_t *source, UINT8 color) +{ + INT32 i, radius, height; + mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); + mobj_t *dust; + mobj_t *truc; + INT32 speed, speed2; + + K_MineFlashScreen(source); K_MatchGenericExtraFlags(smoldering, source); smoldering->tics = TICRATE*3; diff --git a/src/k_kart.h b/src/k_kart.h index 8b0f755d6..bf648dcf5 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -69,6 +69,7 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers); void K_DestroyBumpers(player_t *player, UINT8 amount); void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); +void K_MineFlashScreen(mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_RunFinishLineBeam(void); UINT16 K_DriftSparkColor(player_t *player, INT32 charge); diff --git a/src/p_enemy.c b/src/p_enemy.c index 5417d3293..a0cf09820 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -310,6 +310,7 @@ void A_JawzExplode(mobj_t *actor); void A_SPBChase(mobj_t *actor); void A_SSMineSearch(mobj_t *actor); void A_SSMineExplode(mobj_t *actor); +void A_LandMineExplode(mobj_t *actor); void A_BallhogExplode(mobj_t *actor); void A_LightningFollowPlayer(mobj_t *actor); void A_FZBoomFlash(mobj_t *actor); @@ -14132,6 +14133,63 @@ void A_SSMineExplode(mobj_t *actor) actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame. } +void A_LandMineExplode(mobj_t *actor) +{ + + mobj_t *expl; + INT32 colour = SKINCOLOR_KETCHUP; // we spell words properly here + INT32 i; + mobj_t *smoldering; + mobj_t *dust; + + if (LUA_CallAction(A_LANDMINEEXPLODE, actor)) + return; + + // we'll base the explosion "timer" off of some stupid variable like uh... cvmem! + // Yeah let's use cvmem since nobody uses that + + if (actor->target && !P_MobjWasRemoved(actor->target)) + colour = actor->target->color; + + K_MineFlashScreen(actor); + + // Spawn smoke remains: + smoldering = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOLDERING); + P_SetScale(smoldering, actor->scale); + smoldering->tics = TICRATE*3; + + // Spawn a ring: + for (i = 0; i < 32; i++) + { + dust = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE); + P_SetMobjState(dust, S_OPAQUESMOKE1); + dust->angle = (ANGLE_180/16) * i; + P_SetScale(dust, actor->scale); + dust->destscale = actor->scale*4; + dust->scalespeed = actor->scale/4; + P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, actor->scale)); + } + + actor->fuse = actor->tics; // disappear when this state ends. + + // spawn a few physics explosions + for (i = 0; i < 15; i++) + { + expl = P_SpawnMobj(actor->x, actor->y, actor->z + actor->scale, MT_BOOMEXPLODE); + expl->color = colour; + expl->tics = (i+1); + + //K_MatchGenericExtraFlags(expl, actor); + P_SetScale(expl, actor->scale*4); + + expl->momx = P_RandomRange(-3, 3)*actor->scale/2; + expl->momy = P_RandomRange(-3, 3)*actor->scale/2; + + // 100/45 = 2.22 fu/t + expl->momz = ((i+1)*actor->scale*5/2)*P_MobjFlip(expl); + } +} + void A_BallhogExplode(mobj_t *actor) { mobj_t *mo2; From a1e8cdf8c5dee9f1f1abe64282230bf2175b5fdf Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 7 Dec 2021 15:33:45 -0800 Subject: [PATCH 37/89] Adjust underwater steering again - 1.5x strafe -> 1.8. - Do not nerf steering at 11 FU or below. --- src/k_kart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e4761ef59..58a82d128 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7672,7 +7672,8 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost); } - if (player->mo->eflags & MFE_UNDERWATER) + if ((player->mo->eflags & MFE_UNDERWATER) && + player->speed > 11 * player->mo->scale) { turnfixed /= 2; } @@ -7690,13 +7691,14 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) INT32 K_GetUnderwaterTurnAdjust(player_t *player) { - if (player->mo->eflags & MFE_UNDERWATER) + if ((player->mo->eflags & MFE_UNDERWATER) && + player->speed > 11 * player->mo->scale) { INT32 steer = (K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE); if (!player->drift) - steer = 3 * steer / 2; + steer = 9 * steer / 5; return FixedMul(steer, 8 * FixedDiv(player->speed, 2 * K_GetKartSpeed(player, false) / 3)); From f2e8d7d469128efa5db3ee5f53436fd2edca337b Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 7 Dec 2021 16:26:52 -0800 Subject: [PATCH 38/89] Increase step up with water-running just like water-skipping --- src/p_map.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index f78a0b402..bcecb1dfa 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2414,6 +2414,20 @@ boolean PIT_PushableMoved(mobj_t *thing) return true; } +static boolean P_WaterRunning(mobj_t *thing) +{ + ffloor_t *rover = thing->floorrover; + return rover && (rover->flags & FF_SWIMMABLE) && + P_IsObjectOnGround(thing); +} + +static boolean P_WaterStepUp(mobj_t *thing) +{ + player_t *player = thing->player; + return (player && player->waterskip) || + P_WaterRunning(thing); +} + // // P_TryMove // Attempt to move to a new position. @@ -2478,7 +2492,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); fixed_t maxstep = maxstepmove; - if (thing->player && thing->player->waterskip) + if (thing->player && P_WaterStepUp(thing)) maxstep += maxstepmove; // Add some extra stepmove when waterskipping // If using type Section1:13, double the maxstep. From a149fa9db9e92a08c95ebaaaae28facd503dad97 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 9 Dec 2021 20:57:15 +0000 Subject: [PATCH 39/89] GL now loads in netgames and doesn't memory leak What is broken: * Encore mode remapping in GL only * Seizure effect in Daytona (NOT IVO SAFE) * God knows what else has been waiting in the wings --- src/f_finale.c | 17 ++++++++++++++--- src/hardware/hw_cache.c | 10 ++++++++++ src/hardware/hw_glob.h | 2 +- src/hardware/hw_main.c | 2 ++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 099fa422d..eff9ed3f7 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -108,8 +108,12 @@ static patch_t *ttcheckers; // *vroom* KART static patch_t *ttkflash; // flash screen */ +#define NOWAY + +#ifdef NOWAY static patch_t *driver[2]; // Driving character on the waiting screen static UINT8 *waitcolormap; // colormap for the spinning character +#endif // ttmode user static patch_t *ttuser[TTMAX_USER]; @@ -2188,14 +2192,17 @@ void F_TitleDemoTicker(void) void F_StartWaitingPlayers(void) { +#ifdef NOWAY INT32 i; INT32 randskin; spritedef_t *sprdef; spriteframe_t *sprframe; +#endif wipegamestate = GS_TITLESCREEN; // technically wiping from title screen finalecount = 0; +#ifdef NOWAY randskin = M_RandomKey(numskins); if (waitcolormap) @@ -2208,8 +2215,9 @@ void F_StartWaitingPlayers(void) for (i = 0; i < 2; i++) { sprframe = &sprdef->spriteframes[i]; - driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } +#endif } void F_WaitingPlayersTicker(void) @@ -2226,14 +2234,17 @@ void F_WaitingPlayersTicker(void) void F_WaitingPlayersDrawer(void) { +#ifdef NOWAY UINT32 frame = (finalecount % 8) / 4; // The game only tics every other frame while waitingplayers - INT32 flags = V_FLIP; +#endif const char *waittext1 = "You will join"; const char *waittext2 = "the next race..."; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<>1))<width / 2, 150<width / 2, 150<mipmap.height = (UINT16)texture->height; grtex->mipmap.format = textureformat; +#ifdef GLENCORE if (encoremap) colormap += COLORMAP_REMAPOFFSET; grtex->mipmap.colormap = Z_Calloc(sizeof(*grtex->mipmap.colormap), PU_HWRPATCHCOLMIPMAP, NULL); grtex->mipmap.colormap->source = colormap; M_Memcpy(grtex->mipmap.colormap->data, colormap, 256 * sizeof(UINT8)); +#endif blockwidth = texture->width; blockheight = texture->height; @@ -891,7 +895,9 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap) GLMipmap_t *grmip; patch_t *patch; +#ifdef GLENCORE UINT8 *colormap = colormaps; +#endif if (flatlumpnum == LUMPERROR) return; @@ -899,12 +905,16 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap) patch = HWR_GetCachedGLPatch(flatlumpnum); grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; +#ifdef GLENCORE if (!noencoremap && encoremap) colormap += COLORMAP_REMAPOFFSET; grmip->colormap = Z_Calloc(sizeof(*grmip->colormap), PU_HWRPATCHCOLMIPMAP, NULL); grmip->colormap->source = colormap; M_Memcpy(grmip->colormap->data, colormap, 256 * sizeof(UINT8)); +#else + (void)noencoremap; +#endif if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index aafef9eb4..79cdba4f3 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -26,7 +26,7 @@ //#define HWR_LOADING_SCREEN // SRB2Kart -#define GLENCORE +//#define GLENCORE // ----------- // structures diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 46f1e9fc9..3bd516a22 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5478,8 +5478,10 @@ static void HWR_ProjectSprite(mobj_t *thing) { vis->colormap = colormaps; +#ifdef GLENCORE if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP)) vis->colormap += COLORMAP_REMAPOFFSET; +#endif } // set top/bottom coords From 69483f2578c5ff6cfb3595c4da89417e8a728f86 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 9 Dec 2021 22:33:57 +0000 Subject: [PATCH 40/89] Additive sign/tether sparkles --- src/info.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/info.c b/src/info.c index b4a8a8012..5d506d98d 100644 --- a/src/info.c +++ b/src/info.c @@ -4076,17 +4076,17 @@ state_t states[NUMSTATES] = //{SPR_ICAP, FF_FLOORSPRITE|4, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_BOTTOM //{SPR_ICAP, FF_FLOORSPRITE|5, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_INSIDE - {SPR_SGNS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 - {SPR_SGNS, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 - {SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 - {SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4 - {SPR_SGNS, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5 - {SPR_SGNS, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6 - {SPR_SGNS, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7 - {SPR_SGNS, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8 - {SPR_SGNS, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9 - {SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10 - {SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11 {SPR_DRIF, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DRIFTSPARK_A2}, // S_DRIFTSPARK_A1 {SPR_DRIF, FF_FULLBRIGHT|FF_TRANS20|1, 1, {NULL}, 0, 0, S_DRIFTSPARK_A3}, // S_DRIFTSPARK_A2 From 76874de965719c914ff18165cc1fcc47543eff10 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 18:32:52 -0500 Subject: [PATCH 41/89] Drop shadow tweaks for OGL - Shadow uses subtractive & additive, like software shadows - Shadow does not change scale or opacity, like software shadows - Fixed shadow the hedgehog seizure --- src/hardware/hw_main.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3bd516a22..9eb7c1104 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3629,14 +3629,14 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; + float ph; extracolormap_t *colormap = NULL; UINT8 i; SINT8 flip = P_MobjFlip(thing); + UINT32 tFlag = PF_ReverseSubtract; INT32 light; fixed_t scalemul; - UINT16 alpha; - fixed_t floordiff; fixed_t groundz; fixed_t slopez; pslope_t *groundslope; @@ -3675,33 +3675,32 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) groundz = R_GetShadowZ(thing, &groundslope); - floordiff = abs((flip < 0 ? thing->height : 0) + interpz - groundz); - - alpha = floordiff / (4*FRACUNIT) + 75; - if (alpha >= 255) return; - alpha = 255 - alpha; - gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE); if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return; HWR_GetPatch(gpatch); - scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + scalemul = FixedMul(scale, (thing->radius * 2) / gpatch->height); + + ph = (float)gpatch->height; fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(interpx); fy = FIXED_TO_FLOAT(interpy); + if (fscale > 0.0) + { + offset = (ph / 2) * fscale; + } + else + { + return; + } + // 3--2 // | /| // |/ | // 0--1 - if (thing && fabsf(fscale - 1.0f) > 1.0E-36f) - offset = ((gpatch->height)/2) * fscale; - else - offset = (float)((gpatch->height)/2); - shadowVerts[2].x = shadowVerts[3].x = fx + offset; shadowVerts[1].x = shadowVerts[0].x = fx - offset; shadowVerts[1].z = shadowVerts[2].z = fy - offset; @@ -3749,10 +3748,15 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) colormap = thing->subsector->sector->extra_colormap; } - HWR_Lighting(&sSurf, 0, colormap); - sSurf.PolyColor.s.alpha = alpha; + HWR_Lighting(&sSurf, 255, colormap); + sSurf.PolyColor.s.alpha = 255; - HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, SHADER_SPRITE, false); // sprite shader + if (thing->whiteshadow == true) + { + tFlag = PF_Additive; + } + + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, tFlag|PF_Modulated, SHADER_SPRITE, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite From a617563bd88c762f1579ad23fcf95c0a4d1eafb9 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 17:44:23 -0800 Subject: [PATCH 42/89] Add gasp sfx when exiting water, but not with bubble shield --- src/p_mobj.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5a9f0925e..9550b0c41 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3059,7 +3059,16 @@ void P_MobjCheckWater(mobj_t *mobj) return; // The rest of this code only executes on a water state change. - if (waterwasnotset || !!(mobj->eflags & MFE_UNDERWATER) == wasinwater) + if (!!(mobj->eflags & MFE_UNDERWATER) == wasinwater) + return; + + if (p && !p->waterskip && + p->curshield != KSHIELD_BUBBLE && wasinwater) + { + S_StartSound(mobj, sfx_gasp); + } + + if (waterwasnotset) return; if ((p) // Players From 95bfe07d66a2b577600ddd896b60530286e3d699 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 21:34:41 -0800 Subject: [PATCH 43/89] Enable sprite rotation in OpenGL --- src/hardware/hw_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9eb7c1104..0da791279 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5249,6 +5249,8 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE + spriterotangle = R_SpriteRotationAngle(thing, NULL); + if (spriterotangle != 0 && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { From c5e3eb7fff9c614c2f56e42fab49240fe09ea213 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 18:35:41 -0800 Subject: [PATCH 44/89] Minorly extend squish time --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 7401b9d4c..c7b406dc4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4545,7 +4545,7 @@ void K_DriftDustHandling(mobj_t *spawner) void K_Squish(mobj_t *mo) { const fixed_t maxstretch = 4*FRACUNIT; - const fixed_t factor = 3 * mo->height / 2; + const fixed_t factor = 5 * mo->height / 4; const fixed_t threshold = factor / 6; const fixed_t old3dspeed = abs(mo->lastmomz); @@ -4571,7 +4571,7 @@ void K_Squish(mobj_t *mo) { mo->spritexscale -= (mo->spritexscale - FRACUNIT) - / (mo->spritexscale < FRACUNIT ? 8 : 2); + / (mo->spritexscale < FRACUNIT ? 8 : 3); } mo->spriteyscale = From 4fc82f0f531d60157ac59bf60327caab86e1f7d9 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 21:28:46 -0800 Subject: [PATCH 45/89] Squish during huge vertical momentum YIKES --- src/k_kart.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c7b406dc4..6b4a3dfc0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4548,10 +4548,15 @@ void K_Squish(mobj_t *mo) const fixed_t factor = 5 * mo->height / 4; const fixed_t threshold = factor / 6; - const fixed_t old3dspeed = abs(mo->lastmomz); - const fixed_t new3dspeed = abs(mo->momz); + fixed_t old3dspeed = abs(mo->lastmomz); + fixed_t new3dspeed = abs(mo->momz); - const fixed_t delta = abs(old3dspeed - new3dspeed); + fixed_t delta = abs(old3dspeed - new3dspeed); + fixed_t grav = mo->height/3; + fixed_t add = abs(grav - new3dspeed); + + if (delta < 2 * add && new3dspeed > grav) + delta += add; if (delta > threshold) { @@ -4561,7 +4566,7 @@ void K_Squish(mobj_t *mo) if (mo->spritexscale > maxstretch) mo->spritexscale = maxstretch; - if (abs(new3dspeed) > abs(old3dspeed)) + if (new3dspeed > old3dspeed || new3dspeed > grav) { mo->spritexscale = FixedDiv(FRACUNIT, mo->spritexscale); From 4f04c0c4309ab5d86f211e9a7b0a8e403fcca863 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 22:13:56 -0800 Subject: [PATCH 46/89] Tilt models --- src/hardware/hw_md2.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index fc73f87e4..1887574d5 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1649,23 +1649,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } - p.rollangle = 0.0f; - - if (spr->mobj->rollangle) { - fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - fixed_t anglef = AngleFixed(spr->mobj->rollangle); + fixed_t anglef = AngleFixed(R_SpriteRotationAngle(spr->mobj, NULL)); - p.rollangle = FIXED_TO_FLOAT(anglef); - p.roll = true; + p.rollangle = 0.0f; - // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + if (anglef) + { + fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - // rotation axes relative to camera - p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); - p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollangle = FIXED_TO_FLOAT(anglef); + p.roll = true; + + // rotation pivot + p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); + p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + + // rotation axes relative to camera + p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + } } p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch)); From 1ac123246dfff52072d75f049449c87013d6459c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 22:41:35 -0800 Subject: [PATCH 47/89] Model stretching --- src/hardware/hw_drv.h | 4 ++-- src/hardware/hw_md2.c | 6 +++++- src/hardware/r_opengl/r_opengl.c | 15 ++++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index b48d39b9c..4f6046123 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -51,7 +51,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *stransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); @@ -136,4 +136,4 @@ extern struct hwdriver_s hwdriver; #endif //not defined _CREATE_DLL_ -#endif //__HWR_DRV_H__ \ No newline at end of file +#endif //__HWR_DRV_H__ diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 1887574d5..259770fee 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1681,7 +1681,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.mirror = atransform.mirror; HWD.pfnSetShader(SHADER_MODEL); // model shader - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); + { + float xs = finalscale * FIXED_TO_FLOAT(spr->mobj->spritexscale); + float ys = finalscale * FIXED_TO_FLOAT(spr->mobj->spriteyscale); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, xs, ys, flip, hflip, &Surf); + } } return true; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 84d6ded6e..b2762dcbf 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2688,7 +2688,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -2712,10 +2712,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 #endif // Affect input model scaling - scale *= 0.5f; - scalex = scale; - scaley = scale; - scalez = scale; + hscale *= 0.5f; + vscale *= 0.5f; + scalex = hscale; + scaley = vscale; + scalez = hscale; if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { @@ -2973,9 +2974,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface); } // -----------------+ From a90520ebdcad4f7485d53b86df8b057809bbddcd Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Dec 2021 00:32:46 -0800 Subject: [PATCH 48/89] Do not factor roll and pitch into model rollangle Those transformations are applied separately so the model tilts in 3d space. --- src/hardware/hw_md2.c | 2 +- src/r_patch.h | 1 + src/r_patchrotation.c | 11 ++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 259770fee..95077a54a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1650,7 +1650,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } { - fixed_t anglef = AngleFixed(R_SpriteRotationAngle(spr->mobj, NULL)); + fixed_t anglef = AngleFixed(R_ModelRotationAngle(spr->mobj, NULL)); p.rollangle = 0.0f; diff --git a/src/r_patch.h b/src/r_patch.h index 601144a1d..b86908281 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -42,6 +42,7 @@ patch_t *Patch_GetRotatedSprite( INT32 R_GetRollAngle(angle_t rollangle); angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer); +angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer); angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer); #endif diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 24c1de5d2..74afeb396 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -64,10 +64,9 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer) return rollAngle; } -angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) +angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer) { - angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer); - angle_t rollAngle = (rollOrPitch + mobj->rollangle); + angle_t rollAngle = mobj->rollangle; if (mobj->player) { @@ -77,6 +76,12 @@ angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) return rollAngle; } +angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) +{ + angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer); + return (rollOrPitch + R_ModelRotationAngle(mobj, viewPlayer)); +} + INT32 R_GetRollAngle(angle_t rollangle) { INT32 ra = AngleFixed(rollangle)>>FRACBITS; From a3d5804da9c80c8b872735a14239fe9f81ce6681 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Dec 2021 02:45:32 -0800 Subject: [PATCH 49/89] Let flame shield resist slope butter --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6b4a3dfc0..924195239 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2682,7 +2682,7 @@ boolean K_ApplyOffroad(player_t *player) boolean K_SlopeResistance(player_t *player) { - if (player->invincibilitytimer || player->sneakertimer || player->tiregrease) + if (player->invincibilitytimer || player->sneakertimer || player->tiregrease || player->flamedash) return true; return false; } From 1adbfcff03fd256793dad2761f88b9ac49475269 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Fri, 10 Dec 2021 14:16:20 +0100 Subject: [PATCH 50/89] Remove Landmine dust ring on explosion --- src/p_enemy.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 7d4ad7400..51319d229 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14143,7 +14143,6 @@ void A_LandMineExplode(mobj_t *actor) INT32 colour = SKINCOLOR_KETCHUP; // we spell words properly here INT32 i; mobj_t *smoldering; - mobj_t *dust; if (LUA_CallAction(A_LANDMINEEXPLODE, actor)) return; @@ -14161,18 +14160,6 @@ void A_LandMineExplode(mobj_t *actor) P_SetScale(smoldering, actor->scale); smoldering->tics = TICRATE*3; - // Spawn a ring: - for (i = 0; i < 32; i++) - { - dust = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE); - P_SetMobjState(dust, S_OPAQUESMOKE1); - dust->angle = (ANGLE_180/16) * i; - P_SetScale(dust, actor->scale); - dust->destscale = actor->scale*4; - dust->scalespeed = actor->scale/4; - P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, actor->scale)); - } - actor->fuse = actor->tics; // disappear when this state ends. // spawn a few physics explosions From 2e79d84f4a8f02bfd4c8cd0491c41ca75a6aa427 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Fri, 10 Dec 2021 16:07:36 +0100 Subject: [PATCH 51/89] Extras menu barebones start, it does nothing --- src/k_menu.h | 29 +++++++++++++++ src/k_menudef.c | 38 ++++++++++++++++++- src/k_menudraw.c | 54 +++++++++++++++++++++++++++ src/k_menufunc.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+), 2 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index f5f4f20e7..3d0cc3272 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -268,6 +268,10 @@ extern menu_t OPTIONS_DataDiscordDef; extern menuitem_t OPTIONS_DataErase[]; extern menu_t OPTIONS_DataEraseDef; +// EXTRAS +extern menuitem_t EXTRAS_Main[]; +extern menu_t EXTRAS_MainDef; + // PAUSE extern menuitem_t PAUSE_Main[]; extern menu_t PAUSE_MainDef; @@ -565,6 +569,27 @@ void M_EraseData(INT32 choice); // For data erasing void M_VideoModeMenu(INT32 choice); void M_HandleVideoModes(INT32 ch); + +// Extras menu: +extern struct extrasmenu_s { + + tic_t ticker; // How long the menu's been open for + INT16 offset; // To make the icons move smoothly when we transition! + + // For moving the button when we get into a submenu. it's smooth and cool! (normal x/y and target x/y.) + // this is only used during menu transitions. (and will probably remain unused until we get the statistics menu + INT16 extx; + INT16 exty; + INT16 textx; + INT16 texty; + +} extrasmenu; + +void M_InitExtras(INT32 choice); // init for the struct +void M_ExtrasTick(void); +boolean M_ExtrasInputs(INT32 ch); +boolean M_ExtrasQuit(void); // resets buttons when you quit + // Pause menu: // Keep track of some pause menu data for visual goodness. @@ -660,6 +685,10 @@ void M_DrawGenericOptions(void); void M_DrawVideoModes(void); void M_DrawItemToggles(void); +// Extras menu: +void M_DrawExtrasMovingButton(void); +void M_DrawExtras(void); + // Misc menus: #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!" #define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make addons!" diff --git a/src/k_menudef.c b/src/k_menudef.c index 9754ae366..6260e9ea5 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -31,9 +31,9 @@ menuitem_t MainMenu[] = "Cut to the chase and start the race!", NULL, M_CharacterSelectInit, 0, 0}, - {IT_STRING, "Extra", + {IT_STRING | IT_CALL, "Extras", "Check out some bonus features.", "MENUI001", - NULL, 0, 0}, + M_InitExtras, 0, 0}, {IT_STRING, "Options", "Configure your controls, settings, and preferences.", NULL, @@ -1103,6 +1103,40 @@ menu_t OPTIONS_DataEraseDef = { NULL, }; + + +// extras menu +menuitem_t EXTRAS_Main[] = +{ + + {IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.", + NULL, NULL, 0, 0}, + + {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", + NULL, NULL, 0, 0}, + + {IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!", + NULL, NULL, 0, 0}, + + {IT_STRING | IT_TRANSTEXT, "Extras Checklist", "View the requirement for some of the secret content you can unlock!", + NULL, NULL, 0, 0}, +}; + +// the extras menu essentially reuses the options menu stuff +menu_t EXTRAS_MainDef = { + sizeof (EXTRAS_Main) / sizeof (menuitem_t), + &MainDef, + 0, + EXTRAS_Main, + 0, 0, + 0, 0, + 2, 10, + M_DrawExtras, + M_ExtrasTick, + NULL, + M_ExtrasInputs +}; + // ------------------- // In-game/pause menus // ------------------- diff --git a/src/k_menudraw.c b/src/k_menudraw.c index f529585d2..1ddbd40d4 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2108,6 +2108,60 @@ void M_DrawItemToggles(void) } +// EXTRAS: +// Copypasted from options but separate either way in case we want it to look more unique later down the line. +void M_DrawExtrasMovingButton(void) +{ + patch_t *butt = W_CachePatchName("OPT_BUTT", PU_CACHE); + UINT8 *c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + + V_DrawFixedPatch((extrasmenu.extx)*FRACUNIT, (extrasmenu.exty)*FRACUNIT, FRACUNIT, 0, butt, c); + V_DrawCenteredGamemodeString((extrasmenu.extx)-3, (extrasmenu.exty) - 16, V_ALLOWLOWERCASE, c, EXTRAS_MainDef.menuitems[EXTRAS_MainDef.lastOn].text); +} + +void M_DrawExtras(void) +{ + UINT8 i; + INT32 x = 140 - (48*itemOn) + extrasmenu.offset; + INT32 y = 70 + extrasmenu.offset; + patch_t *buttback = W_CachePatchName("OPT_BUTT", PU_CACHE); + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + + UINT8 *c = NULL; + + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + + for (i=0; i < currentMenu->numitems; i++) + { + INT32 py = y - (itemOn*48); + INT32 px = x - menutransition.tics*64; + INT32 tflag = 0; + + if (i == itemOn) + c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + else + c = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLACK, GTC_CACHE); + + if (currentMenu->menuitems[i].status & IT_TRANSTEXT) + tflag = V_TRANSLUCENT; + + if (!(menutransition.tics && i == itemOn)) + { + V_DrawFixedPatch(px*FRACUNIT, py*FRACUNIT, FRACUNIT, 0, buttback, c); + V_DrawCenteredGamemodeString(px-3, py - 16, V_ALLOWLOWERCASE|tflag, (i == itemOn ? c : NULL), currentMenu->menuitems[i].text); + } + + y += 48; + x += 48; + } + + M_DrawMenuTooltips(); + + if (menutransition.tics) + M_DrawExtrasMovingButton(); + +} + // // INGAME / PAUSE MENUS // diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 902a38d33..cd5b09a94 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3378,6 +3378,103 @@ void M_HandleItemToggles(INT32 choice) } +// Extras menu; +// this is copypasted from the options menu but all of these are different functions in case we ever want it to look more unique + +struct extrasmenu_s extrasmenu; + +void M_InitExtras(INT32 choice) +{ + (void)choice; + + extrasmenu.ticker = 0; + extrasmenu.offset = 0; + + extrasmenu.extx = 0; + extrasmenu.exty = 0; + extrasmenu.textx = 0; + extrasmenu.texty = 0; + + M_SetupNextMenu(&EXTRAS_MainDef, false); +} + +// For statistics, will maybe remain unused for a while +boolean M_ExtrasQuit(void) +{ + extrasmenu.textx = 140-1; + extrasmenu.texty = 70+1; + + return true; // Always allow quitting, duh. +} + +void M_ExtrasTick(void) +{ + extrasmenu.offset /= 2; + extrasmenu.ticker++; + + extrasmenu.extx += (extrasmenu.textx - extrasmenu.extx)/2; + extrasmenu.exty += (extrasmenu.texty - extrasmenu.exty)/2; + + if (abs(extrasmenu.extx - extrasmenu.exty) < 2) + { + extrasmenu.extx = extrasmenu.textx; + extrasmenu.exty = extrasmenu.texty; // Avoid awkward 1 px errors. + } + + // Move the button for cool animations + if (currentMenu == &EXTRAS_MainDef) + { + M_ExtrasQuit(); // reset the options button. + } + else + { + extrasmenu.textx = 160; + extrasmenu.texty = 50; + } +} + +boolean M_ExtrasInputs(INT32 ch) +{ + + switch (ch) + { + case KEY_DOWNARROW: + { + extrasmenu.offset += 48; + M_NextOpt(); + S_StartSound(NULL, sfx_menu1); + + if (itemOn == 0) + extrasmenu.offset -= currentMenu->numitems*48; + + return true; + } + case KEY_UPARROW: + { + extrasmenu.offset -= 48; + M_PrevOpt(); + S_StartSound(NULL, sfx_menu1); + + if (itemOn == currentMenu->numitems-1) + extrasmenu.offset += currentMenu->numitems*48; + + return true; + } + case KEY_ENTER: + { + + if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) + return true; // No. + + extrasmenu.extx = 140; + extrasmenu.exty = 70; // Default position for the currently selected option. + + return false; // Don't eat. + } + } + return false; +} + // ===================== // PAUSE / IN-GAME MENUS // ===================== From 75df86da2f83037bf23581b15b584f0beebd2c3e Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Fri, 10 Dec 2021 16:15:54 +0100 Subject: [PATCH 52/89] extras menu: addons --- src/k_menudef.c | 2 +- src/k_menudraw.c | 8 ++++++++ src/k_menufunc.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/k_menudef.c b/src/k_menudef.c index 6260e9ea5..594d4475d 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -1110,7 +1110,7 @@ menuitem_t EXTRAS_Main[] = { {IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.", - NULL, NULL, 0, 0}, + NULL, M_Addons, 0, 0}, {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", NULL, NULL, 0, 0}, diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 1ddbd40d4..a865fcb97 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2543,6 +2543,14 @@ void M_DrawAddons(void) M_CacheAddonPatches(); + // hack: If we're calling this from GS_MENU, that means we're in the extras menu! + // so draw the apropriate background + if (gamestate == GS_MENU) + { + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + } + // hack - need to refresh at end of frame to handle addfile... if (refreshdirmenu & M_AddonsRefresh()) { diff --git a/src/k_menufunc.c b/src/k_menufunc.c index cd5b09a94..15cbf7316 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3839,7 +3839,7 @@ void M_Addons(INT32 choice) dir_on[menudepthleft] = 0; MISC_AddonsDef.prevMenu = currentMenu; - M_SetupNextMenu(&MISC_AddonsDef, false); + M_SetupNextMenu(&MISC_AddonsDef, true); // No transitions. } From 9de737682dca3b7f29a5f53e03a72ba7e03a97d9 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Fri, 10 Dec 2021 20:30:09 +0100 Subject: [PATCH 53/89] extras: replay hut --- src/k_menu.h | 29 ++++ src/k_menudef.c | 58 +++++++- src/k_menudraw.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++- src/k_menufunc.c | 211 ++++++++++++++++++++++++++ 4 files changed, 677 insertions(+), 2 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 3d0cc3272..7eca2ca0d 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -18,6 +18,7 @@ #include "d_event.h" #include "command.h" #include "doomstat.h" // MAXSPLITSCREENPLAYERS +#include "g_demo.h" //menudemo_t // flags for items in the menu // menu handle (what we do when key is pressed @@ -272,6 +273,12 @@ extern menu_t OPTIONS_DataEraseDef; extern menuitem_t EXTRAS_Main[]; extern menu_t EXTRAS_MainDef; +extern menuitem_t EXTRAS_ReplayHut[]; +extern menu_t EXTRAS_ReplayHutDef; + +extern menuitem_t EXTRAS_ReplayStart[]; +extern menu_t EXTRAS_ReplayStartDef; + // PAUSE extern menuitem_t PAUSE_Main[]; extern menu_t PAUSE_MainDef; @@ -571,6 +578,8 @@ void M_HandleVideoModes(INT32 ch); // Extras menu: +#define DF_ENCORE 0x40 + extern struct extrasmenu_s { tic_t ticker; // How long the menu's been open for @@ -583,6 +592,16 @@ extern struct extrasmenu_s { INT16 textx; INT16 texty; + + // The replay vars...... oh no...... + menudemo_t *demolist; + + INT16 replayScrollTitle; + SINT8 replayScrollDelay; + SINT8 replayScrollDir; + + + } extrasmenu; void M_InitExtras(INT32 choice); // init for the struct @@ -590,6 +609,13 @@ void M_ExtrasTick(void); boolean M_ExtrasInputs(INT32 ch); boolean M_ExtrasQuit(void); // resets buttons when you quit +// Extras: Replay Hut +void M_HandleReplayHutList(INT32 choice); +boolean M_QuitReplayHut(void); +void M_HutStartReplay(INT32 choice); +void M_PrepReplayList(void); + + // Pause menu: // Keep track of some pause menu data for visual goodness. @@ -688,6 +714,9 @@ void M_DrawItemToggles(void); // Extras menu: void M_DrawExtrasMovingButton(void); void M_DrawExtras(void); +void M_DrawReplayHut(void); +void M_DrawReplayStartMenu(void); +void M_DrawReplayHutReplayInfo(void); // Misc menus: #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!" diff --git a/src/k_menudef.c b/src/k_menudef.c index 594d4475d..6a9487828 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -1113,7 +1113,7 @@ menuitem_t EXTRAS_Main[] = NULL, M_Addons, 0, 0}, {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", - NULL, NULL, 0, 0}, + NULL, M_ReplayHut, 0, 0}, {IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!", NULL, NULL, 0, 0}, @@ -1137,6 +1137,62 @@ menu_t EXTRAS_MainDef = { M_ExtrasInputs }; +// extras menu: replay hut +menuitem_t EXTRAS_ReplayHut[] = +{ + {IT_KEYHANDLER|IT_NOTHING, "", "", // Dummy menuitem for the replay list + NULL, M_HandleReplayHutList, 0, 0}, + + {IT_NOTHING, "", "", // Dummy for handling wrapping to the top of the menu.. + NULL, NULL, 0, 0}, +}; + +menu_t EXTRAS_ReplayHutDef = +{ + sizeof (EXTRAS_ReplayHut)/sizeof (menuitem_t), + &EXTRAS_MainDef, + 0, + EXTRAS_ReplayHut, + 30, 80, + 0, 0, + 0, 0, + M_DrawReplayHut, + NULL, + M_QuitReplayHut, + NULL +}; + +menuitem_t EXTRAS_ReplayStart[] = +{ + {IT_CALL |IT_STRING, "Load Addons and Watch", NULL, + NULL, M_HutStartReplay, 0, 0}, + + {IT_CALL |IT_STRING, "Load Without Addons", NULL, + NULL, M_HutStartReplay, 10, 0}, + + {IT_CALL |IT_STRING, "Watch Replay", NULL, + NULL, M_HutStartReplay, 10, 0}, + + {IT_SUBMENU |IT_STRING, "Go Back", NULL, + NULL, &EXTRAS_ReplayHutDef, 30, 0}, +}; + + +menu_t EXTRAS_ReplayStartDef = +{ + sizeof (EXTRAS_ReplayStart)/sizeof (menuitem_t), + &EXTRAS_ReplayHutDef, + 0, + EXTRAS_ReplayStart, + 27, 80, + 0, 0, + 0, 0, + M_DrawReplayStartMenu, + NULL, + NULL, + NULL +}; + // ------------------- // In-game/pause menus // ------------------- diff --git a/src/k_menudraw.c b/src/k_menudraw.c index a865fcb97..c9fc729c3 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -342,7 +342,7 @@ static const char *M_CreateSecretMenuOption(const char *str) // void M_DrawGenericMenu(void) { - INT32 x = 0, y = 0, w, i, cursory = 0; + INT32 x = currentMenu->x, y = currentMenu->y, w, i, cursory = 0; M_DrawMenuTooltips(); @@ -2456,6 +2456,385 @@ void M_DrawPlaybackMenu(void) } +// replay hut... +// ...dear lord this is messy, but Ima be real I ain't fixing this. + +#define SCALEDVIEWWIDTH (vid.width/vid.dupx) +#define SCALEDVIEWHEIGHT (vid.height/vid.dupy) +void M_DrawReplayHutReplayInfo(void) +{ + lumpnum_t lumpnum; + patch_t *patch; + UINT8 *colormap; + INT32 x, y, w, h; + + switch (extrasmenu.demolist[dir_on[menudepthleft]].type) + { + case MD_NOTLOADED: + V_DrawCenteredString(160, 40, V_SNAPTOTOP, "Loading replay information..."); + break; + + case MD_INVALID: + V_DrawCenteredString(160, 40, V_SNAPTOTOP|warningflags, "This replay cannot be played."); + break; + + case MD_SUBDIR: + break; // Can't think of anything to draw here right now + + case MD_OUTDATED: + V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); + /* FALLTHRU */ + default: + // Draw level stuff + x = 15; y = 15; + + // A 160x100 image of the level as entry MAPxxP + //CONS_Printf("%d %s\n", extrasmenu.demolist[dir_on[menudepthleft]].map, G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map)); + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map))); + if (lumpnum != LUMPERROR) + patch = W_CachePatchNum(lumpnum, PU_CACHE); + else + patch = W_CachePatchName("M_NOLVL", PU_CACHE); + + if (!(extrasmenu.demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) + V_DrawSmallScaledPatch(x, y, V_SNAPTOTOP, patch); + else + { + w = SHORT(patch->width); + h = SHORT(patch->height); + V_DrawSmallScaledPatch(x+(w>>1), y, V_SNAPTOTOP|V_FLIP, patch); + + { + static angle_t rubyfloattime = 0; + const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); + V_DrawFixedPatch((x+(w>>2))<>2))<width), y+20, V_SNAPTOTOP, patch, colormap); + + break; + } +} + +void M_DrawReplayHut(void) +{ + INT32 x, y, cursory = 0; + INT16 i; + INT16 replaylistitem = currentMenu->numitems-2; + boolean processed_one_this_frame = false; + + static UINT16 replayhutmenuy = 0; + + M_DrawEggaChannel(); + + // Draw menu choices + x = currentMenu->x; + y = currentMenu->y; + + if (itemOn > replaylistitem) + { + itemOn = replaylistitem; + dir_on[menudepthleft] = sizedirmenu-1; + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + else if (itemOn < replaylistitem) + { + dir_on[menudepthleft] = 0; + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + + if (itemOn == replaylistitem) + { + INT32 maxy; + // Scroll menu items if needed + cursory = y + currentMenu->menuitems[replaylistitem].mvar1 + dir_on[menudepthleft]*10; + maxy = y + currentMenu->menuitems[replaylistitem].mvar1 + sizedirmenu*10; + + if (cursory > maxy - 20) + cursory = maxy - 20; + + if (cursory - replayhutmenuy > SCALEDVIEWHEIGHT-50) + replayhutmenuy += (cursory-SCALEDVIEWHEIGHT-replayhutmenuy + 51)/2; + else if (cursory - replayhutmenuy < 110) + replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2; + } + else + replayhutmenuy /= 2; + + y -= replayhutmenuy; + + // Draw static menu items + for (i = 0; i < replaylistitem; i++) + { + INT32 localy = y + currentMenu->menuitems[i].mvar1; + + if (localy < 65) + continue; + + if (i == itemOn) + cursory = localy; + + if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT, currentMenu->menuitems[i].text); + else + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text); + } + + y += currentMenu->menuitems[replaylistitem].mvar1; + + for (i = 0; i < (INT16)sizedirmenu; i++) + { + INT32 localy = y+i*10; + INT32 localx = x; + + if (localy < 65) + continue; + if (localy >= SCALEDVIEWHEIGHT) + break; + + if (extrasmenu.demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) + { + processed_one_this_frame = true; + G_LoadDemoInfo(&extrasmenu.demolist[i]); + } + + if (extrasmenu.demolist[i].type == MD_SUBDIR) + { + localx += 8; + V_DrawScaledPatch(x - 4, localy, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE)); + } + + if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft]) + { + cursory = localy; + + if (extrasmenu.replayScrollDelay) + extrasmenu.replayScrollDelay--; + else if (extrasmenu.replayScrollDir > 0) + { + if (extrasmenu.replayScrollTitle < (V_StringWidth(extrasmenu.demolist[i].title, 0) - (SCALEDVIEWWIDTH - (x<<1)))<<1) + extrasmenu.replayScrollTitle++; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = -1; + } + } + else + { + if (extrasmenu.replayScrollTitle > 0) + extrasmenu.replayScrollTitle--; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + } + } + + V_DrawString(localx - (extrasmenu.replayScrollTitle>>1), localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title); + } + else + V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title); + } + + // Draw scrollbar + y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].mvar1 + 30; + if (y > SCALEDVIEWHEIGHT-80) + { + V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|159); + V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|149); + } + + // Draw the cursor + V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT, + W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text); + + // Now draw some replay info! + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); + + if (itemOn == replaylistitem) + { + M_DrawReplayHutReplayInfo(); + } +} + +void M_DrawReplayStartMenu(void) +{ + const char *warning; + UINT8 i; + + M_DrawEggaChannel(); + M_DrawGenericMenu(); + +#define STARTY 62-(extrasmenu.replayScrollTitle>>1) + // Draw rankings beyond first + for (i = 1; i < MAXPLAYERS && extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking; i++) + { + patch_t *patch; + UINT8 *colormap; + + V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, V_SNAPTOTOP|highlightflags, va("%2d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking)); + V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_SNAPTOTOP|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].standings[i].name); + + if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) + V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST"); + else if (extrasmenu.demolist[dir_on[menudepthleft]].gametype == GT_RACE) + V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d", + G_TicsToMinutes(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), + G_TicsToSeconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore), + G_TicsToCentiseconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore) + )); + else + V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore)); + + // Character face! + + // Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this) + // and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid. + + if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin != 0xFF) + { + patch = faceprefix[extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin][FACE_RANK]; + colormap = R_GetTranslationColormap( + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin, + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + } + else + { + patch = W_CachePatchName("M_NORANK", PU_CACHE); + colormap = R_GetTranslationColormap( + TC_RAINBOW, + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + } + + V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap); + } +#undef STARTY + + // Handle scrolling rankings + if (extrasmenu.replayScrollDelay) + extrasmenu.replayScrollDelay--; + else if (extrasmenu.replayScrollDir > 0) + { + if (extrasmenu.replayScrollTitle < (i*20 - SCALEDVIEWHEIGHT + 100)<<1) + extrasmenu.replayScrollTitle++; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = -1; + } + } + else + { + if (extrasmenu.replayScrollTitle > 0) + extrasmenu.replayScrollTitle--; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + } + } + + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); + M_DrawReplayHutReplayInfo(); + + V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].title); + + // Draw a warning prompt if needed + switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + warning = "Some addons in this replay cannot be loaded.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + warning = "Loading addons will mark your game as modified, and Record Attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; + break; + + case DFILE_ERROR_EXTRAFILES: + warning = "You have addons loaded that were not present in this replay.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_OUTOFORDER: + warning = "You have this replay's addons loaded, but they are out of order.\nYou can watch anyway, but desyncs may occur."; + break; + + default: + return; + } + + V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning); +} + // Draw misc menus: // Addons (this is merely copypasted, original code by toaster) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 15cbf7316..5ced69765 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3783,12 +3783,223 @@ void M_PlaybackQuit(INT32 choice) D_StartTitle(); } +void M_PrepReplayList(void) +{ + size_t i; + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + + extrasmenu.demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); + + for (i = 0; i < sizedirmenu; i++) + { + if (dirmenu[i][DIR_TYPE] == EXT_UP) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + sprintf(extrasmenu.demolist[i].title, "UP"); + } + else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + strncpy(extrasmenu.demolist[i].title, dirmenu[i] + DIR_STRING, 64); + } + else + { + extrasmenu.demolist[i].type = MD_NOTLOADED; + snprintf(extrasmenu.demolist[i].filepath, 255, "%s%s", menupath, dirmenu[i] + DIR_STRING); + sprintf(extrasmenu.demolist[i].title, "....."); + } + } +} + void M_ReplayHut(INT32 choice) { (void)choice; + + extrasmenu.replayScrollTitle = 0; + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + + if (!demo.inreplayhut) + { + snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + } + if (!preparefilemenu(false, true)) + { + M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); + return; + } + else if (!demo.inreplayhut) + dir_on[menudepthleft] = 0; + demo.inreplayhut = true; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + M_PrepReplayList(); + + menuactive = true; + M_SetupNextMenu(&EXTRAS_ReplayHutDef, false); + //G_SetGamestate(GS_TIMEATTACK); + //titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + + demo.rewinding = false; + CL_ClearRewinds(); + + //S_ChangeMusicInternal("replst", true); } +// key handler +void M_HandleReplayHutList(INT32 choice) +{ + switch (choice) + { + case KEY_UPARROW: + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; + else + return; + //M_PrevOpt(); + + S_StartSound(NULL, sfx_menu1); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + break; + + case KEY_DOWNARROW: + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; + else + return; + //itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item + + S_StartSound(NULL, sfx_menu1); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + break; + + case KEY_ESCAPE: + M_QuitReplayHut(); + break; + + case KEY_ENTER: + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false, true)) + { + S_StartSound(NULL, sfx_s224); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true, true)) + { + M_QuitReplayHut(); + return; + } + } + else + { + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; + M_PrepReplayList(); + } + } + else + { + S_StartSound(NULL, sfx_s26d); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_menu1); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false, true)) + { + M_QuitReplayHut(); + return; + } + M_PrepReplayList(); + break; + default: + // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! + currentMenu->lastOn = itemOn; + currentMenu = &EXTRAS_ReplayStartDef; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + // Only show "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 0; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 1; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_CALL|IT_STRING; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 10; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 0; + break; + + case DFILE_ERROR_EXTRAFILES: + case DFILE_ERROR_OUTOFORDER: + default: + // Show "Watch Replay" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_DISABLED; + EXTRAS_ReplayStart[2].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[2].alphaKey = 0; + itemOn = 2; + break; + } + } + + break; + } +} + +boolean M_QuitReplayHut(void) +{ + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + extrasmenu.demolist = NULL; + + demo.inreplayhut = false; + + return true; +} + +void M_HutStartReplay(INT32 choice) +{ + (void)choice; + + M_ClearMenus(false); + demo.loadfiles = (itemOn == 0); + demo.ignorefiles = (itemOn != 0); + + G_DoPlayDemo(extrasmenu.demolist[dir_on[menudepthleft]].filepath); +} + + static void Splitplayers_OnChange(void) { #if 0 From f093d5783f2954dec8a9f9961bff227b2faf52fb Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Fri, 10 Dec 2021 20:31:07 +0100 Subject: [PATCH 54/89] Put back the transition for addons screen after all... --- src/k_menufunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 5ced69765..349f9e560 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -4050,7 +4050,7 @@ void M_Addons(INT32 choice) dir_on[menudepthleft] = 0; MISC_AddonsDef.prevMenu = currentMenu; - M_SetupNextMenu(&MISC_AddonsDef, true); // No transitions. + M_SetupNextMenu(&MISC_AddonsDef, false); } From 07d5691b73673635a9e77f25d6c141f89420c99f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 10 Dec 2021 16:23:41 -0500 Subject: [PATCH 55/89] Make them commit harder to turning - Removed the "minor adjustment" threshold, since that was done before global easing - Removed the "accel + brake to slowdown and reorient yourself if you're facing too far away from the track" bit, because 1.) it was done before accel + brake was turned into EBrake (so it now often makes them come to a STOP instead of simply slowing down) and 2.) turning harshly will slow them down anyway, so maybe isn't necessary --- src/k_bot.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 435eb1c6b..9c5dff35b 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -1120,18 +1120,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Don't turn at all turnamt = 0; } - else - { - // Make minor adjustments - turnamt /= 4; - } - } - - if (anglediff > 60) - { - // Actually, don't go too fast... - cmd->forwardmove /= 2; - cmd->buttons |= BT_BRAKE; } } } From 19463d6b207afb1a90f9e1b009ff48b473833fc0 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 10 Dec 2021 17:42:00 -0500 Subject: [PATCH 56/89] New bot prediction wall detection Instead of searching for walls around the player, and then deciding to make the radius tighter if it found anyway, it instead checks if the waypoint it's trying to predict towards was blocked by any walls / hazards. Needs adjusted some, I think its being pulled back too hard sometimes, but I am optimistic about some of the improvements I already saw. --- src/k_bot.c | 37 ++++++++-- src/k_bot.h | 15 ++-- src/k_botsearch.c | 181 +-------------------------------------------- src/p_local.h | 3 + src/p_map.c | 56 +++++++++----- src/p_sight.c | 182 +++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 265 insertions(+), 209 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 9c5dff35b..1d9b8ff83 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -575,14 +575,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to - const fixed_t distreduce = K_BotReducePrediction(player); - const fixed_t radreduce = min(distreduce + FRACUNIT/4, FRACUNIT); - const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict - const fixed_t speed = max(P_AproxDistance(player->rmomx, player->rmomy), K_GetKartSpeed(player, false)); + const fixed_t speed = P_AproxDistance(player->rmomx, player->rmomy); - const INT32 startDist = (768 * mapobjectscale) / FRACUNIT; - const INT32 distance = ((FixedMul(speed, distreduce) / FRACUNIT) * futuresight) + startDist; + const INT32 startDist = (1536 * mapobjectscale) / FRACUNIT; + const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist; botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); waypoint_t *wp = player->nextwaypoint; @@ -591,6 +588,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) fixed_t smallestradius = INT32_MAX; angle_t angletonext = ANGLE_MAX; + // Halves radius when encountering a wall on your way to your destination. + fixed_t radreduce = FRACUNIT; + size_t nwp; size_t i; @@ -603,7 +603,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { predict->x = wp->mobj->x; predict->y = wp->mobj->y; - predict->radius = FixedMul(wp->mobj->radius, radreduce); + predict->radius = wp->mobj->radius; return predict; } @@ -653,6 +653,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) continue; } + if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[i]->mobj) == false) + { + continue; + } + // Unlike the other parts of this function, we're comparing the player's physical position, NOT the position of the waypoint!! // This should roughly correspond with how players will think about path splits. a = R_PointToAngle2( @@ -672,6 +677,24 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) delta = a; } } + + if (i == wp->numnextwaypoints) + { + // No usable waypoint, we don't want to check any further + radreduce /= 2; + distanceleft = 0; + break; + } + } + else + { + if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false) + { + // If we can't get a direct path to this waypoint, we don't want to check any further. + radreduce /= 2; + distanceleft = 0; + break; + } } angletonext = R_PointToAngle2( diff --git a/src/k_bot.h b/src/k_bot.h index 94694c2dd..41c8df5e0 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -185,19 +185,22 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y); /*-------------------------------------------------- - fixed_t K_BotReducePrediction(player_t *player); + boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) - Finds walls nearby the specified player, to create a multiplier - to pull bot predictions back by. + Tells us if a bot will play more careful around + this sector. Checks FOFs in the sector, as well. Input Arguments:- - player - Player to compare. + player - Player to check against. + sec - Sector to check against. + x - Linedef cross X position, for slopes + y - Linedef cross Y position, for slopes Return:- - Multiplier in fixed point scale. + true if avoiding this sector, false otherwise. --------------------------------------------------*/ -fixed_t K_BotReducePrediction(player_t *player); +boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y); /*-------------------------------------------------- diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 80650030d..846521e6f 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -162,21 +162,11 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) } /*-------------------------------------------------- - static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) + boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) - Tells us if a bot will play more careful around - this sector. Checks FOFs in the sector, as well. - - Input Arguments:- - player - Player to check against. - sec - Sector to check against. - x - Linedef cross X position, for slopes - y - Linedef cross Y position, for slopes - - Return:- - true if avoiding this sector, false otherwise. + See header file for description. --------------------------------------------------*/ -static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) +boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) { const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); INT32 specialflag = 0; @@ -257,171 +247,6 @@ static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, return K_BotHatesThisSectorsSpecial(player, bestsector); } -/*-------------------------------------------------- - static boolean K_FindBlockingWalls(line_t *line) - - Blockmap search function. - Reels the bot prediction back in based on solid walls - or other obstacles surrounding the bot. - - Input Arguments:- - line - Linedef passed in from iteration. - - Return:- - true continues searching, false ends the search early. ---------------------------------------------------*/ -static boolean K_FindBlockingWalls(line_t *line) -{ - // Condensed version of PIT_CheckLine - const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); - fixed_t maxstep = maxstepmove; - fixed_t linedist = INT32_MAX; - INT32 lineside = 0; - vertex_t pos; - - if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) - { - return false; - } - - if (line->polyobj && !(line->polyobj->flags & POF_SOLID)) - { - return true; - } - - if (tmbbox[BOXRIGHT] <= line->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= line->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= line->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= line->bbox[BOXTOP]) - { - return true; - } - - if (P_BoxOnLineSide(tmbbox, line) != -1) - { - return true; - } - - lineside = P_PointOnLineSide(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line); - - // one sided line - if (!line->backsector) - { - if (lineside) - { - // don't hit the back side - return true; - } - - goto blocked; - } - - if ((line->flags & ML_IMPASSABLE) || (line->flags & ML_BLOCKPLAYERS)) - { - goto blocked; - } - - // set openrange, opentop, openbottom - P_LineOpening(line, globalsmuggle.botmo); - - if (globalsmuggle.botmo->player->waterskip) - maxstep += maxstepmove; - - if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 13, false)) - maxstep <<= 1; - else if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 12, false)) - maxstep = 0; - - if ((openrange < globalsmuggle.botmo->height) // doesn't fit - || (opentop - globalsmuggle.botmo->z < globalsmuggle.botmo->height) // mobj is too high - || (openbottom - globalsmuggle.botmo->z > maxstep)) // too big a step up - { - goto blocked; - } - - // Treat damage sectors like walls - P_ClosestPointOnLine(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line, &pos); - - if (lineside) - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->frontsector, pos.x, pos.y)) - goto blocked; - } - else - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->backsector, pos.x, pos.y)) - goto blocked; - } - - // We weren't blocked! - return true; - -blocked: - linedist = K_DistanceOfLineFromPoint(line->v1->x, line->v1->y, line->v2->x, line->v2->y, globalsmuggle.botmo->x, globalsmuggle.botmo->y); - linedist -= (globalsmuggle.botmo->radius * 8); // Maintain a reasonable distance away from it - - if (linedist > globalsmuggle.distancetocheck) - { - return true; - } - - if (linedist <= 0) - { - globalsmuggle.closestlinedist = 0; - return false; - } - - if (linedist < globalsmuggle.closestlinedist) - { - globalsmuggle.closestlinedist = linedist; - } - - return true; -} - -/*-------------------------------------------------- - fixed_t K_BotReducePrediction(player_t *player) - - See header file for description. ---------------------------------------------------*/ -fixed_t K_BotReducePrediction(player_t *player) -{ - INT32 xl, xh, yl, yh, bx, by; - - globalsmuggle.botmo = player->mo; - globalsmuggle.distancetocheck = (player->mo->radius * 32); - globalsmuggle.closestlinedist = INT32_MAX; - - tmx = player->mo->x; - tmy = player->mo->y; - - xl = (unsigned)(tmx - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmx + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmy - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmy + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - - BMBOUNDFIX(xl, xh, yl, yh); - - tmbbox[BOXTOP] = tmy + globalsmuggle.distancetocheck; - tmbbox[BOXBOTTOM] = tmy - globalsmuggle.distancetocheck; - tmbbox[BOXRIGHT] = tmx + globalsmuggle.distancetocheck; - tmbbox[BOXLEFT] = tmx - globalsmuggle.distancetocheck; - - // Check for lines that the bot might collide with - for (bx = xl; bx <= xh; bx++) - { - for (by = yl; by <= yh; by++) - { - P_BlockLinesIterator(bx, by, K_FindBlockingWalls); - } - } - - if (globalsmuggle.closestlinedist == INT32_MAX) - { - return FRACUNIT; - } - - return (FRACUNIT/2) + (FixedDiv(globalsmuggle.closestlinedist, globalsmuggle.distancetocheck) / 2); -} - /*-------------------------------------------------- static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) diff --git a/src/p_local.h b/src/p_local.h index db9e9e6dd..d90bfde4c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -404,6 +404,8 @@ boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing); boolean P_IsLineTripWire(const line_t *ld); boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y); boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); +fixed_t P_BaseStepUp(void); +fixed_t P_GetThingStepUp(mobj_t *thing); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); @@ -413,6 +415,7 @@ void P_BouncePlayerMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2); +boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2); void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius); boolean P_CheckSector(sector_t *sector, boolean crunch); diff --git a/src/p_map.c b/src/p_map.c index bcecb1dfa..966c332b8 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2428,6 +2428,42 @@ static boolean P_WaterStepUp(mobj_t *thing) P_WaterRunning(thing); } +fixed_t P_BaseStepUp(void) +{ + return FixedMul(MAXSTEPMOVE, mapobjectscale); +} + +fixed_t P_GetThingStepUp(mobj_t *thing) +{ + const fixed_t maxstepmove = P_BaseStepUp(); + fixed_t maxstep = maxstepmove; + + if (thing->type == MT_SKIM) + { + // Skim special (not needed for kart?) + return 0; + } + + if (P_WaterStepUp(thing) == true) + { + // Add some extra stepmove when waterskipping + maxstep += maxstepmove; + } + + if (P_MobjTouchingSectorSpecial(thing, 1, 13, false)) + { + // If using type Section1:13, double the maxstep. + maxstep <<= 1; + } + else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false)) + { + // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin + maxstep = 0; + } + + return maxstep; +} + // // P_TryMove // Attempt to move to a new position. @@ -2489,21 +2525,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (!(thing->flags & MF_NOCLIP)) { //All things are affected by their scale. - const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); - fixed_t maxstep = maxstepmove; - - if (thing->player && P_WaterStepUp(thing)) - maxstep += maxstepmove; // Add some extra stepmove when waterskipping - - // If using type Section1:13, double the maxstep. - if (P_MobjTouchingSectorSpecial(thing, 1, 13, false)) - maxstep <<= 1; - // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin - else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false)) - maxstep = 0; - - if (thing->type == MT_SKIM) - maxstep = 0; + fixed_t maxstep = P_GetThingStepUp(thing); if (tmceilingz - tmfloorz < thing->height) { @@ -2740,7 +2762,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) if (!(thing->flags & MF_NOCLIP)) { - const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale); + const fixed_t maxstep = P_BaseStepUp(); if (tmceilingz - tmfloorz < thing->height) return false; // doesn't fit @@ -3202,7 +3224,7 @@ static boolean PTR_LineIsBlocking(line_t *li) if (opentop - slidemo->z < slidemo->height) return true; // mobj is too high - if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapobjectscale)) + if (openbottom - slidemo->z > P_GetThingStepUp(slidemo)) return true; // too big a step up return false; diff --git a/src/p_sight.c b/src/p_sight.c index 38a50df36..a5aebf55c 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -18,6 +18,8 @@ #include "r_main.h" #include "r_state.h" +#include "k_bot.h" // K_BotHatesThisSector + // // P_CheckSight // @@ -572,7 +574,7 @@ static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb if (P_IsLineBlocking(line, tb->compareThing) == true) { - // This line will block us + // This line will always block us return false; } } @@ -656,3 +658,181 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2) // the head node is the last node output return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb); } + +// +// ANOTHER version, this time for bot traversal. +// (TODO: since we have so many versions of this function, the differences +// should maybe just be a function var that gets called?) +// + +static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t *tb) +{ + seg_t *seg; + INT32 count; + +#ifdef RANGECHECK + if (num >= numsubsectors) + I_Error("P_CrossBotTraversalSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); +#endif + + // haleyjd 02/23/06: this assignment should be after the above check + seg = segs + subsectors[num].firstline; + + for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines + { + line_t *line = seg->linedef; + divline_t divl; + const vertex_t *v1,*v2; + fixed_t maxstep = INT32_MAX; + + if (seg->glseg) + continue; + + // already checked other side? + if (line->validcount == validcount) + continue; + + line->validcount = validcount; + + // OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test + if (line->bbox[BOXLEFT ] > tb->bbox[BOXRIGHT ] || + line->bbox[BOXRIGHT ] < tb->bbox[BOXLEFT ] || + line->bbox[BOXBOTTOM] > tb->bbox[BOXTOP ] || + line->bbox[BOXTOP] < tb->bbox[BOXBOTTOM]) + continue; + + v1 = line->v1; + v2 = line->v2; + + // line isn't crossed? + if (P_DivlineSide(v1->x, v1->y, &tb->strace) == + P_DivlineSide(v2->x, v2->y, &tb->strace)) + continue; + + // stop because it is not two sided anyway + if (!(line->flags & ML_TWOSIDED)) + return false; + + divl.dx = v2->x - (divl.x = v1->x); + divl.dy = v2->y - (divl.y = v1->y); + + // line isn't crossed? + if (P_DivlineSide(tb->strace.x, tb->strace.y, &divl) == + P_DivlineSide(tb->t2x, tb->t2y, &divl)) + continue; + + if (P_IsLineBlocking(line, tb->compareThing) == true) + { + // This line will always block us + return false; + } + + // set openrange, opentop, openbottom + P_LineOpening(line, tb->compareThing); + maxstep = P_GetThingStepUp(tb->compareThing); + + if ((openrange < tb->compareThing->height) // doesn't fit + || (opentop - tb->compareThing->z < tb->compareThing->height) // mobj is too high + || (openbottom - tb->compareThing->z > maxstep)) // too big a step up + { + // This line situationally blocks us + return false; + } + + // Treat damage sectors like walls + if (tb->compareThing->player != NULL) + { + INT32 lineside = 0; + vertex_t pos; + + P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); + lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); + + if (K_BotHatesThisSector(tb->compareThing->player, lineside ? line->frontsector : line->backsector, pos.x, pos.y)) + { + // This line does not block us, but we don't want to be in it. + return false; + } + } + } + + // passed the subsector ok + return true; +} + +static boolean P_CrossBSPNodeBotTraversal(INT32 bspnum, register traceblocking_t *tb) +{ + while (!(bspnum & NF_SUBSECTOR)) + { + register node_t *bsp = nodes + bspnum; + INT32 side = P_DivlineSide(tb->strace.x,tb->strace.y,(divline_t *)bsp)&1; + if (side == P_DivlineSide(tb->t2x, tb->t2y, (divline_t *) bsp)) + bspnum = bsp->children[side]; // doesn't touch the other side + else // the partition plane is crossed here + { + if (!P_CrossBSPNodeBotTraversal(bsp->children[side], tb)) + return false; // cross the starting side + else + bspnum = bsp->children[side^1]; // cross the ending side + } + } + + return P_CrossBotTraversalSubsector((bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR), tb); +} + +boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2) +{ + const sector_t *s1, *s2; + size_t pnum; + traceblocking_t tb; + + // First check for trivial rejection. + if (!t1 || !t2) + return false; + + I_Assert(!P_MobjWasRemoved(t1)); + I_Assert(!P_MobjWasRemoved(t2)); + + if (!t1->subsector || !t2->subsector + || !t1->subsector->sector || !t2->subsector->sector) + return false; + + s1 = t1->subsector->sector; + s2 = t2->subsector->sector; + pnum = (s1-sectors)*numsectors + (s2-sectors); + + if (rejectmatrix != NULL) + { + // Check in REJECT table. + if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected + return false; + } + + // killough 11/98: shortcut for melee situations + // same subsector? obviously visible + // haleyjd 02/23/06: can't do this if there are polyobjects in the subsec + if (!t1->subsector->polyList && + t1->subsector == t2->subsector) + return true; + + validcount++; + + tb.strace.dx = (tb.t2x = t2->x) - (tb.strace.x = t1->x); + tb.strace.dy = (tb.t2y = t2->y) - (tb.strace.y = t1->y); + + if (t1->x > t2->x) + tb.bbox[BOXRIGHT] = t1->x, tb.bbox[BOXLEFT] = t2->x; + else + tb.bbox[BOXRIGHT] = t2->x, tb.bbox[BOXLEFT] = t1->x; + + if (t1->y > t2->y) + tb.bbox[BOXTOP] = t1->y, tb.bbox[BOXBOTTOM] = t2->y; + else + tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; + + tb.compareThing = t1; + + // the head node is the last node output + return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb); +} + From 08bfd6e8811f77a666235f79215ce7d6104d72e4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 11 Dec 2021 01:51:40 -0500 Subject: [PATCH 57/89] Improve the new wall detection further They didn't fall off on Hardhat, I'm so proud of my sons --- src/k_bot.c | 34 +++++++++------------------------- src/k_bot.h | 1 + src/p_sight.c | 21 +++++++++++++-------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 1d9b8ff83..d11142119 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -576,9 +576,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict - const fixed_t speed = P_AproxDistance(player->rmomx, player->rmomy); + const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy); - const INT32 startDist = (1536 * mapobjectscale) / FRACUNIT; + const INT32 startDist = (768 * mapobjectscale) / FRACUNIT; const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist; botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); @@ -653,11 +653,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) continue; } - if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[i]->mobj) == false) - { - continue; - } - // Unlike the other parts of this function, we're comparing the player's physical position, NOT the position of the waypoint!! // This should roughly correspond with how players will think about path splits. a = R_PointToAngle2( @@ -677,24 +672,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) delta = a; } } - - if (i == wp->numnextwaypoints) - { - // No usable waypoint, we don't want to check any further - radreduce /= 2; - distanceleft = 0; - break; - } - } - else - { - if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false) - { - // If we can't get a direct path to this waypoint, we don't want to check any further. - radreduce /= 2; - distanceleft = 0; - break; - } } angletonext = R_PointToAngle2( @@ -704,6 +681,13 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) disttonext = (INT32)wp->nextwaypointdistances[nwp]; + if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false) + { + // If we can't get a direct path to this waypoint, we don't want to check much further... + disttonext *= 2; + radreduce = FRACUNIT/2; + } + if (disttonext > distanceleft) { break; diff --git a/src/k_bot.h b/src/k_bot.h index 41c8df5e0..d354bbb2c 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -15,6 +15,7 @@ #include "k_waypoint.h" #include "d_player.h" +#include "r_defs.h" // Maximum value of botvars.difficulty #define MAXBOTDIFFICULTY 9 diff --git a/src/p_sight.c b/src/p_sight.c index a5aebf55c..8e63f1be4 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -742,16 +742,21 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t // Treat damage sectors like walls if (tb->compareThing->player != NULL) { - INT32 lineside = 0; - vertex_t pos; + boolean alreadyHates = K_BotHatesThisSector(tb->compareThing->player, tb->compareThing->subsector->sector, tb->compareThing->x, tb->compareThing->y); - P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); - lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); - - if (K_BotHatesThisSector(tb->compareThing->player, lineside ? line->frontsector : line->backsector, pos.x, pos.y)) + if (alreadyHates == false) { - // This line does not block us, but we don't want to be in it. - return false; + INT32 lineside = 0; + vertex_t pos; + + P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); + lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); + + if (K_BotHatesThisSector(tb->compareThing->player, ((lineside == 1) ? line->frontsector : line->backsector), pos.x, pos.y)) + { + // This line does not block us, but we don't want to be in it. + return false; + } } } } From ba26a3a22350b442e22e77e9e2f3c2a04b2804e8 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 11 Dec 2021 02:22:33 -0500 Subject: [PATCH 58/89] Require bots to be much slower to consider spindash --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index d11142119..1a75ea06c 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -776,7 +776,7 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } - if (speedDiff < (3 * baseAccel / 4)) + if (speedDiff < (baseAccel / 4)) { if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) { From 8d5cec5ebf31b2cb74a042f4ebe2d335f82bc049 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 11 Dec 2021 04:12:06 -0500 Subject: [PATCH 59/89] Move where PF_HITFINISHLINE is removed Also removes a few remaining instances of player->bot being checked to affect gameplay where it shouldn't from vanilla, but it's code that is rarely used / completely unused anyway. --- src/k_kart.c | 2 -- src/p_mobj.c | 2 +- src/p_user.c | 8 +++++--- src/r_skins.c | 5 ----- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 7401b9d4c..2b5d1ace9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8629,8 +8629,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) boolean HOLDING_ITEM = (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)); boolean NO_HYUDORO = (player->stealingtimer == 0); - player->pflags &= ~PF_HITFINISHLINE; - if (!player->exiting) { if (player->oldposition < player->position) // But first, if you lost a place, diff --git a/src/p_mobj.c b/src/p_mobj.c index 5a9f0925e..ad86d0434 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4095,7 +4095,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->bot || player->spectator) + if (player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) diff --git a/src/p_user.c b/src/p_user.c index 5f5242e66..5af3386d6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4222,9 +4222,6 @@ void P_PlayerThink(player_t *player) ticcmd_t *cmd; const size_t playeri = (size_t)(player - players); - player->old_drawangle = player->drawangle; - player->old_viewrollangle = player->viewrollangle; - #ifdef PARANOIA if (!player->mo) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); @@ -4237,6 +4234,11 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } + player->old_drawangle = player->drawangle; + player->old_viewrollangle = player->viewrollangle; + + player->pflags &= ~PF_HITFINISHLINE; + if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid diff --git a/src/r_skins.c b/src/r_skins.c index 1e80e18ce..ba7ed0811 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -311,11 +311,6 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) } player->skincolor = newcolor = skin->prefcolor; - if (player->bot && botingame) - { - botskin = (UINT8)(skinnum + 1); - botcolor = skin->prefcolor; - } } #endif From bfdae2840995b7031c1c8d64da6e6616bb840f94 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 11 Dec 2021 04:18:09 -0500 Subject: [PATCH 60/89] Not Climable flag on a bot controller disables rubberbanding --- src/k_bot.c | 142 +++++++++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 64 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 1a75ea06c..f3555deed 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -283,6 +283,70 @@ boolean K_BotCanTakeCut(player_t *player) return false; } +/*-------------------------------------------------- + static INT16 K_FindBotController(mobj_t *mo) + + Finds if any bot controller linedefs are tagged to the bot's sector. + + Input Arguments:- + mo - The bot player's mobj. + + Return:- + Line number of the bot controller. -1 if it doesn't exist. +--------------------------------------------------*/ +static INT16 K_FindBotController(mobj_t *mo) +{ + msecnode_t *node; + ffloor_t *rover; + INT16 lineNum = -1; + mtag_t tag; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (!node->m_sector) + { + continue; + } + + tag = Tag_FGet(&node->m_sector->tags); + lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag + + if (lineNum != -1) + { + return lineNum; + } + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + sector_t *rs = NULL; + + if (!(rover->flags & FF_EXISTS)) + { + continue; + } + + if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) + { + continue; + } + + rs = §ors[rover->secnum]; + tag = Tag_FGet(&rs->tags); + lineNum = P_FindSpecialLineFromTag(2004, tag, -1); + + if (lineNum != -1) + { + return lineNum; + } + } + } + + return -1; +} + /*-------------------------------------------------- static UINT32 K_BotRubberbandDistance(player_t *player) @@ -346,6 +410,7 @@ fixed_t K_BotRubberband(player_t *player) fixed_t rubberband = FRACUNIT; fixed_t max, min; player_t *firstplace = NULL; + INT16 botController = -1; UINT8 i; if (player->exiting) @@ -354,6 +419,19 @@ fixed_t K_BotRubberband(player_t *player) return FRACUNIT; } + botController = K_FindBotController(player->mo); + + if (botController != -1) + { + line_t *controllerLine = &lines[botController]; + + // No Climb Flag: Disable rubberbanding + if (controllerLine->flags & ML_NOCLIMB) + { + return FRACUNIT; + } + } + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -812,70 +890,6 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } -/*-------------------------------------------------- - static INT16 K_FindBotController(mobj_t *mo) - - Finds if any bot controller linedefs are tagged to the bot's sector. - - Input Arguments:- - mo - The bot player's mobj. - - Return:- - Line number of the bot controller. -1 if it doesn't exist. ---------------------------------------------------*/ -static INT16 K_FindBotController(mobj_t *mo) -{ - msecnode_t *node; - ffloor_t *rover; - INT16 lineNum = -1; - mtag_t tag; - - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (!node->m_sector) - { - continue; - } - - tag = Tag_FGet(&node->m_sector->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag - - if (lineNum != -1) - { - return lineNum; - } - - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - sector_t *rs = NULL; - - if (!(rover->flags & FF_EXISTS)) - { - continue; - } - - if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) - { - continue; - } - - rs = §ors[rover->secnum]; - tag = Tag_FGet(&rs->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); - - if (lineNum != -1) - { - return lineNum; - } - } - } - - return -1; -} - /*-------------------------------------------------- static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) From 841649c7ead29ad63cad01c382711279a581c9b9 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Sat, 11 Dec 2021 11:23:48 +0100 Subject: [PATCH 61/89] opengl: fake the pause fade background --- src/k_menudraw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index c9fc729c3..de9a354d0 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -245,7 +245,10 @@ void M_Drawer(void) } else if (!WipeInAction && currentMenu != &PAUSE_PlaybackMenuDef) { - V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...) + if (rendermode == render_opengl) // OGL can't handle what SW is doing so let's fake it; + V_DrawFadeScreen(122, 3); // palette index aproximation... + else // Software can keep its unique fade + V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...) } if (currentMenu->drawroutine) From cdb3b1ca982a41f10db10b100742ace229307a17 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Sat, 11 Dec 2021 18:22:56 +0100 Subject: [PATCH 62/89] Difficulty select before GP, match race & netgames --- src/k_menu.h | 15 ++++++ src/k_menudef.c | 52 +++++++++++++++++-- src/k_menudraw.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ src/k_menufunc.c | 104 +++++++++++++++++++++++++++++++++++--- 4 files changed, 291 insertions(+), 9 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 7eca2ca0d..1f70256d0 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -174,6 +174,9 @@ extern menu_t PLAY_GamemodesDef; extern menuitem_t PLAY_RaceGamemodesMenu[]; extern menu_t PLAY_RaceGamemodesDef; +extern menuitem_t PLAY_RaceDifficulty[]; +extern menu_t PLAY_RaceDifficultyDef; + extern menuitem_t PLAY_CupSelect[]; extern menu_t PLAY_CupSelectDef; @@ -478,6 +481,16 @@ void M_CupSelectTick(void); void M_LevelSelectHandler(INT32 choice); void M_LevelSelectTick(void); +// dummy consvars for GP & match race setup +extern consvar_t cv_dummygpdifficulty; +extern consvar_t cv_dummykartspeed; +extern consvar_t cv_dummygpencore; +extern consvar_t cv_dummymatchbots; + +void M_SetupDifficultySelect(INT32 choice); +void M_SetupDifficultySelectMP(INT32 choice); +void M_DifficultySelectInputs(INT32 choice); + // Multiplayer menu stuff // Keep track of multiplayer menu related data @@ -692,6 +705,8 @@ void M_DrawCupSelect(void); void M_DrawLevelSelect(void); void M_DrawTimeAttack(void); +void M_DrawRaceDifficulty(void); + // Multiplayer menu stuff void M_DrawMPOptSelect(void); void M_DrawMPHost(void); diff --git a/src/k_menudef.c b/src/k_menudef.c index 6a9487828..38ddcbe29 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -100,10 +100,10 @@ menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); menuitem_t PLAY_RaceGamemodesMenu[] = { {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", - NULL, M_LevelSelectInit, 2, GT_RACE}, + NULL, M_SetupDifficultySelect, 0, 0}, {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", - "MENIMG01", M_LevelSelectInit, 0, GT_RACE}, + "MENIMG01", M_SetupDifficultySelect, 1, 0}, {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", NULL, M_LevelSelectInit, 1, GT_RACE}, @@ -113,6 +113,52 @@ menuitem_t PLAY_RaceGamemodesMenu[] = menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); + +// difficulty selection: +menuitem_t PLAY_RaceDifficulty[] = +{ + // local play + {IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty", + NULL, &cv_dummygpdifficulty, 0, 0}, + + // netgames + {IT_STRING | IT_CVAR, "Difficulty", "Select the game speed", + NULL, &cv_dummykartspeed, 0, 0}, + + // DISABLE THAT OPTION OUTSIDE OF MATCH RACE + {IT_STRING2 | IT_CVAR, "CPU Players", "Enable or disable CPU players.", // 2 whitestring is used by the drawer to know to draw shitstring + NULL, &cv_dummymatchbots, 0, 0}, + + {IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", // 3 + NULL, &cv_dummygpencore, 0, 0}, + + // For GP: + {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, M_LevelSelectInit, 2, GT_RACE}, // 4 + + // For Match Race: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_LevelSelectInit, 0, GT_RACE}, // 5 + + // For Match Race in NETGAMES: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_MPSetupNetgameMapSelect, 0, GT_RACE}, // 6 + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, +}; + +menu_t PLAY_RaceDifficultyDef = { + sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_RaceDifficulty, + 0, 0, + 0, 0, + 1, 10, + M_DrawRaceDifficulty, + NULL, + NULL, + NULL +}; + + menuitem_t PLAY_CupSelect[] = { {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CupSelectHandler, 0, 0}, @@ -234,7 +280,7 @@ menuitem_t PLAY_MP_Host[] = NULL, &cv_dummygametype, 0, 0}, {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", - NULL, M_MPSetupNetgameMapSelect, 0, 0}, + NULL, M_SetupDifficultySelectMP, 0, 0}, }; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index de9a354d0..abc29e912 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1020,6 +1020,135 @@ void M_DrawCharacterSelect(void) M_DrawCharSelectCursor(priority); } +// DIFFICULTY SELECT +// This is a mix of K_DrawKartGamemodeMenu and the generic menu drawer depending on what we need. +// This is only ever used here (I hope because this is starting to pile up on hacks to look like the old m_menu.c lol...) + +void M_DrawRaceDifficulty(void) +{ + UINT8 n = currentMenu->numitems-4; + patch_t *box = W_CachePatchName("M_DBOX", PU_CACHE); + + INT32 i; + INT32 x = 120; + INT32 y = 48; + + M_DrawMenuTooltips(); + + // Draw the box for difficulty... + V_DrawFixedPatch((111 + 24*menutransition.tics)*FRACUNIT, 33*FRACUNIT, FRACUNIT, 0, box, NULL); + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + + for (i = 0; i < currentMenu->numitems; i++) + { + if (i >= n) + { + + x = GM_STARTX + (GM_XOFFSET * 5 / 2); + y = GM_STARTY + (GM_YOFFSET * 5 / 2); + + if (i < currentMenu->numitems-1) + { + x -= GM_XOFFSET; + y -= GM_YOFFSET; + } + + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + } + + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + // This is HACKY...... + + case IT_STRING2: + { + + INT32 f = (i == itemOn) ? highlightflags : 0; + + V_DrawString(140 + 24*menutransition.tics, y, f, currentMenu->menuitems[i].text); + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + // implicitely we'll only take care of normal cvars + INT32 cx = 260 + 24*menutransition.tics; + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawCenteredString(cx, y, f, cv->string); + + if (i == itemOn) + { + + INT32 w = V_StringWidth(cv->string, 0)/2; + + V_DrawCharacter(cx - 10 - w - (skullAnimCounter/5), y, '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(cx + w + 2 + (skullAnimCounter/5), y, '\x1D' | highlightflags, false); // right arrow + } + } + + y += 12; + + break; + } + + case IT_STRING: + { + + UINT8 *colormap = NULL; + + if (i == itemOn) + { + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + } + else + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_MOSS, GTC_CACHE); + } + + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + + INT32 fx = (x - 24*menutransition.tics); + INT32 centx = fx + (320-fx)/2 + (menutransition.tics*24); // undo the menutransition movement to redo it here otherwise the text won't move at the same speed lole. + + // implicitely we'll only take care of normal consvars + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUSHRT", PU_CACHE), colormap); + V_DrawCenteredGamemodeString(centx, y - 3, V_ALLOWLOWERCASE, colormap, cv->string); + + if (i == itemOn) + { + patch_t *arr_r = W_CachePatchName("GM_ARRL", PU_CACHE); + patch_t *arr_l = W_CachePatchName("GM_ARRR", PU_CACHE); + + V_DrawFixedPatch((centx-54 - arr_r->width - (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_r, colormap); + V_DrawFixedPatch((centx+54 + (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_l, colormap); + } + + } + else // not a cvar + { + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUPLTR", PU_CACHE), colormap); + V_DrawGamemodeString(x + 16, y - 3, V_ALLOWLOWERCASE, colormap, currentMenu->menuitems[i].text); + } + x += GM_XOFFSET; + y += GM_YOFFSET; + + break; + } + } + } +} + // LEVEL SELECT static void M_DrawCupPreview(INT16 y, cupheader_t *cup) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 349f9e560..a507f1632 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -166,6 +166,9 @@ static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"} static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; static CV_PossibleValue_t dummygametype_cons_t[] = {{0, "Race"}, {1, "Battle"}, {0, NULL}}; +static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}}; +static CV_PossibleValue_t dummykartspeed_cons_t[] = {{-1, "Auto"}, {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}}; + //static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL); //static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); @@ -176,6 +179,26 @@ consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); +consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, dummygpdifficulty_cons_t, NULL); +consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL); +consvar_t cv_dummygpencore = CVAR_INIT ("dummygpdifficulty", "No", CV_HIDDEN, CV_YesNo, NULL); + +static CV_PossibleValue_t dummymatchbots_cons_t[] = { + {0, "Off"}, + {1, "Lv.1"}, + {2, "Lv.2"}, + {3, "Lv.3"}, + {4, "Lv.4"}, + {5, "Lv.5"}, + {6, "Lv.6"}, + {7, "Lv.7"}, + {8, "Lv.8"}, + {9, "Lv.9"}, + {0, NULL} +}; + +consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN|CV_SAVE, dummymatchbots_cons_t, NULL); // Save this one if you wanna test your stuff without bots for instance + // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE // ========================================================================== @@ -1629,6 +1652,11 @@ void M_Init(void) CV_RegisterVar(&cv_dummygametype); CV_RegisterVar(&cv_dummyip); + CV_RegisterVar(&cv_dummygpdifficulty); + CV_RegisterVar(&cv_dummykartspeed); + CV_RegisterVar(&cv_dummygpencore); + CV_RegisterVar(&cv_dummymatchbots); + M_UpdateMenuBGImage(true); #if 0 @@ -2347,6 +2375,60 @@ boolean M_CharacterSelectQuit(void) return true; } +// DIFFICULTY SELECT + +void M_SetupDifficultySelect(INT32 choice) +{ + // check what we picked. + choice = currentMenu->menuitems[itemOn].mvar1; + + // setup the difficulty menu and then remove choices depending on choice + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[1].status = IT_DISABLED; + PLAY_RaceDifficulty[2].status = IT_DISABLED; + PLAY_RaceDifficulty[3].status = IT_DISABLED; + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_DISABLED; + + if (choice) // Match Race + { + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[5].status = IT_STRING|IT_CALL; // Level Select (Match Race) + itemOn = 5; // Select cup select by default. + + } + else // GP + { + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_STRING|IT_CALL; // Level Select (GP) + itemOn = 4; // Select cup select by default. + } +} + +// calls the above but changes the cvar we set +void M_SetupDifficultySelectMP(INT32 choice) +{ + (void) choice; + + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_DISABLED; + PLAY_RaceDifficulty[1].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_STRING|IT_CALL; + + itemOn = 6; // Select cup select by default. +} + // LEVEL SELECT // @@ -2585,10 +2667,11 @@ void M_CupSelectHandler(INT32 choice) memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); - // TODO: game settings screen - grandprixinfo.gamespeed = KARTSPEED_NORMAL; - grandprixinfo.masterbots = false; - grandprixinfo.encore = false; + // read our dummy cvars + + grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value); + grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3); + grandprixinfo.encore = (boolean)cv_dummygpencore.value; grandprixinfo.cup = newcup; @@ -2744,9 +2827,18 @@ void M_LevelSelectHandler(INT32 choice) SV_StartSinglePlayerServer(); multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this... netgame = levellist.netgame; // ^ ditto. - } - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); + // this is considered to be CV_CHEAT however... + CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); // Match the kartbot value to the dummy match bots value. + + if (netgame) // check for the dummy kartspeed value + CV_StealthSet(&cv_kartspeed, cv_dummykartspeed.string); + + + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); + } + else // directly do the map change + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); M_ClearMenus(true); } From 813b2da06576b436d365f1def8b9a36deb804529 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Sat, 11 Dec 2021 18:32:50 +0100 Subject: [PATCH 63/89] Fix the host menu re-folding on itself if you backed out of difficulty selection --- src/k_menufunc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index a507f1632..11774e85c 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -2427,6 +2427,9 @@ void M_SetupDifficultySelectMP(INT32 choice) PLAY_RaceDifficulty[6].status = IT_STRING|IT_CALL; itemOn = 6; // Select cup select by default. + + // okay this is REALLY stupid but this fixes the host menu re-folding on itself when we go back. + mpmenu.modewinextend[0][0] = 1; } // LEVEL SELECT From 0e43a04dee4196d8f7080b2038a4f6123d84753c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 12 Dec 2021 02:07:21 -0500 Subject: [PATCH 64/89] Try adding tripwire support Kind of lazy. When checking bot traversal, it considers tripwires as walls. K_BotCanTakeCut now is limited to whatever can take tripwires (no more hyudoro invisibility). Probably should have something more foolproof, but it's annoying to test any changes to this. The only maps I can think of with really easy tripwires clearly don't have their waypoints with bots in mind, the rest are very optional or out of the way or otherwise the bots don't want to even touch them at all. --- src/k_bot.c | 16 ++++++++++++---- src/p_sight.c | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index f3555deed..6bb5a6080 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -273,14 +273,22 @@ boolean K_PlayerUsesBotMovement(player_t *player) --------------------------------------------------*/ boolean K_BotCanTakeCut(player_t *player) { - if (!K_ApplyOffroad(player) + if ( +#if 1 + K_TripwirePass(player) == true +#else + K_ApplyOffroad(player) == false +#endif || player->itemtype == KITEM_SNEAKER || player->itemtype == KITEM_ROCKETSNEAKER || player->itemtype == KITEM_INVINCIBILITY - || player->itemtype == KITEM_HYUDORO) + ) + { return true; + } return false; +#endif } /*-------------------------------------------------- @@ -721,12 +729,12 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) for (i = 0; i < wp->numnextwaypoints; i++) { - if (!K_GetWaypointIsEnabled(wp->nextwaypoints[i])) + if (K_GetWaypointIsEnabled(wp->nextwaypoints[i]) == false) { continue; } - if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) && !K_BotCanTakeCut(player)) + if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) == true && K_BotCanTakeCut(player) == false) { continue; } diff --git a/src/p_sight.c b/src/p_sight.c index 8e63f1be4..00c2f09d9 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -758,6 +758,12 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t return false; } } + + if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false) + { + // Can't go through trip wire. + return false; + } } } From cd0a259bbead81294ccbd9f9bfe2c11769ed8e6e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 12 Dec 2021 02:32:03 -0500 Subject: [PATCH 65/89] Code cleanup - K_FindBotController returns the line_t directly, instead of a linedef index. - Trick panel code is in its own function. - Try to fix infinite bot heat death --- src/k_bot.c | 108 ++++++++++++++++++++++++++++++-------------------- src/k_bot.h | 4 +- src/p_sight.c | 1 + src/p_user.c | 16 +++++++- 4 files changed, 84 insertions(+), 45 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 6bb5a6080..2a5bb665d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -288,11 +288,10 @@ boolean K_BotCanTakeCut(player_t *player) } return false; -#endif } /*-------------------------------------------------- - static INT16 K_FindBotController(mobj_t *mo) + static line_t *K_FindBotController(mobj_t *mo) Finds if any bot controller linedefs are tagged to the bot's sector. @@ -300,9 +299,9 @@ boolean K_BotCanTakeCut(player_t *player) mo - The bot player's mobj. Return:- - Line number of the bot controller. -1 if it doesn't exist. + Linedef of the bot controller. NULL if it doesn't exist. --------------------------------------------------*/ -static INT16 K_FindBotController(mobj_t *mo) +static line_t *K_FindBotController(mobj_t *mo) { msecnode_t *node; ffloor_t *rover; @@ -324,7 +323,7 @@ static INT16 K_FindBotController(mobj_t *mo) if (lineNum != -1) { - return lineNum; + break; } for (rover = node->m_sector->ffloors; rover; rover = rover->next) @@ -347,12 +346,19 @@ static INT16 K_FindBotController(mobj_t *mo) if (lineNum != -1) { - return lineNum; + break; } } } - return -1; + if (lineNum != -1) + { + return &lines[lineNum]; + } + else + { + return NULL; + } } /*-------------------------------------------------- @@ -418,7 +424,7 @@ fixed_t K_BotRubberband(player_t *player) fixed_t rubberband = FRACUNIT; fixed_t max, min; player_t *firstplace = NULL; - INT16 botController = -1; + line_t *botController = NULL; UINT8 i; if (player->exiting) @@ -429,12 +435,10 @@ fixed_t K_BotRubberband(player_t *player) botController = K_FindBotController(player->mo); - if (botController != -1) + if (botController != NULL) { - line_t *controllerLine = &lines[botController]; - // No Climb Flag: Disable rubberbanding - if (controllerLine->flags & ML_NOCLIMB) + if (botController->flags & ML_NOCLIMB) { return FRACUNIT; } @@ -962,6 +966,50 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) } } +/*-------------------------------------------------- + static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController) + + Determines inputs for trick panels. + + Input Arguments:- + player - Player to generate the ticcmd for. + cmd - The player's ticcmd to modify. + botController - Linedef for the bot controller. + + Return:- + None +--------------------------------------------------*/ +static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController) +{ + // Trick panel state -- do nothing until a controller line is found, in which case do a trick. + if (botController == NULL) + { + return; + } + + if (player->trickpanel == 1) + { + INT32 type = (sides[botController->sidenum[0]].rowoffset / FRACUNIT); + + // Y Offset: Trick type + switch (type) + { + case 1: + cmd->turning = KART_FULLTURN; + break; + case 2: + cmd->turning = -KART_FULLTURN; + break; + case 3: + cmd->buttons |= BT_FORWARD; + break; + case 4: + cmd->buttons |= BT_BACKWARD; + break; + } + } +} + /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) @@ -973,7 +1021,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) boolean trySpindash = true; UINT8 spindash = 0; INT32 turnamt = 0; - INT16 botController = -1; + line_t *botController = NULL; // Can't build a ticcmd if we aren't spawned... if (!player->mo) @@ -996,7 +1044,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } // Complete override of all ticcmd functionality - if (LUAh_BotTiccmd(player, cmd)) + if (LUAh_BotTiccmd(player, cmd) == true) { return; } @@ -1005,30 +1053,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (player->trickpanel != 0) { - // Trick panel state -- do nothing until a controller line is found, in which case do a trick. - - if (player->trickpanel == 1 && botController != -1) - { - line_t *controllerLine = &lines[botController]; - INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT); - - // Y Offset: Trick type - switch (type) - { - case 1: - cmd->turning = KART_FULLTURN; - break; - case 2: - cmd->turning = -KART_FULLTURN; - break; - case 3: - cmd->buttons |= BT_FORWARD; - break; - case 4: - cmd->buttons |= BT_BACKWARD; - break; - } - } + K_BotTrick(player, cmd, botController); // Don't do anything else. return; @@ -1037,20 +1062,19 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if ((player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj)) - || (botController != -1)) + || (botController != NULL)) { // Handle steering towards waypoints! SINT8 turnsign = 0; angle_t destangle, moveangle, angle; INT16 anglediff; - if (botController != -1) + if (botController != NULL) { const fixed_t dist = (player->mo->radius * 4); - line_t *controllerLine = &lines[botController]; // X Offset: Movement direction - destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset); + destangle = FixedAngle(sides[botController->sidenum[0]].textureoffset); // Overwritten prediction predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); diff --git a/src/k_bot.h b/src/k_bot.h index d354bbb2c..a04d5c174 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -223,8 +223,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd); - Gives a multiplier for a bot's rubberbanding. Meant to be used for top speed, - acceleration, and handling. + Creates a bot's ticcmd, looking at its surroundings to + try and figure out what it should do. Input Arguments:- player - Player to generate the ticcmd for. diff --git a/src/p_sight.c b/src/p_sight.c index 00c2f09d9..cdc8df864 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -19,6 +19,7 @@ #include "r_state.h" #include "k_bot.h" // K_BotHatesThisSector +#include "k_kart.h" // K_TripwirePass // // P_CheckSight diff --git a/src/p_user.c b/src/p_user.c index 5af3386d6..7ab85b6ec 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2502,6 +2502,8 @@ static void P_ConsiderAllGone(void) // static void P_DeathThink(player_t *player) { + boolean playerGone = false; + player->deltaviewheight = 0; if (player->deadtimer < INT32_MAX) @@ -2522,7 +2524,19 @@ static void P_DeathThink(player_t *player) K_KartPlayerHUDUpdate(player); - if (player->lives > 0 && !(player->pflags & PF_NOCONTEST) && player->deadtimer > TICRATE) + if (player->pflags & PF_NOCONTEST) + { + playerGone = true; + } + else if (player->bot == false) + { + if (G_GametypeUsesLives() == true && player->lives == 0) + { + playerGone = true; + } + } + + if (playerGone == false && player->deadtimer > TICRATE) { player->playerstate = PST_REBORN; } From bfa3311eca552fa57fba43f5ef948c55ce681a41 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 12 Dec 2021 03:28:49 -0500 Subject: [PATCH 66/89] Make rivals even more aggressive to players :) --- src/k_botitem.c | 204 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 152 insertions(+), 52 deletions(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index 67d858ea4..4bb83931c 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -86,7 +86,7 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r } /*-------------------------------------------------- - static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) + static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) Looks for players around a specified x/y coordinate. @@ -97,9 +97,9 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r radius - The radius to look for players in. Return:- - true if a player was found around the coordinate, otherwise false. + The player we found, NULL if nothing was found. --------------------------------------------------*/ -static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) +static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) { UINT8 i; @@ -129,15 +129,15 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t if (dist <= radius) { - return true; + return target; } } - return false; + return NULL; } /*-------------------------------------------------- - static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) + static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) Looks for players around the predicted coordinates of their thrown item. @@ -146,9 +146,9 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t extra - Extra throwing distance, for aim forward on mines. Return:- - true if a player was found around the coordinate, otherwise false. + The player we're trying to throw at, NULL if none was found. --------------------------------------------------*/ -static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) +static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) { const fixed_t dist = (30 + (extra * 10)) * player->mo->scale; const UINT32 airtime = FixedDiv(dist + player->mo->momz, gravity); @@ -159,7 +159,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) } /*-------------------------------------------------- - static boolean K_PlayerInCone(player_t *player, UINT16 cone, boolean flip) + static player_t *K_PlayerInCone(player_t *player, UINT16 cone, boolean flip) Looks for players in the . @@ -172,7 +172,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) Return:- true if a player was found in the cone, otherwise false. --------------------------------------------------*/ -static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip) +static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip) { UINT8 i; @@ -222,22 +222,96 @@ static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boo { if (ad >= 180-cone) { - return true; + return target; } } else { if (ad <= cone) { - return true; + return target; } } } } + return NULL; +} + +/*-------------------------------------------------- + static boolean K_RivalBotAggression(player_t *bot, player_t *target) + + Returns if a bot is a rival & wants to be aggressive to a player. + + Input Arguments:- + bot - Bot to check. + target - Who the bot wants to attack. + + Return:- + false if not the rival. false if the target is another bot. Otherwise, true. +--------------------------------------------------*/ +static boolean K_RivalBotAggression(player_t *bot, player_t *target) +{ + if (bot == NULL || target == NULL) + { + // Invalid. + return false; + } + + if (bot->bot == false) + { + // lol + return false; + } + + if (bot->botvars.rival == false) + { + // Not the rival, we aren't self-aware. + return false; + } + + if (target->bot == false) + { + // This bot knows that the real threat is the player. + return true; + } + + // Calling them your friends is misleading, but you'll at least spare them. return false; } +/*-------------------------------------------------- + static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount) + + Handles updating item confirm values for offense items. + + Input Arguments:- + bot - Bot to check. + target - Who the bot wants to attack. + amount - Amount to increase item confirm time by. + + Return:- + None +--------------------------------------------------*/ +static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount) +{ + if (bot == NULL || target == NULL) + { + return; + } + + if (K_RivalBotAggression(bot, target) == true) + { + // Double the rate when you're aggressive. + bot->botvars.itemconfirm += amount << 1; + } + else + { + // Do as normal. + bot->botvars.itemconfirm += amount; + } +} + /*-------------------------------------------------- static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) @@ -316,21 +390,21 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean } // Check the predicted throws. - if (K_PlayerPredictThrow(player, 0)) + if (K_PlayerPredictThrow(player, 0) != NULL) { return true; } if (mine) { - if (K_PlayerPredictThrow(player, 1)) + if (K_PlayerPredictThrow(player, 1) != NULL) { return true; } } // Check your behind. - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + if (K_PlayerInCone(player, player->mo->radius * 16, 10, true) != NULL) { return true; } @@ -447,7 +521,6 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) } } - /*-------------------------------------------------- static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) @@ -464,9 +537,17 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) { SINT8 throwdir = -1; + player_t *target = NULL; player->botvars.itemconfirm++; + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + throwdir = -1; + } + if (abs(turnamt) >= KART_FULLTURN/2) { player->botvars.itemconfirm += player->botvars.difficulty / 2; @@ -474,19 +555,15 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) } else { - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 1; } } - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) - { - player->botvars.itemconfirm += player->botvars.difficulty; - throwdir = -1; - } - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); @@ -509,12 +586,14 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { SINT8 throwdir = 0; + player_t *target = NULL; player->botvars.itemconfirm++; - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } @@ -525,21 +604,21 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) } else { - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 0; } - if (K_PlayerPredictThrow(player, 1)) + target = K_PlayerPredictThrow(player, 1); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 1; } } - - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); @@ -561,6 +640,8 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) --------------------------------------------------*/ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { + player_t *target = NULL; + player->botvars.itemconfirm++; if (abs(turnamt) >= KART_FULLTURN/2) @@ -568,9 +649,10 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) player->botvars.itemconfirm += player->botvars.difficulty / 2; } - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); } if (player->botvars.itemconfirm > 2*TICRATE) @@ -595,18 +677,21 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) { const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); SINT8 throwdir = -1; + player_t *target = NULL; player->botvars.itemconfirm++; - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty / 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty / 2); throwdir = 1; } - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } @@ -636,6 +721,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) static boolean K_BotRevealsEggbox(player_t *player) { const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); + player_t *target = NULL; // This is a stealthy spot for an eggbox, lets reveal it! if (stealth > 1) @@ -644,13 +730,15 @@ static boolean K_BotRevealsEggbox(player_t *player) } // Check the predicted throws. - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { return true; } // Check your behind. - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { return true; } @@ -677,7 +765,7 @@ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) return; } - if (K_BotRevealsEggbox(player) || (player->botvars.itemconfirm++ > 20*TICRATE)) + if (K_BotRevealsEggbox(player) == true || (player->botvars.itemconfirm++ > 20*TICRATE)) { K_BotGenericPressItem(player, cmd, 0); } @@ -699,8 +787,9 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) { if (player->position == 1) { + // Hey, we aren't gonna find anyone up here... + // why don't we slow down a bit? :) cmd->forwardmove /= 2; - cmd->buttons |= BT_BRAKE; } K_BotUseItemNearPlayer(player, cmd, 128*player->mo->scale); @@ -724,6 +813,7 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) fixed_t radius = (player->mo->radius * 32); SINT8 throwdir = -1; UINT8 snipeMul = 2; + player_t *target = NULL; if (player->speed > topspeed) { @@ -733,15 +823,21 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) player->botvars.itemconfirm++; - if (K_PlayerInCone(player, radius, 10, false)) + target = K_PlayerInCone(player, radius, 10, false); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * snipeMul; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); throwdir = 1; } else if (K_PlayerInCone(player, radius, 10, true)) { - player->botvars.itemconfirm += player->botvars.difficulty; - throwdir = -1; + target = K_PlayerInCone(player, radius, 10, true); + + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + throwdir = -1; + } } if (player->botvars.itemconfirm > 5*TICRATE) @@ -769,6 +865,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) SINT8 throwdir = 1; UINT8 snipeMul = 2; INT32 lastTarg = player->lastjawztarget; + player_t *target = NULL; if (player->speed > topspeed) { @@ -778,9 +875,10 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) player->botvars.itemconfirm++; - if (K_PlayerInCone(player, radius, 10, true)) + target = K_PlayerInCone(player, radius, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } @@ -790,16 +888,18 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) && players[lastTarg].mo != NULL && P_MobjWasRemoved(players[lastTarg].mo) == false) { - mobj_t *targ = players[lastTarg].mo; + mobj_t *targMo = players[lastTarg].mo; mobj_t *mobj = NULL, *next = NULL; boolean targettedAlready = false; + target = &players[lastTarg]; + // Make sure no other Jawz are targetting this player. for (mobj = kitemcap; mobj; mobj = next) { next = mobj->itnext; - if (mobj->type == MT_JAWZ && mobj->target == targ) + if (mobj->type == MT_JAWZ && mobj->target == targMo) { targettedAlready = true; break; @@ -808,7 +908,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) if (targettedAlready == false) { - player->botvars.itemconfirm += player->botvars.difficulty * snipeMul; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); throwdir = 1; } } @@ -833,7 +933,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemThunder(player_t *player, ticcmd_t *cmd) { - if (!K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale)) + if (K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale) == false) { if (player->botvars.itemconfirm > 10*TICRATE) { From cec81378644f74f6675a43907678d89a638de8aa Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 12 Dec 2021 04:07:32 -0500 Subject: [PATCH 67/89] Require Effect 1 for using bot controller angle. --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 2a5bb665d..24f3517a2 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -1069,7 +1069,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) angle_t destangle, moveangle, angle; INT16 anglediff; - if (botController != NULL) + if (botController != NULL && (botController->flags & ML_EFFECT1)) { const fixed_t dist = (player->mo->radius * 4); From 9e1146bc3052a2a766a8ebddb9e00df183700104 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Dec 2021 02:47:46 -0800 Subject: [PATCH 68/89] Disable downloading for now --- src/d_netfil.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/d_netfil.c b/src/d_netfil.c index 5714c39cd..f8edfbf03 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -276,11 +276,16 @@ boolean CL_CheckDownloadable(void) } // Downloading locally disabled +#if 0 if (!dlstatus && M_CheckParm("-nodownload")) dlstatus = 3; if (!dlstatus) return true; +#else + if (!dlstatus) + dlstatus = 3; +#endif // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); From 32127f37ee5e94844178ab6414ae1ec116306baa Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Dec 2021 02:58:06 -0800 Subject: [PATCH 69/89] Check mainwads netgame md5 in developer build --- src/d_netfil.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index f8edfbf03..7aec8d13e 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -161,10 +161,16 @@ UINT8 *PutFileNeeded(UINT16 firstfile) char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - for (i = mainwads+1; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad +#ifdef DEVELOP + i = 0; +#else + i = mainwads + 1; +#endif + + for (; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad { // If it has only music/sound lumps, don't put it in the list - if (!wadfiles[i]->important) + if (i > mainwads && !wadfiles[i]->important) continue; if (firstfile) @@ -494,7 +500,12 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = mainwads+1; wadfiles[j]; j++) +#ifdef DEVELOP + j = 0; +#else + j = mainwads + 1; +#endif + for (; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && From 35238510e34d0fb3950170cee5436ea64dccb7b1 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Dec 2021 03:28:59 -0800 Subject: [PATCH 70/89] Use sfx_s3k38 --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9550b0c41..0151b9114 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3065,7 +3065,7 @@ void P_MobjCheckWater(mobj_t *mobj) if (p && !p->waterskip && p->curshield != KSHIELD_BUBBLE && wasinwater) { - S_StartSound(mobj, sfx_gasp); + S_StartSound(mobj, sfx_s3k38); } if (waterwasnotset) From 184a89db4399a61d27dd43d183a48b17e2872b3c Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Dec 2021 03:30:08 -0800 Subject: [PATCH 71/89] Always play splash sfx when entering/exiting water --- src/p_mobj.c | 112 +++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0151b9114..61bbe60e5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3068,14 +3068,67 @@ void P_MobjCheckWater(mobj_t *mobj) S_StartSound(mobj, sfx_s3k38); } - if (waterwasnotset) - return; - if ((p) // Players || (mobj->flags & MF_PUSHABLE) // Pushables || ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still ) { + // Time to spawn the bubbles! + { + INT32 i; + INT32 bubblecount; + UINT8 prandom[4]; + mobj_t *bubble; + mobjtype_t bubbletype; + + if (mobj->eflags & MFE_GOOWATER || wasingoo) + S_StartSound(mobj, sfx_ghit); + else if (mobj->eflags & MFE_TOUCHLAVA) + S_StartSound(mobj, sfx_splash); + else + S_StartSound(mobj, sfx_splish); // And make a sound! + + bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); + // Max bubble count + if (bubblecount > 128) + bubblecount = 128; + + // Create tons of bubbles + for (i = 0; i < bubblecount; i++) + { + // P_RandomByte()s are called individually to allow consistency + // across various compilers, since the order of function calls + // in C is not part of the ANSI specification. + prandom[0] = P_RandomByte(); + prandom[1] = P_RandomByte(); + prandom[2] = P_RandomByte(); + prandom[3] = P_RandomByte(); + + bubbletype = MT_SMALLBUBBLE; + if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32 + bubbletype = MT_MEDIUMBUBBLE; + + bubble = P_SpawnMobj( + mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale), + mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale), + mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype); + + if (bubble) + { + if (P_MobjFlip(mobj)*mobj->momz < 0) + bubble->momz = mobj->momz >> 4; + else + bubble->momz = 0; + + bubble->destscale = mobj->scale; + P_SetScale(bubble, mobj->scale); + } + } + } + + if (waterwasnotset) + return; + // Check to make sure you didn't just cross into a sector to jump out of // that has shallower water than the block you were originally in. if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1) @@ -3160,59 +3213,6 @@ void P_MobjCheckWater(mobj_t *mobj) P_SetScale(splish, mobj->scale); } } - - // Time to spawn the bubbles! - { - INT32 i; - INT32 bubblecount; - UINT8 prandom[4]; - mobj_t *bubble; - mobjtype_t bubbletype; - - if (mobj->eflags & MFE_GOOWATER || wasingoo) - S_StartSound(mobj, sfx_ghit); - else if (mobj->eflags & MFE_TOUCHLAVA) - S_StartSound(mobj, sfx_splash); - else - S_StartSound(mobj, sfx_splish); // And make a sound! - - bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); - // Max bubble count - if (bubblecount > 128) - bubblecount = 128; - - // Create tons of bubbles - for (i = 0; i < bubblecount; i++) - { - // P_RandomByte()s are called individually to allow consistency - // across various compilers, since the order of function calls - // in C is not part of the ANSI specification. - prandom[0] = P_RandomByte(); - prandom[1] = P_RandomByte(); - prandom[2] = P_RandomByte(); - prandom[3] = P_RandomByte(); - - bubbletype = MT_SMALLBUBBLE; - if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32 - bubbletype = MT_MEDIUMBUBBLE; - - bubble = P_SpawnMobj( - mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale), - mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale), - mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype); - - if (bubble) - { - if (P_MobjFlip(mobj)*mobj->momz < 0) - bubble->momz = mobj->momz >> 4; - else - bubble->momz = 0; - - bubble->destscale = mobj->scale; - P_SetScale(bubble, mobj->scale); - } - } - } } } From 033a489b8549517c2bfefe6c79a361a18e3b50ab Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Dec 2021 01:29:20 -0800 Subject: [PATCH 72/89] Fix bad merge @ 4a8340cd4 --- src/hardware/hw_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b4dc1accb..2cdbd02c3 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -113,7 +113,7 @@ typedef struct UINT8 splitscreen; boolean flip; // screenflip boolean shearing; // 14042019 - angle_t viewaiming; // 17052019 + float viewaiming; // 17052019 boolean roll; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ FLOAT centerx, centery; From 1140410e2cf11dedf6a1aa607e68d82a1d6f68be Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Dec 2021 18:49:40 -0800 Subject: [PATCH 73/89] Spawn SPHERE BOXES randomly in Battle They look like random item boxes (the ones in Race) but have a blue sphere inside of them. One box is worth 10 blue spheres. More boxes spawn during Overtime. New sprite: SBOX --- src/deh_tables.c | 3 +++ src/info.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/info.h | 16 ++++++++++++++++ src/k_battle.c | 38 ++++++++++++++++++++++++++++++++++++++ src/k_battle.h | 1 + src/p_enemy.c | 4 +++- src/p_inter.c | 23 ++++++++--------------- src/p_local.h | 2 +- src/p_mobj.c | 2 ++ src/p_user.c | 20 ++++++++++++++++++++ 10 files changed, 133 insertions(+), 17 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 7e309c33f..894157639 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3476,6 +3476,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_RANDOMITEM12", "S_DEADRANDOMITEM", + // Sphere Box (for Battle) + "S_SPHEREBOX", + // Random Item Pop "S_RANDOMITEMPOP1", "S_RANDOMITEMPOP2", diff --git a/src/info.c b/src/info.c index 5d506d98d..2db296b99 100644 --- a/src/info.c +++ b/src/info.c @@ -526,6 +526,7 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites (sort later) "RNDM", // Random Item Box + "SBOX", // Sphere Box (for Battle) "RPOP", // Random Item Box Pop "SGNS", // Signpost sparkle "FAST", // Speed boost trail @@ -4061,6 +4062,19 @@ state_t states[NUMSTATES] = {SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12 {SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM + {SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1 + {SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2 + {SPR_SBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX4}, // S_SPHEREBOX3 + {SPR_SBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX5}, // S_SPHEREBOX4 + {SPR_SBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX6}, // S_SPHEREBOX5 + {SPR_SBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX7}, // S_SPHEREBOX6 + {SPR_SBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX8}, // S_SPHEREBOX7 + {SPR_SBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX9}, // S_SPHEREBOX8 + {SPR_SBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX10}, // S_SPHEREBOX9 + {SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10 + {SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11 + {SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12 + {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 {SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3 @@ -23017,6 +23031,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPHEREBOX + -1, // doomednum + S_SPHEREBOX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_DEADRANDOMITEM, // deathstate + S_NULL, // xdeathstate + sfx_kc2e, // deathsound + 60*FRACUNIT, // speed + 48*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_RANDOMITEMPOP, // damage + sfx_None, // activesound + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_RANDOMITEMPOP -1, // doomednum S_INVISIBLE, // spawnstate diff --git a/src/info.h b/src/info.h index 115948905..eab11e86a 100644 --- a/src/info.h +++ b/src/info.h @@ -1070,6 +1070,7 @@ typedef enum sprite // SRB2Kart SPR_RNDM, // Random Item Box + SPR_SBOX, // Sphere Box (for Battle) SPR_RPOP, // Random Item Box Pop SPR_SGNS, // Signpost sparkle SPR_FAST, // Speed boost trail @@ -4453,6 +4454,20 @@ typedef enum state S_RANDOMITEM12, S_DEADRANDOMITEM, + // Sphere Box (for Battle) + S_SPHEREBOX1, + S_SPHEREBOX2, + S_SPHEREBOX3, + S_SPHEREBOX4, + S_SPHEREBOX5, + S_SPHEREBOX6, + S_SPHEREBOX7, + S_SPHEREBOX8, + S_SPHEREBOX9, + S_SPHEREBOX10, + S_SPHEREBOX11, + S_SPHEREBOX12, + // Random Item Pop S_RANDOMITEMPOP1, S_RANDOMITEMPOP2, @@ -6465,6 +6480,7 @@ typedef enum mobj_type // SRB2kart MT_RANDOMITEM, + MT_SPHEREBOX, MT_RANDOMITEMPOP, MT_FLOATINGITEM, MT_ITEMCAPSULE, diff --git a/src/k_battle.c b/src/k_battle.c index c33ea6bcc..83c47d43e 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -229,6 +229,28 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT return emerald; } +mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount) +{ + mobj_t *drop = P_SpawnMobj(x, y, z, MT_SPHEREBOX); + + (void)amount; + + drop->angle = angle; + P_Thrust(drop, + FixedAngle(P_RandomFixed() * 180) + angle, + P_RandomRange(4, 12) * mapobjectscale); + + drop->momz = flip * 12 * mapobjectscale; + if (drop->eflags & MFE_UNDERWATER) + drop->momz = (117 * drop->momz) / 200; + + drop->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); + + drop->extravalue1 = amount; + + return drop; +} + void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType) { UINT8 i; @@ -352,6 +374,14 @@ void K_RunPaperItemSpawners(void) firstUnspawnedEmerald ); } + else if (P_RandomChance(FRACUNIT/2)) + { + K_SpawnSphereBox( + battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip), + FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, + 10 + ); + } else { K_CreatePaperItem( @@ -441,6 +471,14 @@ void K_RunPaperItemSpawners(void) firstUnspawnedEmerald ); } + else if (P_RandomChance(FRACUNIT/3)) + { + drop = K_SpawnSphereBox( + spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), + FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, + 10 + ); + } else { drop = K_CreatePaperItem( diff --git a/src/k_battle.h b/src/k_battle.h index 221873b04..c56c576d6 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -22,6 +22,7 @@ void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_CheckBumpers(void); void K_CheckEmeralds(player_t *player); mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType); +mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount); void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType); UINT8 K_NumEmeralds(player_t *player); void K_RunPaperItemSpawners(void); diff --git a/src/p_enemy.c b/src/p_enemy.c index 7d4ad7400..8bc40525e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13308,7 +13308,9 @@ void A_ItemPop(mobj_t *actor) if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound); - if (!((gametyperules & GTR_BUMPERS) && actor->target->player->bumpers <= 0)) + if (gametyperules & GTR_BUMPERS) + P_GivePlayerSpheres(actor->target->player, actor->extravalue1); + else actor->target->player->itemroulette = 1; remains->flags2 &= ~MF2_AMBUSH; diff --git a/src/p_inter.c b/src/p_inter.c index 0a2bb4e13..4dafa91c2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -268,12 +268,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_CanPickupItem(player, 1)) return; - if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0) - { - return; - } - special->momx = special->momy = special->momz = 0; + P_SetTarget(&special->target, toucher); + P_KillMobj(special, toucher, toucher, DMG_NORMAL); + break; + case MT_SPHEREBOX: + if (player->bumpers <= 0) + return; + P_SetTarget(&special->target, toucher); P_KillMobj(special, toucher, toucher, DMG_NORMAL); break; @@ -510,16 +512,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!(P_CanPickupItem(player, 0))) return; - // Reached the cap, don't waste 'em! - if (player->spheres >= 40) - return; - - // Not alive - if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0)) - return; - - special->momx = special->momy = special->momz = 0; - player->spheres++; + P_GivePlayerSpheres(player, 1); break; // Secret emblem thingy diff --git a/src/p_local.h b/src/p_local.h index d90bfde4c..227d915f8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -175,7 +175,7 @@ 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); -void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); +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); diff --git a/src/p_mobj.c b/src/p_mobj.c index ad86d0434..08c6ca088 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8597,6 +8597,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } break; case MT_RANDOMITEM: + case MT_SPHEREBOX: if (gametype == GT_BATTLE && mobj->threshold == 70) { mobj->color = K_RainbowColor(leveltime); @@ -9377,6 +9378,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) thing->shadowscale = 12*FRACUNIT/5; break; case MT_RANDOMITEM: + case MT_SPHEREBOX: thing->shadowscale = FRACUNIT/2; thing->whiteshadow = false; break; diff --git a/src/p_user.c b/src/p_user.c index 7ab85b6ec..4837022e2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -500,6 +500,26 @@ 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->bumpers <= 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 // From 514501125193e32e8d80b1c52248c8d8b8edcd5f Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Dec 2021 18:11:08 -0800 Subject: [PATCH 74/89] Add some missing G_SetGametype calls Fixes timelimit not being reset when switching gametypes on the vote screen. --- src/g_demo.c | 1 + src/y_inter.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_demo.c b/src/g_demo.c index 712e628f8..2dd3cd277 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2793,6 +2793,7 @@ void G_DoPlayDemo(char *defdemoname) demoflags = READUINT8(demo_p); gametype = READUINT8(demo_p); + G_SetGametype(gametype); if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. G_SkipDemoExtraFiles(&demo_p); diff --git a/src/y_inter.c b/src/y_inter.c index e050deddc..415672713 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1459,7 +1459,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level) if (gametype != votelevels[level][1]) { INT16 lastgametype = gametype; - gametype = votelevels[level][1]; + G_SetGametype(votelevels[level][1]); D_GameTypeChanged(lastgametype); forceresetplayers = true; } From 2ac9761af08301287a3e5a3cff6e1b6b449665ed Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Dec 2021 23:19:45 -0800 Subject: [PATCH 75/89] Free unused texture lumps in R_LoadTextures PU_CACHE never gets freed automatically and Z_Unlock does NOTHING. --- src/r_textures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_textures.c b/src/r_textures.c index 9716724b5..df7709374 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -814,7 +814,7 @@ Rloadflats (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(flatlump); + Z_Free(flatlump); texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; @@ -915,7 +915,7 @@ Rloadtextures (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(patchlump); + Z_Free(patchlump); texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; From 152f4224d94c133c9cca17c63754e033535d0206 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 14:02:56 -0800 Subject: [PATCH 76/89] Read only header bytes when creating textures list R_LoadTextures was reading in the entirety of every texture lump, now it only reads the 8 byte PNG header. This saved more than 1 second for me (1.68 s -> 0.24 s). PNG still need to be read in entirely to check their dimensions; I didn't bother looking into optimizing it since we don't have many PNG textures right now. --- src/r_picformats.h | 1 + src/r_textures.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/r_picformats.h b/src/r_picformats.h index 8d3999013..0a822cc48 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -105,6 +105,7 @@ typedef struct } spriteinfo_t; // Portable Network Graphics +#define PNG_HEADER_SIZE (8) boolean Picture_IsLumpPNG(const UINT8 *d, size_t s); #define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic diff --git a/src/r_textures.c b/src/r_textures.c index df7709374..4ec110556 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -725,6 +725,7 @@ Rloadflats (INT32 i, INT32 w) UINT16 texstart, texend; texture_t *texture; texpatch_t *patch; + UINT8 header[PNG_HEADER_SIZE]; // Yes if (wadfiles[w]->type == RET_PK3) @@ -743,7 +744,6 @@ Rloadflats (INT32 i, INT32 w) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); j++) { - UINT8 *flatlump; UINT16 wadnum = (UINT16)w; lumpnum_t lumpnum = texstart + j; size_t lumplength; @@ -755,7 +755,7 @@ Rloadflats (INT32 i, INT32 w) continue; // If it is then SKIP IT } - flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); lumplength = W_LumpLengthPwad(wadnum, lumpnum); switch (lumplength) @@ -790,12 +790,14 @@ Rloadflats (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength)) + if (Picture_IsLumpPNG(header, lumplength)) { + UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); INT32 width, height; Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength); texture->width = (INT16)width; texture->height = (INT16)height; + Z_Free(flatlump); } else #endif @@ -814,8 +816,6 @@ Rloadflats (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Free(flatlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; @@ -835,8 +835,8 @@ Rloadtextures (INT32 i, INT32 w) UINT16 j; UINT16 texstart, texend, texturesLumpPos; texture_t *texture; - softwarepatch_t *patchlump; texpatch_t *patch; + softwarepatch_t patchlump; // Get the lump numbers for the markers in the WAD, if they exist. if (wadfiles[w]->type == RET_PK3) @@ -876,7 +876,7 @@ Rloadtextures (INT32 i, INT32 w) continue; // If it is then SKIP IT } - patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0); #ifndef NO_PNG_LUMPS lumplength = W_LumpLengthPwad(wadnum, lumpnum); #endif @@ -888,18 +888,20 @@ Rloadtextures (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength)) + if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) { + UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); INT32 width, height; - Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength); + Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); texture->width = (INT16)width; texture->height = (INT16)height; + Z_Free(png); } else #endif { - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + texture->width = SHORT(patchlump.width); + texture->height = SHORT(patchlump.height); } texture->type = TEXTURETYPE_SINGLEPATCH; @@ -915,8 +917,6 @@ Rloadtextures (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Free(patchlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; From de2eab5e7a057ff30ae719868c3f33ac065210cc Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 14:01:40 -0800 Subject: [PATCH 77/89] Inflate only size out bytes Saves time uncompressing an entire lump when only part of it is needed. --- src/w_wad.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 4e7e97dbb..60339c426 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1480,10 +1480,10 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si int zErr; // Helper var. z_stream strm; unsigned long rawSize = l->disksize; - unsigned long decSize = l->size; + unsigned long decSize = size; rawData = Z_Malloc(rawSize, PU_STATIC, NULL); - decData = Z_Malloc(decSize, PU_STATIC, NULL); + decData = dest; if (fread(rawData, 1, rawSize, handle) < rawSize) I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); @@ -1501,12 +1501,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si zErr = inflateInit2(&strm, -15); if (zErr == Z_OK) { - zErr = inflate(&strm, Z_FINISH); - if (zErr == Z_STREAM_END) - { - M_Memcpy(dest, decData, size); - } - else + zErr = inflate(&strm, Z_SYNC_FLUSH); + if (zErr != Z_OK && zErr != Z_STREAM_END) { size = 0; zerr(zErr); @@ -1520,7 +1516,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si } Z_Free(rawData); - Z_Free(decData); #ifdef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)dest, size)) From 29399f603389f587c6228a96a564995f8cbd4994 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 15:34:51 -0800 Subject: [PATCH 78/89] Send R_GenerateBlendTables number crunch to parallel thread --- src/d_main.c | 3 +++ src/r_draw.c | 40 +++++++++++++++++++++++++++++++--------- src/r_main.c | 2 +- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index b8fad8ec6..27ee40926 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1417,6 +1417,9 @@ void D_SRB2Main(void) // setup loading screen SCR_Startup(); + // Do this in background; lots of number crunching + R_InitTranslucencyTables(); + CON_SetLoadingProgress(LOADED_ISTARTUPGRAPHICS); CONS_Printf("HU_Init()...\n"); diff --git a/src/r_draw.c b/src/r_draw.c index 4adfb6663..377cca156 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -26,6 +26,7 @@ #include "z_zone.h" #include "console.h" // Until buffering gets finished #include "k_color.h" // SRB2kart +#include "i_threads.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -192,6 +193,29 @@ CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for " #define TRANSTAB_AMTMUL10 (255.0f / 10.0f) +static void R_AllocateBlendTables(void) +{ + INT32 i; + + for (i = 0; i < NUMBLENDMAPS; i++) + { + if (i == blendtab_modulate) + continue; + blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); + } + + // Modulation blending only requires a single table + blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); +} + +#ifdef HAVE_THREADS +static void R_GenerateBlendTables_Thread(void *userdata) +{ + (void)userdata; + R_GenerateBlendTables(); +} +#endif + /** \brief Initializes the translucency tables used by the Software renderer. */ void R_InitTranslucencyTables(void) @@ -212,20 +236,20 @@ void R_InitTranslucencyTables(void) W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); + R_AllocateBlendTables(); + +#ifdef HAVE_THREADS + I_spawn_thread("blend-tables", + R_GenerateBlendTables_Thread, NULL); +#else R_GenerateBlendTables(); +#endif } void R_GenerateBlendTables(void) { INT32 i; - for (i = 0; i < NUMBLENDMAPS; i++) - { - if (i == blendtab_modulate) - continue; - blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); - } - for (i = 0; i <= 9; i++) { const size_t offs = (0x10000 * i); @@ -236,8 +260,6 @@ void R_GenerateBlendTables(void) R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha); } - // Modulation blending only requires a single table - blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0); } diff --git a/src/r_main.c b/src/r_main.c index 210a97627..c3e044ef2 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1137,7 +1137,7 @@ void R_Init(void) R_InitLightTables(); //I_OutputMsg("\nR_InitTranslucencyTables\n"); - R_InitTranslucencyTables(); + //R_InitTranslucencyTables(); R_InitDrawNodes(); From c39edbbf7fea25a8f915e970af78553d3102149d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 16:02:23 -0800 Subject: [PATCH 79/89] Read only PNG header bytes to confirm a sprite is a PNG Saves about 300 ms for R_InitSkins. --- src/r_things.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index eccbe7e23..c370a2c67 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -286,16 +286,18 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 #ifndef NO_PNG_LUMPS { - softwarepatch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); + UINT8 header[PNG_HEADER_SIZE]; size_t len = W_LumpLengthPwad(wadnum, l); - if (Picture_IsLumpPNG((UINT8 *)png, len)) + W_ReadLumpHeaderPwad(wadnum, l, header, sizeof header, 0); + + if (Picture_IsLumpPNG(header, len)) { + UINT8 *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len); isPNG = true; + Z_Free(png); } - - Z_Free(png); } if (!isPNG) From cfe8a1bfa4f11d80bf8d673e60d106ee1eedcd88 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 15 Dec 2021 21:21:54 -0500 Subject: [PATCH 80/89] No random chance for sphere box Asked Oni how it should be done, he said item + sphere box at the same time --- src/k_battle.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 83c47d43e..8a5257206 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -374,14 +374,6 @@ void K_RunPaperItemSpawners(void) firstUnspawnedEmerald ); } - else if (P_RandomChance(FRACUNIT/2)) - { - K_SpawnSphereBox( - battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip), - FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, - 10 - ); - } else { K_CreatePaperItem( @@ -389,6 +381,12 @@ void K_RunPaperItemSpawners(void) FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, 0, 0 ); + + K_SpawnSphereBox( + battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip), + FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, + 10 + ); } } else From ccdbd9ccc9086e8a93f3a39eadecc7e94618ba4b Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 22:32:14 -0800 Subject: [PATCH 81/89] A_ItemPop: var1 determines roulette or sphere award --- src/info.c | 3 ++- src/info.h | 1 + src/p_enemy.c | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 2db296b99..062d1fbb2 100644 --- a/src/info.c +++ b/src/info.c @@ -4074,6 +4074,7 @@ state_t states[NUMSTATES] = {SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10 {SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11 {SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12 + {SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 @@ -23044,7 +23045,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADRANDOMITEM, // deathstate + S_DEADSPHEREBOX, // deathstate S_NULL, // xdeathstate sfx_kc2e, // deathsound 60*FRACUNIT, // speed diff --git a/src/info.h b/src/info.h index eab11e86a..dfb0d3c43 100644 --- a/src/info.h +++ b/src/info.h @@ -4467,6 +4467,7 @@ typedef enum state S_SPHEREBOX10, S_SPHEREBOX11, S_SPHEREBOX12, + S_DEADSPHEREBOX, // Random Item Pop S_RANDOMITEMPOP1, diff --git a/src/p_enemy.c b/src/p_enemy.c index 8bc40525e..3017850cf 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13254,6 +13254,8 @@ void A_ChangeHeight(mobj_t *actor) void A_ItemPop(mobj_t *actor) { + INT32 locvar1 = var1; + mobj_t *remains; mobjtype_t explode; @@ -13308,9 +13310,9 @@ void A_ItemPop(mobj_t *actor) if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound); - if (gametyperules & GTR_BUMPERS) + if (locvar1 == 1) P_GivePlayerSpheres(actor->target->player, actor->extravalue1); - else + else if (locvar1 == 0) actor->target->player->itemroulette = 1; remains->flags2 &= ~MF2_AMBUSH; From 04c1a9dcb1b3068434bb5a80ed05ebdb76f03448 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 16 Dec 2021 09:40:14 -0500 Subject: [PATCH 82/89] Brightmaps on walls --- src/Sourcefile | 1 + src/k_brightmap.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++ src/k_brightmap.h | 38 +++++++ src/p_setup.c | 4 + src/r_data.c | 6 ++ src/r_draw.c | 2 + src/r_draw.h | 3 + src/r_draw8.c | 153 ++++++++++++++++++++++++--- src/r_plane.c | 5 + src/r_segs.c | 95 +++++++++++++---- src/r_state.h | 3 + src/r_textures.c | 21 ++++ src/r_textures.h | 1 + src/r_things.c | 50 +++++++-- src/r_things.h | 4 +- 15 files changed, 597 insertions(+), 45 deletions(-) create mode 100644 src/k_brightmap.c create mode 100644 src/k_brightmap.h diff --git a/src/Sourcefile b/src/Sourcefile index 9bc27d4da..e142ebcc1 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -111,3 +111,4 @@ k_botitem.c k_botsearch.c k_grandprix.c k_hud.c +k_brightmap.c diff --git a/src/k_brightmap.c b/src/k_brightmap.c new file mode 100644 index 000000000..b9ef07ab8 --- /dev/null +++ b/src/k_brightmap.c @@ -0,0 +1,256 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_brightmap.c +/// \brief Brightmap texture loading. + +#include "k_brightmap.h" + +#include "doomdata.h" +#include "doomdef.h" +#include "doomtype.h" +#include "fastcmp.h" +#include "r_textures.h" +#include "w_wad.h" +#include "z_zone.h" + +static brightmapStorage_t *brightmapStorage = NULL; +static size_t maxBrightmapStorage = 0; + +/*-------------------------------------------------- + static brightmapStorage_t *K_NewBrightmap(void) + + Increases the size of maxBrightmapStorage by 1. + + Input Arguments:- + None + + Return:- + The new brightmap storage struct. +--------------------------------------------------*/ +static brightmapStorage_t *K_NewBrightmap(void) +{ + maxBrightmapStorage++; + brightmapStorage = (brightmapStorage_t *)Z_Realloc(brightmapStorage, sizeof(brightmapStorage_t) * (maxBrightmapStorage + 1), PU_STATIC, NULL); + return &brightmapStorage[ maxBrightmapStorage - 1 ]; +} + +/*-------------------------------------------------- + static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex) + + See header file for description. +--------------------------------------------------*/ +static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex) +{ + if (checkIndex >= maxBrightmapStorage) + { + return NULL; + } + + return &brightmapStorage[checkIndex]; +} + +/*-------------------------------------------------- + static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ +static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName) +{ + size_t i; + + if (maxBrightmapStorage == 0) + { + return NULL; + } + + for (i = 0; i < maxBrightmapStorage; i++) + { + brightmapStorage_t *bms = &brightmapStorage[i]; + + if (stricmp(checkName, bms->textureName) == 0) + { + // Name matches. + return bms; + } + } + + return NULL; +} + +/*-------------------------------------------------- + static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size) + + Parses inputted lump data as a BRIGHT lump. + + Input Arguments:- + data - Pointer to lump data. + size - The length of the lump data. + + Return:- + false if any errors occured, otherwise true. +--------------------------------------------------*/ +static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size) +{ + char *tkn = M_GetToken((char *)data); + size_t pos = 0; + + while (tkn && (pos = M_GetTokenPos()) < size) + { + boolean valid = true; + + if (stricmp(tkn, "texture") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + brightmapStorage_t *bms = K_GetBrightmapStorageByTextureName(tkn); + + if (bms == NULL) + { + bms = K_NewBrightmap(); + strncpy(bms->textureName, tkn, 9); + } + + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + strncpy(bms->brightmapName, tkn, 9); + } + else + { + CONS_Alert(CONS_ERROR, "No brightmap for brightmap definition.\n"); + valid = false; + } + } + else + { + CONS_Alert(CONS_ERROR, "No texture for brightmap definition.\n"); + valid = false; + } + } + // todo: SPRITE brightmaps?! + else + { + CONS_Alert(CONS_ERROR, "Unknown keyword '%s' found in BRIGHT lump.\n", tkn); + valid = false; + } + + Z_Free(tkn); + + if (valid == false) + { + return false; + } + + tkn = M_GetToken(NULL); + } + + Z_Free(tkn); + return true; +} + +/*-------------------------------------------------- + void K_InitBrightmaps(void) + + See header file for description. +--------------------------------------------------*/ +void K_InitBrightmaps(void) +{ + INT32 wadNum; + size_t i; + + I_Assert(brightmapStorage == NULL); + maxBrightmapStorage = 0; + + for (wadNum = 0; wadNum < numwadfiles; wadNum++) + { + lumpinfo_t *lump_p = wadfiles[wadNum]->lumpinfo; + UINT16 lumpNum; + + // Find BRIGHT lump in the WAD + lumpNum = W_CheckNumForNamePwad("BRIGHT", wadNum, 0); + + while (lumpNum != INT16_MAX) + { + UINT8 *data; + data = (UINT8 *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + + // If that didn't exist, we have nothing to do here. + if (data == NULL) + { + lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1); + continue; + } + else + { + size_t size = W_LumpLengthPwad(wadNum, lumpNum); + + size_t nameLength = strlen(wadfiles[wadNum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name + char *name = malloc(nameLength + 1); + + sprintf(name, "%s|%s", wadfiles[wadNum]->filename, lump_p->fullname); + name[nameLength] = '\0'; + + size = W_LumpLengthPwad(wadNum, lumpNum); + + CONS_Printf(M_GetText("Loading BRIGHT from %s\n"), name); + K_BRIGHTLumpParser(data, size); + + free(name); + } + + lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1); + } + } + + if (maxBrightmapStorage == 0) + { + // No brightmaps were defined. + return; + } + + for (i = 0; i < maxBrightmapStorage; i++) + { + brightmapStorage_t *bms = K_GetBrightmapStorageByIndex(i); + INT32 texNum, bmNum; + + if (bms == NULL) + { + // Shouldn't happen. + break; + } + + texNum = R_CheckTextureNumForName(bms->textureName); + if (texNum != -1) + { + bmNum = R_CheckTextureNumForName(bms->brightmapName); + if (bmNum == -1) + { + texturebrightmaps[texNum] = 0; + } + else + { + texturebrightmaps[texNum] = bmNum; + } + } + } + + R_ClearTextureNumCache(false); + + // Clear brightmapStorage now that we're done with it. + Z_Free(brightmapStorage); + brightmapStorage = NULL; +} diff --git a/src/k_brightmap.h b/src/k_brightmap.h new file mode 100644 index 000000000..8d33ae5cb --- /dev/null +++ b/src/k_brightmap.h @@ -0,0 +1,38 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_brightmap.h +/// \brief Brightmap texture loading. + +#ifndef __K_BRIGHTMAP_H__ +#define __K_BRIGHTMAP_H__ + +#include "doomdata.h" +#include "doomdef.h" +#include "doomtype.h" + +typedef struct brightmapStorage_s +{ + // Brightmap storage struct. + // Stores data for brightmap definitions, + // before putting them into texturebrightmaps. + + char textureName[9]; // The texture's name. + char brightmapName[9]; // The brightmap's name. +} brightmapStorage_t; + +/*-------------------------------------------------- + void K_InitBrightmaps(void); + + Finds all BRIGHT lumps and processes them. +--------------------------------------------------*/ + +void K_InitBrightmaps(void); + +#endif // __K_BRIGHTMAP_H__ diff --git a/src/p_setup.c b/src/p_setup.c index fab5429b8..db9a35a11 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -91,6 +91,7 @@ #include "k_waypoint.h" #include "k_bot.h" #include "k_grandprix.h" +#include "k_brightmap.h" // Replay names have time #if !defined (UNDER_CE) @@ -4457,6 +4458,9 @@ boolean P_AddWadFile(const char *wadfilename) // Reload ANIMDEFS P_InitPicAnims(); + // Reload BRIGHT + K_InitBrightmaps(); + // Flush and reload HUD graphics ST_UnloadGraphics(); HU_LoadGraphics(); diff --git a/src/r_data.c b/src/r_data.c index bb2e508ba..ddeb5e3b5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -30,6 +30,9 @@ #include "byteptr.h" #include "dehacked.h" +// DRRR +#include "k_brightmap.h" + // // Graphics. // SRB2 graphics for walls and sprites @@ -1175,6 +1178,9 @@ void R_InitTextureData(void) CONS_Printf("P_InitPicAnims()...\n"); P_InitPicAnims(); + + CONS_Printf("K_InitBrightmaps()...\n"); + K_InitBrightmaps(); } // diff --git a/src/r_draw.c b/src/r_draw.c index 4adfb6663..c3bc2ac3c 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -71,12 +71,14 @@ UINT8 *topleft; // ========================================================================= lighttable_t *dc_colormap; +lighttable_t *dc_fullbright; INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; fixed_t dc_iscale, dc_texturemid; UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit, // soo lets make it a byte on all system for the ASM code UINT8 *dc_source; +UINT8 *dc_brightmap; // ----------------------- // translucency stuff here diff --git a/src/r_draw.h b/src/r_draw.h index 646eb5ec8..b5cea0420 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -32,11 +32,13 @@ extern UINT8 *topleft; // ------------------------- extern lighttable_t *dc_colormap; +extern lighttable_t *dc_fullbright; extern INT32 dc_x, dc_yl, dc_yh; extern fixed_t dc_iscale, dc_texturemid; extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column +extern UINT8 *dc_brightmap; // brightmap texture column, can be NULL // translucency stuff here extern UINT8 *dc_transmap; @@ -167,6 +169,7 @@ void R_DrawViewBorder(void); #endif #define TRANSPARENTPIXEL 255 +#define BRIGHTPIXEL 0 // ----------------- // 8bpp DRAWING CODE diff --git a/src/r_draw8.c b/src/r_draw8.c index af64edbce..1771614db 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -57,7 +57,9 @@ void R_DrawColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; if (dc_texheight & heightmask) // not a power of 2 -- killough { @@ -75,7 +77,14 @@ void R_DrawColumn_8(void) // Re-map color indices from wall texture column // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = colormap[source[frac>>FRACBITS]]; + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[source[frac>>FRACBITS]]; + } + else + { + *dest = colormap[source[frac>>FRACBITS]]; + } dest += vid.width; // Avoid overflow. @@ -92,15 +101,42 @@ void R_DrawColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + dest += vid.width; frac += fracstep; - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + dest += vid.width; frac += fracstep; } + if (count & 1) - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + } } } } @@ -140,7 +176,9 @@ void R_Draw2sMultiPatchColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; register UINT8 val; if (dc_texheight & heightmask) // not a power of 2 -- killough @@ -160,9 +198,17 @@ void R_Draw2sMultiPatchColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix val = source[frac>>FRACBITS]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } dest += vid.width; @@ -182,20 +228,51 @@ void R_Draw2sMultiPatchColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } + dest += vid.width; frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } + dest += vid.width; frac += fracstep; } + if (count & 1) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } } } } @@ -236,8 +313,10 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const UINT8 *transmap = dc_transmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; register UINT8 val; if (dc_texheight & heightmask) // not a power of 2 -- killough @@ -257,9 +336,17 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix val = source[frac>>FRACBITS]; - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } dest += vid.width; @@ -279,12 +366,33 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + dest += vid.width; frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + dest += vid.width; frac += fracstep; } @@ -292,7 +400,16 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } } } } @@ -2114,8 +2231,12 @@ void R_DrawColumnShadowed_8(void) if (height <= dc_yl) { dc_colormap = dc_lightlist[i].rcolormap; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (solid && dc_yl < bheight) dc_yl = bheight; continue; @@ -2132,8 +2253,12 @@ void R_DrawColumnShadowed_8(void) dc_yl = dc_yh + 1; dc_colormap = dc_lightlist[i].rcolormap; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } dc_yh = realyh; if (dc_yl <= realyh) diff --git a/src/r_plane.c b/src/r_plane.c index 8ec7e2b99..58e6ce5ea 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -651,8 +651,12 @@ static void R_DrawSkyPlane(visplane_t *pl) // Because of this hack, sky is not affected // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; @@ -669,6 +673,7 @@ static void R_DrawSkyPlane(visplane_t *pl) dc_source = R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + dc_brightmap = NULL; colfunc(); } } diff --git a/src/r_segs.c b/src/r_segs.c index 5c9538e34..033bcca73 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -36,6 +36,7 @@ static boolean markceiling; static boolean maskedtexture; static INT32 toptexture, bottomtexture, midtexture; +static INT32 topbrightmap, bottombrightmap, midbrightmap; static INT32 numthicksides, numbackffloors; angle_t rw_normalangle; @@ -83,7 +84,7 @@ static fixed_t *maskedtextureheight = NULL; // multi-patch textures. They are not normally needed as multi-patch // textures don't have holes in it. At least not for now. -static void R_Render2sidedMultiPatchColumn(column_t *column) +static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap) { INT32 topscreen, bottomscreen; @@ -93,6 +94,8 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; + dc_brightmap = NULL; + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) { dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); @@ -110,6 +113,10 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) { dc_source = (UINT8 *)column + 3; + if (brightmap != NULL) + { + dc_brightmap = (UINT8 *)brightmap + 3; + } if (colfunc == colfuncs[BASEDRAWFUNC]) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); @@ -132,12 +139,12 @@ transnum_t R_GetLinedefTransTable(line_t *ldef) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; - column_t *col; - INT32 lightnum, texnum, i; + column_t *col, *bmCol = NULL; + INT32 lightnum, texnum, bmnum, i; fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *); + void (*colfunc_2s)(column_t *, column_t *); line_t *ldef; sector_t *front, *back; INT32 times, repeats; @@ -155,6 +162,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); + bmnum = R_GetTextureBrightmap(texnum); windowbottom = windowtop = sprbotscreen = INT32_MAX; ldef = curline->linedef; @@ -215,6 +223,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); + if (bmnum) { R_CheckTextureCache(bmnum); } + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) @@ -400,6 +410,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } for (i = 0; i < dc_numlights; i++) { @@ -431,8 +442,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } continue; } @@ -440,7 +455,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (windowbottom >= realbot) { windowbottom = realbot; - colfunc_2s(col); + colfunc_2s(col, bmCol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -449,15 +464,19 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) continue; } - colfunc_2s(col); + colfunc_2s(col, bmCol); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } windowbottom = realbot; if (windowtop < windowbottom) - colfunc_2s(col); + colfunc_2s(col, bmCol); spryscale += rw_scalestep; continue; @@ -470,8 +489,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -481,6 +504,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) @@ -535,7 +559,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else #endif - colfunc_2s(col); + colfunc_2s(col, bmCol); } spryscale += rw_scalestep; } @@ -544,10 +568,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col) +static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm) { while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col); + R_DrawMaskedColumn(col, bm); if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else @@ -555,10 +579,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } } -static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm) { do { - R_DrawFlippedMaskedColumn(col); + R_DrawFlippedMaskedColumn(col, bm); sprtopscreen += dc_texheight*spryscale; } while (sprtopscreen < sprbotscreen); } @@ -582,9 +606,9 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { size_t pindex; - column_t * col; + column_t * col, *bmCol = NULL; INT32 lightnum; - INT32 texnum; + INT32 texnum, bmnum; sector_t tempsec; INT32 templight; INT32 i, p; @@ -605,7 +629,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; - void (*colfunc_2s) (column_t *); + void (*colfunc_2s) (column_t *, column_t *); // Calculate light table. // Use different light tables @@ -616,6 +640,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); + bmnum = R_GetTextureBrightmap(texnum); colfunc = colfuncs[BASEDRAWFUNC]; @@ -624,6 +649,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) size_t linenum = curline->linedef-backsector->lines[0]; newline = pfloor->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); + bmnum = R_GetTextureBrightmap(texnum); } if (pfloor->flags & FF_TRANSLUCENT) @@ -833,6 +859,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); + if (bmnum) { R_CheckTextureCache(bmnum); } + //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) @@ -916,6 +944,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Get data for the column col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -998,8 +1027,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } if (solid && windowtop < bheight) windowtop = bheight; @@ -1011,7 +1044,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { windowbottom = sprbotscreen; // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -1022,7 +1055,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); if (solid) windowtop = bheight; else @@ -1030,14 +1063,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } } windowbottom = sprbotscreen; // draw the texture, if there is any space left if (windowtop < windowbottom) - colfunc_2s (col); + colfunc_2s (col, bmCol); spryscale += rw_scalestep; continue; @@ -1050,9 +1087,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1060,7 +1101,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); spryscale += rw_scalestep; } } @@ -1311,8 +1352,12 @@ static void R_RenderSegLoop (void) pindex = MAXLIGHTSCALE-1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; @@ -1366,6 +1411,7 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_midtexturemid; dc_source = R_GetColumn(midtexture,texturecolumn); + dc_brightmap = (midbrightmap ? R_GetColumn(midbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1427,6 +1473,7 @@ static void R_RenderSegLoop (void) dc_yh = mid; dc_texturemid = rw_toptexturemid; dc_source = R_GetColumn(toptexture,texturecolumn); + dc_brightmap = (topbrightmap ? R_GetColumn(topbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1462,8 +1509,8 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn); + dc_source = R_GetColumn(bottomtexture,texturecolumn); + dc_brightmap = (bottombrightmap ? R_GetColumn(bottombrightmap, texturecolumn) : NULL); dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; @@ -1738,6 +1785,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) worldbottomslope -= viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; + midbrightmap = topbrightmap = bottombrightmap = 0; ds_p->maskedtexturecol = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; @@ -1785,6 +1833,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t texheight; // single sided line midtexture = R_GetTextureNum(sidedef->midtexture); + midbrightmap = R_GetTextureBrightmap(midtexture); texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; @@ -2021,11 +2070,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!toptexture) //Second side has no texture, use the first side's instead. toptexture = R_GetTextureNum(sidedef->toptexture); + + topbrightmap = R_GetTextureBrightmap(toptexture); texheight = textureheight[toptexture]; } else { toptexture = R_GetTextureNum(sidedef->toptexture); + topbrightmap = R_GetTextureBrightmap(toptexture); texheight = textureheight[toptexture]; } if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked @@ -2052,6 +2104,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); + bottombrightmap = R_GetTextureBrightmap(bottomtexture); if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGBOTTOM) diff --git a/src/r_state.h b/src/r_state.h index 6f9008cc7..dc577448e 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -54,6 +54,9 @@ extern extracolormap_t *extra_colormaps; // for global animation extern INT32 *texturetranslation; +// for brightmaps +extern INT32 *texturebrightmaps; + // Sprites extern size_t numspritelumps, max_spritelumps; diff --git a/src/r_textures.c b/src/r_textures.c index df7709374..c08feeece 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -55,6 +55,7 @@ INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; +INT32 *texturebrightmaps; // Painfully simple texture id cacheing to make maps load faster. :3 static struct { @@ -500,6 +501,20 @@ INT32 R_GetTextureNum(INT32 texnum) return texturetranslation[texnum]; } +// +// R_GetTextureBrightmap +// +// Returns the actual texture id that we should use. +// This can either be the texture's brightmap, +// or 0 if not valid. +// +INT32 R_GetTextureBrightmap(INT32 texnum) +{ + if (texnum < 0 || texnum >= numtextures) + return 0; + return texturebrightmaps[texnum]; +} + // // R_CheckTextureCache // @@ -944,6 +959,7 @@ void R_LoadTextures(void) Z_Free(textures[i]); Z_Free(texturecache[i]); } + Z_Free(texturebrightmaps); Z_Free(texturetranslation); Z_Free(textures); } @@ -1044,9 +1060,14 @@ void R_LoadTextures(void) textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); + // Create brightmap texture table. + texturebrightmaps = Z_Malloc((numtextures + 1) * sizeof(*texturebrightmaps), PU_STATIC, NULL); for (i = 0; i < numtextures; i++) + { texturetranslation[i] = i; + texturebrightmaps[i] = 0; + } for (i = 0, w = 0; w < numwadfiles; w++) { diff --git a/src/r_textures.h b/src/r_textures.h index 6e0cc168a..dada043a6 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -82,6 +82,7 @@ void R_FlushTextureCache(void); UINT8 *R_GenerateTexture(size_t texnum); UINT8 *R_GenerateTextureAsFlat(size_t texnum); INT32 R_GetTextureNum(INT32 texnum); +INT32 R_GetTextureBrightmap(INT32 texnum); void R_CheckTextureCache(INT32 tex); void R_ClearTextureNumCache(boolean btell); diff --git a/src/r_things.c b/src/r_things.c index eccbe7e23..134c21dae 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -602,7 +602,7 @@ INT16 *mceilingclip; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -void R_DrawMaskedColumn(column_t *column) +void R_DrawMaskedColumn(column_t *column, column_t *brightmap) { INT32 topscreen; INT32 bottomscreen; @@ -610,6 +610,7 @@ void R_DrawMaskedColumn(column_t *column) INT32 topdelta, prevdelta = 0; basetexturemid = dc_texturemid; + dc_brightmap = NULL; for (; column->topdelta != 0xff ;) { @@ -645,6 +646,11 @@ void R_DrawMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = (UINT8 *)column + 3; + if (brightmap != NULL) + { + dc_brightmap = (UINT8 *)brightmap + 3; + } + dc_texturemid = basetexturemid - (topdelta<length + 4); + if (brightmap != NULL) + { + brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4); + } } dc_texturemid = basetexturemid; @@ -666,7 +676,7 @@ void R_DrawMaskedColumn(column_t *column) INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height -void R_DrawFlippedMaskedColumn(column_t *column) +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap) { INT32 topscreen; INT32 bottomscreen; @@ -674,6 +684,8 @@ void R_DrawFlippedMaskedColumn(column_t *column) INT32 topdelta, prevdelta = -1; UINT8 *d,*s; + dc_brightmap = NULL; + for (; column->topdelta != 0xff ;) { // calculate unclipped screen coordinates @@ -712,6 +724,14 @@ void R_DrawFlippedMaskedColumn(column_t *column) dc_source = ZZ_Alloc(column->length); for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) *d++ = *s; + + if (brightmap != NULL) + { + dc_brightmap = ZZ_Alloc(brightmap->length); + for (s = (UINT8 *)brightmap+2+brightmap->length, d = dc_brightmap; d < dc_brightmap+brightmap->length; --s) + *d++ = *s; + } + dc_texturemid = basetexturemid - (topdelta<length + 4); + if (brightmap != NULL) + { + brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4); + } } dc_texturemid = basetexturemid; @@ -779,7 +803,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; - void (*localcolfunc)(column_t *); + void (*localcolfunc)(column_t *, column_t *); INT32 texturecolumn; INT32 pwidth; fixed_t frac; @@ -805,6 +829,7 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; + dc_fullbright = colormaps; dc_translation = R_GetSpriteTranslation(vis); if (R_SpriteIsFlashing(vis)) // Bosses "flash" @@ -834,8 +859,13 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!dc_colormap) dc_colormap = colormaps; + dc_fullbright = colormaps; + if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += COLORMAP_REMAPOFFSET; + { + dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_texturemid = vis->texturemid; dc_texheight = 0; @@ -908,7 +938,7 @@ static void R_DrawVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column); + localcolfunc (column, NULL); } } else if (vis->cut & SC_SHEAR) @@ -930,7 +960,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #endif sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - localcolfunc (column); + localcolfunc (column, NULL); } } else @@ -950,7 +980,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - localcolfunc (column); + localcolfunc (column, NULL); } } @@ -989,8 +1019,12 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) } dc_colormap = colormaps; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = vis->texturemid; @@ -1019,7 +1053,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - R_DrawMaskedColumn(column); + R_DrawMaskedColumn(column, NULL); } colfunc = colfuncs[BASEDRAWFUNC]; diff --git a/src/r_things.h b/src/r_things.h index cbbb0f2d8..7ff1bd4c7 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -47,8 +47,8 @@ extern fixed_t windowtop; extern fixed_t windowbottom; extern INT32 lengthcol; -void R_DrawMaskedColumn(column_t *column); -void R_DrawFlippedMaskedColumn(column_t *column); +void R_DrawMaskedColumn(column_t *column, column_t *brightmap); +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap); // ---------------- // SPRITE RENDERING From daab86f4611d6d94a08bacdf19d0dc8b63b122ee Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 16 Dec 2021 11:48:32 -0500 Subject: [PATCH 83/89] Implement brightmaps for span drawers, fix column loop bug --- src/r_draw.c | 2 + src/r_draw.h | 2 + src/r_draw8.c | 994 ++++++++++++++++++++++++++++++------------------- src/r_plane.c | 31 ++ src/r_splats.c | 1 + 5 files changed, 642 insertions(+), 388 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index c3bc2ac3c..d9ae3e4a5 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -110,6 +110,7 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; +lighttable_t *ds_fullbright; lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; @@ -119,6 +120,7 @@ UINT16 ds_flatwidth, ds_flatheight; boolean ds_powersoftwo; UINT8 *ds_source; // points to the start of a flat +UINT8 *ds_brightmap; // start of brightmap flat UINT8 *ds_transmap; // one of the translucency tables // Vectors for Software's tilted slope drawers diff --git a/src/r_draw.h b/src/r_draw.h index b5cea0420..7b44d6185 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -59,6 +59,7 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; +extern lighttable_t *ds_fullbright; extern lighttable_t *ds_translation; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; @@ -68,6 +69,7 @@ extern UINT16 ds_flatwidth, ds_flatheight; extern boolean ds_powersoftwo; extern UINT8 *ds_source; +extern UINT8 *ds_brightmap; extern UINT8 *ds_transmap; typedef struct { diff --git a/src/r_draw8.c b/src/r_draw8.c index 1771614db..0dd8463f6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -101,7 +101,7 @@ void R_DrawColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; } @@ -113,7 +113,7 @@ void R_DrawColumn_8(void) dest += vid.width; frac += fracstep; - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; } @@ -128,7 +128,7 @@ void R_DrawColumn_8(void) if (count & 1) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; } @@ -229,7 +229,7 @@ void R_Draw2sMultiPatchColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[val]; } @@ -245,7 +245,7 @@ void R_Draw2sMultiPatchColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[val]; } @@ -264,7 +264,7 @@ void R_Draw2sMultiPatchColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = fullbright[val]; } @@ -367,7 +367,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = *(transmap + (fullbright[val]<<8) + (*dest)); } @@ -383,7 +383,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = *(transmap + (fullbright[val]<<8) + (*dest)); } @@ -401,7 +401,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) { - if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) { *dest = *(transmap + (fullbright[val]<<8) + (*dest)); } @@ -489,8 +489,10 @@ void R_DrawTranslucentColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const UINT8 *transmap = dc_transmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight - 1; if (dc_texheight & heightmask) { @@ -509,7 +511,14 @@ void R_DrawTranslucentColumn_8(void) // Re-map color indices from wall texture column // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest)); + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[frac>>FRACBITS]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest)); + } dest += vid.width; if ((frac += fracstep) >= heightmask) frac -= heightmask; @@ -520,15 +529,39 @@ void R_DrawTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } dest += vid.width; frac += fracstep; - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } dest += vid.width; frac += fracstep; } if (count & 1) - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + } } } } @@ -579,7 +612,14 @@ void R_DrawTranslatedTranslucentColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + if (dc_brightmap != NULL && dc_brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + } dest += vid.width; if ((frac += fracstep) >= heightmask) @@ -591,15 +631,41 @@ void R_DrawTranslatedTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + dest += vid.width; frac += fracstep; - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + dest += vid.width; frac += fracstep; } if (count & 1) - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + { + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + } } } } @@ -641,7 +707,14 @@ void R_DrawTranslatedColumn_8(void) // used with PLAY sprites. // Thus the "green" ramp of the player 0 sprite // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + if (dc_brightmap != NULL && dc_brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = dc_fullbright[dc_translation[dc_source[frac>>FRACBITS]]]; + } + else + { + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + } dest += vid.width; @@ -656,6 +729,9 @@ void R_DrawTranslatedColumn_8(void) #define SPANSIZE 16 #define INVSPAN 0.0625f +// 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) +#define MAXFLATBYTES 4194303 + /** \brief The R_DrawSpan_8 function Draws the actual span. */ @@ -664,13 +740,17 @@ void R_DrawSpan_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -686,7 +766,9 @@ void R_DrawSpan_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; if (dest+8 > deststop) @@ -697,44 +779,37 @@ void R_DrawSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[source[bit]]; + } + else + { + dest[i] = colormap[source[bit]]; + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest++ = fullbright[source[bit]]; + } + else + { + *dest++ = colormap[source[bit]]; + } + xposition += xstep; yposition += ystep; } @@ -775,13 +850,16 @@ void R_DrawTiltedSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; double startz, startu, startv; double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -801,8 +879,11 @@ void R_DrawTiltedSpan_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -812,10 +893,16 @@ void R_DrawTiltedSpan_8(void) double z = 1.f/iz; u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -848,8 +935,16 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; u += stepu; v += stepv; @@ -864,8 +959,16 @@ void R_DrawTiltedSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } } else { @@ -885,8 +988,16 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; u += stepu; v += stepv; @@ -908,13 +1019,16 @@ void R_DrawTiltedTranslucentSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; double startz, startu, startv; double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -934,8 +1048,11 @@ void R_DrawTiltedTranslucentSpan_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -946,8 +1063,16 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -980,8 +1105,16 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; u += stepu; v += stepv; @@ -996,8 +1129,16 @@ void R_DrawTiltedTranslucentSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } } else { @@ -1017,8 +1158,16 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; u += stepu; v += stepv; @@ -1040,7 +1189,9 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 *dsrc; @@ -1048,6 +1199,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -1069,7 +1221,9 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -1080,8 +1234,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -1114,8 +1276,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; u += stepu; v += stepv; @@ -1130,8 +1300,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } } else { @@ -1151,8 +1329,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; u += stepu; v += stepv; @@ -1171,7 +1357,9 @@ void R_DrawTiltedSplat_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 val; @@ -1180,6 +1368,7 @@ void R_DrawTiltedSplat_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -1199,8 +1388,11 @@ void R_DrawTiltedSplat_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -1211,11 +1403,20 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; iz += ds_szp->x; @@ -1249,10 +1450,20 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; u += stepu; v += stepv; @@ -1267,10 +1478,20 @@ void R_DrawTiltedSplat_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } } else { @@ -1290,10 +1511,20 @@ void R_DrawTiltedSplat_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; u += stepu; v += stepv; @@ -1311,13 +1542,17 @@ void R_DrawSplat_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1334,7 +1569,9 @@ void R_DrawSplat_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1342,80 +1579,44 @@ void R_DrawSplat_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[val]; + } + else + { + dest[i] = colormap[val]; + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } dest++; xposition += xstep; yposition += ystep; @@ -1430,13 +1631,17 @@ void R_DrawTranslucentSplat_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1453,7 +1658,9 @@ void R_DrawTranslucentSplat_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1461,62 +1668,45 @@ void R_DrawTranslucentSplat_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[val] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[val] << 8) + dest[i]); + } + + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[val] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + + } dest++; xposition += xstep; yposition += ystep; @@ -1531,14 +1721,18 @@ void R_DrawFloorSprite_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1555,7 +1749,9 @@ void R_DrawFloorSprite_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; @@ -1564,70 +1760,43 @@ void R_DrawFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[0] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[1] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[2] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[3] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[4] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[5] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[6] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[7] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val & 0xFF00) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; xposition += xstep; yposition += ystep; @@ -1642,14 +1811,18 @@ void R_DrawTranslucentFloorSprite_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1666,7 +1839,9 @@ void R_DrawTranslucentFloorSprite_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; @@ -1675,62 +1850,43 @@ void R_DrawTranslucentFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[0] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[1] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[2] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[3] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[4] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[5] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[6] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[7] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val & 0xFF00) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[i]); + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; xposition += xstep; yposition += ystep; @@ -1749,7 +1905,9 @@ void R_DrawTiltedFloorSprite_8(void) int i; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; UINT16 val; @@ -1758,6 +1916,7 @@ void R_DrawTiltedFloorSprite_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); @@ -1765,7 +1924,9 @@ void R_DrawTiltedFloorSprite_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; startz = 1.f/iz; @@ -1794,9 +1955,19 @@ void R_DrawTiltedFloorSprite_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; u += stepu; @@ -1812,9 +1983,19 @@ void R_DrawTiltedFloorSprite_8(void) { u = (INT64)(startu); v = (INT64)(startv); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } } else { @@ -1834,9 +2015,19 @@ void R_DrawTiltedFloorSprite_8(void) for (; width != 0; width--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; u += stepu; @@ -1858,7 +2049,9 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) int i; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; UINT16 val; @@ -1867,6 +2060,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); @@ -1874,7 +2068,9 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; startz = 1.f/iz; @@ -1903,9 +2099,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; u += stepu; @@ -1921,9 +2127,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) { u = (INT64)(startu); v = (INT64)(startv); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } } else { @@ -1943,9 +2159,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) for (; width != 0; width--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; u += stepu; @@ -1963,14 +2189,17 @@ void R_DrawTranslucentSpan_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); - UINT32 val; + size_t i; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -1986,7 +2215,9 @@ void R_DrawTranslucentSpan_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1994,45 +2225,35 @@ void R_DrawTranslucentSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[source[bit]] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[i]); + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; xposition += xstep; yposition += ystep; @@ -2044,13 +2265,17 @@ void R_DrawTranslucentWaterSpan_8(void) UINT32 xposition; UINT32 yposition; UINT32 xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 *dsrc; size_t count; + size_t i; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -2063,7 +2288,9 @@ void R_DrawTranslucentWaterSpan_8(void) xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; count = ds_x2 - ds_x1 + 1; @@ -2073,44 +2300,35 @@ void R_DrawTranslucentWaterSpan_8(void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + else + { + dest[i] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count--) { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest++ = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + else + { + *dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } xposition += xstep; yposition += ystep; } diff --git a/src/r_plane.c b/src/r_plane.c index 58e6ce5ea..f19de384d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -235,7 +235,9 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) } if (currentplane->slope) + { ds_colormap = colormaps; + } else { pindex = distance >> LIGHTZSHIFT; @@ -244,8 +246,13 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_colormap = planezlight[pindex]; } + ds_fullbright = colormaps; + if (encoremap && !currentplane->noencore) + { ds_colormap += COLORMAP_REMAPOFFSET; + ds_fullbright += COLORMAP_REMAPOFFSET; + } if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -970,6 +977,30 @@ void R_DrawSinglePlane(visplane_t *pl) R_CheckFlatLength(ds_flatwidth * ds_flatheight); } + ds_brightmap = NULL; + + if (type == LEVELFLAT_TEXTURE) + { + // Get the span's brightmap. + // FLATS not supported, SORRY!! + INT32 texNum = R_GetTextureNum(levelflat->u.texture.num); + INT32 bmNum = R_GetTextureBrightmap(texNum); + + if (bmNum != 0) + { + texture_t *brightmap = textures[bmNum]; + + if (brightmap->flat == NULL) + { + ds_brightmap = R_GenerateTextureAsFlat(bmNum); + } + else + { + ds_brightmap = (UINT8 *)brightmap->flat; + } + } + } + if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later && viewangle != pl->viewangle+pl->plangle) { diff --git a/src/r_splats.c b/src/r_splats.c index 63052049e..39801812f 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -444,6 +444,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr } ds_colormap = vis->colormap; + ds_fullbright = colormaps; ds_translation = R_GetSpriteTranslation(vis); if (ds_translation == NULL) ds_translation = colormaps; From 6399cd57e138abc82e61bd2c8554a42cca25d209 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 16 Dec 2021 11:52:51 -0500 Subject: [PATCH 84/89] Fix the print's file extension --- src/k_brightmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_brightmap.c b/src/k_brightmap.c index b9ef07ab8..f481938f2 100644 --- a/src/k_brightmap.c +++ b/src/k_brightmap.c @@ -177,7 +177,6 @@ void K_InitBrightmaps(void) for (wadNum = 0; wadNum < numwadfiles; wadNum++) { - lumpinfo_t *lump_p = wadfiles[wadNum]->lumpinfo; UINT16 lumpNum; // Find BRIGHT lump in the WAD @@ -196,6 +195,7 @@ void K_InitBrightmaps(void) } else { + lumpinfo_t *lump_p = &wadfiles[wadNum]->lumpinfo[lumpNum]; size_t size = W_LumpLengthPwad(wadNum, lumpNum); size_t nameLength = strlen(wadfiles[wadNum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name From 603a97938b32b37a89120dcf083be3e1cbaf333c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 16 Dec 2021 13:05:37 -0500 Subject: [PATCH 85/89] "Support" ASM functions (By that, I mean it defaults to ASM, but uses the C version when drawing brightmapped stuff. Was this worth the minor performance gain over just making NOASM=1 default? I dunno.) --- src/r_plane.c | 14 ++------- src/r_segs.c | 48 ++++++++++++++++++----------- src/r_splats.c | 5 +-- src/r_things.c | 21 +++++++------ src/screen.c | 82 ++++++++++++++++++++++++++++++++++++++++++-------- src/screen.h | 10 ++++++ 6 files changed, 126 insertions(+), 54 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index f19de384d..6276ab7ee 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -648,7 +648,7 @@ static void R_DrawSkyPlane(visplane_t *pl) // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); // use correct aspect ratio scale dc_iscale = skyscale[viewssnum]; @@ -820,7 +820,7 @@ void R_DrawSinglePlane(visplane_t *pl) } planeripple.active = false; - spanfunc = spanfuncs[BASEDRAWFUNC]; + R_SetSpanFunc(BASEDRAWFUNC, false, false); if (pl->polyobj) { @@ -1116,15 +1116,7 @@ void R_DrawSinglePlane(visplane_t *pl) planezlight = zlight[light]; // Use the correct span drawer depending on the powers-of-twoness - if (!ds_powersoftwo) - { - if (spanfuncs_npo2[spanfunctype]) - spanfunc = spanfuncs_npo2[spanfunctype]; - else - spanfunc = spanfuncs[spanfunctype]; - } - else - spanfunc = spanfuncs[spanfunctype]; + R_SetSpanFunc(spanfunctype, !ds_powersoftwo, ds_brightmap != NULL); // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; diff --git a/src/r_segs.c b/src/r_segs.c index 033bcca73..5a8172615 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -118,9 +118,9 @@ static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap dc_brightmap = (UINT8 *)brightmap + 3; } - if (colfunc == colfuncs[BASEDRAWFUNC]) + if (R_CheckColumnFunc(BASEDRAWFUNC) == true) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); else colfunc(); @@ -196,16 +196,18 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (transtable != NUMTRANSMAPS && (blendmode || transtable)) { dc_transmap = R_GetBlendTable(blendmode, transtable); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); } else if (ldef->special == 909) { - colfunc = colfuncs[COLDRAWFUNC_FOG]; + R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); windowtop = frontsector->ceilingheight; windowbottom = frontsector->floorheight; } else - colfunc = colfuncs[BASEDRAWFUNC]; + { + R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); + } if (curline->polyseg && curline->polyseg->translucency > 0) { @@ -213,7 +215,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) return; dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); } range = max(ds->x2-ds->x1, 1); @@ -275,7 +277,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) rlight->extra_colormap = *light->extra_colormap; rlight->flags = light->flags; - if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false) || (rlight->flags & FF_FOG) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); @@ -292,13 +294,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else { - if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else lightnum = LIGHTLEVELS - 1; - if (colfunc == colfuncs[COLDRAWFUNC_FOG] + if ((R_CheckColumnFunc(COLDRAWFUNC_FOG) == true) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) ; else @@ -564,7 +566,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) spryscale += rw_scalestep; } } - colfunc = colfuncs[BASEDRAWFUNC]; + + R_SetColumnFunc(BASEDRAWFUNC, false); } // Loop through R_DrawMaskedColumn calls @@ -642,7 +645,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); bmnum = R_GetTextureBrightmap(texnum); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); if (pfloor->master->flags & ML_TFERLINE) { @@ -667,10 +670,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + { + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); + } } else if (pfloor->flags & FF_FOG) - colfunc = colfuncs[COLDRAWFUNC_FOG]; + { + R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); + } range = max(ds->x2-ds->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations @@ -778,7 +785,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else if (pfloor->flags & FF_FOG) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) @@ -1105,7 +1112,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) spryscale += rw_scalestep; } } - colfunc = colfuncs[BASEDRAWFUNC]; + + R_SetColumnFunc(BASEDRAWFUNC, false); #undef CLAMPMAX #undef CLAMPMIN @@ -1395,7 +1403,7 @@ static void R_RenderSegLoop (void) else dc_lightlist[i].rcolormap = xwalllights[pindex]; - colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; + R_SetColumnFunc(COLDRAWFUNC_SHADOWED, false); } } @@ -1414,6 +1422,8 @@ static void R_RenderSegLoop (void) dc_brightmap = (midbrightmap ? R_GetColumn(midbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[midtexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); + //profile stuff --------------------------------------------------------- #ifdef TIMING ProfZeroTimer(); @@ -1475,6 +1485,7 @@ static void R_RenderSegLoop (void) dc_source = R_GetColumn(toptexture,texturecolumn); dc_brightmap = (topbrightmap ? R_GetColumn(topbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[toptexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); colfunc(); ceilingclip[rw_x] = (INT16)mid; } @@ -1512,6 +1523,7 @@ static void R_RenderSegLoop (void) dc_source = R_GetColumn(bottomtexture,texturecolumn); dc_brightmap = (bottombrightmap ? R_GetColumn(bottombrightmap, texturecolumn) : NULL); dc_texheight = textureheight[bottomtexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); colfunc(); floorclip[rw_x] = (INT16)mid; } @@ -1605,7 +1617,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) memset(&segleft, 0x00, sizeof(segleft)); memset(&segright, 0x00, sizeof(segright)); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); if (ds_p == drawsegs+maxdrawsegs) { @@ -2825,7 +2837,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_bsilheight = &(ds_p->bsilheight); R_RenderSegLoop(); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); if (portalline) // if curline is a portal, set portalrender for drawseg ds_p->portalpass = portalrender+1; diff --git a/src/r_splats.c b/src/r_splats.c index 39801812f..28acd0ab0 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -469,10 +469,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr else ds_transmap = NULL; - if (ds_powersoftwo) - spanfunc = spanfuncs[spanfunctype]; - else - spanfunc = spanfuncs_npo2[spanfunctype]; + R_SetSpanFunc(spanfunctype, !ds_powersoftwo, false); if (maxy >= vid.height) maxy = vid.height-1; diff --git a/src/r_things.c b/src/r_things.c index 134c21dae..8161457d2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -610,6 +610,8 @@ void R_DrawMaskedColumn(column_t *column, column_t *brightmap) INT32 topdelta, prevdelta = 0; basetexturemid = dc_texturemid; + + R_SetColumnFunc(colfunctype, brightmap != NULL); dc_brightmap = NULL; for (; column->topdelta != 0xff ;) @@ -684,6 +686,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap) INT32 topdelta, prevdelta = -1; UINT8 *d,*s; + R_SetColumnFunc(colfunctype, brightmap != NULL); dc_brightmap = NULL; for (; column->topdelta != 0xff ;) @@ -827,27 +830,27 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } - colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. + R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; dc_fullbright = colormaps; dc_translation = R_GetSpriteTranslation(vis); if (R_SpriteIsFlashing(vis)) // Bosses "flash" - colfunc = colfuncs[COLDRAWFUNC_TRANS]; // translate certain pixels to white + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); // translate certain pixels to white else if (vis->mobj->color && vis->transmap) // Color mapping { - colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANSTRANS, false); dc_transmap = vis->transmap; } else if (vis->transmap) { - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, false); dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) // translate green skin to another color - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS)) { @@ -984,7 +987,7 @@ static void R_DrawVisSprite(vissprite_t *vis) } } - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); dc_hires = 0; vis->x1 = x1; @@ -1014,7 +1017,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->transmap) { - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, false); dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } @@ -1056,7 +1059,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) R_DrawMaskedColumn(column, NULL); } - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); } // diff --git a/src/screen.c b/src/screen.c index ef5fa7769..3cf8e80d3 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,10 +49,13 @@ // -------------------------------------------- void (*colfunc)(void); void (*colfuncs[COLDRAWFUNC_MAX])(void); +void (*colfuncs_asm[COLDRAWFUNC_MAX])(void); +int colfunctype; void (*spanfunc)(void); void (*spanfuncs[SPANDRAWFUNC_MAX])(void); void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); +void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); // ------------------ // global video state @@ -118,9 +121,6 @@ void SCR_SetDrawFuncs(void) colfuncs[BASEDRAWFUNC] = R_DrawColumn_8; spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8; - colfunc = colfuncs[BASEDRAWFUNC]; - spanfunc = spanfuncs[BASEDRAWFUNC]; - colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8; colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8; colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; @@ -165,21 +165,24 @@ void SCR_SetDrawFuncs(void) { if (R_MMX) { - colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_MMX; - //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; - //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX; - spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8_MMX; + colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_MMX; + //colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX; + spanfuncs_asm[BASEDRAWFUNC] = R_DrawSpan_8_MMX; } else { - colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_ASM; - //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; - //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM; + colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM; } } #endif + + R_SetColumnFunc(BASEDRAWFUNC, false); + R_SetSpanFunc(BASEDRAWFUNC, false, false); } /* else if (vid.bpp > 1) { @@ -201,6 +204,61 @@ void SCR_SetDrawFuncs(void) */ } +void R_SetColumnFunc(size_t id, boolean brightmapped) +{ + I_Assert(id < COLDRAWFUNC_MAX); + + colfunctype = id; + + if (colfuncs_asm[id] != NULL && brightmapped == false) + { + colfunc = colfuncs_asm[id]; + } + else + { + colfunc = colfuncs[id]; + } +} + +void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped) +{ + I_Assert(id < COLDRAWFUNC_MAX); + + if (spanfuncs_npo2[id] != NULL && npo2 == true) + { + spanfunc = spanfuncs_npo2[id]; + } + else if (spanfuncs_asm[id] != NULL && brightmapped == false) + { + spanfunc = spanfuncs_asm[id]; + } + else + { + spanfunc = spanfuncs[id]; + } +} + +boolean R_CheckColumnFunc(size_t id) +{ + size_t i; + + if (colfunc == NULL) + { + // Shouldn't happen. + return false; + } + + for (i = 0; i < COLDRAWFUNC_MAX; i++) + { + if (colfunc == colfuncs[id] || colfunc == colfuncs_asm[id]) + { + return true; + } + } + + return false; +} + void SCR_SetMode(void) { if (dedicated) diff --git a/src/screen.h b/src/screen.h index 549d59377..86807be76 100644 --- a/src/screen.h +++ b/src/screen.h @@ -135,6 +135,8 @@ enum extern void (*colfunc)(void); extern void (*colfuncs[COLDRAWFUNC_MAX])(void); +extern void (*colfuncs_asm[COLDRAWFUNC_MAX])(void); +extern int colfunctype; enum { @@ -163,6 +165,7 @@ enum extern void (*spanfunc)(void); extern void (*spanfuncs[SPANDRAWFUNC_MAX])(void); extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); +extern void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); // ----- // CPUID @@ -205,6 +208,13 @@ void SCR_SetMode(void); // Set drawer functions for Software void SCR_SetDrawFuncs(void); +// Set current column / span drawers +void R_SetColumnFunc(size_t id, boolean brightmapped); +void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped); + +// Compare current column drawer +boolean R_CheckColumnFunc(size_t id); + // Recalc screen size dependent stuff void SCR_Recalc(void); From 5183d3161c486988a70152d83edf37434da710ee Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 17 Dec 2021 03:42:59 -0500 Subject: [PATCH 86/89] Simplify span brightmap load --- src/r_plane.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 6276ab7ee..ff5698c0b 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -988,16 +988,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (bmNum != 0) { - texture_t *brightmap = textures[bmNum]; - - if (brightmap->flat == NULL) - { - ds_brightmap = R_GenerateTextureAsFlat(bmNum); - } - else - { - ds_brightmap = (UINT8 *)brightmap->flat; - } + ds_brightmap = R_GenerateTextureAsFlat(bmNum); } } From 510c65699b08516761be9ffa742b0f3486ffed7d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 17 Dec 2021 04:16:51 -0500 Subject: [PATCH 87/89] Fixed animated span brightmaps being offset `levelflat->u.texture.num` is modified at run-time to do animations, unlike wall textures which use `texturetranslation`. --- src/r_plane.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index ff5698c0b..d2f294cdc 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -820,6 +820,7 @@ void R_DrawSinglePlane(visplane_t *pl) } planeripple.active = false; + ds_brightmap = NULL; R_SetSpanFunc(BASEDRAWFUNC, false, false); if (pl->polyobj) @@ -977,18 +978,14 @@ void R_DrawSinglePlane(visplane_t *pl) R_CheckFlatLength(ds_flatwidth * ds_flatheight); } - ds_brightmap = NULL; - if (type == LEVELFLAT_TEXTURE) { // Get the span's brightmap. // FLATS not supported, SORRY!! - INT32 texNum = R_GetTextureNum(levelflat->u.texture.num); - INT32 bmNum = R_GetTextureBrightmap(texNum); - + INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num); if (bmNum != 0) { - ds_brightmap = R_GenerateTextureAsFlat(bmNum); + ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum); } } From 4a34eb5e96a4585146b5c7bf32b1217a527b49aa Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 17 Dec 2021 16:39:09 -0500 Subject: [PATCH 88/89] Disable ASM column / span entirely Causes strange unidentifiable bugs, and testing with tape who has a few framerate issues. perfstats outputted practically the same frames for everyone. Whatever frame drops exist are simply something else and ASM is not helping at all, so decided it's not worth it. Behind a define anyway, if someone decides to fix it anyway. --- src/screen.c | 10 +++++++++- src/screen.h | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/screen.c b/src/screen.c index 3cf8e80d3..25dcbb1f7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,13 +49,17 @@ // -------------------------------------------- void (*colfunc)(void); void (*colfuncs[COLDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM void (*colfuncs_asm[COLDRAWFUNC_MAX])(void); +#endif int colfunctype; void (*spanfunc)(void); void (*spanfuncs[SPANDRAWFUNC_MAX])(void); void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); +#endif // ------------------ // global video state @@ -160,7 +164,7 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed -#ifdef RUSEASM +#if (defined(RUSEASM) && defined(USE_COL_SPAN_ASM)) if (R_ASM) { if (R_MMX) @@ -210,11 +214,13 @@ void R_SetColumnFunc(size_t id, boolean brightmapped) colfunctype = id; +#ifdef USE_COL_SPAN_ASM if (colfuncs_asm[id] != NULL && brightmapped == false) { colfunc = colfuncs_asm[id]; } else +#endif { colfunc = colfuncs[id]; } @@ -228,10 +234,12 @@ void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped) { spanfunc = spanfuncs_npo2[id]; } +#ifdef USE_COL_SPAN_ASM else if (spanfuncs_asm[id] != NULL && brightmapped == false) { spanfunc = spanfuncs_asm[id]; } +#endif else { spanfunc = spanfuncs[id]; diff --git a/src/screen.h b/src/screen.h index 86807be76..66c52dd67 100644 --- a/src/screen.h +++ b/src/screen.h @@ -116,6 +116,8 @@ extern vmode_t specialmodes[NUMSPECIALMODES]; // color mode dependent drawer function pointers // --------------------------------------------- +#define USE_COL_SPAN_ASM 0 + #define BASEDRAWFUNC 0 enum @@ -135,7 +137,9 @@ enum extern void (*colfunc)(void); extern void (*colfuncs[COLDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM extern void (*colfuncs_asm[COLDRAWFUNC_MAX])(void); +#endif extern int colfunctype; enum @@ -165,7 +169,9 @@ enum extern void (*spanfunc)(void); extern void (*spanfuncs[SPANDRAWFUNC_MAX])(void); extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM extern void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); +#endif // ----- // CPUID From 7d2633f5723d152ddc6ee39e01a07341907a397b Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 17 Dec 2021 17:32:19 -0800 Subject: [PATCH 89/89] Correct spherebox dehacked states list --- src/deh_tables.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 894157639..e7e211f0c 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3477,7 +3477,19 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DEADRANDOMITEM", // Sphere Box (for Battle) - "S_SPHEREBOX", + "S_SPHEREBOX1", + "S_SPHEREBOX2", + "S_SPHEREBOX3", + "S_SPHEREBOX4", + "S_SPHEREBOX5", + "S_SPHEREBOX6", + "S_SPHEREBOX7", + "S_SPHEREBOX8", + "S_SPHEREBOX9", + "S_SPHEREBOX10", + "S_SPHEREBOX11", + "S_SPHEREBOX12", + "S_DEADSPHEREBOX", // Random Item Pop "S_RANDOMITEMPOP1",