diff --git a/src/k_hud.cpp b/src/k_hud.cpp index ec93ed554..db6d7e701 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -1889,6 +1889,179 @@ static void K_drawKartItem(void) } } +// So, like, we've already established that HUD code is unsavable, right? +static void K_drawBackupItem(void) +{ + // ITEM_X = BASEVIDWIDTH-50; // 270 + // ITEM_Y = 24; // 24 + + // Why write V_DrawScaledPatch calls over and over when they're all the same? + // Set to 'no item' just in case. + const UINT8 offset = 1; + patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw }; + UINT8 localamt[3] = {0, 0, 0}; + patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); + patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]); + INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags... + const INT32 numberdisplaymin = ((!offset && stplyr->itemtype == KITEM_ORBINAUT) ? 5 : 2); + skincolornum_t localcolor[3] = { static_cast(stplyr->skincolor) }; + SINT8 colormode[3] = { TC_RAINBOW }; + boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff + + fixed_t rouletteOffset = 0; + fixed_t rouletteSpace = ROULETTE_SPACING; + vector2_t rouletteCrop = {7, 7}; + + boolean flashOnOne = false; + boolean flashOnTwo = false; + + if (stplyr->backupitemamount <= 0) + return; + + switch (stplyr->backupitemtype) + { + case KITEM_INVINCIBILITY: + localpatch[1] = localinv; + localbg = kp_itembg[offset+1]; + break; + + case KITEM_ORBINAUT: + localpatch[1] = kp_orbinaut[(offset ? 4 : std::min(stplyr->itemamount-1, 3))]; + break; + + case KITEM_SPB: + case KITEM_LIGHTNINGSHIELD: + case KITEM_BUBBLESHIELD: + case KITEM_FLAMESHIELD: + localbg = kp_itembg[offset+1]; + /*FALLTHRU*/ + + default: + localpatch[1] = K_GetCachedItemPatch(stplyr->backupitemtype, offset); + + if (localpatch[1] == NULL) + localpatch[1] = kp_nodraw; // diagnose underflows + break; + } + + // pain and suffering defined below + if (offset) + { + if (!(R_GetViewNumber() & 1)) // If we are P1 or P3... + { + fx = 0; + fy = 0; + fflags = V_SNAPTOLEFT|V_SNAPTOTOP|V_SPLITSCREEN; + } + else // else, that means we're P2 or P4. + { + fx = ITEM2_X*2; + fy = 0; + fflags = V_SNAPTORIGHT|V_SNAPTOTOP|V_SPLITSCREEN; + flipamount = true; + } + + rouletteSpace = ROULETTE_SPACING_SPLITSCREEN; + rouletteOffset = FixedMul(rouletteOffset, FixedDiv(ROULETTE_SPACING_SPLITSCREEN, ROULETTE_SPACING)); + rouletteCrop.x = 16; + rouletteCrop.y = 15; + } + else + { + fx = ITEM_X; + fy = ITEM_Y; + fflags = V_SNAPTOTOP|V_SNAPTOLEFT|V_SPLITSCREEN; + } + + if (r_splitscreen == 1) + { + fy -= 5; + } + + auto draw_item = [&](fixed_t y, int i) + { + const UINT8 *colormap = (localcolor[i] ? R_GetTranslationColormap(colormode[i], localcolor[i], GTC_CACHE) : NULL); + V_DrawFixedPatch( + fx< 1) + { + using srb2::Draw; + Draw( + fx + rouletteCrop.x + FixedToFloat(rouletteSpace/2), + fy + rouletteCrop.y + FixedToFloat(rouletteOffset + y + rouletteSpace) - (r_splitscreen > 1 ? 15 : 33)) + .font(r_splitscreen > 1 ? Draw::Font::kRollingNum4P : Draw::Font::kRollingNum) + .align(Draw::Align::kCenter) + .flags(V_HUDTRANS|V_SLIDEIN|fflags) + .colormap(colormap) + .text("{}", localamt[i]); + } + }; + + draw_item(rouletteSpace, 0); + draw_item(-rouletteSpace, 2); + + if (false) + { + // Draw the item underneath the box. + draw_item(0, 1); + V_ClearClipRect(); + } + else + { + // Draw the item above the box. + V_ClearClipRect(); + + boolean transflag = V_HUDTRANS; + + if (cv_reducevfx.value && (flashOnOne || flashOnTwo)) + { + transflag = V_HUDTRANSHALF; + } + + if (stplyr->backupitemamount >= numberdisplaymin && stplyr->itemRoulette.active == false) + { + /* + // Then, the numbers: + V_DrawScaledPatch( + fx + (flipamount ? 48 : 0), fy, + V_HUDTRANS|V_SLIDEIN|fflags|(flipamount ? V_FLIP : 0), + kp_itemmulsticker[offset] + ); // flip this graphic for p2 and p4 in split and shift it. + */ + + V_DrawFixedPatch( + fx<backupitemamount)); + else + V_DrawString(fx+24, fy+31, V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->backupitemamount)); + } + else + { + V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx); + V_DrawTimerString(fx+38, fy+36, V_HUDTRANS|V_SLIDEIN|fflags, va("%d", stplyr->backupitemamount)); + } + } + else + { + V_DrawFixedPatch( + fx<backupitemtype) + K_drawBackupItem(); } } } diff --git a/src/k_hud_track.cpp b/src/k_hud_track.cpp index 0307babb5..301f2f52d 100644 --- a/src/k_hud_track.cpp +++ b/src/k_hud_track.cpp @@ -378,6 +378,17 @@ bool is_object_tracking_target(const mobj_t* mobj) return !(mobj->renderflags & (RF_TRANSMASK | RF_DONTDRAW)) && // the spraycan wasn't collected yet P_CheckSight(stplyr->mo, const_cast(mobj)); + case MT_JAWZ: + case MT_JAWZ_SHIELD: + case MT_ORBINAUT: + case MT_ORBINAUT_SHIELD: + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + case MT_LANDMINE: + case MT_BANANA: + case MT_BANANA_SHIELD: + return (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player && stplyr == mobj->target->player); + default: return false; } diff --git a/src/k_kart.c b/src/k_kart.c index c524af727..7395d9aa1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8349,6 +8349,21 @@ static void K_MoveHeldObjects(player_t *player) } } +// If we can move our backup item into main slots, do so. +static void K_TryMoveBackupItem(player_t *player) +{ + if (player->itemtype == KITEM_NONE && player->backupitemtype) + { + player->itemtype = player->backupitemtype; + player->itemamount = player->backupitemamount; + + player->backupitemtype = 0; + player->backupitemamount = 0; + + S_StartSound(player->mo, sfx_mbs54); + } +} + mobj_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) { fixed_t best = INT32_MAX; @@ -9158,16 +9173,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->itemtype == KITEM_NONE) player->itemflags &= ~IF_HOLDREADY; - if (player->itemtype == KITEM_NONE && player->backupitemtype) - { - player->itemtype = player->backupitemtype; - player->itemamount = player->backupitemamount; - - player->backupitemtype = 0; - player->backupitemamount = 0; - - S_StartSound(player->mo, sfx_mbs54); - } + K_TryMoveBackupItem(player); if (onground || player->transfer < 10*player->mo->scale) { @@ -15464,7 +15470,7 @@ UINT32 K_GetNumGradingPoints(void) return numlaps * (1 + Obj_GetCheckpointCount()); } -static SINT8 K_PickUp(player_t *player, mobj_t *picked) +static void K_PickUp(player_t *player, mobj_t *picked) { SINT8 type = -1; SINT8 amount = 1; @@ -15502,7 +15508,9 @@ static SINT8 K_PickUp(player_t *player, mobj_t *picked) break; } - if (player->itemtype == type && player->itemamount && !player->itemflags & IF_ITEMOUT) + // CONS_Printf("it %d ia %d t %d a %d\n", player->itemtype, player->itemamount, type, amount); + + if (player->itemtype == type && player->itemamount && !(player->itemflags & IF_ITEMOUT)) { // We have this item in main slot but not deployed, just add it player->itemamount += amount; @@ -15519,6 +15527,7 @@ static SINT8 K_PickUp(player_t *player, mobj_t *picked) K_DropPaperItem(player, player->backupitemtype, player->backupitemamount); player->backupitemtype = type; player->backupitemamount = amount; + S_StartSound(player->mo, sfx_kc65); } } else @@ -15529,6 +15538,7 @@ static SINT8 K_PickUp(player_t *player, mobj_t *picked) } S_StartSound(player->mo, sfx_gsha7); + K_TryMoveBackupItem(player); } // ACHTUNG this destroys items when returning true, make sure to bail out @@ -15546,7 +15556,7 @@ boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2) if (m1->type == MT_PLAYER && m2->type == MT_PLAYER) return false; - CONS_Printf("player check passed\n"); + // CONS_Printf("player check passed\n"); mobj_t *victim = m1; mobj_t *inflictor = m2; @@ -15561,9 +15571,9 @@ boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2) if (inflictor->target != victim) return false; - CONS_Printf("target check passed\n"); + // CONS_Printf("target check passed\n"); - K_AddHitLag(victim, 2, false); + K_AddHitLag(victim, 3, false); K_PickUp(victim->player, inflictor); P_RemoveMobj(inflictor); diff --git a/src/p_mobj.c b/src/p_mobj.c index ee7a8f5e0..52c6fec00 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5402,6 +5402,16 @@ static boolean P_IsTrackerType(INT32 type) case MT_GARDENTOP: // Frey return true; + case MT_JAWZ_SHIELD: // Pick-me-up + case MT_ORBINAUT: + case MT_ORBINAUT_SHIELD: + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + case MT_LANDMINE: + case MT_BANANA: + case MT_BANANA_SHIELD: + return true; + default: return false; }