From 98bacdeafe93f898601ebb35b5e6626c20be613a Mon Sep 17 00:00:00 2001 From: eebrozgi Date: Wed, 18 Jun 2025 14:43:31 +0300 Subject: [PATCH 01/64] Splitscreen flatmap camera height 3/4 -> 5/6 The camera tilting upwards in motion was a bigger deal than I originally noticed; splitscreen camera height adjusted accordingly. --- src/p_spec.c | 2 +- src/p_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index ca923d809..713dc2719 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9666,7 +9666,7 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) // For 2p SPLITSCREEN SPECIFICALLY: // The view is pretty narrow, so move it back 1/4th of the way towards default camera height. else - maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*3 + cv_cam_height[view].value)/4, mapobjectscale) * 3 / 4; + maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*5 + cv_cam_height[view].value)/6, mapobjectscale) * 3 / 4; } if (battle) diff --git a/src/p_user.c b/src/p_user.c index a7753235e..78b0d17c8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3386,7 +3386,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // The view is pretty narrow, so move it back 1/4th of the way towards default camera height. else { // CONS_Printf( "Camera values: %f / %f / %f \n", FixedToFloat(mapheaderinfo[gamemap-1]->cameraHeight), FixedToFloat(cv_cam_height[num].value), FixedToFloat(cameraScale) ); - camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*3 + cv_cam_height[num].value)/4, cameraScale); + camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*5 + cv_cam_height[num].value)/6, cameraScale); } } From 21929bb11152f317516e2e7ddf502258c39311e5 Mon Sep 17 00:00:00 2001 From: eebrozgi Date: Wed, 18 Jun 2025 15:17:34 +0300 Subject: [PATCH 02/64] Splitscreen flatmap camera height 3/4 -> 13/16 --- src/p_spec.c | 4 ++-- src/p_user.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 713dc2719..1f83438c3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9664,9 +9664,9 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) maxShake = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, mapobjectscale) * 3 / 4; // For 2p SPLITSCREEN SPECIFICALLY: - // The view is pretty narrow, so move it back 1/4th of the way towards default camera height. + // The view is pretty narrow, so move it back 3/16 of the way towards default camera height. else - maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*5 + cv_cam_height[view].value)/6, mapobjectscale) * 3 / 4; + maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*13 + cv_cam_height[view].value*3)/16, mapobjectscale) * 3 / 4; } if (battle) diff --git a/src/p_user.c b/src/p_user.c index 78b0d17c8..a81793503 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3383,10 +3383,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camheight = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, cameraScale); // For 2p SPLITSCREEN SPECIFICALLY: - // The view is pretty narrow, so move it back 1/4th of the way towards default camera height. + // The view is pretty narrow, so move it back 3/16 of the way towards default camera height. else { // CONS_Printf( "Camera values: %f / %f / %f \n", FixedToFloat(mapheaderinfo[gamemap-1]->cameraHeight), FixedToFloat(cv_cam_height[num].value), FixedToFloat(cameraScale) ); - camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*5 + cv_cam_height[num].value)/6, cameraScale); + camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*13 + cv_cam_height[num].value*3)/16, cameraScale); } } From 6b0dd78d6133c9d23fb2804635bb707ee2901784 Mon Sep 17 00:00:00 2001 From: eebrozgi Date: Wed, 18 Jun 2025 15:40:37 +0300 Subject: [PATCH 03/64] 13/16 -> 17/20 FUMBLED MY MATH, NEVERMIND --- src/p_spec.c | 4 ++-- src/p_user.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 1f83438c3..a64533ec7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9664,9 +9664,9 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) maxShake = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, mapobjectscale) * 3 / 4; // For 2p SPLITSCREEN SPECIFICALLY: - // The view is pretty narrow, so move it back 3/16 of the way towards default camera height. + // The view is pretty narrow, so move it back 3/20 of the way towards default camera height. else - maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*13 + cv_cam_height[view].value*3)/16, mapobjectscale) * 3 / 4; + maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*17 + cv_cam_height[view].value*3)/20, mapobjectscale) * 3 / 4; } if (battle) diff --git a/src/p_user.c b/src/p_user.c index a81793503..3f74f422b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3383,10 +3383,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camheight = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, cameraScale); // For 2p SPLITSCREEN SPECIFICALLY: - // The view is pretty narrow, so move it back 3/16 of the way towards default camera height. + // The view is pretty narrow, so move it back 3/20 of the way towards default camera height. else { // CONS_Printf( "Camera values: %f / %f / %f \n", FixedToFloat(mapheaderinfo[gamemap-1]->cameraHeight), FixedToFloat(cv_cam_height[num].value), FixedToFloat(cameraScale) ); - camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*13 + cv_cam_height[num].value*3)/16, cameraScale); + camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*17 + cv_cam_height[num].value*3)/20, cameraScale); } } From 331110e6cff7d15606e03908fd45ee6f1742e766 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 02:22:50 -0400 Subject: [PATCH 04/64] Use rank percentage for Sealed Star entry, not grade --- src/doomstat.h | 2 ++ src/g_game.c | 2 +- src/k_hud.cpp | 3 +++ src/k_rank.cpp | 50 ++++++++++++++++++++++++++++--------------------- src/k_rank.h | 1 + src/y_inter.cpp | 8 ++++---- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 97c58c441..748b0773e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -198,6 +198,8 @@ typedef enum GRADE_S } gp_rank_e; +#define SEALED_STAR_ENTRY (370*FRACUNIT/400) + struct cupwindata_t { UINT8 best_placement; diff --git a/src/g_game.c b/src/g_game.c index cb6ea7697..4909e9bd2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4381,7 +4381,7 @@ void G_GetNextMap(void) && grandprixinfo.gamespeed >= KARTSPEED_NORMAL) { // On A rank pace? Then you get a chance for S rank! - permitrank = (K_CalculateGPGrade(&grandprixinfo.rank) >= GRADE_A); + permitrank = (K_CalculateGPPercent(&grandprixinfo.rank) >= SEALED_STAR_ENTRY); // If you're on Master, a win floats you to rank-restricted levels for free. // (This is a different class of challenge!) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 1bf954bec..5ad7d4d43 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -7119,6 +7119,7 @@ static void K_DrawGPRankDebugger(void) } grade = K_CalculateGPGrade(&grandprixinfo.rank); + fixed_t percent = K_CalculateGPPercent(&grandprixinfo.rank); V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT, va("POS: %d / %d", grandprixinfo.rank.position, RANK_NEUTRAL_POSITION)); @@ -7132,6 +7133,8 @@ static void K_DrawGPRankDebugger(void) va("RINGS: %d / %d", grandprixinfo.rank.rings, grandprixinfo.rank.totalRings)); V_DrawThinString(0, 60, V_SNAPTOTOP|V_SNAPTOLEFT, va("EMERALD: %s", (grandprixinfo.rank.specialWon == true) ? "YES" : "NO")); + V_DrawThinString(0, 70, V_SNAPTOTOP|V_SNAPTOLEFT, + va("PERCENT: %.2f", FixedToFloat(percent))); switch (grade) { diff --git a/src/k_rank.cpp b/src/k_rank.cpp index c2e222158..0f981f5ff 100644 --- a/src/k_rank.cpp +++ b/src/k_rank.cpp @@ -548,13 +548,10 @@ void K_UpdateGPRank(gpRank_t *rankData) rankData->Update(); } -/*-------------------------------------------------- - gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) - - See header file for description. ---------------------------------------------------*/ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) { + INT32 retGrade = GRADE_E; + { extern consvar_t cv_debugrank; @@ -564,6 +561,8 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) } } + fixed_t percent = K_CalculateGPPercent(rankData); + static const fixed_t gradePercents[GRADE_A] = { 7*FRACUNIT/20, // D: 35% or higher 10*FRACUNIT/20, // C: 50% or higher @@ -571,8 +570,31 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) 17*FRACUNIT/20 // A: 85% or higher }; - INT32 retGrade = GRADE_E; + for (retGrade = GRADE_E; retGrade < GRADE_A; retGrade++) + { + if (percent < gradePercents[retGrade]) + { + break; + } + } + if (rankData->specialWon == true) + { + // Winning the Special Stage gives you + // a free grade increase. + retGrade++; + } + + return static_cast(retGrade); +} + +/*-------------------------------------------------- + gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) + + See header file for description. +--------------------------------------------------*/ +fixed_t K_CalculateGPPercent(gpRank_t *rankData) +{ rankData->scorePosition = 0; rankData->scoreGPPoints = 0; rankData->scoreExp = 0; @@ -625,22 +647,8 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData) rankData->scoreContinues; const fixed_t percent = FixedDiv(rankData->scoreTotal, total); - for (retGrade = GRADE_E; retGrade < GRADE_A; retGrade++) - { - if (percent < gradePercents[retGrade]) - { - break; - } - } - if (rankData->specialWon == true) - { - // Winning the Special Stage gives you - // a free grade increase. - retGrade++; - } - - return static_cast(retGrade); + return percent; } /*-------------------------------------------------- diff --git a/src/k_rank.h b/src/k_rank.h index aa28727e3..943cb40c0 100644 --- a/src/k_rank.h +++ b/src/k_rank.h @@ -159,6 +159,7 @@ void K_UpdateGPRank(gpRank_t *rankData); --------------------------------------------------*/ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData); +fixed_t K_CalculateGPPercent(gpRank_t *rankData); /*-------------------------------------------------- diff --git a/src/y_inter.cpp b/src/y_inter.cpp index 0f966e2e9..449324357 100644 --- a/src/y_inter.cpp +++ b/src/y_inter.cpp @@ -400,14 +400,14 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) if (roundqueue.position == roundqueue.size-1) { // On A rank pace? Then you get a chance for S rank! - gp_rank_e rankforline = K_CalculateGPGrade(&grandprixinfo.rank); + fixed_t rankforline = K_CalculateGPPercent(&grandprixinfo.rank); - data.showrank = (rankforline >= GRADE_A); + data.showrank = (rankforline >= SEALED_STAR_ENTRY); data.linemeter = - (std::min(rankforline, GRADE_A) + (std::min(rankforline, SEALED_STAR_ENTRY) * (2 * TICRATE) - ) / GRADE_A; + ) / SEALED_STAR_ENTRY; // G_NextMap will float you to rank-restricted stages on Master wins. // Fudge the rank display. From a8ef3d0204290795e404e62b1af32bffe4f1403f Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 04:08:29 -0400 Subject: [PATCH 05/64] Slow down bots on straightaways (reinventing the accel wheel) --- src/d_player.h | 1 + src/k_bot.cpp | 9 +++++++++ src/k_bot.h | 4 ++++ src/k_hud.cpp | 1 + src/p_saveg.cpp | 4 +++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index 5cb2f7afc..5e2dddb0b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -430,6 +430,7 @@ struct botvars_t tic_t rouletteTimeout; // If it takes too long to decide, try lowering priority until we find something valid. angle_t predictionError; // How bad is our momentum angle relative to where we're trying to go? + INT16 straightawayTime; // How long have we been going straight? (See k_bot.h) }; // player_t struct for round-specific condition tracking diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 3918a2e6b..ce321c43f 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -823,6 +823,7 @@ fixed_t K_BotRubberband(const player_t *player) fixed_t K_UpdateRubberband(player_t *player) { fixed_t dest = K_BotRubberband(player); + dest = (player->botvars.straightawayTime > 0) ? FixedMul(BOTSTRAIGHTSTRENGTH, dest) : dest; fixed_t ret = player->botvars.rubberband; UINT8 ease_soften = 8; @@ -2123,6 +2124,14 @@ void K_UpdateBotGameplayVars(player_t *player) } } + if (player->botvars.predictionError <= BOTSTRAIGHTANGLE) + player->botvars.straightawayTime++; + else + player->botvars.straightawayTime -= 5; + + player->botvars.straightawayTime = std::min(player->botvars.straightawayTime, BOTSTRAIGHTTIME); + player->botvars.straightawayTime = std::max(player->botvars.straightawayTime, -1 * BOTSTRAIGHTTIME); + const botcontroller_t *botController = K_GetBotController(player->mo); if (K_TryRingShooter(player, botController) == true) { diff --git a/src/k_bot.h b/src/k_bot.h index 6044bbd92..ac3092c8b 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -46,6 +46,10 @@ extern "C" { // How long it takes for a Lv.1 bot to decide to pick an item. #define BOT_ITEM_DECISION_TIME (2*TICRATE) +#define BOTSTRAIGHTTIME (TICRATE/2) +#define BOTSTRAIGHTSTRENGTH (85*FRACUNIT/100) +#define BOTSTRAIGHTANGLE (ANG10) + // Point for bots to aim for struct botprediction_t { diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 1bf954bec..1a39d56b2 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -7096,6 +7096,7 @@ static void K_DrawBotDebugger(void) V_DrawSmallString(8, 70, 0, va("Bot modifier: %.2f", FixedToFloat(K_BotMapModifier()))); V_DrawSmallString(8, 76, 0, va("Prediction error: %d", bot->botvars.predictionError)); + V_DrawSmallString(8, 80, 0, va("Straight: %d", bot->botvars.straightawayTime)); } static void K_DrawGPRankDebugger(void) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8e6bcc6e8..e0c2d88b9 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -756,7 +756,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].botvars.spindashconfirm); WRITEUINT32(save->p, players[i].botvars.respawnconfirm); WRITEUINT8(save->p, players[i].botvars.roulettePriority); - WRITEUINT32(save->p, players[i].botvars.rouletteTimeout); + WRITEINT32(save->p, players[i].botvars.rouletteTimeout); + WRITEINT16(save->p, players[i].botvars.straightawayTime); // itemroulette_t WRITEUINT8(save->p, players[i].itemRoulette.active); @@ -1409,6 +1410,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].botvars.respawnconfirm = READUINT32(save->p); players[i].botvars.roulettePriority = READUINT8(save->p); players[i].botvars.rouletteTimeout = READUINT32(save->p); + players[i].botvars.straightawayTime = READINT16(save->p); // itemroulette_t players[i].itemRoulette.active = (boolean)READUINT8(save->p); From d4c8fac82d9f75099f6dc16a7c336a578f660ef1 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 19:23:39 -0400 Subject: [PATCH 06/64] Straight slowdown attempt 2: use momentum angle --- src/d_player.h | 3 ++- src/k_bot.cpp | 35 ++++++++++++++++++++++++++--------- src/k_bot.h | 9 +++++---- src/k_hud.cpp | 4 ++-- src/p_saveg.cpp | 8 ++++++-- src/p_slopes.c | 8 ++++++-- 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 5e2dddb0b..16339b32a 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -430,7 +430,8 @@ struct botvars_t tic_t rouletteTimeout; // If it takes too long to decide, try lowering priority until we find something valid. angle_t predictionError; // How bad is our momentum angle relative to where we're trying to go? - INT16 straightawayTime; // How long have we been going straight? (See k_bot.h) + angle_t recentDeflection; // How long have we been going straight? (See k_bot.h) + angle_t lastAngle; }; // player_t struct for round-specific condition tracking diff --git a/src/k_bot.cpp b/src/k_bot.cpp index ce321c43f..d1f64f150 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -586,7 +586,7 @@ const botcontroller_t *K_GetBotController(const mobj_t *mobj) fixed_t K_BotMapModifier(void) { // fuck it we ball - // return 10*FRACUNIT/10; + return 5*FRACUNIT/10; constexpr INT32 complexity_scale = 10000; fixed_t modifier_max = (10 * FRACUNIT / 10) - FRACUNIT; @@ -690,9 +690,9 @@ fixed_t K_BotRubberband(const player_t *player) // Allow the status quo to assert itself a bit. Bots get most of their speed from their // mechanics adjustments, not from items, so kill some bot speed if they've got bad EXP. - if (player->gradingfactor < FRACUNIT && !(player->botvars.rival)) + if (player->gradingfactor < FRACUNIT && !(player->botvars.rival) && player->botvars.difficulty > 1) { - UINT8 levelreduce = 3; // How much to drop the "effective level" of bots that are consistently behind + UINT8 levelreduce = std::min(3, player->botvars.difficulty); // How much to drop the "effective level" of bots that are consistently behind expreduce = Easing_Linear((K_EffectiveGradingFactor(player) - MINGRADINGFACTOR) * 2, levelreduce*FRACUNIT, 0); } @@ -823,7 +823,17 @@ fixed_t K_BotRubberband(const player_t *player) fixed_t K_UpdateRubberband(player_t *player) { fixed_t dest = K_BotRubberband(player); - dest = (player->botvars.straightawayTime > 0) ? FixedMul(BOTSTRAIGHTSTRENGTH, dest) : dest; + + fixed_t deflect = player->botvars.recentDeflection; + if (deflect > BOTMAXDEFLECTION) + deflect = BOTMAXDEFLECTION; + + dest = FixedMul(dest, Easing_Linear( + FixedDiv(deflect, BOTMAXDEFLECTION), + BOTSTRAIGHTSPEED, + BOTTURNSPEED + )); + fixed_t ret = player->botvars.rubberband; UINT8 ease_soften = 8; @@ -2124,13 +2134,20 @@ void K_UpdateBotGameplayVars(player_t *player) } } - if (player->botvars.predictionError <= BOTSTRAIGHTANGLE) - player->botvars.straightawayTime++; + angle_t mangle = K_MomentumAngleEx(player->mo, 5*mapobjectscale); // magic threshold + angle_t langle = player->botvars.lastAngle; + angle_t dangle = 0; + if (mangle >= langle) + dangle = mangle - langle; else - player->botvars.straightawayTime -= 5; + dangle = langle - mangle; + // Writing this made me move my tongue around in my mouth - player->botvars.straightawayTime = std::min(player->botvars.straightawayTime, BOTSTRAIGHTTIME); - player->botvars.straightawayTime = std::max(player->botvars.straightawayTime, -1 * BOTSTRAIGHTTIME); + UINT32 smo = BOTANGLESAMPLES - 1; + + player->botvars.recentDeflection = (smo * player->botvars.recentDeflection / BOTANGLESAMPLES) + (dangle / BOTANGLESAMPLES); + + player->botvars.lastAngle = mangle; const botcontroller_t *botController = K_GetBotController(player->mo); if (K_TryRingShooter(player, botController) == true) diff --git a/src/k_bot.h b/src/k_bot.h index ac3092c8b..e58e4e8be 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -35,7 +35,7 @@ extern "C" { // How many tics in a row do you need to turn in this direction before we'll let you turn. // Made it as small as possible without making it look like the bots are twitching constantly. -#define BOTTURNCONFIRM 4 +#define BOTTURNCONFIRM 1 // How many tics with only one spindash-viable condition before we'll let you spindash. #define BOTSPINDASHCONFIRM (4*TICRATE) @@ -46,9 +46,10 @@ extern "C" { // How long it takes for a Lv.1 bot to decide to pick an item. #define BOT_ITEM_DECISION_TIME (2*TICRATE) -#define BOTSTRAIGHTTIME (TICRATE/2) -#define BOTSTRAIGHTSTRENGTH (85*FRACUNIT/100) -#define BOTSTRAIGHTANGLE (ANG10) +#define BOTSTRAIGHTSPEED (80*FRACUNIT/100) // How fast we move when at 0 deflection. +#define BOTTURNSPEED (100*FRACUNIT/100) // How fast we move when at MAXDEFLECTION deflection. +#define BOTANGLESAMPLES (TICRATE) // Time period to average over. Higher values produce lower peaks that last longer. +#define BOTMAXDEFLECTION (ANG1*3) // Measured in "degrees per tic" here, use debugbots. // Point for bots to aim for struct botprediction_t diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 1a39d56b2..de8e97208 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -7095,8 +7095,8 @@ static void K_DrawBotDebugger(void) V_DrawSmallString(8, 66, 0, va("Complexity: %d", K_GetTrackComplexity())); V_DrawSmallString(8, 70, 0, va("Bot modifier: %.2f", FixedToFloat(K_BotMapModifier()))); - V_DrawSmallString(8, 76, 0, va("Prediction error: %d", bot->botvars.predictionError)); - V_DrawSmallString(8, 80, 0, va("Straight: %d", bot->botvars.straightawayTime)); + V_DrawSmallString(8, 76, 0, va("Prediction error: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.predictionError, ANG1)))); + V_DrawSmallString(8, 80, 0, va("Recent deflection: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.recentDeflection, ANG1)))); } static void K_DrawGPRankDebugger(void) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index e0c2d88b9..98e544cd4 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -757,7 +757,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].botvars.respawnconfirm); WRITEUINT8(save->p, players[i].botvars.roulettePriority); WRITEINT32(save->p, players[i].botvars.rouletteTimeout); - WRITEINT16(save->p, players[i].botvars.straightawayTime); + WRITEUINT32(save->p, players[i].botvars.predictionError); + WRITEUINT32(save->p, players[i].botvars.recentDeflection); + WRITEUINT32(save->p, players[i].botvars.lastAngle); // itemroulette_t WRITEUINT8(save->p, players[i].itemRoulette.active); @@ -1410,7 +1412,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].botvars.respawnconfirm = READUINT32(save->p); players[i].botvars.roulettePriority = READUINT8(save->p); players[i].botvars.rouletteTimeout = READUINT32(save->p); - players[i].botvars.straightawayTime = READINT16(save->p); + players[i].botvars.predictionError = READUINT32(save->p); + players[i].botvars.recentDeflection = READUINT32(save->p); + players[i].botvars.lastAngle = READUINT32(save->p); // itemroulette_t players[i].itemRoulette.active = (boolean)READUINT8(save->p); diff --git a/src/p_slopes.c b/src/p_slopes.c index 7ae2567bd..aca454f3a 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1206,11 +1206,15 @@ void P_ButteredSlope(mobj_t *mo) // Let's get the gravity strength for the object... thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); - if (mo->friction != ORIG_FRICTION) + fixed_t basefriction = ORIG_FRICTION; + if (mo->player && false) + basefriction = K_PlayerBaseFriction(mo->player, ORIG_FRICTION); + + if (mo->friction != basefriction && basefriction != 0) { // ... and its friction against the ground for good measure. // (divided by original friction to keep behaviour for normal slopes the same) - thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION)); + thrust = FixedMul(thrust, FixedDiv(mo->friction, basefriction)); // Sal: Also consider movefactor of players. // We want ice to make slopes *really* funnel you in a specific direction. From 2e66e4df8ad31932ee26c26f1ca719a93776105f Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 21:20:50 -0400 Subject: [PATCH 07/64] Unset vortexboost when null checks fail --- src/k_kart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9caf07617..bd95dbadb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5180,6 +5180,8 @@ void K_UpdateWavedashIndicator(player_t *player) { mobj_t *mobj = NULL; + player->vortexBoost = 0; + if (player == NULL) { return; @@ -5193,7 +5195,6 @@ void K_UpdateWavedashIndicator(player_t *player) if (player->wavedashIndicator == NULL || P_MobjWasRemoved(player->wavedashIndicator) == true) { K_InitWavedashIndicator(player); - player->vortexBoost = 0; return; } From 63b55c0abd794db5b14b5182f896307401354574 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 23:55:28 -0400 Subject: [PATCH 08/64] oni fuckup vol69 --- src/k_bot.cpp | 6 +++--- src/p_slopes.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_bot.cpp b/src/k_bot.cpp index d1f64f150..3caab89e7 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -836,10 +836,10 @@ fixed_t K_UpdateRubberband(player_t *player) fixed_t ret = player->botvars.rubberband; - UINT8 ease_soften = 8; + UINT8 ease_soften = (ret > dest) ? 3 : 8; if (player->botvars.bumpslow && dest > ret) - ease_soften *= 10; + ease_soften = 80; // Ease into the new value. ret += (dest - player->botvars.rubberband) / ease_soften; @@ -2146,7 +2146,7 @@ void K_UpdateBotGameplayVars(player_t *player) UINT32 smo = BOTANGLESAMPLES - 1; player->botvars.recentDeflection = (smo * player->botvars.recentDeflection / BOTANGLESAMPLES) + (dangle / BOTANGLESAMPLES); - + player->botvars.lastAngle = mangle; const botcontroller_t *botController = K_GetBotController(player->mo); diff --git a/src/p_slopes.c b/src/p_slopes.c index aca454f3a..a64ebfaa0 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1207,7 +1207,7 @@ void P_ButteredSlope(mobj_t *mo) thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); fixed_t basefriction = ORIG_FRICTION; - if (mo->player && false) + if (mo->player) basefriction = K_PlayerBaseFriction(mo->player, ORIG_FRICTION); if (mo->friction != basefriction && basefriction != 0) From 96d78eeb0ffc39955c07657159db614d523e9f22 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 22 Jun 2025 00:15:25 -0400 Subject: [PATCH 09/64] Slow down bots tethering to other bots --- src/k_kart.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9caf07617..856db5f9d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1607,13 +1607,16 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed // How much this increments every tic biases toward acceleration! (min speed gets 1.5% per tic, max speed gets 0.5% per tic) if (player->draftpower < FRACUNIT) { - fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));; + fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600)); player->draftpower += add; - if (player->bot && (player->botvars.rival || cv_levelskull.value)) + if (player->bot) { // Double speed for the rival! - player->draftpower += add; + if (player->botvars.rival || cv_levelskull.value) + player->draftpower += add; + else if (dest->player->bot) // Reduce bot gluts. + player->draftpower -= 3*add/4; } if (gametyperules & GTR_CLOSERPLAYERS) From 9cc434d4249cd166b1bf734292a6c41e1475024a Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 22 Jun 2025 15:38:59 -0400 Subject: [PATCH 10/64] Remove bubble drag when popping bubble --- src/k_kart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3cda6c47a..231d9f290 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -78,7 +78,8 @@ static void K_PopBubbleShield(player_t *player) K_StripItems(player); K_AddHitLag(player->mo, 4, false); vector3_t offset = { 0, 0, 0 }; - K_SpawnSingleHitLagSpark(player->mo, &offset, player->mo->scale*2, 4, 0, player->skincolor); + K_SpawnSingleHitLagSpark(player->mo, &offset, player->mo->scale*2, 4, 0, player->skincolor); + player->bubbledrag = false; } boolean K_ThunderDome(void) From 2ec0fdcc46350395a5911a37a8f739a8a834b0de Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 22 Jun 2025 18:54:15 -0400 Subject: [PATCH 11/64] Refactor EXP logic to reuse math in minmax calcs --- src/k_kart.c | 98 +++++++++++++++++++++++++++------------------------- src/k_kart.h | 2 +- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3cda6c47a..aedc6ac0b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -15964,18 +15964,11 @@ boolean K_PlayerCanUseItem(player_t *player) return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime); } -fixed_t K_GetGradingFactorAdjustment(player_t *player) +static UINT8 K_Opponents(player_t *player) { - fixed_t power = EXP_POWER; // adjust to change overall xp volatility - const fixed_t stablerate = EXP_STABLERATE; // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain - fixed_t result = 0; + UINT8 opponents = 0; // players we are competing against - if (g_teamplay) - power = 3 * power / 4; - - INT32 live_players = 0; // players we are competing against - - for (INT32 i = 0; i < MAXPLAYERS; i++) + for (UINT8 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator || player == players+i) continue; @@ -15986,13 +15979,42 @@ fixed_t K_GetGradingFactorAdjustment(player_t *player) continue; } - live_players++; + opponents++; } - if (live_players < 8) - { - power += (8 - live_players) * power/4; - } + return opponents; +} + +static fixed_t K_EXPPower(player_t *player) +{ + fixed_t power = EXP_POWER; // adjust to change overall xp volatility + UINT8 opponents = K_Opponents(player); + + if (g_teamplay) + power = 3 * power / 4; + + if (opponents < 8) + power += (8 - opponents) * power/4; + + return power; +} + +static fixed_t K_EXPGainPerWin(player_t *player) +{ + return K_EXPPower(player); +} + +static fixed_t K_EXPDrainPerCheckpoint(player_t *player) +{ + // EXP_STABLERATE: How low do you have to place before losing XP? 4*FRACUNIT/10 = top 40% of race gains, 60% loses. + UINT8 opponents = K_Opponents(player); + fixed_t power = K_EXPPower(player); + return FixedMul(power, FixedMul(opponents*FRACUNIT, FRACUNIT - EXP_STABLERATE)); +} + +fixed_t K_GetGradingFactorAdjustment(player_t *player) +{ + fixed_t result = 0; // Increase XP for each player you're beating... for (INT32 i = 0; i < MAXPLAYERS; i++) @@ -16007,49 +16029,31 @@ fixed_t K_GetGradingFactorAdjustment(player_t *player) } if (player->position < players[i].position) - result += power; + result += K_EXPGainPerWin(player); } // ...then take all of the XP you could possibly have earned, // and lose it proportional to the stable rate. If you're below // the stable threshold, this results in you losing XP. - result -= FixedMul(power, FixedMul(live_players*FRACUNIT, FRACUNIT - stablerate)); + result -= K_EXPDrainPerCheckpoint(player); return result; } -fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max) +fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max) { - // Create a dummy player structure for the theoretical last-place player - player_t dummy_player; - memset(&dummy_player, 0, sizeof(player_t)); - dummy_player.gradingfactor = FRACUNIT; // Start at 1.0 + fixed_t factor = FRACUNIT; // Starting EXP. + UINT8 opponents = K_Opponents(player); + UINT8 winning = (max) ? opponents : 0; - if (G_GametypeHasTeams()) + for (UINT8 i = 0; i < player->gradingpointnum; i++) // For each gradingpoint you've reached... { - const UINT8 orange_count = G_CountTeam(TEAM_ORANGE); - const UINT8 blue_count = G_CountTeam(TEAM_BLUE); - if (orange_count <= blue_count) - { - dummy_player.team = TEAM_ORANGE; - } - else - { - dummy_player.team = TEAM_BLUE; - } - dummy_player.position = max ? 0 : D_NumPlayersInRace() + 1; // Ensures that all enemy players are counted, and our dummy won't overlap + for (UINT8 j = 0; j < winning; j++) + factor += K_EXPGainPerWin(player); // If max, increase EXP for each player you could have been beating. + factor -= K_EXPDrainPerCheckpoint(player); // Then, drain like usual. } - else - { - dummy_player.position = max ? 1 : D_NumPlayersInRace(); - } - - // Apply the adjustment for each grading point - for (UINT32 i = 0; i < gradingpointnum; i++) - { - dummy_player.gradingfactor += K_GetGradingFactorAdjustment(&dummy_player); - } - return dummy_player.gradingfactor; + + return factor; } UINT16 K_GetEXP(player_t *player) @@ -16057,8 +16061,8 @@ UINT16 K_GetEXP(player_t *player) UINT32 numgradingpoints = K_GetNumGradingPoints(); UINT16 targetminexp = (MINEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a last place player should be at this stage of the race UINT16 targetexp = (MAXEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a 1.0 factor should be at this stage of the race - fixed_t factormin = K_GetGradingFactorMinMax(player->gradingpointnum, false); - fixed_t factormax = K_GetGradingFactorMinMax(player->gradingpointnum, true); + fixed_t factormin = K_GetGradingFactorMinMax(player, false); + fixed_t factormax = K_GetGradingFactorMinMax(player, true); fixed_t clampedfactor = max(factormin, min(factormax, player->gradingfactor)); fixed_t range = factormax - factormin; fixed_t normalizedfactor = FixedDiv(clampedfactor - factormin, range); diff --git a/src/k_kart.h b/src/k_kart.h index ff269dbb9..9d9f3fdf8 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -325,7 +325,7 @@ boolean K_ThunderDome(void); boolean K_PlayerCanUseItem(player_t *player); fixed_t K_GetGradingFactorAdjustment(player_t *player); -fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max); +fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max); UINT16 K_GetEXP(player_t *player); UINT32 K_GetNumGradingPoints(void); From bc328e50403481779e1114003bc9347ca1cf046d Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 22 Jun 2025 19:10:46 -0400 Subject: [PATCH 12/64] Avoid duplicated opponents check --- src/k_kart.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index aedc6ac0b..858db0b12 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -15964,22 +15964,32 @@ boolean K_PlayerCanUseItem(player_t *player) return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime); } +// === +// THE EXP ZONE +// === + +static boolean K_IsValidOpponent(player_t *me, player_t *them) +{ + UINT8 i = (them - players); + + if (!playeringame[i] || players[i].spectator) + return false; + if (me == them) + return false; + if (G_SameTeam(me, them)) + return false; + + return true; +} + static UINT8 K_Opponents(player_t *player) { UINT8 opponents = 0; // players we are competing against for (UINT8 i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].spectator || player == players+i) - continue; - - if (G_SameTeam(player, &players[i]) == true) - { - // You don't win/lose against your teammates. - continue; - } - - opponents++; + if (K_IsValidOpponent(player, &players[i])) + opponents++; } return opponents; @@ -16019,15 +16029,9 @@ fixed_t K_GetGradingFactorAdjustment(player_t *player) // Increase XP for each player you're beating... for (INT32 i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].spectator || player == players+i) + if (!K_IsValidOpponent(player, &players[i])) continue; - if (G_SameTeam(player, &players[i]) == true) - { - // You don't win/lose against your teammates. - continue; - } - if (player->position < players[i].position) result += K_EXPGainPerWin(player); } @@ -16084,6 +16088,10 @@ UINT32 K_GetNumGradingPoints(void) return numlaps * (1 + Obj_GetCheckpointCount()); } +// === +// END EXP ZONE +// === + void K_BotHitPenalty(player_t *player) { if (K_PlayerUsesBotMovement(player)) From 092f8a63e6ab396e4ee1c33cb0990b61471effe2 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 22 Jun 2025 23:12:34 -0400 Subject: [PATCH 13/64] New Rescale functions First use in cleanup of K_GetEXP --- src/k_kart.c | 20 +++++------ src/m_easing.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/m_easing.h | 3 ++ 3 files changed, 101 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 858db0b12..84c2cceae 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16063,20 +16063,16 @@ fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max) UINT16 K_GetEXP(player_t *player) { UINT32 numgradingpoints = K_GetNumGradingPoints(); - UINT16 targetminexp = (MINEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a last place player should be at this stage of the race - UINT16 targetexp = (MAXEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a 1.0 factor should be at this stage of the race + fixed_t targetminexp = (MINEXP*player->gradingpointnum<gradingpointnum<gradingfactor)); - fixed_t range = factormax - factormin; - fixed_t normalizedfactor = FixedDiv(clampedfactor - factormin, range); - fixed_t easedexp = Easing_Linear(normalizedfactor, targetminexp, targetexp); - // fixed_t easedexp = Easing_Linear(normalizedfactor, MINEXP*FRACUNIT, MAXEXP*FRACUNIT); - UINT16 exp = easedexp; - // CONS_Printf("Player %s numgradingpoints=%d targetminexp=%d targetexp=%d factormin=%.2f factormax=%.2f clampedfactor=%.2f normalizedfactor=%.2f easedexp=%d\n", - // player_names[player - players], numgradingpoints, targetminexp, targetexp, FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax), - // FIXED_TO_FLOAT(clampedfactor), FIXED_TO_FLOAT(normalizedfactor), easedexp); - // UINT16 exp = (player->gradingfactor*100)>>FRACBITS; + + UINT16 exp = FixedRescale(player->gradingfactor, factormin, factormax, Easing_Linear, targetminexp, targetmaxexp)>>FRACBITS; + + // CONS_Printf("Player %s numgradingpoints=%d gradingpoint=%d targetminexp=%d targetmaxexp=%d factor=%.2f factormin=%.2f factormax=%.2f exp=%d\n", + // player_names[player - players], numgradingpoints, player->gradingpointnum, targetminexp, targetmaxexp, FIXED_TO_FLOAT(player->gradingfactor), FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax), exp); + return exp; } diff --git a/src/m_easing.c b/src/m_easing.c index ef48abe51..e1e225ecd 100644 --- a/src/m_easing.c +++ b/src/m_easing.c @@ -430,3 +430,93 @@ const char *easing_funcnames[EASE_MAX] = #undef COMMA #undef EASINGFUNC + +// ================== +// FEATURE RESCALING +// ================== + +/*-------------------------------------------------- + fixed_t Rescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax) + + Rescales a feature value from [min, max] to [start, end] using + a custom easing function pointer. + + Input Arguments:- + value - The input value to rescale + inmin - Minimum value of the input range + inmax - Maximum value of the input range + easing_func - Pointer to the easing function to use + outmin - Start value of the output range + outmax - End value of the output range + + Return:- + The rescaled value using the specified easing function. +--------------------------------------------------*/ +fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax) +{ + // Handle edge case where min == max + if (inmin == inmax) + return outmin; + + // Clamp the input value to the range + max(inmin, min(inmax, value)); + + // Normalize the value to [0, FRACUNIT] range + fixed_t t = FixedDiv(value - inmin, inmax - inmin); + + // Apply the easing function if provided + if (easing_func != NULL) + { + return easing_func(t, outmin, outmax); + } + + // Fallback to linear if no function provided + return Easing_Linear(t, outmin, outmax); +} + +/*-------------------------------------------------- + INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax) + + Rescales a feature value from [min, max] to [start, end] using + a custom easing function pointer. + Can only take in up to INT16 because it uses fixed_t internally + + Input Arguments:- + value - The input value to rescale + inmin - Minimum value of the input range + inmax - Maximum value of the input range + easing_func - Pointer to the easing function to use + outmin - Start value of the output range + outmax - End value of the output range + + Return:- + The rescaled value using the specified easing function. +--------------------------------------------------*/ +INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax) +{ + // Handle edge case where min == max + if (inmin == inmax) + return outmin; + + // Clamp the input value to the range + max(inmin, min(inmax, value)); + + // Conversion shit + value = value<>FRACBITS; + } + + // Fallback to linear if no function provided + return Easing_Linear(t, outmin, outmax)>>FRACBITS; +} diff --git a/src/m_easing.h b/src/m_easing.h index 3685ed192..bae0029c6 100644 --- a/src/m_easing.h +++ b/src/m_easing.h @@ -105,6 +105,9 @@ EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */ #undef EASINGFUNC +fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax); +INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax); + #ifdef __cplusplus } // extern "C" #endif From 741097888293eb1ea655365f22fb36394f85db18 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 22 Jun 2025 23:36:21 -0400 Subject: [PATCH 14/64] Cleanup No functionality changes --- src/doomdef.h | 6 +++--- src/k_kart.c | 34 +++++++++++++++++----------------- src/k_podium.cpp | 14 +++++++------- src/k_rank.cpp | 12 ++++++------ src/k_tally.cpp | 2 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 3ff5c274b..2842e4d80 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -747,9 +747,9 @@ extern int // Exp #define EXP_STABLERATE 3*FRACUNIT/10 // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain #define EXP_POWER 3*FRACUNIT/100 // adjust to change overall xp volatility -#define MINEXP 25 // The min value target -#define TARGETEXP 120 // Used for grading ... -#define MAXEXP 120 // The max value displayed by the hud and in the tally screen and GP results screen +#define EXP_MIN 25 // The min value target +#define EXP_TARGET 120 // Used for grading ... +#define EXP_MAX 120 // The max value displayed by the hud and in the tally screen and GP results screen #ifdef __cplusplus } // extern "C" diff --git a/src/k_kart.c b/src/k_kart.c index 84c2cceae..5ac1ba0ad 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -15995,9 +15995,9 @@ static UINT8 K_Opponents(player_t *player) return opponents; } -static fixed_t K_EXPPower(player_t *player) +static fixed_t K_GradingFactorPower(player_t *player) { - fixed_t power = EXP_POWER; // adjust to change overall xp volatility + fixed_t power = EXP_POWER; // adjust to change overall exp volatility UINT8 opponents = K_Opponents(player); if (g_teamplay) @@ -16009,16 +16009,16 @@ static fixed_t K_EXPPower(player_t *player) return power; } -static fixed_t K_EXPGainPerWin(player_t *player) +static fixed_t K_GradingFactorGainPerWin(player_t *player) { - return K_EXPPower(player); + return K_GradingFactorPower(player); } -static fixed_t K_EXPDrainPerCheckpoint(player_t *player) +static fixed_t K_GradingFactorDrainPerCheckpoint(player_t *player) { - // EXP_STABLERATE: How low do you have to place before losing XP? 4*FRACUNIT/10 = top 40% of race gains, 60% loses. + // EXP_STABLERATE: How low do you have to place before losing gradingfactor? 4*FRACUNIT/10 = top 40% of race gains, 60% loses. UINT8 opponents = K_Opponents(player); - fixed_t power = K_EXPPower(player); + fixed_t power = K_GradingFactorPower(player); return FixedMul(power, FixedMul(opponents*FRACUNIT, FRACUNIT - EXP_STABLERATE)); } @@ -16026,35 +16026,35 @@ fixed_t K_GetGradingFactorAdjustment(player_t *player) { fixed_t result = 0; - // Increase XP for each player you're beating... + // Increase gradingfactor for each player you're beating... for (INT32 i = 0; i < MAXPLAYERS; i++) { if (!K_IsValidOpponent(player, &players[i])) continue; if (player->position < players[i].position) - result += K_EXPGainPerWin(player); + result += K_GradingFactorGainPerWin(player); } - // ...then take all of the XP you could possibly have earned, + // ...then take all of the gradingfactor you could possibly have earned, // and lose it proportional to the stable rate. If you're below - // the stable threshold, this results in you losing XP. - result -= K_EXPDrainPerCheckpoint(player); + // the stable threshold, this results in you losing gradingfactor + result -= K_GradingFactorDrainPerCheckpoint(player); return result; } fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max) { - fixed_t factor = FRACUNIT; // Starting EXP. + fixed_t factor = FRACUNIT; // Starting gradingfactor UINT8 opponents = K_Opponents(player); UINT8 winning = (max) ? opponents : 0; for (UINT8 i = 0; i < player->gradingpointnum; i++) // For each gradingpoint you've reached... { for (UINT8 j = 0; j < winning; j++) - factor += K_EXPGainPerWin(player); // If max, increase EXP for each player you could have been beating. - factor -= K_EXPDrainPerCheckpoint(player); // Then, drain like usual. + factor += K_GradingFactorGainPerWin(player); // If max, increase gradingfactor for each player you could have been beating. + factor -= K_GradingFactorDrainPerCheckpoint(player); // Then, drain like usual. } return factor; @@ -16063,8 +16063,8 @@ fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max) UINT16 K_GetEXP(player_t *player) { UINT32 numgradingpoints = K_GetNumGradingPoints(); - fixed_t targetminexp = (MINEXP*player->gradingpointnum<gradingpointnum<gradingpointnum<gradingpointnum<totalExp = TARGETEXP; + lvl->totalExp = EXP_TARGET; texp += lvl->totalExp * rank.numPlayers; break; } @@ -203,7 +203,7 @@ void podiumData_s::Init(void) dta->rings = M_RandomRange(0, 20); rgs += dta->rings; - dta->exp = M_RandomRange(MINEXP, MAXEXP); + dta->exp = M_RandomRange(EXP_MIN, EXP_MAX); pexp += dta->exp; } @@ -727,8 +727,8 @@ void podiumData_s::Draw(void) // Colorize the crystal, just like we do for hud skincolornum_t overlaycolor = SKINCOLOR_MUSTARD; fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE; - INT16 exp_range = MAXEXP-MINEXP; - INT16 exp_offset = dta->exp-MINEXP; + INT16 exp_range = EXP_MAX-EXP_MIN; + INT16 exp_offset = dta->exp-EXP_MIN; fixed_t factor = (exp_offset*FRACUNIT) / exp_range; // 0.0 to 1.0 in fixed // amount of blue is how much factor is above EXP_STABLERATE, and amount of red is how much factor is below // assume that EXP_STABLERATE is within 0.0 to 1.0 in fixed @@ -892,9 +892,9 @@ void podiumData_s::Draw(void) .patch("K_STEXP"); // Colorize the crystal for the totals, just like we do for in race hud - fixed_t extraexpfactor = (MAXEXP*FRACUNIT) / TARGETEXP; + fixed_t extraexpfactor = (EXP_MAX*FRACUNIT) / EXP_TARGET; INT16 totalExpMax = FixedMul(rank.totalExp*FRACUNIT, extraexpfactor) / FRACUNIT; // im just going to calculate it from target lol - INT16 totalExpMin = rank.numPlayers*MINEXP; + INT16 totalExpMin = rank.numPlayers*EXP_MIN; skincolornum_t overlaycolor = SKINCOLOR_MUSTARD; fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE; INT16 exp_range = totalExpMax-totalExpMin; diff --git a/src/k_rank.cpp b/src/k_rank.cpp index c2e222158..3ca026fc8 100644 --- a/src/k_rank.cpp +++ b/src/k_rank.cpp @@ -322,7 +322,7 @@ void gpRank_t::Init(void) // (Should this account for all coop players?) for (i = 0; i < numHumans; i++) { - totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(MAXEXP, i+1, totalPlayers); + totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(EXP_MAX, i+1, totalPlayers); } totalRings = grandprixinfo.cup->numlevels * numHumans * 20; @@ -332,7 +332,7 @@ void gpRank_t::Init(void) const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[i]; if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL) { - exp += TARGETEXP; + exp += EXP_TARGET; } } @@ -372,7 +372,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI { for (i = 0; i < numPlayers; i++) { - deltaPoints += K_CalculateGPRankPoints(MAXEXP, i + 1, totalPlayers); + deltaPoints += K_CalculateGPRankPoints(EXP_MAX, i + 1, totalPlayers); } if (addedgt == GT_RACE) totalPoints += deltaPoints; @@ -391,7 +391,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI { if (removedgt == GT_RACE) { - deltaExp -= TARGETEXP; + deltaExp -= EXP_TARGET; } if ((gametypes[removedgt]->rules & GTR_SPHERES) == 0) { @@ -408,7 +408,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI { if (addedgt == GT_RACE) { - deltaExp += TARGETEXP; + deltaExp += EXP_TARGET; } if ((gametypes[addedgt]->rules & GTR_SPHERES) == 0) { @@ -492,7 +492,7 @@ void gpRank_t::Update(void) lvl->time = UINT32_MAX; - lvl->totalExp = TARGETEXP; + lvl->totalExp = EXP_TARGET; lvl->totalPrisons = maptargets; UINT8 i; diff --git a/src/k_tally.cpp b/src/k_tally.cpp index f8e91b46c..ba17f4153 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -347,7 +347,7 @@ void level_tally_t::Init(player_t *player) if (player->exp) { exp = player->exp; - totalExp = TARGETEXP; + totalExp = EXP_TARGET; } } From dc45f4427b1f40079ecfcc33eb105f4c03297261 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 23 Jun 2025 14:10:57 -0400 Subject: [PATCH 15/64] Try fixing vote party crash --- src/d_clisrv.c | 9 +++++++-- src/g_game.c | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index fac79bcab..1e342a39f 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3738,8 +3738,6 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum); - //G_SpectatePlayerOnJoin(newplayernum); -- caused desyncs in this spot :( - if (newplayernum+1 > doomcom->numslots) doomcom->numslots = (INT16)(newplayernum+1); @@ -3755,6 +3753,13 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) G_AddPlayer(newplayernum, console); memcpy(players[newplayernum].public_key, public_key, PUBKEYLENGTH); + // Previously called at the top of this function, commented as + // "caused desyncs in this spot :(". But we can't do this in + // G_PlayerReborn, since that only runs for level contexts and + // allows people to party-crash the vote screen even when + // maxplayers is too low for them. Let's try it here...? + G_SpectatePlayerOnJoin(newplayernum); + for (i = 0; i < MAXAVAILABILITY; i++) { newplayer->availabilities[i] = READUINT8(*p); diff --git a/src/g_game.c b/src/g_game.c index 4909e9bd2..bd3acb7f0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2313,7 +2313,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) jointime = players[player].jointime; if (jointime <= 1) { - G_SpectatePlayerOnJoin(player); + // Now called in Got_AddPlayer. In case of weirdness, break glass. + // G_SpectatePlayerOnJoin(player); betweenmaps = true; } From 5a01279c1080aee755f1d425bd30df198fba59c9 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 23 Jun 2025 15:00:18 -0400 Subject: [PATCH 16/64] Move join spectate below bot set, just in case --- src/d_clisrv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1e342a39f..b32a4a48a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3753,13 +3753,6 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) G_AddPlayer(newplayernum, console); memcpy(players[newplayernum].public_key, public_key, PUBKEYLENGTH); - // Previously called at the top of this function, commented as - // "caused desyncs in this spot :(". But we can't do this in - // G_PlayerReborn, since that only runs for level contexts and - // allows people to party-crash the vote screen even when - // maxplayers is too low for them. Let's try it here...? - G_SpectatePlayerOnJoin(newplayernum); - for (i = 0; i < MAXAVAILABILITY; i++) { newplayer->availabilities[i] = READUINT8(*p); @@ -3798,6 +3791,13 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) players[newplayernum].splitscreenindex = splitscreenplayer; players[newplayernum].bot = false; + // Previously called at the top of this function, commented as + // "caused desyncs in this spot :(". But we can't do this in + // G_PlayerReborn, since that only runs for level contexts and + // allows people to party-crash the vote screen even when + // maxplayers is too low for them. Let's try it here...? + G_SpectatePlayerOnJoin(newplayernum); + if (node == mynode && splitscreenplayer == 0) S_AttemptToRestoreMusic(); // Earliest viable point From aa44b140e20d69fb3050399cd5105e40900e8771 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 2 May 2025 12:02:56 -0400 Subject: [PATCH 17/64] WIP: Bail --- src/d_player.h | 2 ++ src/k_hitlag.c | 3 +++ src/k_kart.c | 66 ++++++++++++++++++++++++++++++++++++++++++++- src/k_kart.h | 4 +++ src/lua_playerlib.c | 4 +++ src/p_enemy.c | 2 +- src/p_inter.c | 2 +- src/p_local.h | 1 + src/p_saveg.cpp | 4 +++ 9 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 16339b32a..8e63357f5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -1081,6 +1081,8 @@ struct player_t UINT16 progressivethrust; // When getting beat up in GTR_BUMPERS, speed up the longer you've been out of control. UINT8 ringvisualwarning; // Check with > 1, not >= 1! Set when put in debt, counts down and holds at 1 when still in debt. + UINT32 baildrop; + boolean analoginput; // Has an input been recorded that requires analog usage? For input display. boolean markedfordeath; diff --git a/src/k_hitlag.c b/src/k_hitlag.c index 9110f1845..ca891eb04 100644 --- a/src/k_hitlag.c +++ b/src/k_hitlag.c @@ -34,6 +34,9 @@ void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage) return; } + if (mo->player && mo->player->overshield) + tics = min(tics, 3); + mo->hitlag += tics; mo->hitlag = min(mo->hitlag, MAXHITLAGTICS); diff --git a/src/k_kart.c b/src/k_kart.c index 5ac1ba0ad..6d260e732 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9998,6 +9998,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->cangrabitems && player->cangrabitems <= EARLY_ITEM_FLICKER) player->cangrabitems++; + if (player->baildrop) + { + if ((player->baildrop % BAIL_DROPFREQUENCY) == 0) + { + P_FlingBurst(player, K_MomentumAngle(player->mo), MT_FLINGRING, 60*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); + S_StartSound(player->mo, sfx_gshad); + } + player->baildrop--; + } + if (!player->invincibilitytimer) player->invincibilityextensions = 0; @@ -10147,7 +10157,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->nextringaward >= ringrate) { - if (player->instaWhipCharge) + if (player->instaWhipCharge || player->baildrop) { // Store award rings to do diabolical horseshit with later. player->nextringaward = ringrate; @@ -13887,6 +13897,60 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } + if ((player->cmd.buttons & BT_VOTE) && !(player->oldcmd.buttons & BT_VOTE) + && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) + { + UINT32 totalrings = player->rings + player->superring + player->pickuprings; + totalrings = max(totalrings, 0); + UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST)); + UINT32 baildrop = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_DROP)); + + if (player->itemRoulette.active) + { + player->itemRoulette.active = false; + } + + K_PopPlayerShield(player); + + if (player->itemamount) + { + K_DropPaperItem(player, player->itemtype, player->itemamount); + player->itemtype = player->itemamount = 0; + } + + + player->rings = min(player->rings, 0); + player->superring = 0; + player->pickuprings = 0; + player->ringboxaward = 0; + player->ringboxdelay = 0; + + player->superringdisplay = 0; + player->superringalert = 0; + player->superringpeak = 0; + + player->counterdash += TICRATE/8; + + player->ringboost += bailboost * (3+K_GetKartRingPower(player, true)); + player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1; + + K_AddHitLag(player->mo, TICRATE/4, false); + mobj_t *broly = Obj_SpawnBrolyKi(player->mo, player->mo->hitlag); + broly->extravalue2 = 16*mapobjectscale; + + INT32 fls = K_GetEffectiveFollowerSkin(player); + if (player->follower && fls >= 0 && fls < numfollowers) + { + const follower_t *fl = &followers[fls]; + S_StartSound(NULL, fl->hornsound); + } + + if (player->amps > 0) + K_DefensiveOverdrive(player); + + S_StartSound(player->mo, sfx_gshdd); + } + if (player && player->mo && K_PlayerCanUseItem(player)) { // First, the really specific, finicky items that function without the item being directly in your item slot. diff --git a/src/k_kart.h b/src/k_kart.h index 9d9f3fdf8..2d07490ac 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,6 +44,10 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) +#define BAIL_DROP (FRACUNIT/2) +#define BAIL_BOOST (FRACUNIT/4) +#define BAIL_DROPFREQUENCY (3) + #define MAXCOMBOTHRUST (mapobjectscale*20) #define MAXCOMBOFLOAT (mapobjectscale*10) #define MINCOMBOTHRUST (mapobjectscale*2) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 1a7d199c0..214eaae8b 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -284,6 +284,8 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->progressivethrust); else if (fastcmp(field,"ringvisualwarning")) lua_pushboolean(L, plr->ringvisualwarning); + else if (fastcmp(field,"baildrop")) + lua_pushboolean(L, plr->baildrop); else if (fastcmp(field,"dotrickfx")) lua_pushboolean(L, plr->dotrickfx); else if (fastcmp(field,"stingfx")) @@ -910,6 +912,8 @@ static int player_set(lua_State *L) plr->progressivethrust = luaL_checkboolean(L, 3); else if (fastcmp(field,"ringvisualwarning")) plr->ringvisualwarning = luaL_checkboolean(L, 3); + else if (fastcmp(field,"baildrop")) + plr->baildrop = luaL_checkinteger(L, 3); else if (fastcmp(field,"analoginput")) plr->analoginput = luaL_checkboolean(L, 3); else if (fastcmp(field,"transfer")) diff --git a/src/p_enemy.c b/src/p_enemy.c index 3006b7369..00f341128 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3503,7 +3503,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 && actor->type != MT_EMERALD) // SRB2Kart { - if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player) + if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player || actor->target->player->baildrop) { P_RemoveMobj(actor); return; diff --git a/src/p_inter.c b/src/p_inter.c index 04a05ce4c..fce601eae 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3612,7 +3612,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da #define RING_LAYER_SIDE_SIZE (3) #define RING_LAYER_SIZE (RING_LAYER_SIDE_SIZE * 2) -static void P_FlingBurst +void P_FlingBurst ( player_t *player, angle_t fa, mobjtype_t objType, diff --git a/src/p_local.h b/src/p_local.h index af4f722bf..6524dd69c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -549,6 +549,7 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End); void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +void P_FlingBurst(player_t *player, angle_t fa, mobjtype_t objType, tic_t objFuse, fixed_t objScale, INT32 i); void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 98e544cd4..c038c1ba4 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -667,6 +667,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].progressivethrust); WRITEUINT8(save->p, players[i].ringvisualwarning); + WRITEUINT32(save->p, players[i].baildrop); + WRITEUINT8(save->p, players[i].analoginput); WRITEUINT8(save->p, players[i].markedfordeath); @@ -1322,6 +1324,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].progressivethrust = READUINT16(save->p); players[i].ringvisualwarning = READUINT8(save->p); + players[i].baildrop = READUINT32(save->p); + players[i].analoginput = READUINT8(save->p); players[i].markedfordeath = READUINT8(save->p); From 92e4bb5909b6ca0f1d50db02de586fe6387808bb Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 2 May 2025 13:02:40 -0400 Subject: [PATCH 18/64] Bail refinement --- src/k_kart.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- src/k_kart.h | 2 +- src/p_inter.c | 11 +++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6d260e732..b8346431a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7772,6 +7772,30 @@ void K_PopPlayerShield(player_t *player) K_UnsetItemOut(player); } +static void K_DeleteHnextList(player_t *player) +{ + mobj_t *work = player->mo, *nextwork; + + if (work == NULL || P_MobjWasRemoved(work)) + { + return; + } + + nextwork = work->hnext; + + while ((work = nextwork) && !(work == NULL || P_MobjWasRemoved(work))) + { + nextwork = work->hnext; + + if (!work->health) + continue; // taking care of itself + + K_SpawnLandMineExplosion(work, player->skincolor, player->mo->hitlag); + + P_RemoveMobj(work); + } +} + void K_DropHnextList(player_t *player) { mobj_t *work = player->mo, *nextwork, *dropwork; @@ -10002,7 +10026,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { if ((player->baildrop % BAIL_DROPFREQUENCY) == 0) { - P_FlingBurst(player, K_MomentumAngle(player->mo), MT_FLINGRING, 60*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); + P_FlingBurst(player, K_MomentumAngle(player->mo), MT_FLINGRING, 10*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); S_StartSound(player->mo, sfx_gshad); } player->baildrop--; @@ -13900,10 +13924,20 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->cmd.buttons & BT_VOTE) && !(player->oldcmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) { + CONS_Printf("rl %d it %d ia %d ri %d sr %d pr %d\n", player->itemRoulette.active, player->itemtype, player->itemamount, player->rings > 0, player->superring > 0, player->pickuprings > 0); + + + UINT32 debtrings = 20; + if (player->rings < 0) + { + debtrings -= player->rings; + player->rings = 0; + } + UINT32 totalrings = player->rings + player->superring + player->pickuprings; totalrings = max(totalrings, 0); UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST)); - UINT32 baildrop = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_DROP)); + UINT32 baildrop = debtrings + FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP)); if (player->itemRoulette.active) { @@ -13911,15 +13945,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } K_PopPlayerShield(player); + K_DeleteHnextList(player); + K_DropItems(player); + player->itemamount = 0; + player->itemtype = 0; + + /* if (player->itemamount) { K_DropPaperItem(player, player->itemtype, player->itemamount); player->itemtype = player->itemamount = 0; } + */ - - player->rings = min(player->rings, 0); + player->rings = -20; player->superring = 0; player->pickuprings = 0; player->ringboxaward = 0; diff --git a/src/k_kart.h b/src/k_kart.h index 2d07490ac..9750f38c5 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,7 +45,7 @@ Make sure this matches the actual number of states #define PUNISHWINDOW (7*TICRATE/10) #define BAIL_DROP (FRACUNIT/2) -#define BAIL_BOOST (FRACUNIT/4) +#define BAIL_BOOST (FRACUNIT/3) #define BAIL_DROPFREQUENCY (3) #define MAXCOMBOTHRUST (mapobjectscale*20) diff --git a/src/p_inter.c b/src/p_inter.c index fce601eae..d71b587e8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -723,6 +723,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->extravalue1) return; + // No picking up rings while SPB is targetting you + if (player->pflags & PF_RINGLOCK) + return; + + // Prepping instawhip? Don't ruin it by collecting rings + if (player->instaWhipCharge) + return; + + if (player->baildrop) + return; + // Don't immediately pick up spilled rings if (special->threshold > 0 || P_PlayerInPain(player) || player->spindash) // player->spindash: Otherwise, players can pick up rings that are thrown out of them from invinc spindash penalty return; From b8a693be32ad9a930401bc1b5d5702338d97b9cf Mon Sep 17 00:00:00 2001 From: Ashnal Date: Fri, 9 May 2025 15:48:39 -0400 Subject: [PATCH 19/64] WIP: Can bail during painstates Not balanced/tuned yet --- src/k_kart.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index b8346431a..08e5fd49e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13978,6 +13978,16 @@ void K_MoveKartPlayer(player_t *player, boolean onground) mobj_t *broly = Obj_SpawnBrolyKi(player->mo, player->mo->hitlag); broly->extravalue2 = 16*mapobjectscale; + if (P_PlayerInPain(player)) + { + player->spinouttimer = 0; + player->spinouttype = 0; + player->tumbleBounces = 0; + player->pflags &= ~PF_TUMBLELASTBOUNCE; + player->mo->rollangle = 0; + P_ResetPitchRoll(player->mo); + } + INT32 fls = K_GetEffectiveFollowerSkin(player); if (player->follower && fls >= 0 && fls < numfollowers) { From 3146110d08154953e59175dd8502398160b7cbdf Mon Sep 17 00:00:00 2001 From: Ashnal Date: Fri, 9 May 2025 17:13:01 -0400 Subject: [PATCH 20/64] bailcharge player var --- src/d_player.h | 1 + src/lua_playerlib.c | 4 ++++ src/p_enemy.c | 2 +- src/p_inter.c | 2 +- src/p_saveg.cpp | 2 ++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 8e63357f5..fddbd9c51 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -1081,6 +1081,7 @@ struct player_t UINT16 progressivethrust; // When getting beat up in GTR_BUMPERS, speed up the longer you've been out of control. UINT8 ringvisualwarning; // Check with > 1, not >= 1! Set when put in debt, counts down and holds at 1 when still in debt. + UINT32 bailcharge; UINT32 baildrop; boolean analoginput; // Has an input been recorded that requires analog usage? For input display. diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 214eaae8b..faea1a8ee 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -284,6 +284,8 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->progressivethrust); else if (fastcmp(field,"ringvisualwarning")) lua_pushboolean(L, plr->ringvisualwarning); + else if (fastcmp(field,"bailcharge")) + lua_pushboolean(L, plr->bailcharge); else if (fastcmp(field,"baildrop")) lua_pushboolean(L, plr->baildrop); else if (fastcmp(field,"dotrickfx")) @@ -912,6 +914,8 @@ static int player_set(lua_State *L) plr->progressivethrust = luaL_checkboolean(L, 3); else if (fastcmp(field,"ringvisualwarning")) plr->ringvisualwarning = luaL_checkboolean(L, 3); + else if (fastcmp(field,"bailcharge")) + plr->bailcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"baildrop")) plr->baildrop = luaL_checkinteger(L, 3); else if (fastcmp(field,"analoginput")) diff --git a/src/p_enemy.c b/src/p_enemy.c index 00f341128..cc7d298a4 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3503,7 +3503,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 && actor->type != MT_EMERALD) // SRB2Kart { - if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player || actor->target->player->baildrop) + if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player || actor->target->player->baildrop || actor->target->player->bailcharge) { P_RemoveMobj(actor); return; diff --git a/src/p_inter.c b/src/p_inter.c index d71b587e8..dea9cd3e2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -731,7 +731,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->instaWhipCharge) return; - if (player->baildrop) + if (player->baildrop || player->bailcharge) return; // Don't immediately pick up spilled rings diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index c038c1ba4..878572929 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -667,6 +667,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].progressivethrust); WRITEUINT8(save->p, players[i].ringvisualwarning); + WRITEUINT32(save->p, players[i].bailcharge); WRITEUINT32(save->p, players[i].baildrop); WRITEUINT8(save->p, players[i].analoginput); @@ -1324,6 +1325,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].progressivethrust = READUINT16(save->p); players[i].ringvisualwarning = READUINT8(save->p); + players[i].bailcharge = READUINT32(save->p); players[i].baildrop = READUINT32(save->p); players[i].analoginput = READUINT8(save->p); From 6cc9de5efde03faa1995f09068c5c1f767c41e0f Mon Sep 17 00:00:00 2001 From: Ashnal Date: Fri, 9 May 2025 21:07:45 -0400 Subject: [PATCH 21/64] Implementing animations non-painstate animation isn't correct yet --- src/deh_tables.c | 5 ++++ src/info.c | 33 ++++++++++++++++++++++++ src/info.h | 8 ++++++ src/k_kart.c | 20 +++++++++++--- src/k_kart.h | 2 ++ src/k_objects.h | 3 +++ src/objects/CMakeLists.txt | 1 + src/objects/bail.c | 53 ++++++++++++++++++++++++++++++++++++++ src/p_mobj.c | 5 ++++ 9 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 src/objects/bail.c diff --git a/src/deh_tables.c b/src/deh_tables.c index cd479a80c..3d5f1ac8e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1574,6 +1574,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKRING", "S_BLOCKBODY", + "S_BAILCHARGE", + "S_TECHCHARGE", + "S_AMPRING", "S_AMPBODY", "S_AMPAURA", @@ -3564,6 +3567,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLOCKRING", "MT_BLOCKBODY", + "MT_BAILCHARGE", + "MT_AMPRING", "MT_AMPBODY", "MT_AMPAURA", diff --git a/src/info.c b/src/info.c index 690b5e5c7..7c79fdeae 100644 --- a/src/info.c +++ b/src/info.c @@ -334,6 +334,9 @@ char sprnames[NUMSPRITES + 1][5] = "GRNG", // Guard ring "GBDY", // Guard body + "BAIL", // Bail charge + "TECH", // Bail tech charge + "TRC1", // Charge aura "TRC2", // Charge fall "TRC3", // Charge flicker/sparks @@ -2160,6 +2163,9 @@ state_t states[NUMSTATES] = {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY + {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 8, 1, S_NULL}, // S_BAILCHARGE + {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_TECHCHARGE + {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING {SPR_AMPC, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBODY {SPR_AMPD, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPAURA @@ -13745,6 +13751,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BAILCHARGE + -1, // doomednum + S_BAILCHARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_AMPRING -1, // doomednum S_AMPRING, // spawnstate diff --git a/src/info.h b/src/info.h index f704e4426..6da6a81a3 100644 --- a/src/info.h +++ b/src/info.h @@ -875,6 +875,9 @@ typedef enum sprite SPR_GRNG, // Guard ring SPR_GBDY, // Guard body + SPR_BAIL, // Bail charge + SPR_TECH, // Bail tech charge + SPR_TRC1, // Charge aura SPR_TRC2, // Charge fall SPR_TRC3, // Charge flicker/sparks @@ -2629,6 +2632,9 @@ typedef enum state S_BLOCKRING, S_BLOCKBODY, + S_BAILCHARGE, + S_TECHCHARGE, + S_AMPRING, S_AMPBODY, S_AMPAURA, @@ -4646,6 +4652,8 @@ typedef enum mobj_type MT_BLOCKRING, MT_BLOCKBODY, + MT_BAILCHARGE, + MT_AMPRING, MT_AMPBODY, MT_AMPAURA, diff --git a/src/k_kart.c b/src/k_kart.c index 08e5fd49e..618d731cd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10181,7 +10181,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->nextringaward >= ringrate) { - if (player->instaWhipCharge || player->baildrop) + if (player->instaWhipCharge || player->baildrop || player->bailcharge) { // Store award rings to do diabolical horseshit with later. player->nextringaward = ringrate; @@ -13921,11 +13921,25 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } - if ((player->cmd.buttons & BT_VOTE) && !(player->oldcmd.buttons & BT_VOTE) - && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) + if ((player->cmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) + { + player->bailcharge++; + if (player->bailcharge == 1) + { + mobj_t * bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); + P_SetTarget(&bail->target, player->mo); + } + } + else + { + player->bailcharge = 0; + } + + if ((!P_PlayerInPain(player) && player->bailcharge >= BAIL_MAXCHARGE) || player->bailcharge >= BAIL_PAINMAXCHARGE) { CONS_Printf("rl %d it %d ia %d ri %d sr %d pr %d\n", player->itemRoulette.active, player->itemtype, player->itemamount, player->rings > 0, player->superring > 0, player->pickuprings > 0); + player->bailcharge = 0; UINT32 debtrings = 20; if (player->rings < 0) diff --git a/src/k_kart.h b/src/k_kart.h index 9750f38c5..be85d7ff1 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,6 +44,8 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) +#define BAIL_MAXCHARGE (9) // tics to bail when not in painstate +#define BAIL_PAINMAXCHARGE (42) // tics to bail when in painstate #define BAIL_DROP (FRACUNIT/2) #define BAIL_BOOST (FRACUNIT/3) #define BAIL_DROPFREQUENCY (3) diff --git a/src/k_objects.h b/src/k_objects.h index f5c36da12..c7cfb2e3d 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -153,6 +153,9 @@ void Obj_ChargeFallThink(mobj_t *charge); void Obj_ChargeReleaseThink(mobj_t *release); void Obj_ChargeExtraThink(mobj_t *extra); +/* Bail VFX */ +void Obj_BailChargeThink(mobj_t *aura); + /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); boolean Obj_PlayerRingShooterFreeze(const player_t *player); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 8d339d8f4..7a9cb347e 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -66,6 +66,7 @@ target_sources(SRB2SDL2 PRIVATE flame-shield.cpp stone-shoe.cpp exp.c + bail.c ) add_subdirectory(versus) diff --git a/src/objects/bail.c b/src/objects/bail.c new file mode 100644 index 000000000..4846af5c4 --- /dev/null +++ b/src/objects/bail.c @@ -0,0 +1,53 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by AJ "Tyron" Martinez. +// Copyright (C) 2025 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file bail.c +/// \brief Charge VFX code. + +#include "../doomdef.h" +#include "../info.h" +#include "../k_objects.h" +#include "../info.h" +#include "../k_kart.h" +#include "../p_local.h" + +void Obj_BailChargeThink (mobj_t *aura) +{ + if (P_MobjWasRemoved(aura->target) + || aura->target->health == 0 + || aura->target->destscale <= 1 // sealed star fall out + || !aura->target->player + || !aura->target->player->bailcharge) + { + P_RemoveMobj(aura); + } + else + { + mobj_t *mo = aura->target; + player_t *player = mo->player; + + if (P_PlayerInPain(player) && aura->state != &states[S_TECHCHARGE]) + { + P_SetMobjState(aura, S_TECHCHARGE); + player->bailcharge = 1; + } + + // Follow player + aura->flags &= ~(MF_NOCLIPTHING); + P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); + aura->flags |= MF_NOCLIPTHING; + // aura->color = mo->color; + + // aura->renderflags &= ~RF_DONTDRAW; + + fixed_t baseScale = 12*mo->scale/10; + + P_SetScale(aura, baseScale); + } +} diff --git a/src/p_mobj.c b/src/p_mobj.c index da3e08bc6..784e9ca0a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8923,6 +8923,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_BlockBodyThink(mobj); break; } + case MT_BAILCHARGE: + { + Obj_BailChargeThink(mobj); + break; + } case MT_AMPRING: { Obj_AmpRingThink(mobj); From d297577d8b90502af178bdb354ae20e6bce8b02a Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 12 May 2025 19:07:55 -0400 Subject: [PATCH 22/64] WIP: Move Bail activation FX to correct spot, buff boost, remove broly --- src/deh_tables.c | 4 ++-- src/info.c | 6 +++--- src/info.h | 4 ++-- src/k_kart.c | 10 +++++----- src/k_kart.h | 2 +- src/k_objects.h | 2 +- src/objects/bail.c | 4 ++-- src/p_mobj.c | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 3d5f1ac8e..ea7767c0f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1574,7 +1574,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKRING", "S_BLOCKBODY", - "S_BAILCHARGE", + "S_BAIL", "S_TECHCHARGE", "S_AMPRING", @@ -3567,7 +3567,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLOCKRING", "MT_BLOCKBODY", - "MT_BAILCHARGE", + "MT_BAIL", "MT_AMPRING", "MT_AMPBODY", diff --git a/src/info.c b/src/info.c index 7c79fdeae..1a5de2115 100644 --- a/src/info.c +++ b/src/info.c @@ -2163,7 +2163,7 @@ state_t states[NUMSTATES] = {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY - {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 8, 1, S_NULL}, // S_BAILCHARGE + {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 8, 1, S_NULL}, // S_BAIL {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_TECHCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING @@ -13751,9 +13751,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BAILCHARGE + { // MT_BAIL -1, // doomednum - S_BAILCHARGE, // spawnstate + S_BAIL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/info.h b/src/info.h index 6da6a81a3..e127e4361 100644 --- a/src/info.h +++ b/src/info.h @@ -2632,7 +2632,7 @@ typedef enum state S_BLOCKRING, S_BLOCKBODY, - S_BAILCHARGE, + S_BAIL, S_TECHCHARGE, S_AMPRING, @@ -4652,7 +4652,7 @@ typedef enum mobj_type MT_BLOCKRING, MT_BLOCKBODY, - MT_BAILCHARGE, + MT_BAIL, MT_AMPRING, MT_AMPBODY, diff --git a/src/k_kart.c b/src/k_kart.c index 618d731cd..7bea99b9b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13926,8 +13926,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge++; if (player->bailcharge == 1) { - mobj_t * bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); - P_SetTarget(&bail->target, player->mo); + // Hi Ashnal } } else @@ -13935,12 +13934,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge = 0; } - if ((!P_PlayerInPain(player) && player->bailcharge >= BAIL_MAXCHARGE) || player->bailcharge >= BAIL_PAINMAXCHARGE) + if ((!P_PlayerInPain(player) && player->bailcharge >= BAIL_MAXCHARGE) || player->bailcharge) { CONS_Printf("rl %d it %d ia %d ri %d sr %d pr %d\n", player->itemRoulette.active, player->itemtype, player->itemamount, player->rings > 0, player->superring > 0, player->pickuprings > 0); player->bailcharge = 0; + mobj_t * bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); + P_SetTarget(&bail->target, player->mo); + UINT32 debtrings = 20; if (player->rings < 0) { @@ -13989,8 +13991,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1; K_AddHitLag(player->mo, TICRATE/4, false); - mobj_t *broly = Obj_SpawnBrolyKi(player->mo, player->mo->hitlag); - broly->extravalue2 = 16*mapobjectscale; if (P_PlayerInPain(player)) { diff --git a/src/k_kart.h b/src/k_kart.h index be85d7ff1..f7227e1df 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -47,7 +47,7 @@ Make sure this matches the actual number of states #define BAIL_MAXCHARGE (9) // tics to bail when not in painstate #define BAIL_PAINMAXCHARGE (42) // tics to bail when in painstate #define BAIL_DROP (FRACUNIT/2) -#define BAIL_BOOST (FRACUNIT/3) +#define BAIL_BOOST (FRACUNIT) #define BAIL_DROPFREQUENCY (3) #define MAXCOMBOTHRUST (mapobjectscale*20) diff --git a/src/k_objects.h b/src/k_objects.h index c7cfb2e3d..e6a0bcc77 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -154,7 +154,7 @@ void Obj_ChargeReleaseThink(mobj_t *release); void Obj_ChargeExtraThink(mobj_t *extra); /* Bail VFX */ -void Obj_BailChargeThink(mobj_t *aura); +void Obj_BailThink(mobj_t *aura); /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); diff --git a/src/objects/bail.c b/src/objects/bail.c index 4846af5c4..52221b28c 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -17,13 +17,13 @@ #include "../k_kart.h" #include "../p_local.h" -void Obj_BailChargeThink (mobj_t *aura) +void Obj_BailThink (mobj_t *aura) { if (P_MobjWasRemoved(aura->target) || aura->target->health == 0 || aura->target->destscale <= 1 // sealed star fall out || !aura->target->player - || !aura->target->player->bailcharge) + || !aura->target->hitlag) { P_RemoveMobj(aura); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 784e9ca0a..b8fb5ad8f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8923,9 +8923,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_BlockBodyThink(mobj); break; } - case MT_BAILCHARGE: + case MT_BAIL: { - Obj_BailChargeThink(mobj); + Obj_BailThink(mobj); break; } case MT_AMPRING: From a57273a2aab516395404e0b741b3c09673b4b95e Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 12 May 2025 20:14:52 -0400 Subject: [PATCH 23/64] WIP: refactor bailcharge into own MT and fix effects still needs gameplay tuning --- src/deh_tables.c | 3 ++- src/info.c | 29 ++++++++++++++++++++++++++++- src/info.h | 3 ++- src/k_kart.c | 9 +++++---- src/k_kart.h | 3 +-- src/k_objects.h | 1 + src/objects/bail.c | 35 +++++++++++++++++++++++++++++------ src/p_mobj.c | 5 +++++ 8 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index ea7767c0f..5b6f8a0bb 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1575,7 +1575,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKBODY", "S_BAIL", - "S_TECHCHARGE", + "S_BAILCHARGE", "S_AMPRING", "S_AMPBODY", @@ -3568,6 +3568,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLOCKBODY", "MT_BAIL", + "MT_BAILCHARGE", "MT_AMPRING", "MT_AMPBODY", diff --git a/src/info.c b/src/info.c index 1a5de2115..b24df4e71 100644 --- a/src/info.c +++ b/src/info.c @@ -2164,7 +2164,7 @@ state_t states[NUMSTATES] = {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 8, 1, S_NULL}, // S_BAIL - {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_TECHCHARGE + {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING {SPR_AMPC, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBODY @@ -13778,6 +13778,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BAILCHARGE + -1, // doomednum + S_BAILCHARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_AMPRING -1, // doomednum S_AMPRING, // spawnstate diff --git a/src/info.h b/src/info.h index e127e4361..ac19008fd 100644 --- a/src/info.h +++ b/src/info.h @@ -2633,7 +2633,7 @@ typedef enum state S_BLOCKBODY, S_BAIL, - S_TECHCHARGE, + S_BAILCHARGE, S_AMPRING, S_AMPBODY, @@ -4653,6 +4653,7 @@ typedef enum mobj_type MT_BLOCKBODY, MT_BAIL, + MT_BAILCHARGE, MT_AMPRING, MT_AMPBODY, diff --git a/src/k_kart.c b/src/k_kart.c index 7bea99b9b..3723e4437 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13924,9 +13924,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->cmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) { player->bailcharge++; - if (player->bailcharge == 1) + if (P_PlayerInPain(player) && player->bailcharge == 1) { - // Hi Ashnal + mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); + P_SetTarget(&bail->target, player->mo); } } else @@ -13934,13 +13935,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge = 0; } - if ((!P_PlayerInPain(player) && player->bailcharge >= BAIL_MAXCHARGE) || player->bailcharge) + if ((!P_PlayerInPain(player) && player->bailcharge) || player->bailcharge >= BAIL_MAXCHARGE) { CONS_Printf("rl %d it %d ia %d ri %d sr %d pr %d\n", player->itemRoulette.active, player->itemtype, player->itemamount, player->rings > 0, player->superring > 0, player->pickuprings > 0); player->bailcharge = 0; - mobj_t * bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); + mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); P_SetTarget(&bail->target, player->mo); UINT32 debtrings = 20; diff --git a/src/k_kart.h b/src/k_kart.h index f7227e1df..b7ac61aff 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,8 +44,7 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) -#define BAIL_MAXCHARGE (9) // tics to bail when not in painstate -#define BAIL_PAINMAXCHARGE (42) // tics to bail when in painstate +#define BAIL_MAXCHARGE (42) // tics to bail when not in painstate #define BAIL_DROP (FRACUNIT/2) #define BAIL_BOOST (FRACUNIT) #define BAIL_DROPFREQUENCY (3) diff --git a/src/k_objects.h b/src/k_objects.h index e6a0bcc77..378632190 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -155,6 +155,7 @@ void Obj_ChargeExtraThink(mobj_t *extra); /* Bail VFX */ void Obj_BailThink(mobj_t *aura); +void Obj_BailChargeThink(mobj_t *aura); /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); diff --git a/src/objects/bail.c b/src/objects/bail.c index 52221b28c..3cf4f95a5 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -32,12 +32,6 @@ void Obj_BailThink (mobj_t *aura) mobj_t *mo = aura->target; player_t *player = mo->player; - if (P_PlayerInPain(player) && aura->state != &states[S_TECHCHARGE]) - { - P_SetMobjState(aura, S_TECHCHARGE); - player->bailcharge = 1; - } - // Follow player aura->flags &= ~(MF_NOCLIPTHING); P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); @@ -51,3 +45,32 @@ void Obj_BailThink (mobj_t *aura) P_SetScale(aura, baseScale); } } + +void Obj_BailChargeThink (mobj_t *aura) +{ + if (P_MobjWasRemoved(aura->target) + || aura->target->health == 0 + || aura->target->destscale <= 1 // sealed star fall out + || !aura->target->player + || !aura->target->player->bailcharge) + { + P_RemoveMobj(aura); + } + else + { + mobj_t *mo = aura->target; + player_t *player = mo->player; + + // Follow player + aura->flags &= ~(MF_NOCLIPTHING); + P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); + aura->flags |= MF_NOCLIPTHING; + // aura->color = mo->color; + + // aura->renderflags &= ~RF_DONTDRAW; + + fixed_t baseScale = 12*mo->scale/10; + + P_SetScale(aura, baseScale); + } +} \ No newline at end of file diff --git a/src/p_mobj.c b/src/p_mobj.c index b8fb5ad8f..d7ed31389 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8928,6 +8928,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_BailThink(mobj); break; } + case MT_BAILCHARGE: + { + Obj_BailChargeThink(mobj); + break; + } case MT_AMPRING: { Obj_AmpRingThink(mobj); From a1ed935aef8c13ce3f41509be32aebf0a9725cbb Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 12 May 2025 21:34:21 -0400 Subject: [PATCH 24/64] WIP: Longer charge for airbourne or tumble Still need animation speed polish --- src/k_kart.c | 5 +++-- src/k_kart.h | 2 +- src/objects/bail.c | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3723e4437..8842cf1b6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13923,8 +13923,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->cmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) { - player->bailcharge++; - if (P_PlayerInPain(player) && player->bailcharge == 1) + boolean onground = P_IsObjectOnGround(player->mo); + onground && player->tumbleBounces == 0 ? player->bailcharge += 2 : player->bailcharge++; // charge twice as fast on the ground + if (P_PlayerInPain(player) && player->bailcharge == 1 || onground && P_PlayerInPain(player) && player->bailcharge == 2) // this is brittle .. { mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); P_SetTarget(&bail->target, player->mo); diff --git a/src/k_kart.h b/src/k_kart.h index b7ac61aff..5d55668ce 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,7 +44,7 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) -#define BAIL_MAXCHARGE (42) // tics to bail when not in painstate +#define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half #define BAIL_DROP (FRACUNIT/2) #define BAIL_BOOST (FRACUNIT) #define BAIL_DROPFREQUENCY (3) diff --git a/src/objects/bail.c b/src/objects/bail.c index 3cf4f95a5..885574b06 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -67,6 +67,13 @@ void Obj_BailChargeThink (mobj_t *aura) aura->flags |= MF_NOCLIPTHING; // aura->color = mo->color; + aura->extravalue1 = max(0, aura->extravalue1-1); + if (aura->extravalue1 == 0 && (!P_IsObjectOnGround(player->mo) || player->tumbleBounces != 0)) + { + aura->anim_duration = 2; // hack the shit out of FF_ANIMATE hell yeah + aura->extravalue1 = 2; + } + // aura->renderflags &= ~RF_DONTDRAW; fixed_t baseScale = 12*mo->scale/10; From 341a018accf2a89fdde0dcf611e5b795abfbd946 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 28 May 2025 17:03:16 -0400 Subject: [PATCH 25/64] Warning fixes --- src/k_kart.c | 4 ++-- src/objects/bail.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8842cf1b6..78aeabf17 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13923,9 +13923,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->cmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) { - boolean onground = P_IsObjectOnGround(player->mo); + boolean grounded = P_IsObjectOnGround(player->mo); onground && player->tumbleBounces == 0 ? player->bailcharge += 2 : player->bailcharge++; // charge twice as fast on the ground - if (P_PlayerInPain(player) && player->bailcharge == 1 || onground && P_PlayerInPain(player) && player->bailcharge == 2) // this is brittle .. + if ((P_PlayerInPain(player) && player->bailcharge == 1) || (grounded && P_PlayerInPain(player) && player->bailcharge == 2)) // this is brittle .. { mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); P_SetTarget(&bail->target, player->mo); diff --git a/src/objects/bail.c b/src/objects/bail.c index 885574b06..2ebd1a359 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -30,7 +30,7 @@ void Obj_BailThink (mobj_t *aura) else { mobj_t *mo = aura->target; - player_t *player = mo->player; + ATTRUNUSED player_t *player = mo->player; // Follow player aura->flags &= ~(MF_NOCLIPTHING); From d0225afacb189d2679c67692f5b119610fd8c7d5 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 1 Jun 2025 16:50:24 -0400 Subject: [PATCH 26/64] Charge animation imprevement just sync the frame to the charge amount --- src/k_kart.h | 2 +- src/objects/bail.c | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/k_kart.h b/src/k_kart.h index 5d55668ce..1193dd60e 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,7 +44,7 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) -#define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half +#define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic #define BAIL_DROP (FRACUNIT/2) #define BAIL_BOOST (FRACUNIT) #define BAIL_DROPFREQUENCY (3) diff --git a/src/objects/bail.c b/src/objects/bail.c index 2ebd1a359..f68d7ef5f 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -67,14 +67,8 @@ void Obj_BailChargeThink (mobj_t *aura) aura->flags |= MF_NOCLIPTHING; // aura->color = mo->color; - aura->extravalue1 = max(0, aura->extravalue1-1); - if (aura->extravalue1 == 0 && (!P_IsObjectOnGround(player->mo) || player->tumbleBounces != 0)) - { - aura->anim_duration = 2; // hack the shit out of FF_ANIMATE hell yeah - aura->extravalue1 = 2; - } - - // aura->renderflags &= ~RF_DONTDRAW; + aura->anim_duration = 999; // This prevents FF_ANIMATE from working, we're gonna animate manually ourselves here + aura->frame = ((player->bailcharge-1)/2); // By syncing the frame with the charge timer here fixed_t baseScale = 12*mo->scale/10; From e9770bcf8770536d5630c62aa123857a5b7c2fd5 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 1 Jun 2025 18:01:42 -0400 Subject: [PATCH 27/64] Bail charge add ghost mobj and scale bump --- src/objects/bail.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/objects/bail.c b/src/objects/bail.c index f68d7ef5f..197f7cb6c 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -70,8 +70,12 @@ void Obj_BailChargeThink (mobj_t *aura) aura->anim_duration = 999; // This prevents FF_ANIMATE from working, we're gonna animate manually ourselves here aura->frame = ((player->bailcharge-1)/2); // By syncing the frame with the charge timer here - fixed_t baseScale = 12*mo->scale/10; + fixed_t baseScale = 13*mo->scale/10; P_SetScale(aura, baseScale); + + mobj_t *ghost = P_SpawnGhostMobj(aura); + ghost->renderflags = (ghost->renderflags & ~RF_TRANSMASK)|RF_ADD; + ghost->fuse = 3; } } \ No newline at end of file From 8711e287e4b84e77e1e968c4e465d47fe20bf135 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 1 Jun 2025 21:44:20 -0400 Subject: [PATCH 28/64] Bail post hitlag VFX --- src/deh_tables.c | 1 + src/info.c | 4 +++- src/info.h | 2 ++ src/objects/bail.c | 7 +------ 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5b6f8a0bb..5fc9b90aa 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1575,6 +1575,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKBODY", "S_BAIL", + "S_BAIB", "S_BAILCHARGE", "S_AMPRING", diff --git a/src/info.c b/src/info.c index b24df4e71..ed3849587 100644 --- a/src/info.c +++ b/src/info.c @@ -335,6 +335,7 @@ char sprnames[NUMSPRITES + 1][5] = "GBDY", // Guard body "BAIL", // Bail charge + "BAIB", // Bail after effect "TECH", // Bail tech charge "TRC1", // Charge aura @@ -2163,7 +2164,8 @@ state_t states[NUMSTATES] = {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY - {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 8, 1, S_NULL}, // S_BAIL + {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 8, {NULL}, 8, 1, S_BAIB}, // S_BAIL + {SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING diff --git a/src/info.h b/src/info.h index ac19008fd..05f3ef121 100644 --- a/src/info.h +++ b/src/info.h @@ -876,6 +876,7 @@ typedef enum sprite SPR_GBDY, // Guard body SPR_BAIL, // Bail charge + SPR_BAIB, // Bail after effect SPR_TECH, // Bail tech charge SPR_TRC1, // Charge aura @@ -2633,6 +2634,7 @@ typedef enum state S_BLOCKBODY, S_BAIL, + S_BAIB, S_BAILCHARGE, S_AMPRING, diff --git a/src/objects/bail.c b/src/objects/bail.c index 197f7cb6c..cd8e2c686 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -23,22 +23,17 @@ void Obj_BailThink (mobj_t *aura) || aura->target->health == 0 || aura->target->destscale <= 1 // sealed star fall out || !aura->target->player - || !aura->target->hitlag) + || P_PlayerInPain(aura->target->player)) // if you got hit when starting to bail, cancel the VFX { P_RemoveMobj(aura); } else { mobj_t *mo = aura->target; - ATTRUNUSED player_t *player = mo->player; - // Follow player aura->flags &= ~(MF_NOCLIPTHING); P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); aura->flags |= MF_NOCLIPTHING; - // aura->color = mo->color; - - // aura->renderflags &= ~RF_DONTDRAW; fixed_t baseScale = 12*mo->scale/10; From 9c0432eb1b3dd5b4e5097a9ea2438622643077e1 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 2 Jun 2025 19:28:20 -0400 Subject: [PATCH 29/64] Bail Sparkle --- src/deh_tables.c | 2 ++ src/info.c | 33 +++++++++++++++++++++++++++++++-- src/info.h | 3 +++ src/k_kart.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5fc9b90aa..7f3ac6310 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1576,6 +1576,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BAIL", "S_BAIB", + "S_BAIC", "S_BAILCHARGE", "S_AMPRING", @@ -3570,6 +3571,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BAIL", "MT_BAILCHARGE", + "MT_BAILSPARKLE", "MT_AMPRING", "MT_AMPBODY", diff --git a/src/info.c b/src/info.c index ed3849587..d3bad37b5 100644 --- a/src/info.c +++ b/src/info.c @@ -336,6 +336,7 @@ char sprnames[NUMSPRITES + 1][5] = "BAIL", // Bail charge "BAIB", // Bail after effect + "BAIC", // Bail sparkle "TECH", // Bail tech charge "TRC1", // Charge aura @@ -2166,6 +2167,7 @@ state_t states[NUMSTATES] = {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 8, {NULL}, 8, 1, S_BAIB}, // S_BAIL {SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB + {SPR_BAIC, FF_FULLBRIGHT|FF_ANIMATE|0, 11, {NULL}, 10, 1, S_NULL}, // S_BAIC {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING @@ -13776,7 +13778,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -13803,7 +13805,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + + { // MT_BAILSPARKLE + -1, // doomednum + S_BAIC, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP|MF_SCENERY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 05f3ef121..3a3354263 100644 --- a/src/info.h +++ b/src/info.h @@ -877,6 +877,7 @@ typedef enum sprite SPR_BAIL, // Bail charge SPR_BAIB, // Bail after effect + SPR_BAIC, // Bail sparkle SPR_TECH, // Bail tech charge SPR_TRC1, // Charge aura @@ -2635,6 +2636,7 @@ typedef enum state S_BAIL, S_BAIB, + S_BAIC, S_BAILCHARGE, S_AMPRING, @@ -4656,6 +4658,7 @@ typedef enum mobj_type MT_BAIL, MT_BAILCHARGE, + MT_BAILSPARKLE, MT_AMPRING, MT_AMPBODY, diff --git a/src/k_kart.c b/src/k_kart.c index 78aeabf17..b94e74757 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10001,6 +10001,35 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Extra tripwire leniency for the end of invincibility if (player->invincibilitytimer <= 0) { player->tripwireLeniency = max( player->tripwireLeniency, TICRATE ); + } + + if (player->baildrop) + { + mobj_t *pmo = player->mo; + // particle spawn + #define BAILSPARKLE_MAXBAIL 61 // amount of bail rings needed for max sparkle spawn frequency + UINT32 baildropinversefreq = BAILSPARKLE_MAXBAIL - min(player->baildrop, BAILSPARKLE_MAXBAIL-6); + UINT32 baildropmodulo = baildropinversefreq *5/3 /10; + if ((leveltime % (1+baildropmodulo)) == 0) + { + mobj_t *sparkle = P_SpawnMobj(pmo->x + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale), + pmo->y + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale), + pmo->z + (pmo->height/2) + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale), + MT_BAILSPARKLE); + + sparkle->scale = pmo->scale; + sparkle->angle = pmo->angle; + sparkle->momx = 3*pmo->momx/4; + sparkle->momy = 3*pmo->momy/4; + sparkle->momz = 3*P_GetMobjZMovement(pmo)/4; + K_MatchGenericExtraFlags(sparkle, pmo); + sparkle->renderflags = (pmo->renderflags & ~RF_TRANSMASK);//|RF_TRANS20|RF_ADD; + } + + if ((player->baildrop % BAIL_DROPFREQUENCY) == 0) + { + P_FlingBurst(player, K_MomentumAngle(pmo), MT_FLINGRING, 10*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); + S_StartSound(pmo, sfx_gshad); } } From 4e6fa59b487976e92ade2d58e64fd68cfd6f1758 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 2 Jun 2025 19:57:31 -0400 Subject: [PATCH 30/64] Bail stun etc --- src/k_kart.c | 13 +++++++++---- src/k_kart.h | 3 ++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b94e74757..cb62aa853 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9813,9 +9813,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // UINT16 oldringboost = player->ringboost; - if (player->superring == 0 || player->stunned) + if (!player->baildrop && (player->superring == 0 || player->stunned)) player->ringboost -= max((player->ringboost / roller), 1); - else if (K_LegacyRingboost(player)) + else if (K_LegacyRingboost(player) || player->baildrop) player->ringboost--; else player->ringboost -= min(K_GetFullKartRingPower(player, false) - 1, max(player->ringboost / 2 / roller, 1)); @@ -10005,6 +10005,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->baildrop) { + if (player->stunned & 0x8000) + player->stunned = 0x8000 | BAILSTUN; + else + player->stunned = BAILSTUN; + mobj_t *pmo = player->mo; // particle spawn #define BAILSPARKLE_MAXBAIL 61 // amount of bail rings needed for max sparkle spawn frequency @@ -13981,10 +13986,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->rings = 0; } - UINT32 totalrings = player->rings + player->superring + player->pickuprings; + UINT32 totalrings = player->rings + player->superring + player->pickuprings + debtrings; totalrings = max(totalrings, 0); UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST)); - UINT32 baildrop = debtrings + FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP)); + UINT32 baildrop = FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP)); if (player->itemRoulette.active) { diff --git a/src/k_kart.h b/src/k_kart.h index 1193dd60e..b2e3a02a6 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,9 +45,10 @@ Make sure this matches the actual number of states #define PUNISHWINDOW (7*TICRATE/10) #define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic -#define BAIL_DROP (FRACUNIT/2) +#define BAIL_DROP (FRACUNIT) #define BAIL_BOOST (FRACUNIT) #define BAIL_DROPFREQUENCY (3) +#define BAILSTUN (TICRATE*10) #define MAXCOMBOTHRUST (mapobjectscale*20) #define MAXCOMBOFLOAT (mapobjectscale*10) From f5aa2a701b08858753d408026b060d4ad7de9a79 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 7 Jun 2025 17:32:42 -0400 Subject: [PATCH 31/64] Bail button Transforms BT_RESPAWN into BT_BAIL User bindings should migrate along with this Respawn is now EBRAKE+BAIL Respawn blocks LOOKBACK Time Attack quick respawn is now VOTE --- src/d_clisrv.c | 2 +- src/d_ticcmd.h | 3 ++- src/deh_tables.c | 3 ++- src/g_build_ticcmd.cpp | 5 +---- src/g_input.h | 2 +- src/hud/input-display.cpp | 2 +- src/hud/spectator.cpp | 2 +- src/k_bot.cpp | 2 +- src/k_follower.c | 2 +- src/k_hud.cpp | 4 ++-- src/k_kart.c | 16 ++++++++++++---- src/k_menufunc.c | 2 +- src/menus/options-profiles-edit-controls.c | 4 ++-- src/objects/ring-shooter.c | 4 ++-- src/p_user.c | 4 ++-- 15 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index fac79bcab..f5a486f1d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5397,7 +5397,7 @@ static void FuzzTiccmd(ticcmd_t* target) { target->buttons |= BT_ACCELERATE; target->buttons &= ~BT_LOOKBACK; - target->buttons &= ~BT_RESPAWN; + target->buttons &= ~BT_BAIL; target->buttons &= ~BT_BRAKE; } } diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index f0c5f4f28..2ac3bb07a 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -32,12 +32,13 @@ typedef enum BT_BRAKE = 1<<3, // Brake BT_ATTACK = 1<<4, // Use Item BT_LOOKBACK = 1<<5, // Look Backward - BT_RESPAWN = 1<<6, // Respawn + BT_BAIL = 1<<6, // Bail BT_VOTE = 1<<7, // Vote BT_SPINDASH = 1<<8, // Spindash BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE), BT_SPINDASHMASK = (BT_ACCELERATE|BT_BRAKE|BT_DRIFT), + BT_RESPAWNMASK = (BT_EBRAKEMASK|BT_BAIL), // free: 1<<9 to 1<<12 diff --git a/src/deh_tables.c b/src/deh_tables.c index 7f3ac6310..9e037f4f2 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5057,11 +5057,12 @@ struct int_const_s const INT_CONST[] = { {"BT_BRAKE",BT_BRAKE}, {"BT_ATTACK",BT_ATTACK}, {"BT_LOOKBACK",BT_LOOKBACK}, - {"BT_RESPAWN",BT_RESPAWN}, + {"BT_BAIL",BT_BAIL}, {"BT_VOTE",BT_VOTE}, {"BT_SPINDASH",BT_SPINDASH}, // Real button now, but triggers the macro same as always. {"BT_EBRAKEMASK",BT_EBRAKEMASK}, // Macro button {"BT_SPINDASHMASK",BT_SPINDASHMASK}, // Macro button + {"BT_RESPAWNMASK",BT_RESPAWNMASK}, // Macro button {"BT_LUAA",BT_LUAA}, // Lua customizable {"BT_LUAB",BT_LUAB}, // Lua customizable {"BT_LUAC",BT_LUAC}, // Lua customizable diff --git a/src/g_build_ticcmd.cpp b/src/g_build_ticcmd.cpp index f32c1f509..cfd962e28 100644 --- a/src/g_build_ticcmd.cpp +++ b/src/g_build_ticcmd.cpp @@ -404,10 +404,7 @@ class TiccmdBuilder map(gc_item, BT_ATTACK); // fire map(gc_lookback, BT_LOOKBACK); // rear view - if (!modeattacking) - { - map(gc_respawn, BT_RESPAWN | (freecam() ? 0 : BT_EBRAKEMASK)); // respawn - } + map(gc_bail, BT_BAIL); // bail map(gc_vote, BT_VOTE); // mp general function button // lua buttons a thru c diff --git a/src/g_input.h b/src/g_input.h index d2f2d535c..7991923e8 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -123,7 +123,7 @@ typedef enum gc_lookback = gc_b, gc_spindash = gc_c, gc_brake = gc_x, - gc_respawn = gc_y, + gc_bail = gc_y, gc_vote = gc_z, gc_item = gc_l, gc_drift = gc_r, diff --git a/src/hud/input-display.cpp b/src/hud/input-display.cpp index c3dab0a53..14678c87a 100644 --- a/src/hud/input-display.cpp +++ b/src/hud/input-display.cpp @@ -113,7 +113,7 @@ void K_DrawInputDisplay(float x, float y, INT32 flags, char mode, UINT8 pid, boo box.patch(but('B', gc_b, BT_LOOKBACK)); box.patch(but('C', gc_c, BT_SPINDASH)); box.patch(but('X', gc_x, BT_BRAKE)); - box.patch(but('Y', gc_y, BT_RESPAWN)); + box.patch(but('Y', gc_y, BT_BAIL)); box.patch(but('Z', gc_z, BT_VOTE)); box.patch(but('L', gc_l, BT_ATTACK)); box.patch(but('R', gc_r, BT_DRIFT)); diff --git a/src/hud/spectator.cpp b/src/hud/spectator.cpp index f0606378a..512f64d6a 100644 --- a/src/hud/spectator.cpp +++ b/src/hud/spectator.cpp @@ -198,7 +198,7 @@ void K_drawSpectatorHUD(boolean director) } else { - bool press = D_LocalTiccmd(viewnum)->buttons & BT_RESPAWN; + bool press = D_LocalTiccmd(viewnum)->buttons & BT_BAIL; const char* label = (press && I_GetTime() % 16 < 8) ? "> <" : ">< "; list.insert({{label, press ? "" : ""}, {"Exit", ""}}); diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 3caab89e7..1d827138a 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -1803,7 +1803,7 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) if (K_TryRingShooter(player, botController) == true && player->botvars.respawnconfirm >= BOTRESPAWNCONFIRM) { // We want to respawn. Simply hold Y and stop here! - cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK); + cmd->buttons |= BT_RESPAWNMASK; return; } diff --git a/src/k_follower.c b/src/k_follower.c index aee769b95..b4ed0bf84 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -546,7 +546,7 @@ void K_HandleFollower(player_t *player) } // Sal: Turn the follower around when looking backwards. - if ( player->cmd.buttons & BT_LOOKBACK ) + if (K_GetKartButtons(player) & BT_LOOKBACK) { destAngle += ANGLE_180; } diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 986b28eaa..a5e25edbf 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -4876,7 +4876,7 @@ static void K_drawKartPlayerCheck(void) return; } - if (stplyr->cmd.buttons & BT_LOOKBACK) + if (K_GetKartButtons(stplyr) & BT_LOOKBACK) { return; } @@ -7521,7 +7521,7 @@ void K_drawKartHUD(void) if (ta) { using srb2::Draw; - Draw::TextElement text = Draw::TextElement().parse(" Restart"); + Draw::TextElement text = Draw::TextElement().parse(" Restart"); Draw(BASEVIDWIDTH - 19, 2) .flags(flags | V_YELLOWMAP) .align(Draw::Align::kRight) diff --git a/src/k_kart.c b/src/k_kart.c index cb62aa853..85d74c0cb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4069,8 +4069,16 @@ boolean K_KartKickstart(const player_t *player) UINT16 K_GetKartButtons(const player_t *player) { - return (player->cmd.buttons | - (K_KartKickstart(player) ? BT_ACCELERATE : 0)); + UINT16 buttons = player->cmd.buttons; + if ((buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK) + { + buttons &= ~BT_LOOKBACK; + } + if (K_KartKickstart(player)) + { + buttons = buttons | BT_ACCELERATE; + } + return buttons; } SINT8 K_GetForwardMove(const player_t *player) @@ -10129,7 +10137,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_RemoveGrowShrink(player); } - if (player->respawn.state != RESPAWNST_MOVE && (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN) + if (player->respawn.state != RESPAWNST_MOVE && (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK) { player->finalfailsafe++; // Decremented by ringshooter to "freeze" this timer // Part-way through the auto-respawn timer, you can tap Ring Shooter to respawn early @@ -13955,7 +13963,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } - if ((player->cmd.buttons & BT_VOTE) && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) + if ((player->cmd.buttons & BT_BAIL) && (player->cmd.buttons & BT_RESPAWNMASK) != BT_RESPAWNMASK && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active)) { boolean grounded = P_IsObjectOnGround(player->mo); onground && player->tumbleBounces == 0 ? player->bailcharge += 2 : player->bailcharge++; // charge twice as fast on the ground diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 3631441b0..4438781cc 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -466,7 +466,7 @@ boolean M_Responder(event_t *ev) if (Playing() && !demo.playback) { // Quick Retry (Y in modeattacking) - if (modeattacking && G_PlayerInputDown(0, gc_respawn, splitscreen + 1) == true) + if (modeattacking && G_PlayerInputDown(0, gc_bail, splitscreen + 1) == true) { M_TryAgain(0); return true; diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 628035f3a..1fc1b914e 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -39,10 +39,10 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL, "Brake / Go back", "Brake / Go back", "TLB_X", {.routine = M_ProfileSetControl}, gc_x, 0}, - {IT_CONTROL, "Respawn", "Respawn", + {IT_CONTROL, "Ring Bail", "Ring Bail / Burst", "TLB_Y", {.routine = M_ProfileSetControl}, gc_y, 0}, - {IT_CONTROL, "Action", "Multiplayer quick-chat / quick-vote", + {IT_CONTROL, "Action", "Quick-vote / Quick-chat / Time Attack Quick Restart", "TLB_Z", {.routine = M_ProfileSetControl}, gc_z, 0}, {IT_CONTROL, "Use Item", "Use item", diff --git a/src/objects/ring-shooter.c b/src/objects/ring-shooter.c index 83613d3c5..2f731a7cd 100644 --- a/src/objects/ring-shooter.c +++ b/src/objects/ring-shooter.c @@ -668,7 +668,7 @@ boolean Obj_PlayerRingShooterFreeze(const player_t *player) const mobj_t *base = player->ringShooter; if (AllowRingShooter(player) == true - && (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN + && (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK && P_MobjWasRemoved(base) == false) { return (rs_base_canceled(base) == 0); @@ -682,7 +682,7 @@ void Obj_RingShooterInput(player_t *player) mobj_t *const base = player->ringShooter; if (AllowRingShooter(player) == true - && (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN) + && (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK) { // "Freeze" final-failsafe timer if we're eligible to ringshooter, but don't reset it. if (player->finalfailsafe) diff --git a/src/p_user.c b/src/p_user.c index 74a4be388..feebebc48 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3067,7 +3067,7 @@ void P_DemoCameraMovement(camera_t *cam, UINT8 num) } // if you hold Y, you will lock on to displayplayer. (The last player you were ""f12-ing"") - if (cam->freecam && cmd->buttons & BT_RESPAWN) + if (cam->freecam && cmd->buttons & BT_BAIL) { lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); @@ -3369,7 +3369,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - lookback = ( player->cmd.buttons & BT_LOOKBACK ); + lookback = K_GetKartButtons(player) & BT_LOOKBACK; camspeed = cv_cam_speed[num].value; camstill = cv_cam_still[num].value || player->seasaw; // RR: seasaws lock the camera so that it isn't disorienting. From 590227a13509751e3e8bd9c802c96afe36c48c48 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 7 Jun 2025 17:37:14 -0400 Subject: [PATCH 32/64] Fix bailcharge fullbright --- src/info.c | 2 +- src/k_kart.c | 1 + src/objects/bail.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index d3bad37b5..a8133ddb3 100644 --- a/src/info.c +++ b/src/info.c @@ -2168,7 +2168,7 @@ state_t states[NUMSTATES] = {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 8, {NULL}, 8, 1, S_BAIB}, // S_BAIL {SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB {SPR_BAIC, FF_FULLBRIGHT|FF_ANIMATE|0, 11, {NULL}, 10, 1, S_NULL}, // S_BAIC - {SPR_TECH, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE + {SPR_TECH, 0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING {SPR_AMPC, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBODY diff --git a/src/k_kart.c b/src/k_kart.c index 85d74c0cb..d133b71db 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13971,6 +13971,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); P_SetTarget(&bail->target, player->mo); + bail->renderflags |= RF_FULLBRIGHT; // set fullbright here, were gonna animate frames in the thinker and it saves us from setting FF_FULLBRIGHT every frame } } else diff --git a/src/objects/bail.c b/src/objects/bail.c index cd8e2c686..c1c3a0d93 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -62,7 +62,6 @@ void Obj_BailChargeThink (mobj_t *aura) aura->flags |= MF_NOCLIPTHING; // aura->color = mo->color; - aura->anim_duration = 999; // This prevents FF_ANIMATE from working, we're gonna animate manually ourselves here aura->frame = ((player->bailcharge-1)/2); // By syncing the frame with the charge timer here fixed_t baseScale = 13*mo->scale/10; From f7c9f5dfafc9a1ae0c832b6b1447a5e7d1d5b76e Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 7 Jun 2025 18:03:56 -0400 Subject: [PATCH 33/64] Rebase whoopsies fixups --- src/k_kart.c | 1 + src/k_menufunc.c | 4 ++-- src/p_setup.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d133b71db..60bc2a5b0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10009,6 +10009,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Extra tripwire leniency for the end of invincibility if (player->invincibilitytimer <= 0) { player->tripwireLeniency = max( player->tripwireLeniency, TICRATE ); + } } if (player->baildrop) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 4438781cc..64da0fecd 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -465,8 +465,8 @@ boolean M_Responder(event_t *ev) // Special mid-game input behaviours if (Playing() && !demo.playback) { - // Quick Retry (Y in modeattacking) - if (modeattacking && G_PlayerInputDown(0, gc_bail, splitscreen + 1) == true) + // Quick Retry (Z in modeattacking) + if (modeattacking && G_PlayerInputDown(0, gc_vote, splitscreen + 1) == true) { M_TryAgain(0); return true; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 9a781ac12..b6bdc8c65 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -8698,7 +8698,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) if (G_IsModeAttackRetrying() && !demo.playback) { nowtime = lastwipetic; - while (G_PlayerInputDown(0, gc_respawn, splitscreen + 1) == true) + while (G_PlayerInputDown(0, gc_vote, splitscreen + 1) == true) { while (!((nowtime = I_GetTime()) - lastwipetic)) { From 254cb891c93c4e7da15868b3d9d2fe4ee24e1b0c Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 7 Jun 2025 20:21:37 -0400 Subject: [PATCH 34/64] Weaker bail boost, fix double flingring baildrop --- src/k_kart.c | 18 +++++------------- src/k_kart.h | 6 +++--- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 60bc2a5b0..32065eaf6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10045,6 +10045,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) P_FlingBurst(player, K_MomentumAngle(pmo), MT_FLINGRING, 10*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); S_StartSound(pmo, sfx_gshad); } + + player->baildrop--; + if (player->baildrop == 0) + player->ringboost /= 3; } // The precise ordering of start-of-level made me want to cut my head off, @@ -10065,16 +10069,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->cangrabitems && player->cangrabitems <= EARLY_ITEM_FLICKER) player->cangrabitems++; - if (player->baildrop) - { - if ((player->baildrop % BAIL_DROPFREQUENCY) == 0) - { - P_FlingBurst(player, K_MomentumAngle(player->mo), MT_FLINGRING, 10*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY); - S_StartSound(player->mo, sfx_gshad); - } - player->baildrop--; - } - if (!player->invincibilitytimer) player->invincibilityextensions = 0; @@ -13982,8 +13976,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((!P_PlayerInPain(player) && player->bailcharge) || player->bailcharge >= BAIL_MAXCHARGE) { - CONS_Printf("rl %d it %d ia %d ri %d sr %d pr %d\n", player->itemRoulette.active, player->itemtype, player->itemamount, player->rings > 0, player->superring > 0, player->pickuprings > 0); - player->bailcharge = 0; mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); @@ -13996,7 +13988,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->rings = 0; } - UINT32 totalrings = player->rings + player->superring + player->pickuprings + debtrings; + UINT32 totalrings = player->rings + player->superring + player->pickuprings; totalrings = max(totalrings, 0); UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST)); UINT32 baildrop = FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP)); diff --git a/src/k_kart.h b/src/k_kart.h index b2e3a02a6..914280fe5 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,9 +45,9 @@ Make sure this matches the actual number of states #define PUNISHWINDOW (7*TICRATE/10) #define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic -#define BAIL_DROP (FRACUNIT) -#define BAIL_BOOST (FRACUNIT) -#define BAIL_DROPFREQUENCY (3) +#define BAIL_DROP (FRACUNIT/2) +#define BAIL_BOOST (40*FRACUNIT/100) +#define BAIL_DROPFREQUENCY (1) #define BAILSTUN (TICRATE*10) #define MAXCOMBOTHRUST (mapobjectscale*20) From 1ef0cd03c665804c617b957a5a857bc282fcf610 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Sat, 7 Jun 2025 21:51:07 -0400 Subject: [PATCH 35/64] Small buff More bail time, more ringboost retention, more drops --- src/k_kart.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.h b/src/k_kart.h index 914280fe5..89f7fd13f 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,9 +45,9 @@ Make sure this matches the actual number of states #define PUNISHWINDOW (7*TICRATE/10) #define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic -#define BAIL_DROP (FRACUNIT/2) -#define BAIL_BOOST (40*FRACUNIT/100) -#define BAIL_DROPFREQUENCY (1) +#define BAIL_DROP (2*FRACUNIT/3) +#define BAIL_BOOST (80*FRACUNIT/100) +#define BAIL_DROPFREQUENCY (2) #define BAILSTUN (TICRATE*10) #define MAXCOMBOTHRUST (mapobjectscale*20) From a9a5e68c8a9f72f5058084ac14d7763b087db84d Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Sat, 7 Jun 2025 22:18:29 -0400 Subject: [PATCH 36/64] Keep even more speed 80%->90% --- src/k_kart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.h b/src/k_kart.h index 89f7fd13f..e5f209b05 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -46,7 +46,7 @@ Make sure this matches the actual number of states #define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic #define BAIL_DROP (2*FRACUNIT/3) -#define BAIL_BOOST (80*FRACUNIT/100) +#define BAIL_BOOST (90*FRACUNIT/100) #define BAIL_DROPFREQUENCY (2) #define BAILSTUN (TICRATE*10) From dc3c3a056ad66f252ed1617720bda9818460ca09 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 8 Jun 2025 08:50:08 -0400 Subject: [PATCH 37/64] Use balanced ringboost rolloff in baildrop instead of legacy ringboost rolloff --- src/k_kart.c | 4 +++- src/k_kart.h | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 32065eaf6..2a33a5da8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9823,7 +9823,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (!player->baildrop && (player->superring == 0 || player->stunned)) player->ringboost -= max((player->ringboost / roller), 1); - else if (K_LegacyRingboost(player) || player->baildrop) + else if (K_LegacyRingboost(player)) player->ringboost--; else player->ringboost -= min(K_GetFullKartRingPower(player, false) - 1, max(player->ringboost / 2 / roller, 1)); @@ -13989,6 +13989,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } UINT32 totalrings = player->rings + player->superring + player->pickuprings; + if (BAIL_CREDIT_DEBTRINGS) + totalrings += debtrings; totalrings = max(totalrings, 0); UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST)); UINT32 baildrop = FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP)); diff --git a/src/k_kart.h b/src/k_kart.h index e5f209b05..4b580f115 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,8 +45,9 @@ Make sure this matches the actual number of states #define PUNISHWINDOW (7*TICRATE/10) #define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic -#define BAIL_DROP (2*FRACUNIT/3) -#define BAIL_BOOST (90*FRACUNIT/100) +#define BAIL_DROP (FRACUNIT) +#define BAIL_BOOST (FRACUNIT) +#define BAIL_CREDIT_DEBTRINGS (true) #define BAIL_DROPFREQUENCY (2) #define BAILSTUN (TICRATE*10) From fffe84fd18f8c06fa1efe1cbbc278a4e153b3303 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 23 Jun 2025 18:02:10 -0400 Subject: [PATCH 38/64] Experimental 2 tics accidental bail guard prevents accidently bailing when trying to mash the respawn macro --- 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 2a33a5da8..53c89cf74 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13974,7 +13974,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge = 0; } - if ((!P_PlayerInPain(player) && player->bailcharge) || player->bailcharge >= BAIL_MAXCHARGE) + if ((!P_PlayerInPain(player) && player->bailcharge >= 5) || player->bailcharge >= BAIL_MAXCHARGE) { player->bailcharge = 0; From 2ec203822fa43d6faa98115a19db4089b89f1666 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 20 Jun 2025 15:19:34 -0400 Subject: [PATCH 39/64] Sakura protection (NEO damage rules) --- src/p_inter.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 04a05ce4c..510fb6d4a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3181,6 +3181,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } } + if (inflictor->momx == 0 && inflictor->momy == 0 && inflictor->momz == 0) + { + // Probably a map hazard. + allowcombo = false; + } + if (allowcombo == false && (target->eflags & MFE_PAUSED)) { return false; @@ -3395,18 +3401,22 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_PopPlayerShield(player); } - if (!(gametyperules & GTR_SPHERES) && player->tripwireLeniency) + boolean downgraded = false; + + if (!(gametyperules & GTR_SPHERES) && player->tripwireLeniency && !P_PlayerInPain(player)) { switch (type) { case DMG_EXPLODE: type = DMG_TUMBLE; + downgraded = true; break; case DMG_TUMBLE: softenTumble = true; break; case DMG_NORMAL: case DMG_WIPEOUT: + downgraded = true; type = DMG_STUMBLE; player->ringburst += 5; // THERE IS SIMPLY NO HOPE AT THIS POINT K_PopPlayerShield(player); @@ -3453,7 +3463,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da ringburst = 0; } - if (type != DMG_STUMBLE && type != DMG_WHUMBLE) + if ((type != DMG_STUMBLE && type != DMG_WHUMBLE) || (type == DMG_STUMBLE && downgraded)) { if (type != DMG_STING) player->flashing = K_GetKartFlashing(player); From 63c654c68cca3442eaef0e7685fcf06cf1ce16e6 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 00:51:08 -0400 Subject: [PATCH 40/64] Check for inflictor in stationary object combo --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 510fb6d4a..fe37ac519 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3181,7 +3181,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } } - if (inflictor->momx == 0 && inflictor->momy == 0 && inflictor->momz == 0) + if (inflictor && !P_MobjWasRemoved(inflictor) && inflictor->momx == 0 && inflictor->momy == 0 && inflictor->momz == 0) { // Probably a map hazard. allowcombo = false; From 3cd254d9476d9faac84c8c0d0832f9a7e6730122 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 23 Jun 2025 19:34:19 -0400 Subject: [PATCH 41/64] Sound effects source from the bail vfx object, so they should cancel if the effect ends early also audible to other players --- src/k_kart.c | 2 ++ src/objects/bail.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 53c89cf74..73d669606 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13965,6 +13965,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((P_PlayerInPain(player) && player->bailcharge == 1) || (grounded && P_PlayerInPain(player) && player->bailcharge == 2)) // this is brittle .. { mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); + S_StartSound(bail, sfx_gshb9); P_SetTarget(&bail->target, player->mo); bail->renderflags |= RF_FULLBRIGHT; // set fullbright here, were gonna animate frames in the thinker and it saves us from setting FF_FULLBRIGHT every frame } @@ -13979,6 +13980,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge = 0; mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); + S_StartSound(bail, sfx_kc33); P_SetTarget(&bail->target, player->mo); UINT32 debtrings = 20; diff --git a/src/objects/bail.c b/src/objects/bail.c index c1c3a0d93..47f839ea5 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -16,6 +16,7 @@ #include "../info.h" #include "../k_kart.h" #include "../p_local.h" +#include "../s_sound.h" void Obj_BailThink (mobj_t *aura) { @@ -56,6 +57,12 @@ void Obj_BailChargeThink (mobj_t *aura) mobj_t *mo = aura->target; player_t *player = mo->player; + // play sound + if (aura->target->player->bailcharge == 34 || aura->target->player->bailcharge == 34) + { + S_StartSound(aura, sfx_kc4e); + } + // Follow player aura->flags &= ~(MF_NOCLIPTHING); P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); From ff9644c278e2b3365886a3d6018e7feec1585552 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 23 Jun 2025 23:41:46 -0400 Subject: [PATCH 42/64] Sound effects again --- src/deh_tables.c | 4 +++- src/info.c | 11 ++++++++--- src/info.h | 4 +++- src/k_kart.c | 6 +++--- src/objects/bail.c | 6 ------ 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 9e037f4f2..a880a1766 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1575,7 +1575,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKBODY", "S_BAIL", - "S_BAIB", + "S_BAIB1", + "S_BAIB2", + "S_BAIB3", "S_BAIC", "S_BAILCHARGE", diff --git a/src/info.c b/src/info.c index a8133ddb3..93f6bddae 100644 --- a/src/info.c +++ b/src/info.c @@ -2165,10 +2165,15 @@ state_t states[NUMSTATES] = {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY - {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 8, {NULL}, 8, 1, S_BAIB}, // S_BAIL - {SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB + // why can we not use actions on spawn? I'd love to fix it but I imagine all sorts of crazy pain if I change something fundamental like that + {SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 9, {NULL}, 8, 1, S_BAIB1}, // S_BAIL + {SPR_BAIB, 0, 0, {A_PlaySound}, sfx_gshb2, 2, S_BAIB2}, // S_BAIB1 + {SPR_BAIB, 0, 0, {A_PlaySound}, sfx_gshbd, 2, S_BAIB3}, // S_BAIB2 + {SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB3 + {SPR_BAIC, FF_FULLBRIGHT|FF_ANIMATE|0, 11, {NULL}, 10, 1, S_NULL}, // S_BAIC - {SPR_TECH, 0, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE + + {SPR_TECH, 1, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE {SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING {SPR_AMPC, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBODY diff --git a/src/info.h b/src/info.h index 3a3354263..996b721e2 100644 --- a/src/info.h +++ b/src/info.h @@ -2635,7 +2635,9 @@ typedef enum state S_BLOCKBODY, S_BAIL, - S_BAIB, + S_BAIB1, + S_BAIB2, + S_BAIB3, S_BAIC, S_BAILCHARGE, diff --git a/src/k_kart.c b/src/k_kart.c index 73d669606..09c7fae63 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13965,7 +13965,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((P_PlayerInPain(player) && player->bailcharge == 1) || (grounded && P_PlayerInPain(player) && player->bailcharge == 2)) // this is brittle .. { mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE); - S_StartSound(bail, sfx_gshb9); + S_StartSound(bail, sfx_gshb9); // I tried to use info.c, but you can't play sounds on mobjspawn via A_PlaySound + S_StartSound(bail, sfx_kc4e); P_SetTarget(&bail->target, player->mo); bail->renderflags |= RF_FULLBRIGHT; // set fullbright here, were gonna animate frames in the thinker and it saves us from setting FF_FULLBRIGHT every frame } @@ -13980,7 +13981,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bailcharge = 0; mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL); - S_StartSound(bail, sfx_kc33); P_SetTarget(&bail->target, player->mo); UINT32 debtrings = 20; @@ -14054,7 +14054,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->amps > 0) K_DefensiveOverdrive(player); - S_StartSound(player->mo, sfx_gshdd); + S_StartSound(player->mo, sfx_kc33); } if (player && player->mo && K_PlayerCanUseItem(player)) diff --git a/src/objects/bail.c b/src/objects/bail.c index 47f839ea5..2b5b7d622 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -57,12 +57,6 @@ void Obj_BailChargeThink (mobj_t *aura) mobj_t *mo = aura->target; player_t *player = mo->player; - // play sound - if (aura->target->player->bailcharge == 34 || aura->target->player->bailcharge == 34) - { - S_StartSound(aura, sfx_kc4e); - } - // Follow player aura->flags &= ~(MF_NOCLIPTHING); P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); From b131b443538b577fa06f4319d3e6d409c67be28b Mon Sep 17 00:00:00 2001 From: Ashnal Date: Tue, 24 Jun 2025 22:45:11 -0400 Subject: [PATCH 43/64] bailquake --- src/d_player.h | 1 + src/k_kart.c | 4 ++++ src/lua_playerlib.c | 8 ++++++-- src/p_saveg.cpp | 2 ++ src/p_spec.c | 9 ++++++++- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index fddbd9c51..b35a60835 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -1083,6 +1083,7 @@ struct player_t UINT32 bailcharge; UINT32 baildrop; + UINT8 bailquake; boolean analoginput; // Has an input been recorded that requires analog usage? For input display. diff --git a/src/k_kart.c b/src/k_kart.c index 09c7fae63..89a9e8c2c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10051,6 +10051,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->ringboost /= 3; } + if (player->bailquake) + player->bailquake--; + // The precise ordering of start-of-level made me want to cut my head off, // so let's try this instead. Whatever! if (leveltime <= starttime || player->gradingpointnum == 0) @@ -14033,6 +14036,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1; K_AddHitLag(player->mo, TICRATE/4, false); + player->bailquake = player->mo->hitlag + TICRATE; // the quake effect that uses this will ignore it during hitlag and trigger after, so it needs to be longer than the hitlag if (P_PlayerInPain(player)) { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index faea1a8ee..ffbd731e6 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -285,9 +285,11 @@ static int player_get(lua_State *L) else if (fastcmp(field,"ringvisualwarning")) lua_pushboolean(L, plr->ringvisualwarning); else if (fastcmp(field,"bailcharge")) - lua_pushboolean(L, plr->bailcharge); + lua_pushinteger(L, plr->bailcharge); else if (fastcmp(field,"baildrop")) - lua_pushboolean(L, plr->baildrop); + lua_pushinteger(L, plr->baildrop); + else if (fastcmp(field,"bailquake")) + lua_pushinteger(L, plr->bailquake); else if (fastcmp(field,"dotrickfx")) lua_pushboolean(L, plr->dotrickfx); else if (fastcmp(field,"stingfx")) @@ -918,6 +920,8 @@ static int player_set(lua_State *L) plr->bailcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"baildrop")) plr->baildrop = luaL_checkinteger(L, 3); + else if (fastcmp(field,"bailquake")) + plr->bailquake = luaL_checkinteger(L, 3); else if (fastcmp(field,"analoginput")) plr->analoginput = luaL_checkboolean(L, 3); else if (fastcmp(field,"transfer")) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 878572929..869a4730b 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -669,6 +669,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].bailcharge); WRITEUINT32(save->p, players[i].baildrop); + WRITEUINT8(save->p, players[i].bailquake); WRITEUINT8(save->p, players[i].analoginput); @@ -1327,6 +1328,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].bailcharge = READUINT32(save->p); players[i].baildrop = READUINT32(save->p); + players[i].bailquake = READUINT8(save->p); players[i].analoginput = READUINT8(save->p); diff --git a/src/p_spec.c b/src/p_spec.c index ca923d809..e543456af 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9635,7 +9635,7 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) quake = quake->next; } - // Add level-based effects. + // Add level-based effects, and local bailquake if (P_MobjWasRemoved(viewer->mo) == false && viewer->speed > viewer->mo->scale && P_IsObjectOnGround(viewer->mo) == true) @@ -9653,6 +9653,13 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) ir = FixedMul((viewer->stairjank * FRACUNIT * 5) / 17, mapobjectscale); addZ += ir; } + + // add bail effect + if (viewer->bailquake > 0 && !viewer->mo->hitlag) // only start after hitlag ends + { + ir = FixedMul((viewer->bailquake * FRACUNIT * 5) / 17, mapobjectscale); + addZ += ir; + } } fixed_t maxShake = FixedMul(cv_cam_height[view].value, mapobjectscale) * 3 / 4; From b4075a7446f7df52a69ab55b0a501fc6ba796ad4 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 14:09:57 -0400 Subject: [PATCH 44/64] Remove Ball Hog missiles when exploding --- src/p_enemy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 3006b7369..788103dcd 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12206,6 +12206,8 @@ void A_BallhogExplode(mobj_t *actor) mo2->destscale = mo2->scale; P_SetTarget(&mo2->target, actor->target); S_StartSound(mo2, actor->info->deathsound); + + actor->fuse = 1; return; } From 9ee69ec1db2f03eee9a9d811ca19d1abfd9a0bde Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 19 Jun 2025 21:46:56 +1000 Subject: [PATCH 45/64] Track player Flybot767 spawns using a mobj pointer instead of a flag in the stunned timer --- src/d_player.h | 1 + src/k_kart.c | 14 ++++---------- src/k_objects.h | 1 + src/lua_playerlib.c | 9 +++++++++ src/objects/flybot767.c | 28 +++++++++++++++++++++++++++- src/p_inter.c | 3 ++- src/p_mobj.c | 5 +++++ src/p_saveg.cpp | 18 ++++++++++++++++-- 8 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 16339b32a..d8500b557 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -741,6 +741,7 @@ struct player_t UINT16 tumbleHeight; // In *mobjscaled* fracunits, or mfu, not raw fu UINT16 stunned; // Number of tics during which rings cannot be picked up UINT8 stunnedCombo; // Number of hits sustained while stunned, reduces consecutive stun penalties + mobj_t *flybot; // One Flybot767 circling the player while stunned UINT8 justDI; // Turn-lockout timer to briefly prevent unintended turning after DI, resets when actionable or no input boolean flipDI; // Bananas flip the DI direction. Was a bug, but it made bananas much more interesting. diff --git a/src/k_kart.c b/src/k_kart.c index 5ac1ba0ad..493776254 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9738,23 +9738,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) && P_IsObjectOnGround(player->mo) ) { - // MEGA FUCKING HACK BECAUSE P_SAVEG MOBJS ARE FULL - // Would updating player_saveflags to 32 bits have any negative consequences? - // For now, player->stunned 16th bit is a flag to determine whether the flybots were spawned - // timer counts down at triple speed while spindashing - player->stunned = (player->stunned & 0x8000) | max(0, (player->stunned & 0x7FFF) - (player->spindash ? 3 : 1)); + player->stunned = max(0, player->stunned - (player->spindash ? 3 : 1)); - // when timer reaches 0, reset the flag and stun combo counter - if ((player->stunned & 0x7FFF) == 0) + // when timer reaches 0, reset the stun combo counter + if (player->stunned == 0) { - player->stunned = 0; player->stunnedCombo = 0; } // otherwise if the flybots aren't spawned, spawn them now! - else if ((player->stunned & 0x8000) == 0) + else if (P_MobjWasRemoved(player->flybot)) { - player->stunned |= 0x8000; Obj_SpawnFlybotsForPlayer(player); } } diff --git a/src/k_objects.h b/src/k_objects.h index f5c36da12..060e43144 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -440,6 +440,7 @@ void Obj_DestroyedKartParticleLanding(mobj_t *part); void Obj_SpawnFlybotsForPlayer(player_t *player); void Obj_FlybotThink(mobj_t *flybot); void Obj_FlybotDeath(mobj_t *flybot); +void Obj_FlybotRemoved(mobj_t *flybot); /* Pulley */ void Obj_PulleyThink(mobj_t *root); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 1a7d199c0..b6ebacae1 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -264,6 +264,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->stunned); else if (fastcmp(field,"stunnedcombo")) lua_pushinteger(L, plr->stunnedCombo); + else if (fastcmp(field,"flybot")) + LUA_PushUserdata(L, plr->flybot, META_MOBJ); else if (fastcmp(field,"justdi")) lua_pushinteger(L, plr->justDI); else if (fastcmp(field,"flipdi")) @@ -898,6 +900,13 @@ static int player_set(lua_State *L) plr->stunned = luaL_checkinteger(L, 3); else if (fastcmp(field,"stunnedcombo")) plr->stunnedCombo = luaL_checkinteger(L, 3); + else if (fastcmp(field,"flybot")) + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->flybot, mo); + } else if (fastcmp(field,"justdi")) plr->justDI = luaL_checkinteger(L, 3); else if (fastcmp(field,"flipdi")) diff --git a/src/objects/flybot767.c b/src/objects/flybot767.c index 790276387..edf59cd57 100644 --- a/src/objects/flybot767.c +++ b/src/objects/flybot767.c @@ -43,6 +43,7 @@ void Obj_SpawnFlybotsForPlayer(player_t *player) { UINT8 i; mobj_t *mo = player->mo; + mobj_t *hprev = mo; fixed_t radius = mo->radius; for (i = 0; i < FLYBOT_QUANTITY; i++) @@ -61,6 +62,17 @@ void Obj_SpawnFlybotsForPlayer(player_t *player) flybot->movedir = flybot->old_angle = flybot->angle = angle + ANGLE_90; flybot->old_z = SetFlybotZ(flybot); flybot->renderflags |= (i * RF_DONTDRAW); + + if (hprev->player) + { + P_SetTarget(&player->flybot, flybot); + } + else + { + P_SetTarget(&hprev->hnext, flybot); + P_SetTarget(&flybot->hprev, hprev); + } + hprev = flybot; } } @@ -80,7 +92,7 @@ void Obj_FlybotThink(mobj_t *flybot) if (mo->player) { - if (((stunned = mo->player->stunned & 0x7FFF) == 0) || (mo->player->playerstate == PST_DEAD)) + if (((stunned = mo->player->stunned) == 0) || (mo->player->playerstate == PST_DEAD)) { P_KillMobj(flybot, NULL, NULL, 0); return; @@ -120,6 +132,11 @@ void Obj_FlybotDeath(mobj_t *flybot) if (!P_MobjWasRemoved(mo)) { + if (mo->player && (flybot == mo->player->flybot)) + { + P_SetTarget(&mo->player->flybot, NULL); + } + mom.x = mo->momx; mom.y = mo->momy; mom.z = mo->momz; @@ -140,3 +157,12 @@ void Obj_FlybotDeath(mobj_t *flybot) angle += ANGLE_90; } } + +void Obj_FlybotRemoved(mobj_t *flybot) +{ + mobj_t *mo = flybot->target; + if (!P_MobjWasRemoved(mo) && mo->player && (flybot == mo->player->flybot)) + { + P_SetTarget(&mo->player->flybot, NULL); + } +} diff --git a/src/p_inter.c b/src/p_inter.c index 04a05ce4c..dea1597d0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3504,7 +3504,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { player->stunnedCombo++; } - player->stunned = (player->stunned & 0x8000) | min(0x7FFF, (player->stunned & 0x7FFF) + stunTics); + stunTics = min(player->stunned + stunTics, UINT16_MAX); + player->stunned = stunTics; #undef MIN_STUNTICS #undef MAX_STUNTICS diff --git a/src/p_mobj.c b/src/p_mobj.c index da3e08bc6..fe7b5f0fc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11855,6 +11855,11 @@ void P_RemoveMobj(mobj_t *mobj) Obj_UnlinkRocks(mobj); break; } + case MT_FLYBOT767: + { + Obj_FlybotRemoved(mobj); + break; + } default: { break; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 98e544cd4..1bbfb36c5 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -72,8 +72,7 @@ static savebuffer_t *current_savebuffer; #define ARCHIVEBLOCK_WAYPOINTS 0x7F46498F #define ARCHIVEBLOCK_RNG 0x7FAAB5BD -// Note: This cannot be bigger -// than an UINT16 (for now) +// Note: This cannot have more than 32 entries typedef enum { AWAYVIEW = 0x0001, @@ -93,6 +92,7 @@ typedef enum BARRIER = 0x4000, BALLHOGRETICULE = 0x8000, STONESHOE = 0x10000, + FLYBOT = 0x20000, } player_saveflags; static inline void P_ArchivePlayer(savebuffer_t *save) @@ -368,6 +368,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (players[i].stoneShoe) flags |= STONESHOE; + if (players[i].flybot) + flags |= FLYBOT; + WRITEUINT32(save->p, flags); if (flags & SKYBOXVIEW) @@ -418,6 +421,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (flags & STONESHOE) WRITEUINT32(save->p, players[i].stoneShoe->mobjnum); + if (flags & FLYBOT) + WRITEUINT32(save->p, players[i].flybot->mobjnum); + WRITEUINT32(save->p, (UINT32)players[i].followitem); WRITEUINT32(save->p, players[i].charflags); @@ -1073,6 +1079,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) if (flags & STONESHOE) players[i].stoneShoe = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & FLYBOT) + players[i].flybot = (mobj_t *)(size_t)READUINT32(save->p); + players[i].followitem = (mobjtype_t)READUINT32(save->p); //SetPlayerSkinByNum(i, players[i].skin); @@ -6232,6 +6241,11 @@ static void P_RelinkPointers(void) if (!RelinkMobj(&players[i].stoneShoe)) CONS_Debug(DBG_GAMELOGIC, "stoneShoe not found on player %d\n", i); } + if (players[i].flybot) + { + if (!RelinkMobj(&players[i].flybot)) + CONS_Debug(DBG_GAMELOGIC, "flybot not found on player %d\n", i); + } } } From 2c11aa36c32ae8b4fbe0a4b9c702369b6eddf9ed Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 19 Jun 2025 22:13:23 +1000 Subject: [PATCH 46/64] Move stunned timer calculations from P_DamageMobj into K_ApplyStun --- src/k_kart.c | 26 ++++++++++++++++++++++++++ src/k_kart.h | 2 ++ src/p_inter.c | 22 +--------------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 493776254..4b3445f2b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16307,4 +16307,30 @@ fixed_t K_TeamComebackMultiplier(player_t *player) return multiplier; } +void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + #define BASE_STUN_TICS_MIN (4 * TICRATE) + #define BASE_STUN_TICS_MAX (10 * TICRATE) + UINT16 stunTics = 0; + + stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, BASE_STUN_TICS_MAX, BASE_STUN_TICS_MIN); + stunTics >>= player->stunnedCombo; // consecutive hits add half as much stun as the previous hit + + // 1/3 base stun values in battle + if (gametyperules & GTR_SPHERES) + { + stunTics /= 3; + } + + if (player->stunnedCombo < UINT8_MAX) + { + player->stunnedCombo++; + } + stunTics = min(player->stunned + stunTics, UINT16_MAX); + player->stunned = stunTics; + + #undef BASE_STUN_TICS_MIN + #undef BASE_STUN_TICS_MAX +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 9d9f3fdf8..a31e886d3 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -340,6 +340,8 @@ boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2, boolean allowHostile); fixed_t K_TeamComebackMultiplier(player_t *player); +void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_inter.c b/src/p_inter.c index dea1597d0..aaf0c7f0b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3041,7 +3041,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da UINT8 type = (damagetype & DMG_TYPEMASK); const boolean hardhit = (type == DMG_EXPLODE || type == DMG_KARMA || type == DMG_TUMBLE); // This damage type can do evil stuff like ALWAYS combo INT16 ringburst = 5; - UINT16 stunTics = 0; // Check if the player is allowed to be damaged! // If not, then spawn the instashield effect instead. @@ -3488,26 +3487,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // Apply stun! - // Feel free to move these calculations higher up if different damage sources should apply variable stun in future - #define MIN_STUNTICS (4 * TICRATE) - #define MAX_STUNTICS (10 * TICRATE) - stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, MAX_STUNTICS, MIN_STUNTICS); - stunTics >>= player->stunnedCombo; // consecutive hits add half as much stun as the previous hit - - // 1/3 base stun values in battle - if (gametyperules & GTR_SPHERES) - { - stunTics /= 3; - } - - if (player->stunnedCombo < UINT8_MAX) - { - player->stunnedCombo++; - } - stunTics = min(player->stunned + stunTics, UINT16_MAX); - player->stunned = stunTics; - #undef MIN_STUNTICS - #undef MAX_STUNTICS + K_ApplyStun(player, inflictor, source, damage, damagetype); K_DefensiveOverdrive(target->player); } From f24a5db5d20118eaa1e92028c8861c2383a4d962 Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 19 Jun 2025 22:14:41 +1000 Subject: [PATCH 47/64] Don't apply any stunned tics on ring sting --- src/p_inter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index aaf0c7f0b..730b53664 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3487,7 +3487,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // Apply stun! - K_ApplyStun(player, inflictor, source, damage, damagetype); + if (damagetype != DMG_STING) + { + K_ApplyStun(player, inflictor, source, damage, damagetype); + } K_DefensiveOverdrive(target->player); } From da6d7ec6b134241d08227973103450c1ac8d3f4f Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 19 Jun 2025 22:24:23 +1000 Subject: [PATCH 48/64] Reduce stunned tics in games with more than 8 players --- 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 4b3445f2b..df60e23ac 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16311,12 +16311,30 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama { #define BASE_STUN_TICS_MIN (4 * TICRATE) #define BASE_STUN_TICS_MAX (10 * TICRATE) - UINT16 stunTics = 0; + INT32 stunTics = 0; + UINT8 numPlayers = 0; + UINT8 i; + // calculate the number of players playing + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + { + numPlayers++; + } + } + + // calculate base stun tics stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, BASE_STUN_TICS_MAX, BASE_STUN_TICS_MIN); stunTics >>= player->stunnedCombo; // consecutive hits add half as much stun as the previous hit - // 1/3 base stun values in battle + // reduce stun in games with more than 8 players + if (numPlayers > 8) + { + stunTics -= 17 * (numPlayers - 8); + } + + // 1/3 stun values in battle if (gametyperules & GTR_SPHERES) { stunTics /= 3; @@ -16326,7 +16344,7 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama { player->stunnedCombo++; } - stunTics = min(player->stunned + stunTics, UINT16_MAX); + stunTics = min(max(player->stunned + stunTics, 0), UINT16_MAX); player->stunned = stunTics; #undef BASE_STUN_TICS_MIN From fceaad44ab8683e2f8d27892e772c1b1b54ca678 Mon Sep 17 00:00:00 2001 From: eebrozgi Date: Thu, 19 Jun 2025 15:49:46 +0300 Subject: [PATCH 49/64] Spindash to spin Flybots faster btw ring sting change doesn't work yet, somehow --- src/objects/flybot767.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/objects/flybot767.c b/src/objects/flybot767.c index edf59cd57..c9bd6014b 100644 --- a/src/objects/flybot767.c +++ b/src/objects/flybot767.c @@ -97,6 +97,13 @@ void Obj_FlybotThink(mobj_t *flybot) P_KillMobj(flybot, NULL, NULL, 0); return; } + + // If player is spindashing, spin faster to hint that stun is going down faster + else if (mo->player->spindash) + { + speed *= 2; + //flybot->movedir += FLYBOT_BOB_FREQUENCY; + } } flybot->frame = flybot->frame & ~FF_TRANSMASK; From d58414b4405a835ab42f9b4f80718e70567ffe04 Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 19 Jun 2025 22:54:19 +1000 Subject: [PATCH 50/64] Don't apply any stunned tics on ring sting (but for real this time) --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 730b53664..ca9183cc8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3487,7 +3487,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // Apply stun! - if (damagetype != DMG_STING) + if (type != DMG_STING) { K_ApplyStun(player, inflictor, source, damage, damagetype); } From fceb325bd4879c48255dcfd52dbd3f55142607f4 Mon Sep 17 00:00:00 2001 From: Lach Date: Fri, 20 Jun 2025 20:40:29 +1000 Subject: [PATCH 51/64] Remove stacked stunned tics --- src/d_player.h | 1 - src/k_kart.c | 17 +++-------------- src/lua_playerlib.c | 4 ---- src/p_saveg.cpp | 2 -- 4 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index d8500b557..a5219c816 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -740,7 +740,6 @@ struct player_t UINT8 tumbleBounces; UINT16 tumbleHeight; // In *mobjscaled* fracunits, or mfu, not raw fu UINT16 stunned; // Number of tics during which rings cannot be picked up - UINT8 stunnedCombo; // Number of hits sustained while stunned, reduces consecutive stun penalties mobj_t *flybot; // One Flybot767 circling the player while stunned UINT8 justDI; // Turn-lockout timer to briefly prevent unintended turning after DI, resets when actionable or no input boolean flipDI; // Bananas flip the DI direction. Was a bug, but it made bananas much more interesting. diff --git a/src/k_kart.c b/src/k_kart.c index df60e23ac..37452e6be 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9741,13 +9741,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // timer counts down at triple speed while spindashing player->stunned = max(0, player->stunned - (player->spindash ? 3 : 1)); - // when timer reaches 0, reset the stun combo counter - if (player->stunned == 0) - { - player->stunnedCombo = 0; - } - // otherwise if the flybots aren't spawned, spawn them now! - else if (P_MobjWasRemoved(player->flybot)) + // if the flybots aren't spawned, spawn them now! + if (player->stunned != 0 && P_MobjWasRemoved(player->flybot)) { Obj_SpawnFlybotsForPlayer(player); } @@ -16326,7 +16321,6 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama // calculate base stun tics stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, BASE_STUN_TICS_MAX, BASE_STUN_TICS_MIN); - stunTics >>= player->stunnedCombo; // consecutive hits add half as much stun as the previous hit // reduce stun in games with more than 8 players if (numPlayers > 8) @@ -16340,12 +16334,7 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama stunTics /= 3; } - if (player->stunnedCombo < UINT8_MAX) - { - player->stunnedCombo++; - } - stunTics = min(max(player->stunned + stunTics, 0), UINT16_MAX); - player->stunned = stunTics; + player->stunned = max(stunTics, 0); #undef BASE_STUN_TICS_MIN #undef BASE_STUN_TICS_MAX diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index b6ebacae1..6dcbc527f 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -262,8 +262,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->tumbleHeight); else if (fastcmp(field,"stunned")) lua_pushinteger(L, plr->stunned); - else if (fastcmp(field,"stunnedcombo")) - lua_pushinteger(L, plr->stunnedCombo); else if (fastcmp(field,"flybot")) LUA_PushUserdata(L, plr->flybot, META_MOBJ); else if (fastcmp(field,"justdi")) @@ -898,8 +896,6 @@ static int player_set(lua_State *L) plr->tumbleHeight = luaL_checkinteger(L, 3); else if (fastcmp(field,"stunned")) plr->stunned = luaL_checkinteger(L, 3); - else if (fastcmp(field,"stunnedcombo")) - plr->stunnedCombo = luaL_checkinteger(L, 3); else if (fastcmp(field,"flybot")) { mobj_t *mo = NULL; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 1bbfb36c5..9908c3bba 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -470,7 +470,6 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].tumbleBounces); WRITEUINT16(save->p, players[i].tumbleHeight); WRITEUINT16(save->p, players[i].stunned); - WRITEUINT8(save->p, players[i].stunnedCombo); WRITEUINT8(save->p, players[i].justDI); WRITEUINT8(save->p, players[i].flipDI); @@ -1129,7 +1128,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].tumbleBounces = READUINT8(save->p); players[i].tumbleHeight = READUINT16(save->p); players[i].stunned = READUINT16(save->p); - players[i].stunnedCombo = READUINT8(save->p); players[i].justDI = READUINT8(save->p); players[i].flipDI = (boolean)READUINT8(save->p); From 546bb52e3b25f969dd1d2367dec4378711712d0a Mon Sep 17 00:00:00 2001 From: Lach Date: Fri, 20 Jun 2025 20:57:31 +1000 Subject: [PATCH 52/64] Reduce stunned tics for damage caused by non-players --- src/k_kart.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 37452e6be..6a83abda4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16334,6 +16334,22 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama stunTics /= 3; } + if (source && source->player) + { + // hits scored by players apply full stun + ; + } + else if (inflictor && (P_IsKartItem(inflictor->type) || P_IsKartFieldItem(inflictor->type))) + { + // items not thrown by a player apply half stun + stunTics /= 2; + } + else + { + // all other hazards apply 1/4 stun + stunTics /= 4; + } + player->stunned = max(stunTics, 0); #undef BASE_STUN_TICS_MIN From 51abee48cd2d1c64ad0b24610e0863c5dd7bdcef Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 14:23:32 -0400 Subject: [PATCH 53/64] Reduce stun based on distance to leader --- src/k_kart.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6a83abda4..794f193b4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16302,10 +16302,12 @@ fixed_t K_TeamComebackMultiplier(player_t *player) return multiplier; } -void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, ATTRUNUSED INT32 damage, ATTRUNUSED UINT8 damagetype) { #define BASE_STUN_TICS_MIN (4 * TICRATE) #define BASE_STUN_TICS_MAX (10 * TICRATE) + #define MAX_STUN_REDUCTION (FRACUNIT/2) + #define STUN_REDUCTION_DISTANCE (20000) INT32 stunTics = 0; UINT8 numPlayers = 0; UINT8 i; @@ -16350,10 +16352,20 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 dama stunTics /= 4; } + UINT32 dist = K_GetItemRouletteDistance(player, D_NumPlayersInRace()); + if (dist > STUN_REDUCTION_DISTANCE) + dist = STUN_REDUCTION_DISTANCE; + + fixed_t distfactor = FixedDiv(dist, STUN_REDUCTION_DISTANCE); // 0-1 as you approach STUN_REDUCTION_DISTANCE + fixed_t stunfactor = Easing_Linear(distfactor, FRACUNIT, MAX_STUN_REDUCTION); + stunTics = FixedMul(stunTics*FRACUNIT, stunfactor)/FRACUNIT; + player->stunned = max(stunTics, 0); #undef BASE_STUN_TICS_MIN #undef BASE_STUN_TICS_MAX + #undef MAX_STUN_REDUCTION + #undef STUN_REDUCTION_DISTANCE } //} From dd0b9a97fcc4c1cce7ea1df0c6b03bbfc8107abc Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 14:59:22 -0400 Subject: [PATCH 54/64] Longer bufo invinc, decreases always --- src/k_powerup.cpp | 2 +- src/p_user.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index 2efd94b84..bf3cad8ed 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -65,7 +65,7 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) } S_StartSound(NULL, sfx_gsha7l); - player->flashing = 2*TICRATE; + player->flashing = 3*TICRATE; player->mo->hitlag += BATTLE_POWERUP_VFX_TIME; player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME); diff --git a/src/p_user.c b/src/p_user.c index 74a4be388..019050b9b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4564,9 +4564,7 @@ void P_PlayerThink(player_t *player) // Strength counts up to diminish fade. if (player->flashing && player->flashing < UINT16_MAX && - (player->spectator || !P_PlayerInPain(player)) && - // Battle: flashing tics do not decrease in the air - (!(gametyperules & GTR_BUMPERS) || P_IsObjectOnGround(player->mo))) + (player->spectator || !P_PlayerInPain(player))) { player->flashing--; } From 4e23ebe95b778cefac784d8c2198367f35473ce6 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 15:33:45 -0400 Subject: [PATCH 55/64] Players with bubbleblowup aren't guarding --- src/k_kart.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 5ac1ba0ad..f9e7b6b8c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1185,6 +1185,11 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) boolean guard1 = K_PlayerGuard(mobj1->player); boolean guard2 = K_PlayerGuard(mobj2->player); + if (mobj1->player->bubbleblowup) + guard1 = false; + if (mobj2->player->bubbleblowup) + guard2 = false; + if (guard1 && guard2) K_DoPowerClash(mobj1, mobj2); else if (guard1) @@ -4556,12 +4561,16 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { UINT8 lag1 = 5; UINT8 lag2 = 5; + boolean stripbubble = (gametyperules & GTR_BUMPERS); + // short-circuit instashield for vfx visibility if (t1->player) { t1->player->instashield = 1; t1->player->speedpunt += 20; lag1 -= min(lag1, t1->player->speedpunt/10); + if (stripbubble && t1->player->curshield == KSHIELD_BUBBLE) + K_PopBubbleShield(t1->player); } if (t2->player) @@ -4569,6 +4578,8 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { t2->player->instashield = 1; t2->player->speedpunt += 20; lag2 -= min(lag1, t2->player->speedpunt/10); + if (stripbubble && t2->player->curshield == KSHIELD_BUBBLE) + K_PopBubbleShield(t2->player); } S_StartSound(t1, sfx_parry); From 72c680b54f25e7e416375b3cf4a62877073fb5b7 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 15:57:34 -0400 Subject: [PATCH 56/64] In Battle, pop bubble on damage or clash and increase cooldown --- src/k_collide.cpp | 14 ++++++++++++-- src/k_kart.c | 7 +++++-- src/k_kart.h | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 0de68598c..443b8fcbc 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -885,18 +885,28 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) thing = oldthing; P_SetTarget(&g_tm.thing, oldg_tm.thing);*/ + boolean hit = false; + if (K_KartBouncing(t2, t1->target) == true) { if (t2->player && t1->target && t1->target->player) { - K_PvPTouchDamage(t2, t1->target); + hit = K_PvPTouchDamage(t2, t1->target); } // Don't play from t1 else it gets cut out... for some reason. S_StartSound(t2, sfx_s3k44); } - return true; + if (hit && (gametyperules & GTR_BUMPERS)) + { + K_PopBubbleShield(t1->target->player); + return false; + } + else + { + return true; + } } if (K_BubbleShieldCanReflect(t1, t2)) diff --git a/src/k_kart.c b/src/k_kart.c index f9e7b6b8c..be13789bf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -72,8 +72,11 @@ // comeback is Battle Mode's karma comeback, also bool // mapreset is set when enough players fill an empty server -static void K_PopBubbleShield(player_t *player) +void K_PopBubbleShield(player_t *player) { + if (player->curshield != KSHIELD_BUBBLE) + return; + S_StartSound(player->mo, sfx_kc31); K_StripItems(player); K_AddHitLag(player->mo, 4, false); @@ -14566,7 +14569,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) S_StartSound(player->mo, sfx_s3k75); player->bubbleblowup++; - player->bubblecool = player->bubbleblowup*4; + player->bubblecool = player->bubbleblowup * (gametyperules & GTR_BUMPERS ? 6 : 4); if (player->bubbleblowup > bubbletime*2) { diff --git a/src/k_kart.h b/src/k_kart.h index 9d9f3fdf8..6b810d6c6 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -111,6 +111,8 @@ Make sure this matches the actual number of states angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); +void K_PopBubbleShield(player_t *player); + boolean K_IsDuelItem(mobjtype_t type); boolean K_DuelItemAlwaysSpawns(mapthing_t *mt); boolean K_InRaceDuel(void); From dfaece7d3d74a08b9cc27000f5a3fe44a5d100ab Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Wed, 25 Jun 2025 16:26:56 -0400 Subject: [PATCH 57/64] Do guardbreak in touchdamage, guarantee punish (PF2_ALWAYSDAMAGED) --- src/d_player.h | 11 ++++++----- src/k_collide.cpp | 21 +++++++++++++++++++++ src/k_kart.c | 21 ++------------------- src/p_inter.c | 6 ++++++ 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 16339b32a..74ff42cdc 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -135,11 +135,12 @@ typedef enum typedef enum { - PF2_SELFMUTE = 1<<1, - PF2_SELFDEAFEN = 1<<2, - PF2_SERVERMUTE = 1<<3, - PF2_SERVERDEAFEN = 1<<4, - PF2_STRICTFASTFALL = 1<<5, + PF2_SELFMUTE = 1<<1, + PF2_SELFDEAFEN = 1<<2, + PF2_SERVERMUTE = 1<<3, + PF2_SERVERDEAFEN = 1<<4, + PF2_STRICTFASTFALL = 1<<5, + PF2_ALWAYSDAMAGED = 1<<6, } pflags2_t; typedef enum diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 443b8fcbc..0392e0133 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -1168,6 +1168,27 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return false; } + + boolean guard1 = K_PlayerGuard(t1->player); + boolean guard2 = K_PlayerGuard(t2->player); + + // Bubble Shield physically extends past guard when inflated, + // makes some sense to suppress this behavior + if (t1->player->bubbleblowup) + guard1 = false; + if (t2->player->bubbleblowup) + guard2 = false; + + if (guard1 && guard2) + K_DoPowerClash(t1, t2); + else if (guard1) + K_DoGuardBreak(t1, t2); + else if (guard2) + K_DoGuardBreak(t2, t1); + + if (guard1 || guard2) + return false; + // Clash instead of damage if both parties have any of these conditions auto canClash = [](mobj_t *t1, mobj_t *t2) { diff --git a/src/k_kart.c b/src/k_kart.c index be13789bf..41087e46c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1182,25 +1182,6 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) K_SpawnBumpForObjs(mobj1, mobj2); - if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER - && !mobj1->player->powerupVFXTimer && !mobj2->player->powerupVFXTimer) - { - boolean guard1 = K_PlayerGuard(mobj1->player); - boolean guard2 = K_PlayerGuard(mobj2->player); - - if (mobj1->player->bubbleblowup) - guard1 = false; - if (mobj2->player->bubbleblowup) - guard2 = false; - - if (guard1 && guard2) - K_DoPowerClash(mobj1, mobj2); - else if (guard1) - K_DoGuardBreak(mobj1, mobj2); - else if (guard2) - K_DoGuardBreak(mobj2, mobj1); - } - K_PlayerJustBumped(mobj1->player); K_PlayerJustBumped(mobj2->player); @@ -4620,7 +4601,9 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { angle_t thrangle = R_PointToAngle2(t2->x, t2->y, t1->x, t1->y); P_Thrust(t1, thrangle, 7*mapobjectscale); + t1->player->pflags2 |= PF2_ALWAYSDAMAGED; P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE); + t1->player->pflags2 &= ~PF2_ALWAYSDAMAGED; clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK); diff --git a/src/p_inter.c b/src/p_inter.c index 04a05ce4c..251dd917a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3094,6 +3094,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da invincible = false; } + if (player->pflags2 && PF2_ALWAYSDAMAGED) + { + invincible = false; + clash = false; + } + // TODO: doing this from P_DamageMobj limits punting to objects that damage the player. // And it may be kind of yucky. // But this is easier than accounting for every condition in PIT_CheckThing! From 71a11753155eccfa4df2c2c859aa4e7612ef63f8 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Wed, 25 Jun 2025 18:07:52 -0400 Subject: [PATCH 58/64] Bail quake is multiversal Everyone should feel that shit --- src/k_kart.c | 15 ++++++++++++++- src/p_spec.c | 7 +------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 89a9e8c2c..1ae47cc90 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10054,6 +10054,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->bailquake) player->bailquake--; + // bail camera shake + if (player->bailquake > 0 && !player->mo->hitlag) // only start after hitlag ends + { + P_StartQuakeFromMobj(1, 50 * player->mo->scale, 2048 * player->mo->scale, player->mo); + } + + + // The precise ordering of start-of-level made me want to cut my head off, // so let's try this instead. Whatever! if (leveltime <= starttime || player->gradingpointnum == 0) @@ -14036,7 +14044,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1; K_AddHitLag(player->mo, TICRATE/4, false); - player->bailquake = player->mo->hitlag + TICRATE; // the quake effect that uses this will ignore it during hitlag and trigger after, so it needs to be longer than the hitlag + player->bailquake = player->mo->hitlag; // the quake effect that uses this will ignore it during hitlag and trigger after, so it needs to be longer than the hitlag + + //if (player->mo->hitlag > 0) // bail blink; make the player invisible during the swish, like classic games. + //{ + //player->mo->renderflags |= RF_DONTDRAW; + //} if (P_PlayerInPain(player)) { diff --git a/src/p_spec.c b/src/p_spec.c index e543456af..4f7606aaa 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9654,12 +9654,7 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) addZ += ir; } - // add bail effect - if (viewer->bailquake > 0 && !viewer->mo->hitlag) // only start after hitlag ends - { - ir = FixedMul((viewer->bailquake * FRACUNIT * 5) / 17, mapobjectscale); - addZ += ir; - } + } fixed_t maxShake = FixedMul(cv_cam_height[view].value, mapobjectscale) * 3 / 4; From 82c0aa400b42edfcddd1c97b2f506386ea840385 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Wed, 25 Jun 2025 18:52:44 -0400 Subject: [PATCH 59/64] 16P Stun Nerf + Flybots bob faster Above 8P, stun timer nerf nerfed from 17t->6t; flybots don't just orbit faster, they bob faster too. --- src/k_kart.c | 2 +- src/objects/flybot767.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 794f193b4..4a05d3f82 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -16327,7 +16327,7 @@ void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, ATTRUNUSED // reduce stun in games with more than 8 players if (numPlayers > 8) { - stunTics -= 17 * (numPlayers - 8); + stunTics -= 6 * (numPlayers - 8); } // 1/3 stun values in battle diff --git a/src/objects/flybot767.c b/src/objects/flybot767.c index c9bd6014b..32293aeec 100644 --- a/src/objects/flybot767.c +++ b/src/objects/flybot767.c @@ -102,7 +102,7 @@ void Obj_FlybotThink(mobj_t *flybot) else if (mo->player->spindash) { speed *= 2; - //flybot->movedir += FLYBOT_BOB_FREQUENCY; + flybot->movedir += FLYBOT_BOB_FREQUENCY*2; } } From 1086c1e7990ed4ff3b4c918c68e9ae5f401f31f9 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 25 Jun 2025 19:07:10 -0400 Subject: [PATCH 60/64] Bailquake Cleanup --- src/d_player.h | 2 +- src/k_kart.c | 20 +++++--------------- src/lua_playerlib.c | 4 ++-- src/p_spec.c | 4 +--- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index b35a60835..2fd34d7f6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -1083,7 +1083,7 @@ struct player_t UINT32 bailcharge; UINT32 baildrop; - UINT8 bailquake; + boolean bailquake; boolean analoginput; // Has an input been recorded that requires analog usage? For input display. diff --git a/src/k_kart.c b/src/k_kart.c index 1ae47cc90..b13d383ee 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10051,16 +10051,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->ringboost /= 3; } - if (player->bailquake) - player->bailquake--; - - // bail camera shake - if (player->bailquake > 0 && !player->mo->hitlag) // only start after hitlag ends + if (player->bailquake) // quake as soon as we leave hitlag { - P_StartQuakeFromMobj(1, 50 * player->mo->scale, 2048 * player->mo->scale, player->mo); - } - - + P_StartQuakeFromMobj(7, 50 * player->mo->scale, 2048 * player->mo->scale, player->mo); + player->bailquake = false; + } // The precise ordering of start-of-level made me want to cut my head off, // so let's try this instead. Whatever! @@ -14044,12 +14039,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1; K_AddHitLag(player->mo, TICRATE/4, false); - player->bailquake = player->mo->hitlag; // the quake effect that uses this will ignore it during hitlag and trigger after, so it needs to be longer than the hitlag - - //if (player->mo->hitlag > 0) // bail blink; make the player invisible during the swish, like classic games. - //{ - //player->mo->renderflags |= RF_DONTDRAW; - //} + player->bailquake = true; // set for a one time quake effect as soon as hitlag ends if (P_PlayerInPain(player)) { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index ffbd731e6..0b0e541bd 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -289,7 +289,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"baildrop")) lua_pushinteger(L, plr->baildrop); else if (fastcmp(field,"bailquake")) - lua_pushinteger(L, plr->bailquake); + lua_pushboolean(L, plr->bailquake); else if (fastcmp(field,"dotrickfx")) lua_pushboolean(L, plr->dotrickfx); else if (fastcmp(field,"stingfx")) @@ -921,7 +921,7 @@ static int player_set(lua_State *L) else if (fastcmp(field,"baildrop")) plr->baildrop = luaL_checkinteger(L, 3); else if (fastcmp(field,"bailquake")) - plr->bailquake = luaL_checkinteger(L, 3); + plr->bailquake = luaL_checkboolean(L, 3); else if (fastcmp(field,"analoginput")) plr->analoginput = luaL_checkboolean(L, 3); else if (fastcmp(field,"transfer")) diff --git a/src/p_spec.c b/src/p_spec.c index 4f7606aaa..36e6531b7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9635,7 +9635,7 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) quake = quake->next; } - // Add level-based effects, and local bailquake + // Add level-based effects if (P_MobjWasRemoved(viewer->mo) == false && viewer->speed > viewer->mo->scale && P_IsObjectOnGround(viewer->mo) == true) @@ -9653,8 +9653,6 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) ir = FixedMul((viewer->stairjank * FRACUNIT * 5) / 17, mapobjectscale); addZ += ir; } - - } fixed_t maxShake = FixedMul(cv_cam_height[view].value, mapobjectscale) * 3 / 4; From e5c981d4ba6dbd2975717bfc674a795bce21f934 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 25 Jun 2025 19:15:57 -0400 Subject: [PATCH 61/64] Bail invisibility --- src/objects/bail.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/objects/bail.c b/src/objects/bail.c index 2b5b7d622..4d3d6824d 100644 --- a/src/objects/bail.c +++ b/src/objects/bail.c @@ -39,6 +39,10 @@ void Obj_BailThink (mobj_t *aura) fixed_t baseScale = 12*mo->scale/10; P_SetScale(aura, baseScale); + + // make target player invisible during the effect, like the retro games + if (aura->state == &states[S_BAIL]) + mo->renderflags |= RF_DONTDRAW; } } From e4c36130e50ecdc53d10a577046bcd5b3e47eec1 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 25 Jun 2025 19:47:58 -0400 Subject: [PATCH 62/64] oops, make sure to only quake after hitlag --- 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 b13d383ee..5c26285fb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10051,11 +10051,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->ringboost /= 3; } - if (player->bailquake) // quake as soon as we leave hitlag + if (player->bailquake && !player->mo->hitlag) // quake as soon as we leave hitlag { P_StartQuakeFromMobj(7, 50 * player->mo->scale, 2048 * player->mo->scale, player->mo); player->bailquake = false; - } + } // The precise ordering of start-of-level made me want to cut my head off, // so let's try this instead. Whatever! From 862dd784d187a61ac08abea758810cbfe5947259 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Wed, 25 Jun 2025 20:02:51 -0400 Subject: [PATCH 63/64] Further reaching sfx All sounds reach further. Charging up noises are 4x away, ring swish and Gunstar explosions are 8x away (gloat dist) --- src/sounds.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sounds.c b/src/sounds.c index a14aa31b5..bb8c55633 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -778,7 +778,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc33", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, @@ -805,7 +805,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop-shot"}, {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, - {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4e", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, @@ -1432,18 +1432,18 @@ sfxinfo_t S_sfx[NUMSFX] = {"gshaf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"gshb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"gshb2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away {"gshb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshb8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"gshb9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"gshb9", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x4away {"gshba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshbb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshbc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"gshbd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"gshbd", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away {"gshbe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshbf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshc0a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, From 6a327ffb286ab9b23cafcf0821534307b02b1456 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Thu, 26 Jun 2025 20:28:14 -0400 Subject: [PATCH 64/64] Absolutely fuck it, noclipthing during powerupvfx --- src/k_kart.c | 2 ++ src/k_powerup.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 41087e46c..2f4b9ac7e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10310,6 +10310,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->powerupVFXTimer > 0) { player->powerupVFXTimer--; + if (player->powerupVFXTimer == 0) + player->mo->flags &= ~MF_NOCLIPTHING; } if (player->dotrickfx && !player->mo->hitlag) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index bf3cad8ed..38ece8439 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -68,6 +68,7 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) player->flashing = 3*TICRATE; player->mo->hitlag += BATTLE_POWERUP_VFX_TIME; player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; + player->mo->flags |= MF_NOCLIPTHING; Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME); g_darkness.start = leveltime;