From febc28a172997f5cedb05e107b4f391d9f7064f2 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Wed, 15 Oct 2025 21:47:53 +0200 Subject: [PATCH] Revive the v2 death animation --- src/info/mobjs.h | 2 + src/info/sprites.h | 2 + src/info/states.h | 4 ++ src/k_collide.c | 1 + src/k_kart.c | 8 ++++ src/p_inter.c | 92 ++++++++++++++++++++++++++++++++++++++++------ src/p_map.c | 15 ++++++++ src/p_mobj.c | 20 +++++++--- src/p_user.c | 7 ++-- 9 files changed, 132 insertions(+), 19 deletions(-) diff --git a/src/info/mobjs.h b/src/info/mobjs.h index f20c04676..024a4cfea 100644 --- a/src/info/mobjs.h +++ b/src/info/mobjs.h @@ -5,6 +5,8 @@ _(UNKNOWN) _(THOK) // Thok! mobj _(SHADOW) // Linkdraw Shadow (for invisible objects) _(PLAYER) +_(KART_LEFTOVER) +_(KART_TIRE) // Enemies _(BLUECRAWLA) // Crawla (Blue) diff --git a/src/info/sprites.h b/src/info/sprites.h index 5f2407e5c..508098164 100644 --- a/src/info/sprites.h +++ b/src/info/sprites.h @@ -7,6 +7,8 @@ _(UNKN) _(THOK) // Thok! mobj _(PLAY) +_(KART) +_(TIRE) // Enemies _(POSS) // Crawla (Blue) diff --git a/src/info/states.h b/src/info/states.h index e6ee33b80..a4fda74b2 100644 --- a/src/info/states.h +++ b/src/info/states.h @@ -48,6 +48,10 @@ _(KART_SIGN) // technically the player goes here but it's an infinite tic state _(OBJPLACE_DUMMY) +_(KART_LEFTOVER) +_(KART_LEFTOVER_NOTIRES) +_(KART_TIRE) + // Blue Crawla _(POSS_STND) _(POSS_RUN1) diff --git a/src/k_collide.c b/src/k_collide.c index a2a9950ed..db3ba4a02 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -593,6 +593,7 @@ boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2) return (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG || t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK + || t2->type == MT_KART_LEFTOVER || (t2->type == MT_PLAYER && t1->target != t2)); } diff --git a/src/k_kart.c b/src/k_kart.c index 01bdf6060..920b236c0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -500,6 +500,14 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) break; weight = K_PlayerWeight(mobj, against); break; + case MT_KART_LEFTOVER: + weight = 5*FRACUNIT/2; + + if (mobj->extravalue1 > 0) + { + weight = mobj->extravalue1 * (FRACUNIT >> 1); + } + break; case MT_BUBBLESHIELD: if (!mobj->target) break; diff --git a/src/p_inter.c b/src/p_inter.c index fdff30205..d37a8faab 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1550,13 +1550,82 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget break; case MT_PLAYER: - if (damagetype != DMG_SPECTATOR) + if (damagetype == DMG_SPECTATOR) + break; + + target->fuse = 3*TICRATE; // timer before mobj disappears from view (even if not an actual player) + target->momx = target->momy = target->momz = 0; + P_SetObjectMomZ(target, 14*FRACUNIT, false); + P_PlayDeathSound(target); + + if (target->player == NULL || skins[target->player->skin].flags & SF_OLDDEATH) + break; + + angle_t flingangle; + if (!P_MobjWasRemoved(source)) + flingangle = R_PointToAngle2( + source->x - source->momx, source->y - source->momy, + target->x, target->y + ); + else { - target->fuse = TICRATE; - target->momx = target->momy = target->momz = 0; - P_SetObjectMomZ(target, 14*FRACUNIT, false); - P_PlayDeathSound(target); + // -45..-30 or 30..45 + fixed_t offset = P_RandomRange(15, 45)*FRACUNIT; + if (offset < 30*FRACUNIT) + offset -= 60*FRACUNIT; + flingangle = target->angle + ANGLE_180 + FixedAngle(offset); } + + // Spawn kart frame + mobj_t *kart = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_LEFTOVER); + + if (kart && !P_MobjWasRemoved(kart)) + { + kart->angle = target->angle; + kart->color = target->color; + kart->extravalue1 = target->player->kartweight; + + // Copy interp data + kart->old_angle = target->old_angle; + kart->old_x = target->old_x; + kart->old_y = target->old_y; + kart->old_z = target->old_z; + + if (damagetype != DMG_TIMEOVER) + { + kart->angle = flingangle + ANGLE_180; + P_KillMobj(kart, inflictor, source, damagetype); + } + else + P_SetMobjState(kart, S_KART_LEFTOVER_NOTIRES); + + // Spawn tires (this makes no sense being here...) + angle_t tireangle = flingangle - ANGLE_90 - ANGLE_22h; + for (INT32 i = 0; i < 4; i++, tireangle += ANGLE_45) + { + if (i == 2) tireangle += ANGLE_90; + + mobj_t *tire = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_TIRE); + tire->fuse = 2*TICRATE; + tire->angle = tireangle; + if (i == 0 || i == 3) + P_SetScale(tire, (tire->destscale = 3*tire->scale/4)); + P_InstaThrust(tire, tireangle, 3 * tire->scale); + P_SetObjectMomZ(tire, 10*FRACUNIT, false); + } + } + + P_InstaThrust(target, flingangle, 4 * target->scale); + break; + + case MT_KART_LEFTOVER: + target->fuse = 2*TICRATE; + target->flags &= ~(MF_SOLID|MF_SHOOTABLE); + P_UnsetThingPosition(target); + target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; + P_SetThingPosition(target); + P_InstaThrust(target, target->angle, target->scale); + P_SetObjectMomZ(target, 10*FRACUNIT, false); break; case MT_METALSONIC_RACE: @@ -1935,15 +2004,16 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, { if (gametyperules & GTR_CIRCUIT) { - mobj_t *boom; - - player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); - player->mo->renderflags |= RF_DONTDRAW; - - boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM); + mobj_t *boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM); boom->scale = player->mo->scale; boom->angle = player->mo->angle; P_SetTarget(&boom->target, player->mo); + + if (skins[player->skin].flags & SF_OLDDEATH) + { + player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); + player->mo->renderflags |= RF_DONTDRAW; + } } K_DestroyBumpers(player, player->bumper); diff --git a/src/p_map.c b/src/p_map.c index 4be5c52b7..a8ed2270f 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1285,6 +1285,21 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return BMIT_CONTINUE; } + else if (thing->type == MT_KART_LEFTOVER) + { + // see if it went over / under + if (g_tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (g_tm.thing->z + g_tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + if (P_IsObjectOnGround(thing) && g_tm.thing->momz < 0) + K_KartBouncing(g_tm.thing, thing, true, false); + else + K_KartBouncing(g_tm.thing, thing, false, false); + + return BMIT_CONTINUE; + } else if (thing->flags & MF_SOLID) { // see if it went over / under diff --git a/src/p_mobj.c b/src/p_mobj.c index 67d2678bb..7e801a78f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7987,15 +7987,21 @@ static boolean P_MobjDeadThink(mobj_t *mobj) return false; } } - else // Apply gravity to fall downwards. + // Apply gravity to fall downwards. + else if (skins[mobj->player->skin].flags & SF_OLDDEATH) { P_SetObjectMomZ(mobj, -3*FRACUNIT/2, true); - - if (mobj->player && (skins[mobj->player->skin].flags & SF_OLDDEATH)) - { + if (mobj->player != NULL) mobj->player->drawangle -= ANGLE_22h; - } } + else + { + P_SetObjectMomZ(mobj, -7*FRACUNIT/8, true); + } + break; + case MT_KART_LEFTOVER: + mobj->angle += ANG15; + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); break; case MT_METALSONIC_RACE: { @@ -10947,6 +10953,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) switch (thing->type) { case MT_PLAYER: + case MT_KART_LEFTOVER: case MT_SMALLMACE: case MT_BIGMACE: case MT_PUMA: @@ -11357,6 +11364,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->color = BALLOONCOLORS[P_RandomKey(sizeof(BALLOONCOLORS))]; } break; + case MT_KART_LEFTOVER: + mobj->color = SKINCOLOR_RED; + break; case MT_REDRING: // Make MT_REDRING red by default mobj->color = skincolor_redring; break; diff --git a/src/p_user.c b/src/p_user.c index f5fc933c6..beaa9d206 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2562,7 +2562,8 @@ static void P_DeathThink(player_t *player) if (player->mo) { player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); - player->mo->renderflags |= RF_DONTDRAW; + if (skins[player->skin].flags & SF_OLDDEATH) + player->mo->renderflags |= RF_DONTDRAW; } } else @@ -2922,14 +2923,14 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mo = player->mo; - /*if (player->playerstate == PST_DEAD) + if (player->playerstate != PST_LIVE && !(skins[player->skin].flags & SF_OLDDEATH)) { // Do not move the camera while dead! if (thiscam->chase) P_CalcChasePostImg(player, thiscam); return true; - }*/ + } if ((player->pflags & PF_NOCONTEST)) // 1 for momentum keep, 2 for turnaround timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1);