From 29e11a03782edd17634fdaf8a09b209c0a13d85d Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 22 Apr 2021 15:11:15 +0200 Subject: [PATCH 01/21] changes to the delay, boost when doing upwards trick --- src/d_player.h | 6 ++++++ src/k_kart.c | 39 +++++++++++++++++++++++++++++++++++---- src/p_mobj.c | 2 +- src/p_saveg.c | 8 ++++++++ src/p_user.c | 2 +- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index afa232991..8f1481499 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -241,6 +241,7 @@ typedef enum // CONSTANTS FOR TRICK PANELS #define TRICKMOMZRAMP (30) #define TRICKLAG (9) +#define TRICKDELAY (TICRATE/2) #define TUMBLEBOUNCES 3 @@ -450,9 +451,14 @@ typedef struct player_s UINT8 jawztargetdelay; // (0 to 5) - Delay for Jawz target switching, to make it less twitchy UINT8 trickpanel; // Trick panel state + tic_t tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold fixed_t trickmomx; fixed_t trickmomy; fixed_t trickmomz; + fixed_t trickboostpower; // Save the rough speed multiplier. Used for upwards tricks. + tic_t trickboostdecay; // used to know how long you've waited + tic_t trickboost; // Trick boost. This one is weird and has variable speed. Dear god. + UINT32 roundscore; // battle score this round UINT8 emeralds; diff --git a/src/k_kart.c b/src/k_kart.c index dedf9dddc..9a5bd8b05 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2546,6 +2546,11 @@ static void K_GetKartBoostPower(player_t *player) } } + if (player->trickboost) // Trick pannel up-boost + { + ADDBOOST(player->trickboostpower, 5*FRACUNIT, 0); // % speed, 500% accel, 0% handling + } + if (player->ringboost) // Ring Boost { ADDBOOST(FRACUNIT/5, 4*FRACUNIT, 0); // + 20% top speed, + 400% acceleration, +0% handling @@ -4868,7 +4873,10 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) thrust = FixedMul(thrust, 9*FRACUNIT/8); } - mo->player->trickmomx = mo->player->trickmomy = mo->player->trickmomz = 0; // Reset post-hitlag momentums. + mo->player->trickmomx = mo->player->trickmomy = mo->player->trickmomz = mo->player->tricktime = 0; // Reset post-hitlag momentums and timer + // Setup the boost for potential upwards trick, at worse, make it your regular max speed. + mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false)) - FRACUNIT, 0); + //CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT); } mo->momz = FixedMul(thrust, vscale); @@ -6284,7 +6292,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Speed lines if (player->sneakertimer || player->ringboost || player->driftboost || player->startboost - || player->eggmanexplode) + || player->eggmanexplode || player->trickboost) { if (player->invincibilitytimer) K_SpawnInvincibilitySpeedLines(player->mo); @@ -6525,6 +6533,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } + if (player->trickboost) + player->trickboost--; + if (player->flamedash) player->flamedash--; @@ -8787,6 +8798,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) fixed_t basespeed = P_AproxDistance(player->mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)); + if (!cmd->turning && !player->throwdir) // increment this counter while your inputs are neutral + player->tricktime++; + // debug shit //CONS_Printf("%d\n", player->mo->momz / mapobjectscale); if (momz < -10*FRACUNIT) // :youfuckedup: @@ -8858,6 +8872,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) relative = false; } + // Calculate speed boost decay: + // Base speed boost duration is 35 tics. + // At most, lose 3/4th of your boost. + player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); + //CONS_Printf("decay: %d\n", player->trickboostdecay); + P_SetObjectMomZ(player->mo, 48*FRACUNIT, relative); player->trickmomx = player->mo->momx; @@ -8866,7 +8886,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_InstaThrust(player->mo, 0, 0); // Sike, you have no speed :) player->mo->momz = 0; - player->trickpanel = 3; + player->trickpanel = 4; player->mo->hitlag = TRICKLAG; } } @@ -8882,8 +8902,19 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } + else if (player->trickpanel == 4 && P_IsObjectOnGround(player->mo)) // Upwards trick landed! + { + //CONS_Printf("apply boost\n"); + S_StartSound(player->mo, sfx_s23c); + K_SpawnDashDustRelease(player); + player->trickboost = TICRATE - player->trickboostdecay; + + player->trickpanel = player->trickboostdecay = 0; + } + // Wait until we let go off the control stick to remove the delay - if ((player->pflags & PF_TRICKDELAY) && !player->throwdir && !cmd->turning) + // buttons must be neutral after the initial trick delay. This prevents weirdness where slight nudges after blast off would send you flying. + if ((player->pflags & PF_TRICKDELAY) && !player->throwdir && !cmd->turning && (player->tricktime >= TRICKDELAY)) { player->pflags &= ~PF_TRICKDELAY; } diff --git a/src/p_mobj.c b/src/p_mobj.c index f3711f819..8cccc7963 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1109,7 +1109,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) gravityadd = (4*gravityadd)/3; } - if (mo->player->trickpanel == 2 || mo->player->trickpanel == 3) + if (mo->player->trickpanel >= 2) { gravityadd = (5*gravityadd)/2; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 35f68be29..9f2d182fb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -305,9 +305,13 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].jawztargetdelay); WRITEUINT8(save_p, players[i].trickpanel); + WRITEUINT32(save_p, players[i].tricktime); WRITEUINT32(save_p, players[i].trickmomx); WRITEUINT32(save_p, players[i].trickmomy); WRITEUINT32(save_p, players[i].trickmomz); + WRITEUINT32(save_p, players[i].trickboostpower); + WRITEUINT32(save_p, players[i].trickboostdecay); + WRITEUINT32(save_p, players[i].trickboost); WRITEUINT32(save_p, players[i].roundscore); WRITEUINT8(save_p, players[i].emeralds); @@ -557,9 +561,13 @@ static void P_NetUnArchivePlayers(void) players[i].jawztargetdelay = READUINT8(save_p); players[i].trickpanel = READUINT8(save_p); + players[i].tricktime = (tic_t)READUINT32(save_p); players[i].trickmomx = READUINT32(save_p); players[i].trickmomy = READUINT32(save_p); players[i].trickmomz = READUINT32(save_p); + players[i].trickboostpower = READUINT32(save_p); + players[i].trickboostdecay = (tic_t)READUINT32(save_p); + players[i].trickboost = (tic_t)READUINT32(save_p); players[i].roundscore = READUINT32(save_p); players[i].emeralds = READUINT8(save_p); diff --git a/src/p_user.c b/src/p_user.c index 3cd0bba5c..18afb0337 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2030,7 +2030,7 @@ void P_MovePlayer(player_t *player) { player->drawangle += ANGLE_22h; } - else if (player->trickpanel == 3) + else if (player->trickpanel >= 3) { player->drawangle -= ANGLE_22h; } From a25b79885d805721946e9ec29f371c08638c4b08 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 22 Apr 2021 19:33:01 +0200 Subject: [PATCH 02/21] 1/4s delay w/o input checks instead of 1/2 w/ input checks --- src/d_player.h | 2 +- src/k_kart.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 8f1481499..84165192b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -241,7 +241,7 @@ typedef enum // CONSTANTS FOR TRICK PANELS #define TRICKMOMZRAMP (30) #define TRICKLAG (9) -#define TRICKDELAY (TICRATE/2) +#define TRICKDELAY (TICRATE/4) #define TUMBLEBOUNCES 3 diff --git a/src/k_kart.c b/src/k_kart.c index 9a5bd8b05..5848f5b09 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8798,8 +8798,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) fixed_t basespeed = P_AproxDistance(player->mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)); - if (!cmd->turning && !player->throwdir) // increment this counter while your inputs are neutral - player->tricktime++; + player->tricktime++; // debug shit //CONS_Printf("%d\n", player->mo->momz / mapobjectscale); From 8b50b0ddd76b0500bae355a778177d24e634806f Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 22 Apr 2021 21:26:00 +0200 Subject: [PATCH 03/21] boost is now 125%, allow turning after upwards trick --- src/k_kart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 5848f5b09..c714a68c2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4874,8 +4874,8 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) } mo->player->trickmomx = mo->player->trickmomy = mo->player->trickmomz = mo->player->tricktime = 0; // Reset post-hitlag momentums and timer - // Setup the boost for potential upwards trick, at worse, make it your regular max speed. - mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false)) - FRACUNIT, 0); + // Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25) + mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false)) - FRACUNIT, 0)*125/100; //CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT); } @@ -7279,9 +7279,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } - if (player->trickpanel != 0) + if (player->trickpanel != 0 && player->trickpanel < 4) { - // No turning during trick panel + // No turning during trick panel unless you did the upwards trick (4) return 0; } From d10f4ea1281059ca4b549386babfe9316c979ae2 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 23 Apr 2021 00:14:36 +0200 Subject: [PATCH 04/21] More suitable data types + lua push --- src/d_player.h | 6 +++--- src/k_kart.c | 6 ++++-- src/lua_playerlib.c | 16 ++++++++++++++++ src/p_saveg.c | 12 ++++++------ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 84165192b..445c1148d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -451,13 +451,13 @@ typedef struct player_s UINT8 jawztargetdelay; // (0 to 5) - Delay for Jawz target switching, to make it less twitchy UINT8 trickpanel; // Trick panel state - tic_t tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold + UINT8 tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold fixed_t trickmomx; fixed_t trickmomy; fixed_t trickmomz; fixed_t trickboostpower; // Save the rough speed multiplier. Used for upwards tricks. - tic_t trickboostdecay; // used to know how long you've waited - tic_t trickboost; // Trick boost. This one is weird and has variable speed. Dear god. + UINT8 trickboostdecay; // used to know how long you've waited + UINT8 trickboost; // Trick boost. This one is weird and has variable speed. Dear god. UINT32 roundscore; // battle score this round diff --git a/src/k_kart.c b/src/k_kart.c index c714a68c2..915d3cd32 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8797,8 +8797,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) fixed_t speedmult = max(0, FRACUNIT - abs(momz)/TRICKMOMZRAMP); // TRICKMOMZRAMP momz is minimum speed (Should be 20) fixed_t basespeed = P_AproxDistance(player->mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)); - - player->tricktime++; + + // We'll never need to go above that. + if (player->tricktime <= TRICKDELAY) + player->tricktime++; // debug shit //CONS_Printf("%d\n", player->mo->momz / mapobjectscale); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index a76eb1990..a9e193543 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -354,12 +354,20 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->glanceDir); else if (fastcmp(field,"trickpanel")) lua_pushinteger(L, plr->trickpanel); + else if (fastcmp(field,"tricktime")) + lua_pushinteger(L, plr->tricktime); else if (fastcmp(field,"trickmomx")) lua_pushfixed(L, plr->trickmomx); else if (fastcmp(field,"trickmomy")) lua_pushfixed(L, plr->trickmomy); else if (fastcmp(field,"trickmomz")) lua_pushfixed(L, plr->trickmomz); + else if (fastcmp(field,"trickboostpower")) + lua_pushfixed(L, plr->trickboostpower); + else if (fastcmp(field,"trickboostdecay")) + lua_pushinteger(L, plr->trickboostdecay); + else if (fastcmp(field,"trickboost")) + lua_pushinteger(L, plr->trickboost); else if (fastcmp(field,"roundscore")) plr->roundscore = luaL_checkinteger(L, 3); else if (fastcmp(field,"emeralds")) @@ -697,12 +705,20 @@ static int player_set(lua_State *L) plr->glanceDir = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickpanel")) plr->trickpanel = luaL_checkinteger(L, 3); + else if (fastcmp(field,"tricktime")) + plr->tricktime = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickmomx")) plr->trickmomx = luaL_checkfixed(L, 3); else if (fastcmp(field,"trickmomy")) plr->trickmomy = luaL_checkfixed(L, 3); else if (fastcmp(field,"trickmomz")) plr->trickmomz = luaL_checkfixed(L, 3); + else if (fastcmp(field,"trickboostpower")) + plr->trickboostpower = luaL_checkfixed(L, 3); + else if (fastcmp(field,"trickboostdecay")) + plr->trickboostdecay = luaL_checkinteger(L, 3); + else if (fastcmp(field,"trickboost")) + plr->trickboost = luaL_checkinteger(L, 3); else if (fastcmp(field,"roundscore")) lua_pushinteger(L, plr->roundscore); else if (fastcmp(field,"emeralds")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 9f2d182fb..e8e992fcc 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -305,13 +305,13 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].jawztargetdelay); WRITEUINT8(save_p, players[i].trickpanel); - WRITEUINT32(save_p, players[i].tricktime); + WRITEUINT8(save_p, players[i].tricktime); WRITEUINT32(save_p, players[i].trickmomx); WRITEUINT32(save_p, players[i].trickmomy); WRITEUINT32(save_p, players[i].trickmomz); WRITEUINT32(save_p, players[i].trickboostpower); - WRITEUINT32(save_p, players[i].trickboostdecay); - WRITEUINT32(save_p, players[i].trickboost); + WRITEUINT8(save_p, players[i].trickboostdecay); + WRITEUINT8(save_p, players[i].trickboost); WRITEUINT32(save_p, players[i].roundscore); WRITEUINT8(save_p, players[i].emeralds); @@ -561,13 +561,13 @@ static void P_NetUnArchivePlayers(void) players[i].jawztargetdelay = READUINT8(save_p); players[i].trickpanel = READUINT8(save_p); - players[i].tricktime = (tic_t)READUINT32(save_p); + players[i].tricktime = READUINT8(save_p); players[i].trickmomx = READUINT32(save_p); players[i].trickmomy = READUINT32(save_p); players[i].trickmomz = READUINT32(save_p); players[i].trickboostpower = READUINT32(save_p); - players[i].trickboostdecay = (tic_t)READUINT32(save_p); - players[i].trickboost = (tic_t)READUINT32(save_p); + players[i].trickboostdecay = READUINT8(save_p); + players[i].trickboost = READUINT8(save_p); players[i].roundscore = READUINT32(save_p); players[i].emeralds = READUINT8(save_p); From f935b3b6f496f480253a4cb18940ebcbaa1c0093 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 23 Apr 2021 02:10:20 +0200 Subject: [PATCH 05/21] wip: starting on visuals --- src/k_kart.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 915d3cd32..593d46409 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8135,6 +8135,53 @@ void K_AdjustPlayerFriction(player_t *player) } } +// +// K_trickPanelTimingVisual +// Spawns the timing visual for trick panels depending on the given player's momz. +// + +#define RADIUSSCALING 6 +#define MINRADIUS 24 + +static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) +{ + + fixed_t pos, tx, ty, tz; + mobj_t *flame; + + angle_t hang = R_PointToAngle(player->mo->x, player->mo->y) + ANG1*90; // horizontal angle + angle_t vang = -leveltime*ANG1*12; // vertical angle... arbitrary rotation speed for now. + fixed_t dist = FixedMul(max(MINRADIUS<mo->scale); // distance. + + UINT8 i; + + //CONS_Printf("a\n"); + + // Do you like trig? cool, me neither. + for (i=0; i < 2; i++) + { + //CONS_Printf("%d\n", i); + pos = FixedMul(dist, FINESINE(vang>>ANGLETOFINESHIFT)); + tx = player->mo->x + FixedMul(pos, FINECOSINE(hang>>ANGLETOFINESHIFT)); + ty = player->mo->y + FixedMul(pos, FINESINE(hang>>ANGLETOFINESHIFT)); + tz = player->mo->z + FixedMul(dist, FINECOSINE(vang>>ANGLETOFINESHIFT)); + + // All coordinates set, spawn our fire, now. + flame = P_SpawnMobj(tx, ty, tz, MT_THOK); // @TODO: Make this into its own object. Duh. + flame->frame = 0; + flame->tics = 2; + + // make sure this is only drawn for our local player + // @TODO + + vang += FixedAngle(180<mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)); - + + K_trickPanelTimingVisual(player, abs(momz)); + + // streaks: + if (momz*P_MobjFlip(player->mo) > 0) // only spawn those while you're going upwards relative to your current gravity + { + // these are all admittedly arbitrary numbers... + INT32 n; + INT32 maxlines = max(1, (momz/FRACUNIT)/8); + INT32 frequency = max(1, 5-(momz/FRACUNIT)/4); + fixed_t sx, sy, sz; + mobj_t *spdl; + + if (!(leveltime % frequency)) + { + for (n=0; n < maxlines; n++) + { + sx = player->mo->x + P_RandomRange(-24, 24)*player->mo->scale; + sy = player->mo->y + P_RandomRange(-24, 24)*player->mo->scale; + sz = player->mo->z + P_RandomRange(0, 48)*player->mo->scale; + + spdl = P_SpawnMobj(sx, sy, sz, MT_FASTLINE); + P_SetTarget(&spdl->target, player->mo); + spdl->angle = R_PointToAngle2(spdl->x, spdl->y, player->mo->x, player->mo->y); + spdl->rollangle = -ANG1*90*P_MobjFlip(player->mo); // angle them downwards relative to the player's gravity... + spdl->spriteyscale = player->trickboostpower+FRACUNIT; + } + + } + + } + // We'll never need to go above that. if (player->tricktime <= TRICKDELAY) player->tricktime++; From a27b825d3c078260d3f7826dcab53cc761519083 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 23 Apr 2021 12:56:46 +0200 Subject: [PATCH 06/21] horiz. lines keep momentum, slightly better visuals --- src/k_kart.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 593d46409..3f1cdebb9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8168,11 +8168,27 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) // All coordinates set, spawn our fire, now. flame = P_SpawnMobj(tx, ty, tz, MT_THOK); // @TODO: Make this into its own object. Duh. - flame->frame = 0; + + // PLACEHOLDER VISUALS + // @TODO: SPRITES + flame->sprite = SPR_FLAM; + flame->frame = ((leveltime%16) /2)|FF_FULLBRIGHT; flame->tics = 2; + flame->rollangle = vang + ANG1*90; // make sure this is only drawn for our local player - // @TODO + flame->renderflags &= ~K_GetPlayerDontDrawFlag(player); + + // second flame for visuals... + flame = P_SpawnMobj(tx, ty, tz, MT_THOK); // @TODO: Make this into its own object. Duh. + + flame->sprite = SPR_FLAM; + flame->frame = ((leveltime%16) /2)|FF_FULLBRIGHT|FF_TRANS60; + flame->tics = 10; + flame->rollangle = vang + ANG1*90; + + // make sure this is only drawn for our local player + flame->renderflags &= ~K_GetPlayerDontDrawFlag(player); vang += FixedAngle(180<angle = R_PointToAngle2(spdl->x, spdl->y, player->mo->x, player->mo->y); spdl->rollangle = -ANG1*90*P_MobjFlip(player->mo); // angle them downwards relative to the player's gravity... spdl->spriteyscale = player->trickboostpower+FRACUNIT; + spdl->momx = player->mo->momx; + spdl->momy = player->mo->momy; } } From d57632e71e4d4e52fc0c7424ae4aa6cc9bced05d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 23 Apr 2021 15:21:45 -0400 Subject: [PATCH 07/21] Change the scaling for different player counts Made more extreme for less than 8, made less extreme for more than 8. 2P: x1.25ish -> x2.5ish 16P: x0.68 -> x0.75 --- src/k_kart.c | 191 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 137 insertions(+), 54 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e8cc80d7c..aa0834326 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -491,6 +491,57 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) } } +static fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush) +{ + const UINT8 basePlayer = 8; // The player count we design most of the game around. + UINT8 playerCount = (spbrush ? 2 : numPlayers); + fixed_t playerScaling = 0; + + // Then, it multiplies it further if the player count isn't equal to basePlayer. + // This is done to make low player count races more interesting and high player count rates more fair. + // (If you're in SPB mode and in 2nd place, it acts like it's a 1v1, so the catch-up game is not weakened.) + if (playerCount < basePlayer) + { + // Less than basePlayer: increase odds significantly. + // 2P: x2.5 + playerScaling = ((basePlayer - playerCount) * (basePlayer - playerCount)) * (FRACUNIT / 14); + } + else if (playerCount > basePlayer) + { + // More than basePlayer: reduce odds slightly. + // 16P: x0.75 + playerScaling = (basePlayer - playerCount) * (FRACUNIT / 32); + } + + return playerScaling; +} + +static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush) +{ + if (mapobjectscale != FRACUNIT) + { + // Bring back to normal scale, so that + distance = FixedDiv(distance * FRACUNIT, mapobjectscale) / FRACUNIT; + } + + if (franticitems == true) + { + // Frantic items arbritrarily make distances shorter, for crazier items. + distance = (15 * distance) / 14; + } + + if (numPlayers > 0) + { + // Items get crazier with the fewer players that you have. + distance = FixedMul( + distance * FRACUNIT, + FRACUNIT + (K_ItemOddsScale(numPlayers, spbrush) / 2) + ) / FRACUNIT; + } + + return distance; +} + /** \brief Item Roulette for Kart \param player player object passed from P_KartPlayerThink @@ -502,9 +553,17 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, { INT32 newodds; INT32 i; + UINT8 pingame = 0, pexiting = 0; + SINT8 first = -1, second = -1; - INT32 secondist = 0; + UINT32 firstdist = UINT32_MAX; + UINT32 secondist = UINT32_MAX; + + boolean powerItem = false; + boolean cooldownOnStart = false; + boolean indirectItem = false; + INT32 shieldtype = KSHIELD_NONE; I_Assert(item > KITEM_NONE); // too many off by one scenarioes. @@ -557,35 +616,19 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, if (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB { - secondist = players[second].distancetofinish - players[first].distancetofinish; - if (franticitems) - secondist = (15 * secondist) / 14; - secondist = ((28 + (8-pingame)) * secondist) / 28; + firstdist = players[first].distancetofinish; + + if (mapobjectscale != FRACUNIT) + { + firstdist = FixedDiv(firstdist * FRACUNIT, mapobjectscale) / FRACUNIT; + } + + secondist = K_ScaleItemDistance( + players[second].distancetofinish - players[first].distancetofinish, + pingame, spbrush + ); } - // POWERITEMODDS handles all of the "frantic item" related functionality, for all of our powerful items. - // First, it multiplies it by 2 if franticitems is true; easy-peasy. - // Next, it multiplies it again if it's in SPB mode and 2nd needs to apply pressure to 1st. - // Then, it multiplies it further if the player count isn't equal to 8. - // This is done to make low player count races more interesting and high player count rates more fair. - // (2P normal would be about halfway between 8P normal and 8P frantic.) - // (This scaling is not done for SPB Rush, so that catchup strength is not weakened.) - // Lastly, it *divides* it by your mashed value, which was determined in K_KartItemRoulette, for lesser items needed in a pinch. - -#define PLAYERSCALING (8 - (spbrush ? 2 : pingame)) - -#define POWERITEMODDS(odds) {\ - if (franticitems) \ - odds *= 2; \ - if (rival) \ - odds *= 2; \ - odds = FixedMul(odds * FRACUNIT, FRACUNIT + ((PLAYERSCALING * FRACUNIT) / 25)) / FRACUNIT; \ - if (mashed > 0) \ - odds = FixedDiv(odds * FRACUNIT, FRACUNIT + mashed) / FRACUNIT; \ -} - -#define COOLDOWNONSTART (leveltime < (30*TICRATE)+starttime) - /* if (bot) { @@ -640,21 +683,21 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, case KRITEM_TRIPLEORBINAUT: case KRITEM_QUADORBINAUT: case KRITEM_DUALJAWZ: - POWERITEMODDS(newodds); + powerItem = true; break; case KITEM_INVINCIBILITY: case KITEM_MINE: case KITEM_GROW: case KITEM_BUBBLESHIELD: case KITEM_FLAMESHIELD: - if (COOLDOWNONSTART) - newodds = 0; - else - POWERITEMODDS(newodds); + cooldownOnStart = true; + powerItem = true; break; case KITEM_SPB: - if ((indirectitemcooldown > 0) || COOLDOWNONSTART - || (first != -1 && players[first].distancetofinish < 8*DISTVAR)) // No SPB near the end of the race + cooldownOnStart = true; + indirectItem = true; + + if (firstdist < 8*DISTVAR) // No SPB near the end of the race { newodds = 0; } @@ -671,26 +714,73 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, } break; case KITEM_SHRINK: - if ((indirectitemcooldown > 0) || COOLDOWNONSTART || (pingame-1 <= pexiting)) + cooldownOnStart = true; + powerItem = true; + indirectItem = true; + + if (pingame-1 <= pexiting) newodds = 0; - else - POWERITEMODDS(newodds); break; case KITEM_THUNDERSHIELD: - if (spbplace != -1 || COOLDOWNONSTART) + cooldownOnStart = true; + powerItem = true; + + if (spbplace != -1) newodds = 0; - else - POWERITEMODDS(newodds); break; case KITEM_HYUDORO: - if ((hyubgone > 0) || COOLDOWNONSTART) + cooldownOnStart = true; + + if (hyubgone > 0) newodds = 0; break; default: break; } -#undef POWERITEMODDS + if (newodds == 0) + { + // Nothing else we want to do with odds matters at this point :p + return newodds; + } + + if ((indirectItem == true) && (indirectitemcooldown > 0)) + { + // Too many items that act indirectly in a match can feel kind of bad. + newodds = 0; + } + else if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime)) + { + // This item should not appear at the beginning of a race. + newodds = 0; + } + else if (powerItem == true) + { + // This item is a "power item". This activates "frantic item" toggle related functionality. + fixed_t fracOdds = newodds * FRACUNIT; + + if (franticitems == true) + { + // First, power items multiply their odds by 2 if frantic items are on; easy-peasy. + fracOdds *= 2; + } + + if (rival == true) + { + // The Rival bot gets frantic-like items, also :p + fracOdds *= 2; + } + + fracOdds = FixedMul(fracOdds, FRACUNIT + K_ItemOddsScale(pingame, spbrush)); + + if (mashed > 0) + { + // Lastly, it *divides* it based on your mashed value, so that power items are less likely when you mash. + fracOdds = FixedDiv(fracOdds, FRACUNIT + mashed); + } + + newodds = fracOdds / FRACUNIT; + } return newodds; } @@ -872,28 +962,21 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } } - if (mapobjectscale != FRACUNIT) - pdis = FixedDiv(pdis * FRACUNIT, mapobjectscale) / FRACUNIT; - - if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items - { - pdis = (15 * pdis) / 14; - } - - if (spbplace != -1 && player->position == spbplace+1) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell + if (spbplace != -1 && player->position == spbplace+1) { + // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell pdis = (3 * pdis) / 2; spbrush = true; } + pdis = K_ScaleItemDistance(pdis, pingame, spbrush); + if (player->bot && player->botvars.rival) { // Rival has better odds :) pdis = (15 * pdis) / 14; } - pdis = ((28 + (8-pingame)) * pdis) / 28; // scale with player count - // SPECIAL CASE No. 1: // Fake Eggman items if (player->roulettetype == 2) From 8958ebd293ddb754483aa47ac25d69662b783bf3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 23 Apr 2021 17:38:38 -0400 Subject: [PATCH 08/21] Sound refactor - Fix splitscreen volume being too low after james volume fix - Use loops instead of horrid code duplication Unfortunately seems to break sounds in menus and I dunno what to look at :pensive: --- src/s_sound.c | 668 +++++++++++++++----------------------------------- 1 file changed, 201 insertions(+), 467 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 3c7957624..8979d1fc9 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -35,7 +35,7 @@ // 3D Sound Interface #include "hardware/hw3sound.h" #else -static INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); +static boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); #endif CV_PossibleValue_t soundvolume_cons_t[] = {{0, "MIN"}, {MAX_VOLUME, "MAX"}, {0, NULL}}; @@ -196,7 +196,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) else if (sfxinfo == channels[cnum].sfxinfo && (sfxinfo->pitch & SF_NOMULTIPLESOUND)) { return -1; - break; } else if (sfxinfo == channels[cnum].sfxinfo && sfxinfo->singularity == true) { @@ -501,24 +500,37 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan) closedcaptions[set].b = 2; // bob } +static INT32 S_ScaleVolumeWithSplitscreen(INT32 volume) +{ + fixed_t root = INT32_MAX; + + if (r_splitscreen == 0) + { + return volume; + } + + root = FixedSqrt((r_splitscreen + 1) * (FRACUNIT/3)); + + return FixedDiv( + volume * FRACUNIT, + root + ) / FRACUNIT; +} + void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { - const INT32 initial_volume = volume; - INT32 sep, pitch, priority, cnum; - const sfxenum_t actual_id = sfx_id; - sfxinfo_t *sfx; - const boolean reverse = (stereoreverse.value ^ encoremode); const mobj_t *origin = (const mobj_t *)origin_p; + const sfxenum_t actual_id = sfx_id; + const boolean reverse = (stereoreverse.value ^ encoremode); + const INT32 initial_volume = (origin ? S_ScaleVolumeWithSplitscreen(volume) : volume); - listener_t listener = {0,0,0,0}; - listener_t listener2 = {0,0,0,0}; - listener_t listener3 = {0,0,0,0}; - listener_t listener4 = {0,0,0,0}; + sfxinfo_t *sfx; + INT32 sep, pitch, priority, cnum; + boolean anyListeners = false; + INT32 i; - mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; - mobj_t *listenmobj2 = NULL; - mobj_t *listenmobj3 = NULL; - mobj_t *listenmobj4 = NULL; + listener_t listener[MAXSPLITSCREENPLAYERS]; + mobj_t *listenmobj[MAXSPLITSCREENPLAYERS]; if (S_SoundDisabled() || !sound_started) return; @@ -527,27 +539,30 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) if (sfx_id == sfx_None) return; - if (players[displayplayers[0]].awayviewtics) - listenmobj = players[displayplayers[0]].awayviewmobj; - - if (r_splitscreen) + for (i = 0; i <= r_splitscreen; i++) { - listenmobj2 = players[displayplayers[1]].mo; - if (players[displayplayers[1]].awayviewtics) - listenmobj2 = players[displayplayers[1]].awayviewmobj; + player_t *player = &players[displayplayers[i]]; - if (r_splitscreen > 1) + memset(&listener[i], 0, sizeof (listener[i])); + listenmobj[i] = NULL; + + if (!player) { - listenmobj3 = players[displayplayers[2]].mo; - if (players[displayplayers[2]].awayviewtics) - listenmobj3 = players[displayplayers[2]].awayviewmobj; + continue; + } - if (r_splitscreen > 2) - { - listenmobj4 = players[displayplayers[3]].mo; - if (players[displayplayers[3]].awayviewtics) - listenmobj4 = players[displayplayers[3]].awayviewmobj; - } + if (i == 0 && democam.soundmobj) + { + continue; + } + + if (player->awayviewtics) + { + listenmobj[i] = player->awayviewmobj; + } + else + { + listenmobj[i] = player->mo; } } @@ -559,75 +574,37 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) }; #endif - if (camera[0].chase && !players[displayplayers[0]].awayviewtics) + for (i = 0; i <= r_splitscreen; i++) { - listener.x = camera[0].x; - listener.y = camera[0].y; - listener.z = camera[0].z; - listener.angle = camera[0].angle; + player_t *player = &players[displayplayers[i]]; + + if (!player) + { + continue; + } + + if (camera[i].chase && !player->awayviewtics) + { + listener[i].x = camera[i].x; + listener[i].y = camera[i].y; + listener[i].z = camera[i].z; + listener[i].angle = camera[i].angle; + anyListeners = true; + } + else if (listenmobj[i]) + { + listener[i].x = listenmobj[i]->x; + listener[i].y = listenmobj[i]->y; + listener[i].z = listenmobj[i]->z; + listener[i].angle = listenmobj[i]->angle; + anyListeners = true; + } } - else if (listenmobj) + + if (origin && anyListeners == false) { - listener.x = listenmobj->x; - listener.y = listenmobj->y; - listener.z = listenmobj->z; - listener.angle = listenmobj->angle; - } - else if (origin) + // If a mobj is trying to make a noise, and no one is around to hear it, does it make a sound? return; - - if (listenmobj2) - { - if (camera[1].chase && !players[displayplayers[1]].awayviewtics) - { - listener2.x = camera[1].x; - listener2.y = camera[1].y; - listener2.z = camera[1].z; - listener2.angle = camera[1].angle; - } - else - { - listener2.x = listenmobj2->x; - listener2.y = listenmobj2->y; - listener2.z = listenmobj2->z; - listener2.angle = listenmobj2->angle; - } - } - - if (listenmobj3) - { - if (camera[2].chase && !players[displayplayers[2]].awayviewtics) - { - listener3.x = camera[2].x; - listener3.y = camera[2].y; - listener3.z = camera[2].z; - listener3.angle = camera[2].angle; - } - else - { - listener3.x = listenmobj3->x; - listener3.y = listenmobj3->y; - listener3.z = listenmobj3->z; - listener3.angle = listenmobj3->angle; - } - } - - if (listenmobj4) - { - if (camera[3].chase && !players[displayplayers[3]].awayviewtics) - { - listener4.x = camera[3].x; - listener4.y = camera[3].y; - listener4.z = camera[3].z; - listener4.angle = camera[3].angle; - } - else - { - listener4.x = listenmobj4->x; - listener4.y = listenmobj4->y; - listener4.z = listenmobj4->z; - listener4.angle = listenmobj4->angle; - } } // check for bogus sound # @@ -647,92 +624,48 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) pitch = NORM_PITCH; priority = NORM_PRIORITY; - if (r_splitscreen && origin) - volume = FixedDiv(volume<>FRACBITS; + // try to find a channel + cnum = S_getChannel(origin, sfx); - if (r_splitscreen && listenmobj2) // Copy the sound for the split player + if (cnum < 0) { - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj2) - { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj2, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - goto dontplay; // Maybe the other player can hear it... - - if (origin->x == listener2.x && origin->y == listener2.y) - sep = NORM_SEP; - } - else if (!origin) - // Do not play origin-less sounds for the second player. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - goto dontplay; - else - sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); + return; // If there's no free channels, it's not gonna be free for anyone. } -dontplay: - - if (r_splitscreen > 1 && listenmobj3) // Copy the sound for the third player + for (i = r_splitscreen; i >= 0; i--) { - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj3) + // Copy the sound for the splitscreen players! + if (!listenmobj[i]) { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj3, origin, &volume, &sep, &pitch, sfx); + continue; + } + + // Check to see if it is audible, and if not, modify the params + if (origin && origin != listenmobj[i]) + { + boolean rc = S_AdjustSoundParams(listenmobj[i], origin, &volume, &sep, &pitch, sfx); if (!rc) - goto dontplay3; // Maybe the other player can hear it... + { + continue; // Maybe the other player can hear it... + } - if (origin->x == listener3.x && origin->y == listener3.y) + if (origin->x == listener[i].x && origin->y == listener[i].y) + { sep = NORM_SEP; + } } - else if (!origin) - // Do not play origin-less sounds for the second player. + else if (i > 0 && !origin) + { + // Do not play origin-less sounds for the splitscreen players. // The first player will be able to hear it just fine, // we really don't want it playing twice. - goto dontplay3; + continue; + } else + { sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. + } // This is supposed to handle the loading/caching. // For some odd reason, the caching is done nearly @@ -741,135 +674,35 @@ dontplay: // cache data if necessary // NOTE: set sfx->data NULL sfx->lump -1 to force a reload if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); - } - -dontplay3: - - if (r_splitscreen > 2 && listenmobj4) // Copy the sound for the split player - { - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj4) { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj4, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - goto dontplay4; // Maybe the other player can hear it... - - if (origin->x == listener4.x && origin->y == listener4.y) - sep = NORM_SEP; - } - else if (!origin) - // Do not play origin-less sounds for the second player. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - goto dontplay4; - else - sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) sfx->data = I_GetSfx(sfx); + } // increase the usefulness if (sfx->usefulness++ < 0) + { sfx->usefulness = -1; + } // Avoid channel reverse if surround if (reverse #ifdef SURROUND && sep != SURROUND_SEP #endif - ) + ) + { sep = (~sep) & 255; + } // Handle closed caption input. S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); // Assigns the handle to one of the channels in the // mix/output buffer. + channels[cnum].volume = initial_volume; channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); + return; // We're done here! } - -dontplay4: - - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj) - { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - return; - - if (origin->x == listener.x && origin->y == listener.y) - sep = NORM_SEP; - } - else - sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Handle closed caption input. - S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].volume = initial_volume; - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } void S_StartSound(const void *origin, sfxenum_t sfx_id) @@ -920,23 +753,13 @@ static INT32 actualdigmusicvolume; void S_UpdateSounds(void) { - INT32 audible, cnum, volume, sep, pitch; + INT32 cnum, volume, sep, pitch; + boolean audible = false; channel_t *c; + INT32 i; - listener_t listener; - listener_t listener2; - listener_t listener3; - listener_t listener4; - - mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; - mobj_t *listenmobj2 = NULL; - mobj_t *listenmobj3 = NULL; - mobj_t *listenmobj4 = NULL; - - memset(&listener, 0, sizeof(listener_t)); - memset(&listener2, 0, sizeof(listener_t)); - memset(&listener3, 0, sizeof(listener_t)); - memset(&listener4, 0, sizeof(listener_t)); + listener_t listener[MAXSPLITSCREENPLAYERS]; + mobj_t *listenmobj[MAXSPLITSCREENPLAYERS]; // Update sound/music volumes, if changed manually at console if (actualsfxvolume != cv_soundvolume.value * USER_VOLUME_SCALE) @@ -949,7 +772,7 @@ void S_UpdateSounds(void) { #ifndef NOMUMBLE // Stop Mumble cutting out. I'm sick of it. - I_UpdateMumble(NULL, listener); + I_UpdateMumble(NULL, listener[0]); #endif goto notinlevel; @@ -958,47 +781,35 @@ void S_UpdateSounds(void) if (dedicated || sound_disabled) return; - if (players[displayplayers[0]].awayviewtics) - listenmobj = players[displayplayers[0]].awayviewmobj; - - if (r_splitscreen) + for (i = 0; i <= r_splitscreen; i++) { - listenmobj2 = players[displayplayers[1]].mo; - if (players[displayplayers[1]].awayviewtics) - listenmobj2 = players[displayplayers[1]].awayviewmobj; + player_t *player = &players[displayplayers[i]]; - if (r_splitscreen > 1) + memset(&listener[i], 0, sizeof (listener[i])); + listenmobj[i] = NULL; + + if (!player) { - listenmobj3 = players[displayplayers[2]].mo; - if (players[displayplayers[2]].awayviewtics) - listenmobj3 = players[displayplayers[2]].awayviewmobj; + continue; + } - if (r_splitscreen > 2) - { - listenmobj4 = players[displayplayers[3]].mo; - if (players[displayplayers[3]].awayviewtics) - listenmobj4 = players[displayplayers[3]].awayviewmobj; - } + if (i == 0 && democam.soundmobj) + { + continue; + } + + if (player->awayviewtics) + { + listenmobj[i] = player->awayviewmobj; + } + else + { + listenmobj[i] = player->mo; } } - if (camera[0].chase && !players[displayplayers[0]].awayviewtics) - { - listener.x = camera[0].x; - listener.y = camera[0].y; - listener.z = camera[0].z; - listener.angle = camera[0].angle; - } - else if (listenmobj) - { - listener.x = listenmobj->x; - listener.y = listenmobj->y; - listener.z = listenmobj->z; - listener.angle = listenmobj->angle; - } - #ifndef NOMUMBLE - I_UpdateMumble(players[consoleplayer].mo, listener); + I_UpdateMumble(players[consoleplayer].mo, listener[0]); #endif #ifdef HW3SOUND @@ -1009,57 +820,28 @@ void S_UpdateSounds(void) } #endif - if (listenmobj2) + for (i = 0; i <= r_splitscreen; i++) { - if (camera[1].chase && !players[displayplayers[1]].awayviewtics) - { - listener2.x = camera[1].x; - listener2.y = camera[1].y; - listener2.z = camera[1].z; - listener2.angle = camera[1].angle; - } - else - { - listener2.x = listenmobj2->x; - listener2.y = listenmobj2->y; - listener2.z = listenmobj2->z; - listener2.angle = listenmobj2->angle; - } - } + player_t *player = &players[displayplayers[i]]; - if (listenmobj3) - { - if (camera[2].chase && !players[displayplayers[2]].awayviewtics) + if (!player) { - listener3.x = camera[2].x; - listener3.y = camera[2].y; - listener3.z = camera[2].z; - listener3.angle = camera[2].angle; + continue; } - else - { - listener3.x = listenmobj3->x; - listener3.y = listenmobj3->y; - listener3.z = listenmobj3->z; - listener3.angle = listenmobj3->angle; - } - } - if (listenmobj4) - { - if (camera[3].chase && !players[displayplayers[3]].awayviewtics) + if (camera[i].chase && !player->awayviewtics) { - listener4.x = camera[3].x; - listener4.y = camera[3].y; - listener4.z = camera[3].z; - listener4.angle = camera[3].angle; + listener[i].x = camera[i].x; + listener[i].y = camera[i].y; + listener[i].z = camera[i].z; + listener[i].angle = camera[i].angle; } - else + else if (listenmobj[i]) { - listener4.x = listenmobj4->x; - listener4.y = listenmobj4->y; - listener4.z = listenmobj4->z; - listener4.angle = listenmobj4->angle; + listener[i].x = listenmobj[i]->x; + listener[i].y = listenmobj[i]->y; + listener[i].z = listenmobj[i]->z; + listener[i].angle = listenmobj[i]->angle; } } @@ -1076,84 +858,54 @@ void S_UpdateSounds(void) pitch = NORM_PITCH; sep = NORM_SEP; - if (r_splitscreen && c->origin) - volume = FixedDiv(volume<>FRACBITS; - // check non-local sounds for distance clipping // or modify their params - if (c->origin && ((c->origin != players[displayplayers[0]].mo) - || (r_splitscreen && c->origin != players[displayplayers[1]].mo) - || (r_splitscreen > 1 && c->origin != players[displayplayers[2]].mo) - || (r_splitscreen > 2 && c->origin != players[displayplayers[3]].mo))) + if (c->origin) { - // Whomever is closer gets the sound, but only in splitscreen. - if (r_splitscreen) + boolean itsUs = false; + + for (i = 0; i <= r_splitscreen; i++) + { + if (c->origin == players[displayplayers[i]].mo) + { + itsUs = true; + break; + } + } + + if (itsUs == false) { const mobj_t *soundmobj = c->origin; - fixed_t recdist = -1; - INT32 i, p = -1; + fixed_t recdist = INT32_MAX; + UINT8 p = 0; for (i = 0; i <= r_splitscreen; i++) { - fixed_t thisdist = -1; + fixed_t thisdist = INT32_MAX; - if (i == 0 && listenmobj) - thisdist = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y); - else if (i == 1 && listenmobj2) - thisdist = P_AproxDistance(listener2.x-soundmobj->x, listener2.y-soundmobj->y); - else if (i == 2 && listenmobj3) - thisdist = P_AproxDistance(listener3.x-soundmobj->x, listener3.y-soundmobj->y); - else if (i == 3 && listenmobj4) - thisdist = P_AproxDistance(listener4.x-soundmobj->x, listener4.y-soundmobj->y); - else + if (!listenmobj[i]) + { continue; + } - if (recdist == -1 || (thisdist != -1 && thisdist < recdist)) + thisdist = P_AproxDistance(listener[i].x - soundmobj->x, listener[i].y - soundmobj->y); + + if (thisdist < recdist) { recdist = thisdist; p = i; } } - if (p != -1) + if (listenmobj[p]) { - if (p == 1) - { - // Player 2 gets the sound - audible = S_AdjustSoundParams(listenmobj2, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else if (p == 2) - { - // Player 3 gets the sound - audible = S_AdjustSoundParams(listenmobj3, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else if (p == 3) - { - // Player 4 gets the sound - audible = S_AdjustSoundParams(listenmobj4, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else - { - // Player 1 gets the sound - audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - - if (audible) - I_UpdateSoundParams(c->handle, volume, sep, pitch); - else - S_StopChannel(cnum); + audible = S_AdjustSoundParams( + listenmobj[p], c->origin, + &volume, &sep, &pitch, + c->sfxinfo + ); } - } - else if (listenmobj && !r_splitscreen) - { - // In the case of a single player, he or she always should get updated sound. - audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - + if (audible) I_UpdateSoundParams(c->handle, volume, sep, pitch); else @@ -1273,54 +1025,39 @@ fixed_t S_CalculateSoundDistance(fixed_t sx1, fixed_t sy1, fixed_t sz1, fixed_t // If the sound is not audible, returns a 0. // Otherwise, modifies parameters and returns 1. // -INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, +boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo) { + const boolean reverse = (stereoreverse.value ^ encoremode); + fixed_t approx_dist; angle_t angle; listener_t listensource; - - const boolean reverse = (stereoreverse.value ^ encoremode); + INT32 i; (void)pitch; + if (!listener) return false; - if (listener == players[displayplayers[0]].mo && camera[0].chase) + // Init listensource with default listener + listensource.x = listener->x; + listensource.y = listener->y; + listensource.z = listener->z; + listensource.angle = listener->angle; + + for (i = 0; i <= r_splitscreen; i++) { - listensource.x = camera[0].x; - listensource.y = camera[0].y; - listensource.z = camera[0].z; - listensource.angle = camera[0].angle; - } - else if (r_splitscreen && listener == players[displayplayers[1]].mo && camera[1].chase) - { - listensource.x = camera[1].x; - listensource.y = camera[1].y; - listensource.z = camera[1].z; - listensource.angle = camera[1].angle; - } - else if (r_splitscreen > 1 && listener == players[displayplayers[2]].mo && camera[2].chase) - { - listensource.x = camera[2].x; - listensource.y = camera[2].y; - listensource.z = camera[2].z; - listensource.angle = camera[2].angle; - } - else if (r_splitscreen > 2 && listener == players[displayplayers[3]].mo && camera[3].chase) - { - listensource.x = camera[3].x; - listensource.y = camera[3].y; - listensource.z = camera[3].z; - listensource.angle = camera[3].angle; - } - else - { - listensource.x = listener->x; - listensource.y = listener->y; - listensource.z = listener->z; - listensource.angle = listener->angle; + // If listener is a chasecam player, use the camera instead + if (listener == players[displayplayers[i]].mo && camera[i].chase) + { + listensource.x = camera[i].x; + listensource.y = camera[i].y; + listensource.z = camera[i].z; + listensource.angle = camera[i].angle; + break; + } } if (sfxinfo->pitch & SF_OUTSIDESOUND) // Rain special case @@ -1370,7 +1107,7 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v approx_dist = FixedDiv(approx_dist,2*FRACUNIT); if (approx_dist > S_CLIPPING_DIST) - return 0; + return false; // angle of source to listener angle = R_PointToAngle2(listensource.x, listensource.y, source->x, source->y); @@ -1405,9 +1142,6 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v *vol = FixedMul(*vol * FRACUNIT / 255, n) / S_ATTENUATOR; } - if (r_splitscreen) - *vol = FixedDiv((*vol)<>FRACBITS; - return (*vol > 0); } From c99b1466ea7fb3e515194400ff80d75cd0864235 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 23 Apr 2021 17:41:02 -0400 Subject: [PATCH 09/21] Fix comments --- 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 aa0834326..52328502e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -520,13 +520,13 @@ static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spb { if (mapobjectscale != FRACUNIT) { - // Bring back to normal scale, so that + // Bring back to normal scale. distance = FixedDiv(distance * FRACUNIT, mapobjectscale) / FRACUNIT; } if (franticitems == true) { - // Frantic items arbritrarily make distances shorter, for crazier items. + // Frantic items pretends everyone's farther apart, for crazier items. distance = (15 * distance) / 14; } From e632e1d70ee4491c2e3085026249c6a2522e0d84 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 24 Apr 2021 01:26:39 +0200 Subject: [PATCH 10/21] Final (?) visuals for trick panel timing --- src/d_player.h | 3 ++ src/info.c | 2 ++ src/info.h | 2 ++ src/k_hud.c | 34 ++++++++++++++++++++ src/k_kart.c | 85 ++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 102 insertions(+), 24 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 445c1148d..8bd2f3fa8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -232,6 +232,9 @@ typedef enum khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly + // Tricks + khud_trickcool, + NUMKARTHUD } karthudtype_t; diff --git a/src/info.c b/src/info.c index eaa800ebc..ff982d6de 100644 --- a/src/info.c +++ b/src/info.c @@ -747,6 +747,8 @@ char sprnames[NUMSPRITES + 1][5] = "SDDS", // Spindash dust "SDWN", // Spindash wind + "TRCK", + "FLBM", // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later diff --git a/src/info.h b/src/info.h index 697d206c6..f012df8a0 100644 --- a/src/info.h +++ b/src/info.h @@ -1289,6 +1289,8 @@ typedef enum sprite SPR_SDDS, // Spindash dust SPR_SDWN, // Spindash wind + SPR_TRCK, + SPR_FLBM, // Finish line beam // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later diff --git a/src/k_hud.c b/src/k_hud.c index c2b29fe3d..e03172ae4 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -162,6 +162,8 @@ static patch_t *kp_cpu; static patch_t *kp_nametagstem; +static patch_t *kp_trickcool[2]; + void K_LoadKartHUDGraphics(void) { INT32 i, j; @@ -601,6 +603,9 @@ void K_LoadKartHUDGraphics(void) kp_cpu = (patch_t *) W_CachePatchName("K_CPU", PU_HUDGFX); kp_nametagstem = (patch_t *) W_CachePatchName("K_NAMEST", PU_HUDGFX); + + kp_trickcool[0] = W_CachePatchName("K_COOL1", PU_HUDGFX); + kp_trickcool[1] = W_CachePatchName("K_COOL2", PU_HUDGFX); } // For the item toggle menu @@ -3951,6 +3956,31 @@ static void K_drawLapStartAnim(void) } } +// stretch for "COOOOOL" popup. +// I can't be fucked to find out any math behind this so have a table lmao +static fixed_t stretch[6][2] = { + {FRACUNIT/4, FRACUNIT*4}, + {FRACUNIT/2, FRACUNIT*2}, + {FRACUNIT, FRACUNIT}, + {FRACUNIT*2, FRACUNIT/2}, + {FRACUNIT*4, FRACUNIT/4}, + {FRACUNIT*2, FRACUNIT/2}, +}; + +static void K_drawTrickCool(void) +{ + + tic_t timer = TICRATE - stplyr->karthud[khud_trickcool]; + if (timer <= 6) + { + V_DrawStretchyFixedPatch(160<karthud[khud_trickcool]) + K_drawTrickCool(); + if (modeattacking || freecam) // everything after here is MP and debug only return; diff --git a/src/k_kart.c b/src/k_kart.c index 3f1cdebb9..938f4a5d0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6099,6 +6099,9 @@ void K_KartPlayerHUDUpdate(player_t *player) if (player->karthud[khud_tauntvoices]) player->karthud[khud_tauntvoices]--; + if (player->karthud[khud_trickcool]) + player->karthud[khud_trickcool]--; + if (!(player->pflags & PF_FAULT)) player->karthud[khud_fault] = 0; else if (player->karthud[khud_fault] > 0 && player->karthud[khud_fault] < 2*TICRATE) @@ -8138,10 +8141,12 @@ void K_AdjustPlayerFriction(player_t *player) // // K_trickPanelTimingVisual // Spawns the timing visual for trick panels depending on the given player's momz. +// If the player has tricked and is not in hitlag, this will send the half circles flying out. +// if you tumble, they'll fall off instead. // #define RADIUSSCALING 6 -#define MINRADIUS 24 +#define MINRADIUS 12 static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) { @@ -8150,8 +8155,8 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) mobj_t *flame; angle_t hang = R_PointToAngle(player->mo->x, player->mo->y) + ANG1*90; // horizontal angle - angle_t vang = -leveltime*ANG1*12; // vertical angle... arbitrary rotation speed for now. - fixed_t dist = FixedMul(max(MINRADIUS<mo->scale); // distance. + angle_t vang = -FixedAngle(momz)*12 + (ANG1*45); // vertical angle... arbitrary rotation speed for now. + fixed_t dist = FixedMul(max(MINRADIUS<mo->scale); // distance. UINT8 i; @@ -8164,31 +8169,48 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) pos = FixedMul(dist, FINESINE(vang>>ANGLETOFINESHIFT)); tx = player->mo->x + FixedMul(pos, FINECOSINE(hang>>ANGLETOFINESHIFT)); ty = player->mo->y + FixedMul(pos, FINESINE(hang>>ANGLETOFINESHIFT)); - tz = player->mo->z + FixedMul(dist, FINECOSINE(vang>>ANGLETOFINESHIFT)); + tz = player->mo->z + player->mo->height/2 + FixedMul(dist, FINECOSINE(vang>>ANGLETOFINESHIFT)); // All coordinates set, spawn our fire, now. - flame = P_SpawnMobj(tx, ty, tz, MT_THOK); // @TODO: Make this into its own object. Duh. + flame = P_SpawnMobj(tx, ty, tz, MT_THOK); - // PLACEHOLDER VISUALS - // @TODO: SPRITES - flame->sprite = SPR_FLAM; - flame->frame = ((leveltime%16) /2)|FF_FULLBRIGHT; - flame->tics = 2; - flame->rollangle = vang + ANG1*90; + P_SetScale(flame, player->mo->scale); + + // Visuals + flame->sprite = SPR_TRCK; + flame->frame = i|FF_FULLBRIGHT; + + if (player->trickpanel <= 1 && !player->tumbleBounces) + flame->tics = 2; + else + { + flame->tics = TICRATE; + + if (player->trickpanel > 1) // we tricked + { + // Send the thing outwards via ghetto maths + pos = FixedMul(48*player->mo->scale, FINESINE((vang +ANG1*90)>>ANGLETOFINESHIFT)); + tx = player->mo->x + FixedMul(pos, FINECOSINE(hang>>ANGLETOFINESHIFT)); + ty = player->mo->y + FixedMul(pos, FINESINE(hang>>ANGLETOFINESHIFT)); + tz = player->mo->z + player->mo->height/2 + FixedMul(48*player->mo->scale, FINECOSINE((vang +ANG1*90)>>ANGLETOFINESHIFT)); + + flame->momx = tx -player->mo->x; + flame->momy = ty -player->mo->y; + flame->momz = tz -(player->mo->z+player->mo->height/2); + } + else // we failed the trick. + { + flame->flags &= ~MF_NOGRAVITY; + P_SetObjectMomZ(flame, 4<mo->x, player->mo->y, flame->x, flame->y), 8*mapobjectscale); + flame->momx += player->mo->momx; + flame->momy += player->mo->momy; + flame->momz += player->mo->momz; + } + } // make sure this is only drawn for our local player - flame->renderflags &= ~K_GetPlayerDontDrawFlag(player); - - // second flame for visuals... - flame = P_SpawnMobj(tx, ty, tz, MT_THOK); // @TODO: Make this into its own object. Duh. - - flame->sprite = SPR_FLAM; - flame->frame = ((leveltime%16) /2)|FF_FULLBRIGHT|FF_TRANS60; - flame->tics = 10; - flame->rollangle = vang + ANG1*90; - - // make sure this is only drawn for our local player - flame->renderflags &= ~K_GetPlayerDontDrawFlag(player); + flame->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player)); vang += FixedAngle(180<mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)); - K_trickPanelTimingVisual(player, abs(momz)); + K_trickPanelTimingVisual(player, momz); // streaks: if (momz*P_MobjFlip(player->mo) > 0) // only spawn those while you're going upwards relative to your current gravity @@ -8907,11 +8929,22 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->pflags &= ~PF_TUMBLESOUND; player->tumbleHeight = 30; // Base tumble bounce height player->trickpanel = 0; + K_trickPanelTimingVisual(player, momz); // fail trick visual P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); } else if (!(player->pflags & PF_TRICKDELAY)) // don't allow tricking at the same frame you tumble obv { + + // "COOL" timing n shit. + if (cmd->turning || player->throwdir) + { + if (abs(momz) < FRACUNIT*99) // Let's use that as baseline for PERFECT trick. + { + player->karthud[khud_trickcool] = TICRATE; + } + } + // Uses cmd->turning over steering intentionally. if (cmd->turning > 0) { @@ -8925,6 +8958,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickpanel = 2; player->mo->hitlag = TRICKLAG; + K_trickPanelTimingVisual(player, momz); } else if (cmd->turning < 0) { @@ -8938,6 +8972,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickpanel = 3; player->mo->hitlag = TRICKLAG; + K_trickPanelTimingVisual(player, momz); } else if (player->throwdir == 1) { @@ -8956,6 +8991,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickpanel = 2; player->mo->hitlag = TRICKLAG; + K_trickPanelTimingVisual(player, momz); } else if (player->throwdir == -1) { @@ -8985,6 +9021,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickpanel = 4; player->mo->hitlag = TRICKLAG; + K_trickPanelTimingVisual(player, momz); } } } From e980be69ef40d6c42b0e9947ce0556bbf08f4b75 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 24 Apr 2021 01:56:34 +0200 Subject: [PATCH 11/21] wip splitscreen garbage. DOES NOT WORK. --- src/k_hud.c | 22 ++++++++++++++++++++-- src/k_kart.c | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index e03172ae4..18809ae6f 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3971,13 +3971,31 @@ static void K_drawTrickCool(void) { tic_t timer = TICRATE - stplyr->karthud[khud_trickcool]; + INT32 x = (BASEVIDWIDTH/2); + INT32 y = ((BASEVIDHEIGHT)/2)-10; + + // @TODO: fix this shit + /*if (r_splitscreen > 2) // 4p split + { + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) + { + x /= 2; + y /= 2; + } + else + { + x /= 2 + BASEVIDWIDTH/2; + y /= 2 + BASEVIDHEIGHT/2; + } + }*/ + if (timer <= 6) { - V_DrawStretchyFixedPatch(160< Date: Fri, 23 Apr 2021 20:03:01 -0400 Subject: [PATCH 12/21] SPB has rainbow item animation when forced onto you --- 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 52328502e..4215fadd8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1083,11 +1083,11 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { K_KartGetItemResult(player, KITEM_SPB); player->karthud[khud_itemblink] = TICRATE; - player->karthud[khud_itemblinkmode] = (mashed ? 1 : 0); + player->karthud[khud_itemblinkmode] = 2; player->itemroulette = 0; player->roulettetype = 0; if (P_IsDisplayPlayer(player)) - S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + S_StartSound(NULL, sfx_itrolk); return; } From db43239ca37d280a9020a4ea0bf486e113531530 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 23 Apr 2021 20:57:14 -0400 Subject: [PATCH 13/21] Fix debug distribution crash --- src/k_hud.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_hud.c b/src/k_hud.c index c2b29fe3d..eb46d20e4 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4023,6 +4023,7 @@ static void K_drawDistributionDebugger(void) kp_superring[1], kp_kitchensink[1], + kp_sneaker[1], kp_sneaker[1], kp_banana[1], kp_banana[1], @@ -4105,6 +4106,9 @@ static void K_drawDistributionDebugger(void) case KRITEM_DUALJAWZ: amount = 2; break; + case KRITEM_DUALSNEAKER: + amount = 2; + break; default: amount = 3; break; From 2ea9164cb1fe82a1b81ddc36925d7a5fc6bc6296 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 24 Apr 2021 00:14:14 -0400 Subject: [PATCH 14/21] Fix natural SPB, prevent getting bananas at the end of the race --- src/k_hud.c | 18 ++++--- src/k_kart.c | 148 ++++++++++++++++++++++++++++++--------------------- src/k_kart.h | 4 +- 3 files changed, 100 insertions(+), 70 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index eb46d20e4..d4910b524 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4063,28 +4063,32 @@ static void K_drawDistributionDebugger(void) } } - if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items - pdis = (15 * pdis) / 14; - - if (spbplace != -1 && stplyr->position == spbplace+1) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell + if (spbplace != -1 && stplyr->position == spbplace+1) { + // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell pdis = (3 * pdis) / 2; spbrush = true; } + pdis = K_ScaleItemDistance(pdis, pingame, spbrush); + if (stplyr->bot && stplyr->botvars.rival) { // Rival has better odds :) pdis = (15 * pdis) / 14; } - pdis = ((28 + (8-pingame)) * pdis) / 28; // scale with player count - useodds = K_FindUseodds(stplyr, 0, pdis, bestbumper, spbrush); for (i = 1; i < NUMKARTRESULTS; i++) { - const INT32 itemodds = K_KartGetItemOdds(useodds, i, 0, spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival)); + INT32 itemodds = K_KartGetItemOdds( + useodds, i, + stplyr->distancetofinish, + 0, + spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival) + ); + if (itemodds <= 0) continue; diff --git a/src/k_kart.c b/src/k_kart.c index 4215fadd8..57eb7c40e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -348,7 +348,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine /*Land Mine*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog - /*Self-Propelled Bomb*/ { 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb + /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow /*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink /*Thunder Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield @@ -400,6 +400,9 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] = }; #define DISTVAR (2048) // Magic number distance for use with item roulette tiers +#define SPBSTARTDIST (5*DISTVAR) // Distance when SPB is forced onto 2nd place +#define SPBFORCEDIST (15*DISTVAR) // Distance when SPB is forced onto 2nd place +#define ENDDIST (12*DISTVAR) // Distance when the game stops giving you bananas // Array of states to pick the starting point of the animation, based on the actual time left for invincibility. static INT32 K_SparkleTrailStartStates[KART_NUMINVSPARKLESANIM][2] = { @@ -491,7 +494,7 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) } } -static fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush) +fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush) { const UINT8 basePlayer = 8; // The player count we design most of the game around. UINT8 playerCount = (spbrush ? 2 : numPlayers); @@ -516,7 +519,7 @@ static fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush) return playerScaling; } -static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush) +UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush) { if (mapobjectscale != FRACUNIT) { @@ -549,7 +552,11 @@ static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spb \return void */ -INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, boolean bot, boolean rival) +INT32 K_KartGetItemOdds( + UINT8 pos, SINT8 item, + UINT32 ourDist, + fixed_t mashed, + boolean spbrush, boolean bot, boolean rival) { INT32 newodds; INT32 i; @@ -557,12 +564,13 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, UINT8 pingame = 0, pexiting = 0; SINT8 first = -1, second = -1; - UINT32 firstdist = UINT32_MAX; - UINT32 secondist = UINT32_MAX; + UINT32 firstDist = UINT32_MAX; + UINT32 secondToFirst = UINT32_MAX; boolean powerItem = false; boolean cooldownOnStart = false; boolean indirectItem = false; + boolean notNearEnd = false; INT32 shieldtype = KSHIELD_NONE; @@ -572,6 +580,24 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, if (!KartItemCVars[item-1]->value && !modeattacking) return 0; + /* + if (bot) + { + // TODO: Item use on bots should all be passed-in functions. + // Instead of manually inserting these, it should return 0 + // for any items without an item use function supplied + + switch (item) + { + case KITEM_SNEAKER: + break; + default: + return 0; + } + } + */ + (void)bot; + if (gametype == GT_BATTLE) { I_Assert(pos < 6); // DO NOT allow positions past the bounds of the table @@ -616,75 +642,41 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, if (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB { - firstdist = players[first].distancetofinish; + firstDist = players[first].distancetofinish; if (mapobjectscale != FRACUNIT) { - firstdist = FixedDiv(firstdist * FRACUNIT, mapobjectscale) / FRACUNIT; + firstDist = FixedDiv(firstDist * FRACUNIT, mapobjectscale) / FRACUNIT; } - secondist = K_ScaleItemDistance( + secondToFirst = K_ScaleItemDistance( players[second].distancetofinish - players[first].distancetofinish, pingame, spbrush ); } - /* - if (bot) - { - // TODO: Item use on bots should all be passed-in functions. - // Instead of manually inserting these, it should return 0 - // for any items without an item use function supplied - - switch (item) - { - case KITEM_SNEAKER: - case KITEM_ROCKETSNEAKER: - case KITEM_INVINCIBILITY: - case KITEM_BANANA: - case KITEM_EGGMAN: - case KITEM_ORBINAUT: - case KITEM_JAWZ: - case KITEM_MINE: - case KITEM_LANDMINE: - case KITEM_BALLHOG: - case KITEM_SPB: - case KITEM_GROW: - case KITEM_SHRINK: - case KITEM_HYUDORO: - case KITEM_SUPERRING: - case KITEM_THUNDERSHIELD: - case KITEM_BUBBLESHIELD: - case KITEM_FLAMESHIELD: - case KRITEM_DUALSNEAKER: - case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - case KRITEM_TENFOLDBANANA: - case KRITEM_TRIPLEORBINAUT: - case KRITEM_QUADORBINAUT: - case KRITEM_DUALJAWZ: - break; - default: - return 0; - } - } - */ - (void)bot; - switch (item) { + case KITEM_BANANA: + case KITEM_EGGMAN: + case KITEM_SUPERRING: + notNearEnd = true; + break; case KITEM_ROCKETSNEAKER: case KITEM_JAWZ: case KITEM_LANDMINE: case KITEM_BALLHOG: case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - case KRITEM_TENFOLDBANANA: case KRITEM_TRIPLEORBINAUT: case KRITEM_QUADORBINAUT: case KRITEM_DUALJAWZ: powerItem = true; break; + case KRITEM_TRIPLEBANANA: + case KRITEM_TENFOLDBANANA: + powerItem = true; + notNearEnd = true; + break; case KITEM_INVINCIBILITY: case KITEM_MINE: case KITEM_GROW: @@ -696,19 +688,24 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, case KITEM_SPB: cooldownOnStart = true; indirectItem = true; + notNearEnd = true; - if (firstdist < 8*DISTVAR) // No SPB near the end of the race + if (firstDist < ENDDIST) // No SPB near the end of the race { newodds = 0; } else { - INT32 multiplier = (secondist - (5*DISTVAR)) / DISTVAR; + const INT32 distFromStart = max(0, secondToFirst - SPBSTARTDIST); + const INT32 distRange = SPBFORCEDIST - SPBSTARTDIST; + const INT32 mulMax = 3; + + INT32 multiplier = (distFromStart * mulMax) / distRange; if (multiplier < 0) multiplier = 0; - if (multiplier > 3) - multiplier = 3; + if (multiplier > mulMax) + multiplier = mulMax; newodds *= multiplier; } @@ -717,6 +714,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, cooldownOnStart = true; powerItem = true; indirectItem = true; + notNearEnd = true; if (pingame-1 <= pexiting) newodds = 0; @@ -730,6 +728,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, break; case KITEM_HYUDORO: cooldownOnStart = true; + notNearEnd = true; if (hyubgone > 0) newodds = 0; @@ -751,7 +750,12 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, } else if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime)) { - // This item should not appear at the beginning of a race. + // This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items) + newodds = 0; + } + else if ((notNearEnd == true) && (ourDist < ENDDIST)) + { + // This item should not appear at the end of a race. (Usually trap items that lose their effectiveness) newodds = 0; } else if (powerItem == true) @@ -811,7 +815,12 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum for (j = 1; j < NUMKARTRESULTS; j++) { - if (K_KartGetItemOdds(i, j, mashed, spbrush, player->bot, (player->bot && player->botvars.rival)) > 0) + if (K_KartGetItemOdds( + i, j, + player->distancetofinish, + mashed, + spbrush, player->bot, (player->bot && player->botvars.rival) + ) > 0) { available = true; break; @@ -1077,7 +1086,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) // SPECIAL CASE No. 5: // Force SPB onto 2nd if they get too far behind - if ((gametyperules & GTR_CIRCUIT) && player->position == 2 && pdis > (DISTVAR*8) + if ((gametyperules & GTR_CIRCUIT) && player->position == 2 && pdis > SPBFORCEDIST && spbplace == -1 && !indirectitemcooldown && !dontforcespb && cv_selfpropelledbomb.value) { @@ -1100,7 +1109,14 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) useodds = K_FindUseodds(player, mashed, pdis, bestbumper, spbrush); for (i = 1; i < NUMKARTRESULTS; i++) - spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(useodds, i, mashed, spbrush, player->bot, (player->bot && player->botvars.rival))); + { + spawnchance[i] = (totalspawnchance += K_KartGetItemOdds( + useodds, i, + player->distancetofinish, + mashed, + spbrush, player->bot, (player->bot && player->botvars.rival)) + ); + } // Award the player whatever power is rolled if (totalspawnchance > 0) @@ -5374,7 +5390,15 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 useodds = amount; for (i = 1; i < NUMKARTRESULTS; i++) - spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(useodds, i, 0, false, false, false)); + { + spawnchance[i] = (totalspawnchance += K_KartGetItemOdds( + useodds, i, + UINT32_MAX, + 0, + false, false, false + ) + ); + } if (totalspawnchance > 0) { diff --git a/src/k_kart.h b/src/k_kart.h index d0668450e..7299ac765 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -34,7 +34,9 @@ fixed_t K_GetKartGameSpeedScalar(SINT8 value); extern consvar_t *KartItemCVars[NUMKARTRESULTS-1]; UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush); -INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, boolean bot, boolean rival); +fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush); +UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush); +INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival); INT32 K_GetShieldFromItem(INT32 item); fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against); boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2); From 9504b6011e4c01ef93637a6ef266aeb0dbd83298 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 24 Apr 2021 00:16:57 -0400 Subject: [PATCH 15/21] Make it linear instead of exponential --- 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 57eb7c40e..c78d094e7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -507,7 +507,7 @@ fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush) { // Less than basePlayer: increase odds significantly. // 2P: x2.5 - playerScaling = ((basePlayer - playerCount) * (basePlayer - playerCount)) * (FRACUNIT / 14); + playerScaling = (basePlayer - playerCount) * (FRACUNIT / 4); } else if (playerCount > basePlayer) { From d253b66524aff3d0577e0a6f9836e7e29cf99f06 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 24 Apr 2021 14:46:39 +0200 Subject: [PATCH 16/21] Fix effects in splitscreen --- src/k_hud.c | 36 ++++++++++++++---------------------- src/k_kart.c | 16 ++++++---------- src/r_main.c | 35 +++++++++++++++++++++++++++++++++++ src/r_main.h | 1 + 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 18809ae6f..d023653a2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -684,6 +684,9 @@ INT32 ITEM2_X, ITEM2_Y; INT32 LAPS2_X, LAPS2_Y; INT32 POSI2_X, POSI2_Y; +// trick "cool" +INT32 TCOOL_X, TCOOL_Y; + void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy) { @@ -987,6 +990,10 @@ static void K_initKartHUD(void) WANT_X = BASEVIDWIDTH - 55; // 270 WANT_Y = BASEVIDHEIGHT- 71; // 176 + // trick COOL + TCOOL_X = (BASEVIDWIDTH)/2; + TCOOL_Y = (BASEVIDHEIGHT)/2 -10; + if (r_splitscreen) // Splitscreen { ITEM_X = 5; @@ -1029,6 +1036,8 @@ static void K_initKartHUD(void) MINI_X = (3*BASEVIDWIDTH/4); MINI_Y = (3*BASEVIDHEIGHT/4); + TCOOL_X = (BASEVIDWIDTH)/4; + if (r_splitscreen > 2) // 4P-only { MINI_X = (BASEVIDWIDTH/2); @@ -3962,40 +3971,23 @@ static fixed_t stretch[6][2] = { {FRACUNIT/4, FRACUNIT*4}, {FRACUNIT/2, FRACUNIT*2}, {FRACUNIT, FRACUNIT}, - {FRACUNIT*2, FRACUNIT/2}, - {FRACUNIT*4, FRACUNIT/4}, - {FRACUNIT*2, FRACUNIT/2}, + {FRACUNIT*4, FRACUNIT/2}, + {FRACUNIT*8, FRACUNIT/4}, + {FRACUNIT*4, FRACUNIT/2}, }; static void K_drawTrickCool(void) { tic_t timer = TICRATE - stplyr->karthud[khud_trickcool]; - INT32 x = (BASEVIDWIDTH/2); - INT32 y = ((BASEVIDHEIGHT)/2)-10; - - // @TODO: fix this shit - /*if (r_splitscreen > 2) // 4p split - { - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) - { - x /= 2; - y /= 2; - } - else - { - x /= 2 + BASEVIDWIDTH/2; - y /= 2 + BASEVIDHEIGHT/2; - } - }*/ if (timer <= 6) { - V_DrawStretchyFixedPatch(x<mo->x, player->mo->y) + ANG1*90; // horizontal angle - angle_t vang = -FixedAngle(momz)*12 + (ANG1*45); // vertical angle... arbitrary rotation speed for now. - fixed_t dist = FixedMul(max(MINRADIUS<mo->scale); // distance. + angle_t hang = R_PointToAnglePlayer(player, player->mo->x, player->mo->y) + ANG1*90; // horizontal angle + angle_t vang = -FixedAngle(momz)*12 + (ANG1*45); // vertical angle dependant on momz, we want it to line up at 45 degrees at the perfect frame to trick at + fixed_t dist = FixedMul(max(MINRADIUS<mo->scale); // distance. UINT8 i; - //CONS_Printf("a\n"); - // Do you like trig? cool, me neither. for (i=0; i < 2; i++) { - //CONS_Printf("%d\n", i); pos = FixedMul(dist, FINESINE(vang>>ANGLETOFINESHIFT)); tx = player->mo->x + FixedMul(pos, FINECOSINE(hang>>ANGLETOFINESHIFT)); ty = player->mo->y + FixedMul(pos, FINESINE(hang>>ANGLETOFINESHIFT)); @@ -8190,7 +8185,8 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) if (player->trickpanel > 1) // we tricked { - // Send the thing outwards via ghetto maths + // Send the thing outwards via ghetto maths which involves redoing the whole 3d sphere again, witht the "vertical" angle shifted by 90 degrees. + // There's probably a simplier way to do this the way I want to but this works. pos = FixedMul(48*player->mo->scale, FINESINE((vang +ANG1*90)>>ANGLETOFINESHIFT)); tx = player->mo->x + FixedMul(pos, FINECOSINE(hang>>ANGLETOFINESHIFT)); ty = player->mo->y + FixedMul(pos, FINESINE(hang>>ANGLETOFINESHIFT)); @@ -8200,7 +8196,7 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) flame->momy = ty -player->mo->y; flame->momz = tz -(player->mo->z+player->mo->height/2); } - else // we failed the trick. + else // we failed the trick, drop the half circles, it'll be funny I promise. { flame->flags &= ~MF_NOGRAVITY; P_SetObjectMomZ(flame, 4<x; + refy = cam->y; + + // Now do whatever tehe fuck is this hellish maths from R_PointToAngle while swapping viewx/viewy for our refx/refy + return (y -= refy, (x -= refx) || y) ? + x >= 0 ? + y >= 0 ? + (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 + ANGLE_90-tantoangle[SlopeDiv(x,y)] : // octant 1 + x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8 + ANGLE_270+tantoangle[SlopeDiv(x,y)] : // octant 7 + y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] : // octant 3 + ANGLE_90 + tantoangle[SlopeDiv(x,y)] : // octant 2 + (x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] : // octant 4 + ANGLE_270-tantoangle[SlopeDiv(x,y)] : // octant 5 + 0; +} + // This version uses 64-bit variables to avoid overflows with large values. // Currently used only by OpenGL rendering. angle_t R_PointToAngle64(INT64 x, INT64 y) diff --git a/src/r_main.h b/src/r_main.h index 49e028149..5208b52a3 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -63,6 +63,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node); INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line); angle_t R_PointToAngle(fixed_t x, fixed_t y); +angle_t R_PointToAnglePlayer(player_t *player, fixed_t x, fixed_t y); angle_t R_PointToAngle64(INT64 x, INT64 y); angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1); From 47a95efa6b6d1ea0e65abc7a07875b08f6e1324e Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 24 Apr 2021 14:49:41 +0200 Subject: [PATCH 17/21] push R_PointToAnlePlayer to Lua, might be super useful for it. --- src/lua_baselib.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index abf0224d2..9e1c909f5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2098,6 +2098,16 @@ static int lib_rPointToAngle(lua_State *L) return 1; } +static int lib_rPointToAnglePlayer(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + //HUDSAFE + lua_pushangle(L, R_PointToAnglePlayer(player, x, y)); + return 1; +} + static int lib_rPointToAngle2(lua_State *L) { fixed_t px2 = luaL_checkfixed(L, 1); @@ -3876,6 +3886,7 @@ static luaL_Reg lib[] = { // r_defs {"R_PointToAngle",lib_rPointToAngle}, + {"R_PointToAnglePlayer", lib_rPointToAnglePlayer}, {"R_PointToAngle2",lib_rPointToAngle2}, {"R_PointToDist",lib_rPointToDist}, {"R_PointToDist2",lib_rPointToDist2}, From 0f14f0cec1d42dea9aa49562c0910598347b4b8a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 26 Apr 2021 04:09:23 -0400 Subject: [PATCH 18/21] Only check for listenmobj for the splitscreen players Steel's comment is what hinted me to compare the code again -- P1 was the only one who didn't care about their listenmobj existing first. --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 8979d1fc9..c4d27e479 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -635,7 +635,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) for (i = r_splitscreen; i >= 0; i--) { // Copy the sound for the splitscreen players! - if (!listenmobj[i]) + if (listenmobj[i] == NULL && i != 0) { continue; } From 710abf68206767c84fa63beef80f798bf0c9d8fe Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 27 Apr 2021 21:27:42 +0100 Subject: [PATCH 19/21] Fix sound crash, let a sound be played for multiple players again too. S_getChannel now doesn't do any alterations to the channel, it *only* returns the number of the free channel. --- src/s_sound.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index c4d27e479..71e97c27b 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -183,8 +183,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) // channel number to use INT32 cnum; - channel_t *c; - // Find an open channel for (cnum = 0; cnum < numofchannels; cnum++) { @@ -239,12 +237,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) } } - c = &channels[cnum]; - - // channel is decided to be cnum. - c->sfxinfo = sfxinfo; - c->origin = origin; - return cnum; } @@ -624,14 +616,6 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) pitch = NORM_PITCH; priority = NORM_PRIORITY; - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - { - return; // If there's no free channels, it's not gonna be free for anyone. - } - for (i = r_splitscreen; i >= 0; i--) { // Copy the sound for the splitscreen players! @@ -697,11 +681,19 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) // Handle closed caption input. S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); - // Assigns the handle to one of the channels in the - // mix/output buffer. + // At this point it is determined that a sound can and should be played, so find a free channel to play it on + cnum = S_getChannel(origin, sfx); + + if (cnum < 0) + { + return; // If there's no free channels, there won't be any for anymore players either + } + + // Now that we know we are going to play a sound, fill out this info + channels[cnum].sfxinfo = sfx; + channels[cnum].origin = origin; channels[cnum].volume = initial_volume; channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); - return; // We're done here! } } @@ -905,7 +897,7 @@ void S_UpdateSounds(void) c->sfxinfo ); } - + if (audible) I_UpdateSoundParams(c->handle, volume, sep, pitch); else From 82fa8755027ff3a6485740909b207ecb5c2fe5c7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 12 Jun 2021 00:56:55 -0400 Subject: [PATCH 20/21] Refactor R_PointToAnglePlayer --- src/r_main.c | 58 ++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 97d946876..dfc11ab4a 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -318,18 +318,7 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) angle_t R_PointToAngle(fixed_t x, fixed_t y) { - return (y -= viewy, (x -= viewx) || y) ? - x >= 0 ? - y >= 0 ? - (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 - ANGLE_90-tantoangle[SlopeDiv(x,y)] : // octant 1 - x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8 - ANGLE_270+tantoangle[SlopeDiv(x,y)] : // octant 7 - y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] : // octant 3 - ANGLE_90 + tantoangle[SlopeDiv(x,y)] : // octant 2 - (x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] : // octant 4 - ANGLE_270-tantoangle[SlopeDiv(x,y)] : // octant 5 - 0; + return R_PointToAngle2(viewx, viewy, x, y); } // Similar to R_PointToAngle, but requires an additional player_t argument. @@ -338,33 +327,26 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y) angle_t R_PointToAnglePlayer(player_t *player, fixed_t x, fixed_t y) { fixed_t refx = viewx, refy = viewy; - camera_t *cam = &camera[0]; - - // Check for splitscreen players and get their cam if possible. - if (player == &players[displayplayers[1]]) - cam = &camera[1]; - else if (player == &players[displayplayers[2]]) - cam = &camera[2]; - else if (player == &players[displayplayers[3]]) - cam = &camera[3]; - + camera_t *cam = NULL; + UINT8 i; + + for (i = 0; i < r_splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + { + cam = &camera[i]; + break; + } + } + // use whatever cam we found's coordinates. - refx = cam->x; - refy = cam->y; - - // Now do whatever tehe fuck is this hellish maths from R_PointToAngle while swapping viewx/viewy for our refx/refy - return (y -= refy, (x -= refx) || y) ? - x >= 0 ? - y >= 0 ? - (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 - ANGLE_90-tantoangle[SlopeDiv(x,y)] : // octant 1 - x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8 - ANGLE_270+tantoangle[SlopeDiv(x,y)] : // octant 7 - y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] : // octant 3 - ANGLE_90 + tantoangle[SlopeDiv(x,y)] : // octant 2 - (x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] : // octant 4 - ANGLE_270-tantoangle[SlopeDiv(x,y)] : // octant 5 - 0; + if (cam != NULL) + { + refx = cam->x; + refy = cam->y; + } + + return R_PointToAngle2(refx, refy, x, y); } // This version uses 64-bit variables to avoid overflows with large values. From 4eee8ab1d7447d0c7495ce8d1ce6b2a73ce80e6d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 12 Jun 2021 02:15:00 -0400 Subject: [PATCH 21/21] Fix tilting in splitscreen R_GetPitchRollAngle used R_PointToAngle. This was fine because it was meant for rendering code. However tilting does its code mostly in player thinker, and it also uses this function, so it was not fine -- it would have some remainder tilt settings from the last player's screen. --- src/p_user.c | 2 +- src/r_patch.h | 6 ++++-- src/r_patchrotation.c | 14 +++++++------- src/r_things.c | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index fc04f5af8..d577faab2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4103,7 +4103,7 @@ DoABarrelRoll (player_t *player) return; } - slope = InvAngle(R_GetPitchRollAngle(player->mo)); + slope = InvAngle(R_GetPitchRollAngle(player->mo, player)); if (AbsAngle(slope) < ANGLE_11hh) { diff --git a/src/r_patch.h b/src/r_patch.h index c6d222617..601144a1d 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -15,6 +15,7 @@ #include "r_defs.h" #include "r_picformats.h" #include "doomdef.h" +#include "d_player.h" // Patch functions patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); @@ -38,9 +39,10 @@ patch_t *Patch_GetRotatedSprite( size_t frame, size_t spriteangle, boolean flip, boolean adjustfeet, void *info, INT32 rotationangle); + INT32 R_GetRollAngle(angle_t rollangle); -angle_t R_GetPitchRollAngle(mobj_t *mobj); -angle_t R_SpriteRotationAngle(mobj_t *mobj); +angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer); +angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer); #endif #endif // __R_PATCH__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 096b678ea..3744dfce2 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -21,9 +21,9 @@ fixed_t rollcosang[ROTANGLES]; fixed_t rollsinang[ROTANGLES]; -angle_t R_GetPitchRollAngle(mobj_t *mobj) +angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer) { - angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y); + angle_t viewingAngle = R_PointToAnglePlayer(viewPlayer, mobj->x, mobj->y); fixed_t pitchMul = -FINESINE(viewingAngle >> ANGLETOFINESHIFT); fixed_t rollMul = FINECOSINE(viewingAngle >> ANGLETOFINESHIFT); @@ -33,9 +33,9 @@ angle_t R_GetPitchRollAngle(mobj_t *mobj) return rollOrPitch; } -static angle_t R_PlayerSpriteRotation(player_t *player) +static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer) { - angle_t viewingAngle = R_PointToAngle(player->mo->x, player->mo->y); + angle_t viewingAngle = R_PointToAnglePlayer(viewPlayer, player->mo->x, player->mo->y); angle_t angleDelta = (viewingAngle - player->mo->angle); angle_t sliptideLift = player->aizdrifttilt; @@ -60,14 +60,14 @@ static angle_t R_PlayerSpriteRotation(player_t *player) return rollAngle; } -angle_t R_SpriteRotationAngle(mobj_t *mobj) +angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) { - angle_t rollOrPitch = R_GetPitchRollAngle(mobj); + angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer); angle_t rollAngle = (rollOrPitch + mobj->rollangle); if (mobj->player) { - rollAngle += R_PlayerSpriteRotation(mobj->player); + rollAngle += R_PlayerSpriteRotation(mobj->player, viewPlayer); } return rollAngle; diff --git a/src/r_things.c b/src/r_things.c index ce62b0ad6..21e0228a3 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1574,7 +1574,7 @@ static void R_ProjectSprite(mobj_t *thing) patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); #ifdef ROTSPRITE - spriterotangle = R_SpriteRotationAngle(thing); + spriterotangle = R_SpriteRotationAngle(thing, NULL); if (spriterotangle && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))