diff --git a/extras/udmf-spec.txt b/extras/udmf-spec.txt index 08c185bc2..cabc7ba6b 100644 --- a/extras/udmf-spec.txt +++ b/extras/udmf-spec.txt @@ -233,6 +233,7 @@ BlanKart's namespace implements the following additional fields: redpogospring = ; // true = players are bounced into the air by this sector. yellowpogospring = ; // true = players are bounced into the air and then speedcapped by this sector. walltransfer = ; // true = players are allowed to slide up walls from this sector. + bumpyroad = ; // true = players are visually tilted by this sector to simulate a bumpy road. Does not effect gameplay. repeatspecial = ; // true = repeatable action. continuousspecial = ; // true = action is executed every game tick. @@ -318,3 +319,6 @@ BK 1.0: 11.03.2025 BK 1.0 22.03.2026 - Added more effects. + +BK 1.0 21.04.2026 +- Added bumpy road effect. diff --git a/src/k_kart.c b/src/k_kart.c index 15d147caa..222aaecf1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12034,4 +12034,21 @@ void K_KartAttractHomingAttack(player_t *player) } #undef TargetThreshold +// Visual effect for bumpy road sector. +void K_KartPlayerBumpyRoad(player_t *player) +{ + if (player->speed > 4*mapobjectscale && abs(player->karttilt) < FRACUNIT/2) + { + fixed_t baseimpulse = 9*FRACUNIT * (player->karttiltmomentum ? intsign(player->karttiltmomentum) : 1); + fixed_t rate = CLAMP(FixedDiv(player->speed, K_GetKartSpeed(player, false, false)), 6*FRACUNIT/10, FRACUNIT); + if (abs(player->karttiltmomentum) < abs(baseimpulse)) + { + player->karttilt = (FRACUNIT/2) * (player->karttiltmomentum ? intsign(player->karttiltmomentum) : 1); + player->karttiltmomentum = 0; + K_AddTiltImpulse(player, player->mo->height/2, baseimpulse); + S_StartSoundAtVolume(player->mo, sfx_s3k56, CLAMP((200*rate)/FRACUNIT, 0, 200)); + } + } +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 9e2c7bb08..841dd0905 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -442,6 +442,8 @@ void K_AddTiltImpulse(player_t *player, fixed_t distance, fixed_t force); void K_KartAttractHomingAttack(player_t *player); +void K_KartPlayerBumpyRoad(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_terrain.c b/src/k_terrain.c index e8dddb4cb..3bfdf79c5 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -633,17 +633,9 @@ void K_ProcessTerrainEffect(mobj_t *mo) K_DoSneaker(player, SNEAKERTYPE_WATERPANEL); } - if ((terrain->flags & TRF_BUMPY) && player->speed > 4*mapobjectscale && abs(player->karttilt) < FRACUNIT/2) + if (terrain->flags & TRF_BUMPY) { - fixed_t baseimpulse = 9*FRACUNIT * (player->karttiltmomentum ? intsign(player->karttiltmomentum) : 1); - fixed_t rate = CLAMP(FixedDiv(player->speed, K_GetKartSpeed(player, false, false)), 6*FRACUNIT/10, FRACUNIT); - if (abs(player->karttiltmomentum) < abs(baseimpulse)) - { - player->karttilt = (FRACUNIT/2) * (player->karttiltmomentum ? intsign(player->karttiltmomentum) : 1); - player->karttiltmomentum = 0; - K_AddTiltImpulse(player, mo->height/2, baseimpulse); - S_StartSoundAtVolume(mo, sfx_s3k56, CLAMP((200*rate)/FRACUNIT, 0, 200)); - } + K_KartPlayerBumpyRoad(player); } // Speed pad diff --git a/src/p_setup.c b/src/p_setup.c index a0a7622c1..38c7bfd51 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1941,6 +1941,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char sectors[i].specialflags |= SSF_GRAVITYOVERRIDE; else if (fastcmp(param, "walltransfer") && fastcmp("true", val)) sectors[i].specialflags |= SSF_WALLTRANSFER; + else if (fastcmp(param, "bumpyroad") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_BUMPYROAD; else if (fastcmp(param, "friction")) sectors[i].friction = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "gravity")) @@ -3164,6 +3166,8 @@ static void P_WriteTextmap(void) fprintf(f, "gravityoverride = true;\n"); if (wsectors[i].specialflags & SSF_WALLTRANSFER) fprintf(f, "walltransfer = true;\n"); + if (wsectors[i].specialflags & SSF_BUMPYROAD) + fprintf(f, "bumpyroad = true;\n"); if (wsectors[i].friction != ORIG_FRICTION) fprintf(f, "friction = %f;\n", FIXED_TO_FLOAT(wsectors[i].friction)); if (wsectors[i].gravity != FRACUNIT) diff --git a/src/p_spec.c b/src/p_spec.c index b7751f8ea..4ca222114 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5232,7 +5232,6 @@ static void P_ProcessPogoSpring(player_t *player, boolean isTouching, int type) static void P_ProcessBoostPanel(player_t *player, boolean isTouching, int type) { - if (player->mo->terrain && K_AffectingTerrainActive()) { if (player->mo->terrain->flags & TRF_SNEAKERPANEL) @@ -5248,7 +5247,6 @@ static void P_ProcessBoostPanel(player_t *player, boolean isTouching, int type) } } - if (isTouching) { if (!player->floorboost) @@ -5360,6 +5358,20 @@ static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end) player->speed = speed; } +static void P_ProcessBumpyRoad(player_t *player, boolean isTouching) +{ + if (player->mo->terrain && (player->mo->terrain->flags & TRF_BUMPY)) + { + // Don't double process bumpy roads. + return; + } + + if (isTouching) + { + K_KartPlayerBumpyRoad(player); + } +} + static boolean P_SectorHasSpecial(sector_t *sec) { if (sec->specialflags) @@ -5433,6 +5445,8 @@ static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t player->pflags |= PF_HITFINISHLINE; } } + if (sector->specialflags & SSF_BUMPYROAD) + P_ProcessBumpyRoad(player, isTouching); } static void P_EvaluateDamageType(player_t *player, sector_t *sector, boolean isTouching) diff --git a/src/r_defs.h b/src/r_defs.h index 5d6506441..057dcb9c2 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -398,6 +398,7 @@ typedef enum SSF_NOPHYSICSCEILING = 1<<18, SSF_GRAVITYOVERRIDE = 1<<19, // combine with MSF_GRAVITYFLIP SSF_WALLTRANSFER = 1<<20, + SSF_BUMPYROAD = 1<<21, } sectorspecialflags_t; typedef enum