From 2caea74cba7fd4e98a0b36f0d8068d5c5ac6604d Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 21 May 2025 02:05:33 -0400 Subject: [PATCH 1/6] Teamplay HUD --- src/k_hud.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 8a1bd177e..11bdd4d56 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -229,6 +229,11 @@ static patch_t *kp_voice_remotemuted; static patch_t *kp_voice_remotedeafened; static patch_t *kp_voice_tagactive[3]; +static patch_t *kp_team_bar; +static patch_t *kp_team_sticker; +static patch_t *kp_team_underlay[2]; +static patch_t *kp_team_you; + patch_t *kp_autoroulette; patch_t *kp_autoring; @@ -1044,6 +1049,12 @@ void K_LoadKartHUDGraphics(void) { HU_UpdatePatch(&kp_voice_tagactive[i], "VOXCTA%d", i); } + + HU_UpdatePatch(&kp_team_bar, "TEAM_B"); + HU_UpdatePatch(&kp_team_sticker, "TEAM_S"); + HU_UpdatePatch(&kp_team_underlay[0], "TEAM_UL"); + HU_UpdatePatch(&kp_team_underlay[1], "TEAM_UR"); + HU_UpdatePatch(&kp_team_you, "TEAM_YOU"); } // For the item toggle menu @@ -3219,6 +3230,149 @@ static void K_drawKartTeamScores(void) return; } + if (TEAM__MAX != 3) + return; // "maybe someday" - the magic conch + + // I get to write HUD code from scratch, so it's going to be horribly + // verbose and obnoxious. + + INT32 basex = BASEVIDWIDTH/2 + 20; + INT32 basey = 0; + INT32 flags = V_HUDTRANS|V_SLIDEIN; + INT32 snapflags = V_SNAPTORIGHT|V_SNAPTOTOP; + + // bar stuff, relative to base + INT32 barwidth = 124; + INT32 barheight = 4; + INT32 barx = 58; + INT32 bary = -8; + + // team score stuff, relative to base + INT32 scorex = 67; + INT32 scorey = 20; + INT32 scoregap = 8; + INT32 scoreoffset = 1; + + // your score, relative to base + INT32 youx = 108; + INT32 youy = 26; // youy you arrive at the rising sus + + UINT8 allies = stplyr->team; + UINT8 enemies = (allies == TEAM_ORANGE) ? TEAM_BLUE : TEAM_ORANGE; + + UINT8 *allycolor = R_GetTranslationColormap(TC_RAINBOW, g_teaminfo[allies].color, GTC_CACHE); + UINT8 *enemycolor = R_GetTranslationColormap(TC_RAINBOW, g_teaminfo[enemies].color, GTC_CACHE); + + UINT16 allyscore = g_teamscores[allies]; + UINT16 enemyscore = g_teamscores[enemies]; + UINT16 totalscore = allyscore + enemyscore; + + // minimap team leaders, relative to bars + INT32 facex = -56; + INT32 facey = 16; + INT32 faceoff = 7; + INT32 facesize = 2; + + UINT32 youscore = stplyr->teamimportance; + if (gametyperules & GTR_POINTLIMIT) + { + youscore = stplyr->roundscore; + } + + fixed_t enemypercent = FixedDiv(enemyscore*FRACUNIT, totalscore*FRACUNIT); + // fixed_t allypercent = FixedDiv(allyscore*FRACUNIT, totalscore*FRACUNIT); + INT32 enemywidth = FixedInt(FixedMul(enemypercent, barwidth*FRACUNIT)); + INT32 allywidth = barwidth - enemywidth; + + UINT8 ri = 6; + INT32 allyfill = skincolors[g_teaminfo[allies].color].ramp[ri]; + INT32 enemyfill = skincolors[g_teaminfo[enemies].color].ramp[ri]; + + INT32 winning = 0; + if (allyscore > enemyscore) + winning = 1; + else if (enemyscore > allyscore) + winning = -1; + + player_t *bestenemy = NULL; + INT32 bestenemyscore = -1; + player_t *bestally = NULL; + INT32 bestallyscore = -1; + + boolean useroundscore = false; + if (gametyperules & GTR_POINTLIMIT) + useroundscore = true; + + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].team == TEAM_UNASSIGNED) + continue; + + INT32 score = useroundscore ? players[i].roundscore : players[i].teamimportance; + + if (players[i].team == allies) + { + if (bestallyscore < score || (bestallyscore == score && useroundscore == false && players[i].teamposition < bestally->teamposition)) + { + bestallyscore = score; + bestally = &players[i]; + } + } + else + { + if (bestenemyscore < score || (bestenemyscore == score && useroundscore == false && players[i].teamposition < bestenemy->teamposition)) + { + bestenemyscore = score; + bestenemy = &players[i]; + } + } + } + + flags |= snapflags; + + V_DrawScaledPatch(basex, basey, flags, kp_team_sticker); + V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[0], enemycolor); + V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[1], allycolor); + V_DrawScaledPatch(basex, basey, flags, kp_team_bar); + V_DrawScaledPatch(basex, basey, flags, kp_team_you); + + if (V_GetHUDTranslucency(0) != 10) + return; + + V_DrawFill(basex+barx, basey+bary, enemywidth, barheight, enemyfill); + V_DrawFill(basex+barx+enemywidth, basey+bary, allywidth, barheight, allyfill); + + using srb2::Draw; + + Draw enemynum = Draw(basex+scorex-scoregap, basey+scorey).flags(flags).font(Draw::Font::kTimer).align(Draw::Align::kRight).colorize(g_teaminfo[enemies].color); + Draw allynum = Draw(basex+scorex+scoregap+scoreoffset, basey+scorey).flags(flags).font(Draw::Font::kTimer).align(Draw::Align::kLeft).colorize(g_teaminfo[allies].color); + enemynum.text("{:02}", enemyscore/2); + allynum.text("{:02}", allyscore/2); + + // Goofy, but we want the winning team to draw on top + boolean drawally = (allyscore < enemyscore); + for (UINT8 drew = 0; drew < 2; drew++) + { + if (bestenemy && !drawally) + { + UINT8 *colormap = R_GetTranslationColormap(bestenemy->skin, static_cast(bestenemy->skincolor), GTC_CACHE); + V_DrawMappedPatch(basex+barx+facex+enemywidth-faceoff-facesize, basey+bary+facey, flags, faceprefix[bestenemy->skin][FACE_MINIMAP], colormap); + } + + if (bestally && drawally) + { + UINT8 *colormap = R_GetTranslationColormap(bestally->skin, static_cast(bestally->skincolor), GTC_CACHE); + V_DrawMappedPatch(basex+barx+facex+enemywidth+facesize, basey+bary+facey, flags, faceprefix[bestally->skin][FACE_MINIMAP], colormap); + } + + drawally = !drawally; + } + + Draw you = Draw(basex+youx, basey+youy).flags(flags).font(Draw::Font::kZVote).colorize(g_teaminfo[allies].color); + you.text("{:02}", youscore/2); + + + /* for (INT32 i = TEAM_UNASSIGNED+1; i < TEAM__MAX; i++) { INT32 x = BASEVIDWIDTH/2; @@ -3238,6 +3392,7 @@ static void K_drawKartTeamScores(void) V_DrawCenteredString(x, 15, g_teaminfo[i].chat_color, va("+%d", individual_score)); } } + */ } static boolean K_drawKartLaps(void) From f0bcc82f901596153613492dca771bb40bd2865a Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 21 May 2025 16:49:51 -0400 Subject: [PATCH 2/6] go go gadget teamplay --- src/d_clisrv.c | 2 +- src/k_hud.cpp | 233 ++++++++++++++++++++++++++++++++++++++----------- src/k_kart.c | 4 +- src/p_inter.c | 15 ++++ src/p_spec.c | 14 +++ 5 files changed, 217 insertions(+), 51 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 33e9dceaa..bc0f899e5 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -7431,7 +7431,7 @@ void NetVoiceUpdate(void) switch (cv_voice_mode.value) { case 0: - if (I_GetTime() - g_local_voice_threshold_time > 15) + i_GetTime() - g_local_voice_threshold_time > 15) { g_local_voice_buffer_len = 0; g_local_voice_detected = false; diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 11bdd4d56..4fb412a1f 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -229,9 +229,10 @@ static patch_t *kp_voice_remotemuted; static patch_t *kp_voice_remotedeafened; static patch_t *kp_voice_tagactive[3]; -static patch_t *kp_team_bar; -static patch_t *kp_team_sticker; -static patch_t *kp_team_underlay[2]; +static patch_t *kp_team_bar[2]; +static patch_t *kp_team_sticker[2]; +static patch_t *kp_team_underlay[2][2]; +static patch_t *kp_team_minihead; static patch_t *kp_team_you; patch_t *kp_autoroulette; @@ -1050,10 +1051,15 @@ void K_LoadKartHUDGraphics(void) HU_UpdatePatch(&kp_voice_tagactive[i], "VOXCTA%d", i); } - HU_UpdatePatch(&kp_team_bar, "TEAM_B"); - HU_UpdatePatch(&kp_team_sticker, "TEAM_S"); - HU_UpdatePatch(&kp_team_underlay[0], "TEAM_UL"); - HU_UpdatePatch(&kp_team_underlay[1], "TEAM_UR"); + HU_UpdatePatch(&kp_team_bar[0], "TEAM_B"); + HU_UpdatePatch(&kp_team_sticker[0], "TEAM_S"); + HU_UpdatePatch(&kp_team_bar[1], "TEAM4B"); + HU_UpdatePatch(&kp_team_sticker[1], "TEAM4S"); + HU_UpdatePatch(&kp_team_underlay[0][0], "TEAM_UL"); + HU_UpdatePatch(&kp_team_underlay[0][1], "TEAM_UR"); + HU_UpdatePatch(&kp_team_underlay[1][0], "TEAM4UL"); + HU_UpdatePatch(&kp_team_underlay[1][1], "TEAM4UR"); + HU_UpdatePatch(&kp_team_minihead, "TEAM4H"); HU_UpdatePatch(&kp_team_you, "TEAM_YOU"); } @@ -3223,6 +3229,12 @@ INT32 K_GetTransFlagFromFixed(fixed_t value) } } +static INT32 easedallyscore = 0; +static tic_t scorechangecooldown = 0; +// Mildly ugly. Don't want to export this to khud when it's so nicely handled here, +// but HUD hooks run at variable timing based on your actual framerate. +static tic_t lastleveltime = 0; + static void K_drawKartTeamScores(void) { if (G_GametypeHasTeams() == false) @@ -3236,16 +3248,21 @@ static void K_drawKartTeamScores(void) // I get to write HUD code from scratch, so it's going to be horribly // verbose and obnoxious. + UINT8 use4p = (r_splitscreen > 1) ? 1 : 0; + INT32 basex = BASEVIDWIDTH/2 + 20; INT32 basey = 0; INT32 flags = V_HUDTRANS|V_SLIDEIN; - INT32 snapflags = V_SNAPTORIGHT|V_SNAPTOTOP; + INT32 snapflags = V_SNAPTOTOP|V_SNAPTORIGHT; + if (use4p) + snapflags = V_SNAPTOTOP; + flags |= snapflags; // bar stuff, relative to base INT32 barwidth = 124; INT32 barheight = 4; - INT32 barx = 58; - INT32 bary = -8; + INT32 barx = 5; // 58 + INT32 bary = 12; // -8 // team score stuff, relative to base INT32 scorex = 67; @@ -3257,6 +3274,30 @@ static void K_drawKartTeamScores(void) INT32 youx = 108; INT32 youy = 26; // youy you arrive at the rising sus + // minimap team leaders, relative to BARS + INT32 facex = -4; + INT32 facey = -4; + INT32 faceoff = 7; + INT32 facesize = 2; + + if (use4p) + { + basex = 127; + basey = 5; + + barwidth = 62; + barheight = 2; + barx = 2; + bary = 6; + + scorex = 33; + scorey = 10; + scoregap = 2; + + facey = -5; + faceoff = 4; + } + UINT8 allies = stplyr->team; UINT8 enemies = (allies == TEAM_ORANGE) ? TEAM_BLUE : TEAM_ORANGE; @@ -3267,11 +3308,26 @@ static void K_drawKartTeamScores(void) UINT16 enemyscore = g_teamscores[enemies]; UINT16 totalscore = allyscore + enemyscore; - // minimap team leaders, relative to bars - INT32 facex = -56; - INT32 facey = 16; - INT32 faceoff = 7; - INT32 facesize = 2; + using srb2::Draw; + srb2::Draw::Font scorefont = Draw::Font::kTimer; + + if (totalscore > 99) + { + scorefont = Draw::Font::kThinTimer; + scoreoffset--; + } + + if (use4p) + { + if (totalscore > 99) + { + scorefont = Draw::Font::kPing; + } + else + { + scorefont = Draw::Font::kZVote; + } + } UINT32 youscore = stplyr->teamimportance; if (gametyperules & GTR_POINTLIMIT) @@ -3279,12 +3335,7 @@ static void K_drawKartTeamScores(void) youscore = stplyr->roundscore; } - fixed_t enemypercent = FixedDiv(enemyscore*FRACUNIT, totalscore*FRACUNIT); - // fixed_t allypercent = FixedDiv(allyscore*FRACUNIT, totalscore*FRACUNIT); - INT32 enemywidth = FixedInt(FixedMul(enemypercent, barwidth*FRACUNIT)); - INT32 allywidth = barwidth - enemywidth; - - UINT8 ri = 6; + UINT8 ri = 6; // "ramp index", picks drawfill color from team skincolors INT32 allyfill = skincolors[g_teaminfo[allies].color].ramp[ri]; INT32 enemyfill = skincolors[g_teaminfo[enemies].color].ramp[ri]; @@ -3294,6 +3345,54 @@ static void K_drawKartTeamScores(void) else if (enemyscore > allyscore) winning = -1; + UINT8 *winnercolor = (winning == 1) ? + R_GetTranslationColormap(TC_RAINBOW, g_teaminfo[allies].color, GTC_CACHE) : + R_GetTranslationColormap(TC_RAINBOW, g_teaminfo[enemies].color, GTC_CACHE); + + if (scorechangecooldown) + scorechangecooldown--; + + // prevent giga flicker on team scoring + if (easedallyscore == allyscore) + { + // :O + } + else + { + if (lastleveltime != leveltime) // Timing consistency + { + INT32 delta = abs(easedallyscore - allyscore); // how wrong is display score? + + if (scorechangecooldown == 0) + { + if (allyscore > easedallyscore) + { + easedallyscore++; + if (!cv_reducevfx.value) + allycolor = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_WHITE, GTC_CACHE); + } + else + { + easedallyscore--; + if (!cv_reducevfx.value) + enemycolor = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_WHITE, GTC_CACHE); + } + scorechangecooldown = TICRATE/delta; + } + } + + // replace scores with eased scores + allyscore = easedallyscore; + enemyscore = totalscore - allyscore; + } + + lastleveltime = leveltime; + + fixed_t enemypercent = FixedDiv(enemyscore*FRACUNIT, totalscore*FRACUNIT); + // fixed_t allypercent = FixedDiv(allyscore*FRACUNIT, totalscore*FRACUNIT); + INT32 enemywidth = FixedInt(FixedMul(enemypercent, barwidth*FRACUNIT)); + INT32 allywidth = barwidth - enemywidth; + player_t *bestenemy = NULL; INT32 bestenemyscore = -1; player_t *bestally = NULL; @@ -3328,49 +3427,85 @@ static void K_drawKartTeamScores(void) } } - flags |= snapflags; + // Draw at the top and bottom of the screen in 4P. + boolean goagain = use4p; - V_DrawScaledPatch(basex, basey, flags, kp_team_sticker); - V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[0], enemycolor); - V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[1], allycolor); - V_DrawScaledPatch(basex, basey, flags, kp_team_bar); - V_DrawScaledPatch(basex, basey, flags, kp_team_you); + draw: + + V_DrawScaledPatch(basex, basey, flags, kp_team_sticker[use4p]); + V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[use4p][0], enemycolor); + V_DrawMappedPatch(basex, basey, flags, kp_team_underlay[use4p][1], allycolor); + V_DrawMappedPatch(basex, basey, flags, kp_team_bar[use4p], winnercolor); + if (!use4p) + V_DrawScaledPatch(basex, basey, flags, kp_team_you); if (V_GetHUDTranslucency(0) != 10) return; - V_DrawFill(basex+barx, basey+bary, enemywidth, barheight, enemyfill); - V_DrawFill(basex+barx+enemywidth, basey+bary, allywidth, barheight, allyfill); - - using srb2::Draw; - - Draw enemynum = Draw(basex+scorex-scoregap, basey+scorey).flags(flags).font(Draw::Font::kTimer).align(Draw::Align::kRight).colorize(g_teaminfo[enemies].color); - Draw allynum = Draw(basex+scorex+scoregap+scoreoffset, basey+scorey).flags(flags).font(Draw::Font::kTimer).align(Draw::Align::kLeft).colorize(g_teaminfo[allies].color); - enemynum.text("{:02}", enemyscore/2); - allynum.text("{:02}", allyscore/2); + V_DrawFill(basex+barx, basey+bary, enemywidth, barheight, enemyfill|flags); + V_DrawFill(basex+barx+enemywidth, basey+bary, allywidth, barheight, allyfill|flags); // Goofy, but we want the winning team to draw on top - boolean drawally = (allyscore < enemyscore); + boolean drawally = (winning != 1); for (UINT8 drew = 0; drew < 2; drew++) { - if (bestenemy && !drawally) + if (use4p) { - UINT8 *colormap = R_GetTranslationColormap(bestenemy->skin, static_cast(bestenemy->skincolor), GTC_CACHE); - V_DrawMappedPatch(basex+barx+facex+enemywidth-faceoff-facesize, basey+bary+facey, flags, faceprefix[bestenemy->skin][FACE_MINIMAP], colormap); + if (bestenemy && !drawally) + { + V_DrawMappedPatch(basex+barx+facex+enemywidth-facesize+faceoff, basey+bary+facey, flags|V_FLIP, kp_team_minihead, enemycolor); + } + if (bestally && drawally) + { + V_DrawMappedPatch(basex+barx+facex+enemywidth+facesize, basey+bary+facey, flags, kp_team_minihead, allycolor); + } + } + else + { + if (bestenemy && !drawally) + { + UINT8 *colormap = R_GetTranslationColormap(bestenemy->skin, static_cast(bestenemy->skincolor), GTC_CACHE); + V_DrawMappedPatch(basex+barx+facex+enemywidth-facesize+faceoff, basey+bary+facey, flags|V_FLIP, faceprefix[bestenemy->skin][FACE_MINIMAP], colormap); + } + if (bestally && drawally) + { + UINT8 *colormap = R_GetTranslationColormap(bestally->skin, static_cast(bestally->skincolor), GTC_CACHE); + V_DrawMappedPatch(basex+barx+facex+enemywidth+facesize, basey+bary+facey, flags, faceprefix[bestally->skin][FACE_MINIMAP], colormap); + } } - if (bestally && drawally) - { - UINT8 *colormap = R_GetTranslationColormap(bestally->skin, static_cast(bestally->skincolor), GTC_CACHE); - V_DrawMappedPatch(basex+barx+facex+enemywidth+facesize, basey+bary+facey, flags, faceprefix[bestally->skin][FACE_MINIMAP], colormap); - } drawally = !drawally; } - Draw you = Draw(basex+youx, basey+youy).flags(flags).font(Draw::Font::kZVote).colorize(g_teaminfo[allies].color); - you.text("{:02}", youscore/2); + Draw enemynum = Draw(basex+scorex-scoregap, basey+scorey).flags(flags).font(scorefont).align(Draw::Align::kRight).colorize(g_teaminfo[enemies].color); + Draw allynum = Draw(basex+scorex+scoregap+scoreoffset, basey+scorey).flags(flags).font(scorefont).align(Draw::Align::kLeft).colorize(g_teaminfo[allies].color); + if (totalscore > 99) + { + enemynum.text("{:03}", enemyscore); + allynum.text("{:03}", allyscore); + } + else + { + enemynum.text("{:02}", enemyscore); + allynum.text("{:02}", allyscore); + } + + if (!use4p) + { + Draw you = Draw(basex+youx, basey+youy).flags(flags).font(Draw::Font::kZVote).colorize(g_teaminfo[allies].color); + you.text("{:02}", youscore); + } + + if (goagain) + { + goagain = false; + flags |= V_SNAPTOBOTTOM; + flags &= ~V_SNAPTOTOP; + basey = 170; + goto draw; + } /* for (INT32 i = TEAM_UNASSIGNED+1; i < TEAM__MAX; i++) @@ -7012,7 +7147,7 @@ void K_drawKartHUD(void) if (r_splitscreen == 1) { - if (LUA_HudEnabled(hud_time)) + if (LUA_HudEnabled(hud_time) && ((gametyperules & GTR_TIMELIMIT) || cv_drawtimer.value)) { K_drawKart2PTimestamp(); } @@ -7024,7 +7159,7 @@ void K_drawKartHUD(void) } else if (viewnum == r_splitscreen) { - if (LUA_HudEnabled(hud_time)) + if (LUA_HudEnabled(hud_time) && ((gametyperules & GTR_TIMELIMIT) || cv_drawtimer.value)) { K_drawKart4PTimestamp(); } diff --git a/src/k_kart.c b/src/k_kart.c index 7ccf885d5..154fa3f49 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4147,7 +4147,9 @@ void K_SpawnAmps(player_t *player, UINT8 amps, mobj_t *impact) scaledamps /= 2; */ - for (int i = 0; i < (scaledamps/2); i++) + UINT16 finalreward = max(1, scaledamps/2); + + for (int i = 0; i < finalreward; i++) { mobj_t *pickup = P_SpawnMobj(impact->x, impact->y, impact->z, MT_AMPS); pickup->momx = P_RandomRange(PR_ITEM_DEBRIS, -40*mapobjectscale, 40*mapobjectscale); diff --git a/src/p_inter.c b/src/p_inter.c index 6d83c4a8f..5f9034eb9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3209,6 +3209,21 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_SpawnAmps(source->player, K_PvPAmpReward((type == DMG_WHUMBLE) ? 30 : 20, source->player, player), target); K_BotHitPenalty(player); + if (g_teamplay) + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || !players[i].mo || P_MobjWasRemoved(players[i].mo)) + continue; + if (!G_SameTeam(source->player, &players[i])) + continue; + if (source->player == &players[i]) + continue; + K_SpawnAmps(&players[i], 5, target); + } + } + + // Extend the invincibility if the hit was a direct hit. if (inflictor == source && source->player->invincibilitytimer && !K_PowerUpRemaining(source->player, POWERUP_SMONITOR)) diff --git a/src/p_spec.c b/src/p_spec.c index db4cc3d4e..5c80fc35f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2071,6 +2071,20 @@ static void K_HandleLapIncrement(player_t *player) K_SpawnDriftElectricSparks(player, SKINCOLOR_SILVER, false); K_SpawnAmps(player, 35, player->mo); + if (g_teamplay) + { + for (UINT8 j = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[j] || players[j].spectator || !players[j].mo || P_MobjWasRemoved(players[j].mo)) + continue; + if (!G_SameTeam(player, &players[j])) + continue; + if (player == &players[j]) + continue; + K_SpawnAmps(&players[j], 10, player->mo); + } + } + rainbowstartavailable = false; } From bf2f9a9898cf61a2fbc068a93c5d4c2efd3ecd26 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 21 May 2025 17:39:33 -0400 Subject: [PATCH 3/6] What the fuck? --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bc0f899e5..33e9dceaa 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -7431,7 +7431,7 @@ void NetVoiceUpdate(void) switch (cv_voice_mode.value) { case 0: - i_GetTime() - g_local_voice_threshold_time > 15) + if (I_GetTime() - g_local_voice_threshold_time > 15) { g_local_voice_buffer_len = 0; g_local_voice_detected = false; From a6f76db0fa2dc63674c6efd1f634140f006e6f76 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 21 May 2025 18:54:24 -0400 Subject: [PATCH 4/6] Fixed misaligned arrows in 4P team hud --- src/k_hud.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 4fb412a1f..8d527e7c0 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3294,6 +3294,7 @@ static void K_drawKartTeamScores(void) scorey = 10; scoregap = 2; + facex = -2; facey = -5; faceoff = 4; } @@ -3389,6 +3390,7 @@ static void K_drawKartTeamScores(void) lastleveltime = leveltime; fixed_t enemypercent = FixedDiv(enemyscore*FRACUNIT, totalscore*FRACUNIT); + enemypercent = FRACUNIT/2; // fixed_t allypercent = FixedDiv(allyscore*FRACUNIT, totalscore*FRACUNIT); INT32 enemywidth = FixedInt(FixedMul(enemypercent, barwidth*FRACUNIT)); INT32 allywidth = barwidth - enemywidth; From b2d9e081b2f7950c81c5e815b6f15833cabd6183 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 21 May 2025 18:55:49 -0400 Subject: [PATCH 5/6] Remove testing visuals --- src/k_hud.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 8d527e7c0..616861b37 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3390,7 +3390,6 @@ static void K_drawKartTeamScores(void) lastleveltime = leveltime; fixed_t enemypercent = FixedDiv(enemyscore*FRACUNIT, totalscore*FRACUNIT); - enemypercent = FRACUNIT/2; // fixed_t allypercent = FixedDiv(allyscore*FRACUNIT, totalscore*FRACUNIT); INT32 enemywidth = FixedInt(FixedMul(enemypercent, barwidth*FRACUNIT)); INT32 allywidth = barwidth - enemywidth; From bd250e34c8b3a0d37890cc87ed79769eff0d9c13 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Thu, 22 May 2025 00:32:14 -0400 Subject: [PATCH 6/6] Teamplay gameplay refinements --- src/k_kart.c | 35 +++++++++++++++++++++++++++++++++++ src/k_kart.h | 2 ++ src/p_inter.c | 9 +++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 154fa3f49..0371c1134 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1478,6 +1478,9 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed return false; } + if (dest->player && G_SameTeam(player, dest->player)) + draftdistance = FixedMul(draftdistance, K_TeamComebackMultiplier(player)); + // Not close enough to draft. if (dist > draftdistance && draftdistance > 0) { @@ -15505,6 +15508,9 @@ fixed_t K_GetGradingMultAdjustment(player_t *player) fixed_t stablerate = 3*FRACUNIT/10; // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain fixed_t result = 0; + if (g_teamplay) + power = 3 * power / 4; + INT32 live_players = 0; // players we are competing against for (INT32 i = 0; i < MAXPLAYERS; i++) @@ -15716,4 +15722,33 @@ boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2) return true; } +fixed_t K_TeamComebackMultiplier(player_t *player) +{ + INT32 myteam = player->team; + INT32 theirteam = (myteam == TEAM_ORANGE) ? TEAM_BLUE : TEAM_ORANGE; + + if (g_teamscores[myteam] >= g_teamscores[theirteam]) + return FRACUNIT; + + UINT32 ourdistance = 0; + UINT32 theirdistance = 0; + + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (players[i].team == myteam) + ourdistance += K_GetItemRouletteDistance(&players[i], players[i].itemRoulette.playing); + else + theirdistance += K_GetItemRouletteDistance(&players[i], players[i].itemRoulette.playing); + } + + fixed_t multiplier = FixedDiv(ourdistance, theirdistance); + multiplier = min(multiplier, 3*FRACUNIT); + multiplier = max(multiplier, FRACUNIT); + + return multiplier; +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index ccc32c6f9..cd5dee152 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -322,6 +322,8 @@ void K_BotHitPenalty(player_t *player); boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2); +fixed_t K_TeamComebackMultiplier(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_inter.c b/src/p_inter.c index 5f9034eb9..2df953dec 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3209,7 +3209,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_SpawnAmps(source->player, K_PvPAmpReward((type == DMG_WHUMBLE) ? 30 : 20, source->player, player), target); K_BotHitPenalty(player); - if (g_teamplay) + if (G_SameTeam(source->player, player)) + { + if (type != DMG_EXPLODE) + type = DMG_STUMBLE; + } + else { for (UINT8 i = 0; i < MAXPLAYERS; i++) { @@ -3219,7 +3224,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da continue; if (source->player == &players[i]) continue; - K_SpawnAmps(&players[i], 5, target); + K_SpawnAmps(&players[i], FixedInt(FixedMul(5, K_TeamComebackMultiplier(player))), target); } }