WIP: more pick-me-up

This commit is contained in:
Antonio Martinez 2025-05-16 13:04:55 -04:00
parent dcbbea4c4b
commit 34ddee575a
4 changed files with 222 additions and 15 deletions

View file

@ -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<skincolornum_t>(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<<FRACBITS, (fy<<FRACBITS) + rouletteOffset + y,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[i], colormap
);
if (localamt[i] > 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<<FRACBITS, (fy<<FRACBITS) + rouletteOffset,
FRACUNIT, transflag|V_SLIDEIN|fflags,
localpatch[1], (localcolor[1] ? R_GetTranslationColormap(colormode[1], localcolor[1], GTC_CACHE) : NULL)
);
if (offset)
{
if (flipamount) // reminder that this is for 3/4p's right end of the screen.
V_DrawString(fx+2, fy+31, V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->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<<FRACBITS, (fy<<FRACBITS) + rouletteOffset,
FRACUNIT, transflag|V_SLIDEIN|fflags,
localpatch[1], (localcolor[1] ? R_GetTranslationColormap(colormode[1], localcolor[1], GTC_CACHE) : NULL)
);
}
}
}
static void K_drawKartSlotMachine(void)
{
// ITEM_X = BASEVIDWIDTH-50; // 270
@ -6876,6 +7049,9 @@ void K_drawKartHUD(void)
{
K_drawKartItem();
}
if (stplyr->backupitemtype)
K_drawBackupItem();
}
}
}

View file

@ -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_t*>(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;
}

View file

@ -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);

View file

@ -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;
}