Merge branch 'item-jumbler' into 'master'

Gameplay prototyping lightning round

See merge request KartKrew/Kart!2439
This commit is contained in:
Oni 2024-08-28 05:10:15 +00:00
commit cb5dcea80d
17 changed files with 215 additions and 23 deletions

View file

@ -511,6 +511,8 @@ struct itemroulette_t
boolean ringbox; boolean ringbox;
boolean autoroulette; boolean autoroulette;
UINT8 reserved; UINT8 reserved;
UINT8 popcorn;
}; };
// enum for bot item priorities // enum for bot item priorities
@ -766,6 +768,9 @@ struct player_t
UINT16 ringboost; // Ring boost timer UINT16 ringboost; // Ring boost timer
UINT8 sparkleanim; // (0 to 19) - Angle offset for ring sparkle animation UINT8 sparkleanim; // (0 to 19) - Angle offset for ring sparkle animation
UINT16 superring; // You were awarded rings, and have this many of them left to spawn on yourself. UINT16 superring; // You were awarded rings, and have this many of them left to spawn on yourself.
UINT16 superringdisplay; // For HUD countup when awarded superring
UINT16 superringpeak; // Display award when getting awarded
UINT8 superringalert; // Timer for displaying award instead of countdown
UINT8 nextringaward; // When should we spawn our next superring ring? UINT8 nextringaward; // When should we spawn our next superring ring?
UINT8 ringvolume; // When consuming lots of rings, lower the sound a little. UINT8 ringvolume; // When consuming lots of rings, lower the sound a little.
UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again. UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again.

View file

@ -1571,6 +1571,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_AMPRING", "S_AMPRING",
"S_AMPBODY", "S_AMPBODY",
"S_AMPAURA", "S_AMPAURA",
"S_AMPBURST",
"S_CHARGEAURA", "S_CHARGEAURA",
"S_CHARGEFALL", "S_CHARGEFALL",
@ -3514,6 +3515,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_AMPRING", "MT_AMPRING",
"MT_AMPBODY", "MT_AMPBODY",
"MT_AMPAURA", "MT_AMPAURA",
"MT_AMPBURST",
"MT_CHARGEAURA", "MT_CHARGEAURA",
"MT_CHARGEFALL", "MT_CHARGEFALL",

View file

@ -2130,6 +2130,7 @@ state_t states[NUMSTATES] =
{SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING {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_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 {SPR_AMPD, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPAURA
{SPR_AMPB, FF_FULLBRIGHT|FF_ADD|FF_PAPERSPRITE|2, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBURST
{SPR_TRC1, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_CHARGEAURA {SPR_TRC1, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_CHARGEAURA
{SPR_TRC2, FF_FULLBRIGHT|FF_ANIMATE|0, 20, {NULL}, 19, 1, S_NULL}, // S_CHARGEFALL {SPR_TRC2, FF_FULLBRIGHT|FF_ANIMATE|0, 20, {NULL}, 19, 1, S_NULL}, // S_CHARGEFALL
@ -13721,6 +13722,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_AMPBURST
-1, // doomednum
S_AMPBURST, // 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_CHARGEAURA { // MT_CHARGEAURA
-1, // doomednum -1, // doomednum
S_CHARGEAURA, // spawnstate S_CHARGEAURA, // spawnstate

View file

@ -2598,6 +2598,7 @@ typedef enum state
S_AMPRING, S_AMPRING,
S_AMPBODY, S_AMPBODY,
S_AMPAURA, S_AMPAURA,
S_AMPBURST,
S_CHARGEAURA, S_CHARGEAURA,
S_CHARGEFALL, S_CHARGEFALL,
@ -4568,6 +4569,7 @@ typedef enum mobj_type
MT_AMPRING, MT_AMPRING,
MT_AMPBODY, MT_AMPBODY,
MT_AMPAURA, MT_AMPAURA,
MT_AMPBURST,
MT_CHARGEAURA, MT_CHARGEAURA,
MT_CHARGEFALL, MT_CHARGEFALL,

View file

@ -1457,7 +1457,7 @@ static void K_drawKartItem(void)
const SINT8 result = stplyr->itemRoulette.itemList[index]; const SINT8 result = stplyr->itemRoulette.itemList[index];
const SINT8 item = K_ItemResultToType(result); const SINT8 item = K_ItemResultToType(result);
const boolean usingDebugItemAmount = cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == item && cv_kartdebugamount.value > 1; const boolean usingDebugItemAmount = cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == item && cv_kartdebugamount.value > 1;
const UINT8 amt = usingDebugItemAmount ? cv_kartdebugamount.value : K_ItemResultToAmount(result); const UINT8 amt = usingDebugItemAmount ? cv_kartdebugamount.value : K_ItemResultToAmount(result, &stplyr->itemRoulette);
switch (item) switch (item)
{ {
@ -1640,7 +1640,12 @@ static void K_drawKartItem(void)
fy -= 5; fy -= 5;
} }
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg); UINT8 *boxmap = NULL;
if (stplyr->itemRoulette.active && (stplyr->itemRoulette.speed - stplyr->itemRoulette.tics < 3) && stplyr->itemRoulette.index == 0)
{
boxmap = R_GetTranslationColormap(TC_ALLWHITE, SKINCOLOR_WHITE, GTC_CACHE);
}
V_DrawMappedPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg, boxmap);
// Need to draw these in a particular order, for sorting. // Need to draw these in a particular order, for sorting.
V_SetClipRect( V_SetClipRect(
@ -3250,13 +3255,29 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
if (stplyr->pflags & PF_RINGLOCK) if (stplyr->pflags & PF_RINGLOCK)
V_DrawScaledPatch(fr-12, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]); V_DrawScaledPatch(fr-12, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]);
UINT32 greyout = V_HUDTRANS;
SINT8 superoffset = 5;
if (stplyr->superringdisplay)
{
greyout = V_HUDTRANSHALF;
if (flipflag && !uselives)
superoffset = -25 - (stplyr->superringdisplay >= 10 ? 3 : 0) - (stplyr->superringdisplay >= 100 ? 3 : 0);
}
// Lives // Lives
if (uselives) if (uselives)
{ {
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, static_cast<skincolornum_t>(stplyr->skincolor), GTC_CACHE); UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, static_cast<skincolornum_t>(stplyr->skincolor), GTC_CACHE);
V_DrawMappedPatch(fr+21, fy-3, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); V_DrawMappedPatch(fr+21, fy-3, V_SLIDEIN|splitflags|greyout, faceprefix[stplyr->skin][FACE_MINIMAP], colormap);
if (stplyr->lives >= 0) if (stplyr->lives >= 0)
K_DrawLivesDigits(fr+34, fy, 4, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font); K_DrawLivesDigits(fr+34, fy, 4, V_SLIDEIN|splitflags|greyout, fontv[PINGNUM_FONT].font);
}
if (stplyr->superringdisplay && !(stplyr->superringalert % 2))
{
using srb2::Draw;
Draw row = Draw(fr+19+superoffset, fy).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kPing).colorize(SKINCOLOR_SAPPHIRE);
row.text("+{:01}", abs(stplyr->superringdisplay));
} }
} }
else else
@ -3303,8 +3324,6 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
} }
} }
// "Why fy-4? Why LAPS_X+29+1?" // "Why fy-4? Why LAPS_X+29+1?"
// "use magic numbers" - jartha 2024-03-05 // "use magic numbers" - jartha 2024-03-05
if (stplyr->hudrings < 0) // Draw the minus for ring debt if (stplyr->hudrings < 0) // Draw the minus for ring debt
@ -3329,11 +3348,18 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
if (stplyr->pflags & PF_RINGLOCK) if (stplyr->pflags & PF_RINGLOCK)
V_DrawScaledPatch(LAPS_X-5, fy-17, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblock[stplyr->karthud[khud_ringspblock]]); V_DrawScaledPatch(LAPS_X-5, fy-17, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblock[stplyr->karthud[khud_ringspblock]]);
UINT32 greyout = V_HUDTRANS;
if (stplyr->superringdisplay)
{
greyout = V_HUDTRANSHALF;
}
// Lives // Lives
if (uselives) if (uselives)
{ {
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, static_cast<skincolornum_t>(stplyr->skincolor), GTC_CACHE); UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, static_cast<skincolornum_t>(stplyr->skincolor), GTC_CACHE);
V_DrawMappedPatch(LAPS_X+46, fy-5, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_RANK], colormap); V_DrawMappedPatch(LAPS_X+46, fy-5, V_SLIDEIN|splitflags|greyout, faceprefix[stplyr->skin][FACE_RANK], colormap);
SINT8 livescount = 0; SINT8 livescount = 0;
if (stplyr->lives > 0) if (stplyr->lives > 0)
{ {
@ -3342,9 +3368,16 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
livescount = 10; livescount = 10;
} }
using srb2::Draw; using srb2::Draw;
Draw row = Draw(LAPS_X+65, fy-4).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer); Draw row = Draw(LAPS_X+65, fy-4).flags(V_SLIDEIN|splitflags|greyout).font(Draw::Font::kThinTimer);
row.text("{}", livescount); row.text("{}", livescount);
} }
if (stplyr->superringdisplay && !(stplyr->superringalert % 2))
{
using srb2::Draw;
Draw row = Draw(LAPS_X+23+3+15, fy-4).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer).colorize(SKINCOLOR_SAPPHIRE);
row.text("+{:01}", abs(stplyr->superringdisplay));
}
} }
} }
@ -6455,7 +6488,8 @@ void K_drawKartHUD(void)
} }
} }
K_drawKartTimestamp(realtime, TIME_X, TIME_Y + (ta ? 2 : 0), flags, 0); if (modeattacking || (gametyperules & GTR_TIMELIMIT))
K_drawKartTimestamp(realtime, TIME_X, TIME_Y + (ta ? 2 : 0), flags, 0);
if (modeattacking) if (modeattacking)
{ {

View file

@ -538,7 +538,7 @@ SINT8 K_ItemResultToType(SINT8 getitem)
return getitem; return getitem;
} }
UINT8 K_ItemResultToAmount(SINT8 getitem) UINT8 K_ItemResultToAmount(SINT8 getitem, const itemroulette_t *roulette)
{ {
switch (getitem) switch (getitem)
{ {
@ -558,6 +558,12 @@ UINT8 K_ItemResultToAmount(SINT8 getitem)
case KITEM_BALLHOG: // Not a special result, but has a special amount case KITEM_BALLHOG: // Not a special result, but has a special amount
return 5; return 5;
case KITEM_SUPERRING:
if (roulette && roulette->popcorn)
return roulette->popcorn;
else
return 1;
default: default:
return 1; return 1;
} }
@ -4128,7 +4134,11 @@ void K_AwardPlayerRings(player_t *player, UINT16 rings, boolean overload)
/* check if not overflow */ /* check if not overflow */
if (superring > player->superring) if (superring > player->superring)
{
player->superring = superring; player->superring = superring;
player->superringpeak = superring;
player->superringalert = TICRATE/2;
}
} }
boolean K_Overdrive(player_t *player) boolean K_Overdrive(player_t *player)
@ -6986,7 +6996,7 @@ void K_DoSneaker(player_t *player, INT32 type)
player->overshield += TICRATE/2; // TEMP prototype player->overshield += TICRATE/2; // TEMP prototype
break; break;
case 2: case 2:
player->sneakertimer = sneakertime + TICRATE/2; player->sneakertimer = 3*sneakertime/4;
player->overshield += TICRATE/2; // TEMP prototype player->overshield += TICRATE/2; // TEMP prototype
break; break;
} }
@ -7582,7 +7592,7 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
// but item roulette will need rewritten to change this // but item roulette will need rewritten to change this
const SINT8 newType = K_ItemResultToType(i); const SINT8 newType = K_ItemResultToType(i);
const UINT8 newAmount = K_ItemResultToAmount(i); const UINT8 newAmount = K_ItemResultToAmount(i, NULL);
if (newAmount > 1) if (newAmount > 1)
{ {
@ -9402,6 +9412,24 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->freeRingShooterCooldown && !player->mo->hitlag) if (player->freeRingShooterCooldown && !player->mo->hitlag)
player->freeRingShooterCooldown--; player->freeRingShooterCooldown--;
if (player->superringalert)
{
player->superringdisplay = player->superringpeak;
player->superringalert--;
}
else
{
if (player->superringdisplay != player->superring)
{
INT16 delta = player->superring - player->superringdisplay;
if (player->superring > player->superringdisplay)
delta = max(delta/8, 1);
else
delta = min(delta/8, -1);
player->superringdisplay += delta;
}
}
if (player->superring) if (player->superring)
{ {
player->nextringaward++; player->nextringaward++;
@ -13788,8 +13816,36 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_SUPERRING: case KITEM_SUPERRING:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{ {
K_AwardPlayerRings(player, 20, true); S_StartSound(player->mo, sfx_gsha7);
player->itemamount--; P_Thrust(player->mo, K_MomentumAngle(player->mo), 25*player->mo->scale);
P_Thrust(player->mo, player->mo->angle, 25*player->mo->scale);
UINT8 numsparks = 8;
for (UINT8 i = 0; i < numsparks; i++)
{
mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RINGSPARKS);
P_InstaScale(sparkle, player->mo->scale*2);
P_SetTarget(&sparkle->target, player->mo);
sparkle->angle = player->mo->angle + FixedAngle((360*i/numsparks)<<FRACBITS);
player->sparkleanim = (player->sparkleanim+1) % 20;
P_SetTarget(&sparkle->owner, player->mo);
sparkle->renderflags |= RF_REDUCEVFX;
}
mobj_t *burst = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height/2, MT_AMPBURST);
burst->momx = player->mo->momx/2;
burst->momy = player->mo->momy/2;
burst->momz = player->mo->momz/2;
burst->angle = player->mo->angle + ANGLE_90;
burst->scalespeed = burst->scale;
burst->destscale = burst->scale*8;
burst->color = SKINCOLOR_GOLD;
burst->fuse = 8;
// player->strongdriftboost += TICRATE;
// player->driftboost += TICRATE;
K_AwardPlayerRings(player, 20*player->itemamount, true);
player->itemamount = 0;
player->botvars.itemconfirm = 0; player->botvars.itemconfirm = 0;
} }
break; break;

View file

@ -105,7 +105,7 @@ fixed_t K_GetKartGameSpeedScalar(SINT8 value);
INT32 K_GetShieldFromItem(INT32 item); INT32 K_GetShieldFromItem(INT32 item);
SINT8 K_ItemResultToType(SINT8 getitem); SINT8 K_ItemResultToType(SINT8 getitem);
UINT8 K_ItemResultToAmount(SINT8 getitem); UINT8 K_ItemResultToAmount(SINT8 getitem, const itemroulette_t *roulette);
tic_t K_GetItemCooldown(SINT8 itemResult); tic_t K_GetItemCooldown(SINT8 itemResult);
void K_SetItemCooldown(SINT8 itemResult, tic_t time); void K_SetItemCooldown(SINT8 itemResult, tic_t time);
void K_RunItemCooldowns(void); void K_RunItemCooldowns(void);

View file

@ -5533,7 +5533,7 @@ void M_DrawItemToggles(void)
cv = &cv_items[currentMenu->menuitems[thisitem].mvar1-1]; cv = &cv_items[currentMenu->menuitems[thisitem].mvar1-1];
drawnum = K_ItemResultToAmount(currentMenu->menuitems[thisitem].mvar1); drawnum = K_ItemResultToAmount(currentMenu->menuitems[thisitem].mvar1, NULL);
V_DrawScaledPatch(x, y, 0, cv->value ? isbg : isbgd); V_DrawScaledPatch(x, y, 0, cv->value ? isbg : isbgd);
@ -5588,7 +5588,7 @@ void M_DrawItemToggles(void)
{ {
cv = &cv_items[currentMenu->menuitems[itemOn].mvar1-1]; cv = &cv_items[currentMenu->menuitems[itemOn].mvar1-1];
drawnum = K_ItemResultToAmount(currentMenu->menuitems[itemOn].mvar1); drawnum = K_ItemResultToAmount(currentMenu->menuitems[itemOn].mvar1, NULL);
if (cv->value) if (cv->value)
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE));

View file

@ -142,6 +142,7 @@ void Obj_GuardBreakThink(mobj_t *fx);
void Obj_AmpRingThink(mobj_t *amp); void Obj_AmpRingThink(mobj_t *amp);
void Obj_AmpBodyThink(mobj_t *amp); void Obj_AmpBodyThink(mobj_t *amp);
void Obj_AmpAuraThink(mobj_t *amp); void Obj_AmpAuraThink(mobj_t *amp);
void Obj_AmpBurstThink(mobj_t *amp);
void Obj_AmpsThink(mobj_t *amps); void Obj_AmpsThink(mobj_t *amps);

View file

@ -98,7 +98,7 @@ static UINT32 K_DynamicItemOddsRace[NUMKARTRESULTS-1][2] =
{66, 9}, // flameshield {66, 9}, // flameshield
{1, 3}, // hyudoro {1, 3}, // hyudoro
{0, 0}, // pogospring {0, 0}, // pogospring
{7, 4}, // superring {30, 8}, // superring (SPECIAL! distance value specifies when this can NO LONGER appear)
{0, 0}, // kitchensink {0, 0}, // kitchensink
{1, 3}, // droptarget {1, 3}, // droptarget
{43, 5}, // gardentop {43, 5}, // gardentop
@ -796,6 +796,8 @@ static void K_InitRoulette(itemroulette_t *const roulette)
roulette->ringbox = false; roulette->ringbox = false;
roulette->autoroulette = false; roulette->autoroulette = false;
roulette->popcorn = 1;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] == false || players[i].spectator == true) if (playeringame[i] == false || players[i].spectator == true)
@ -1497,6 +1499,26 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
deltas[i] = min(targetpower - powers[i], powers[i] - targetpower); deltas[i] = min(targetpower - powers[i], powers[i] - targetpower);
} }
// == "POPCORN" Super Ring in Race.
// This can appear anywhere from 0 to its specified distance, to pad the
// reels with non-disruptive catchup (since we have a ton of offensive items
// and not many front/mid speed items).
boolean canfiltersuperring = true;
if ((gametyperules & GTR_CIRCUIT) && (specialstageinfo.valid == false))
{
if (targetpower > powers[KITEM_SUPERRING])
{
permit[KITEM_SUPERRING] = false;
}
else
{
permit[KITEM_SUPERRING] = true;
deltas[KITEM_SUPERRING] = 0;
canfiltersuperring = false;
roulette->popcorn = (player->position > 1) ? max(1, targetpower/humanscaler/3) : 1;
}
}
// == LONELINESS DETECTION // == LONELINESS DETECTION
// A lot of items suck if no players are nearby to interact with them. // A lot of items suck if no players are nearby to interact with them.
// Should we bias towards items that get us back to the action? // Should we bias towards items that get us back to the action?
@ -1612,7 +1634,7 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
V_DrawThinString(BASE_X + 65, BASE_Y, FLAGS, va("D%d", deltas[bestitem]/humanscaler)); V_DrawThinString(BASE_X + 65, BASE_Y, FLAGS, va("D%d", deltas[bestitem]/humanscaler));
V_DrawThinString(BASE_X + 20, BASE_Y, FLAGS, va("%d", dupetolerance[bestitem])); V_DrawThinString(BASE_X + 20, BASE_Y, FLAGS, va("%d", dupetolerance[bestitem]));
V_DrawFixedPatch(BASE_X*FRACUNIT, (BASE_Y-7)*FRACUNIT, (FRACUNIT >> 1), FLAGS, K_GetSmallStaticCachedItemPatch(bestitem), NULL); V_DrawFixedPatch(BASE_X*FRACUNIT, (BASE_Y-7)*FRACUNIT, (FRACUNIT >> 1), FLAGS, K_GetSmallStaticCachedItemPatch(bestitem), NULL);
UINT8 amount = K_ItemResultToAmount(bestitem); UINT8 amount = K_ItemResultToAmount(bestitem, roulette);
if (amount > 1) if (amount > 1)
V_DrawThinString(BASE_X, BASE_Y, FLAGS, va("x%d", amount)); V_DrawThinString(BASE_X, BASE_Y, FLAGS, va("x%d", amount));
} }
@ -1654,6 +1676,10 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
// feels exciting, low-rolling feels punishing! // feels exciting, low-rolling feels punishing!
boolean reject = (filterweakitems) && (powers[i] + DISTVAR < meanreelpower); boolean reject = (filterweakitems) && (powers[i] + DISTVAR < meanreelpower);
// Popcorn Super Ring is always strong enough, we put it there on purpose.
if (i == KITEM_SUPERRING && !canfiltersuperring)
reject = false;
// Before we actually apply that rejection, draw the simple odds debugger. // Before we actually apply that rejection, draw the simple odds debugger.
// This one is just to watch the distribution for vibes as you drive around. // This one is just to watch the distribution for vibes as you drive around.
if (cv_kartdebugdistribution.value && candidates[i]) if (cv_kartdebugdistribution.value && candidates[i])
@ -1667,7 +1693,7 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
V_DrawThinString(BASE_X - 12, 5+36, FLAGS, va("%d", loneliness)); V_DrawThinString(BASE_X - 12, 5+36, FLAGS, va("%d", loneliness));
for(UINT8 k = 0; k < candidates[i]; k++) for(UINT8 k = 0; k < candidates[i]; k++)
V_DrawFixedPatch((BASE_X + 3*k)*FRACUNIT, (BASE_Y-7)*FRACUNIT, (FRACUNIT >> 1), FLAGS, K_GetSmallStaticCachedItemPatch(i), NULL); V_DrawFixedPatch((BASE_X + 3*k)*FRACUNIT, (BASE_Y-7)*FRACUNIT, (FRACUNIT >> 1), FLAGS, K_GetSmallStaticCachedItemPatch(i), NULL);
UINT8 amount = K_ItemResultToAmount(i); UINT8 amount = K_ItemResultToAmount(i, roulette);
if (amount > 1) if (amount > 1)
V_DrawThinString(BASE_X, BASE_Y, FLAGS, va("x%d", amount)); V_DrawThinString(BASE_X, BASE_Y, FLAGS, va("x%d", amount));
if (reject) if (reject)
@ -1835,7 +1861,7 @@ static void K_KartGetItemResult(player_t *const player, kartitems_t getitem)
player->botvars.itemconfirm = 0; player->botvars.itemconfirm = 0;
player->itemtype = K_ItemResultToType(getitem); player->itemtype = K_ItemResultToType(getitem);
UINT8 itemamount = K_ItemResultToAmount(getitem); UINT8 itemamount = K_ItemResultToAmount(getitem, &player->itemRoulette);
if (cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == player->itemtype && cv_kartdebugamount.value > 1) if (cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == player->itemtype && cv_kartdebugamount.value > 1)
itemamount = cv_kartdebugamount.value; itemamount = cv_kartdebugamount.value;
player->itemamount = itemamount; player->itemamount = itemamount;
@ -2001,6 +2027,13 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
S_StartSound(NULL, sfx_s240); S_StartSound(NULL, sfx_s240);
else else
S_StartSound(NULL, sfx_itrol1 + roulette->sound); S_StartSound(NULL, sfx_itrol1 + roulette->sound);
if (roulette->index == 0)
{
S_StartSound(NULL, sfx_kc50);
S_StartSound(NULL, sfx_kc50);
}
} }
} }
else else

View file

@ -432,6 +432,12 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->sparkleanim); lua_pushinteger(L, plr->sparkleanim);
else if (fastcmp(field,"superring")) else if (fastcmp(field,"superring"))
lua_pushinteger(L, plr->superring); lua_pushinteger(L, plr->superring);
else if (fastcmp(field,"superringdisplay"))
lua_pushinteger(L, plr->superringdisplay);
else if (fastcmp(field,"superringpeak"))
lua_pushinteger(L, plr->superringpeak);
else if (fastcmp(field,"superringalert"))
lua_pushinteger(L, plr->superringalert);
else if (fastcmp(field,"nextringaward")) else if (fastcmp(field,"nextringaward"))
lua_pushinteger(L, plr->nextringaward); lua_pushinteger(L, plr->nextringaward);
else if (fastcmp(field,"ringvolume")) else if (fastcmp(field,"ringvolume"))
@ -1010,6 +1016,12 @@ static int player_set(lua_State *L)
plr->sparkleanim = luaL_checkinteger(L, 3); plr->sparkleanim = luaL_checkinteger(L, 3);
else if (fastcmp(field,"superring")) else if (fastcmp(field,"superring"))
plr->superring = luaL_checkinteger(L, 3); plr->superring = luaL_checkinteger(L, 3);
else if (fastcmp(field,"superringdisplay"))
plr->superringdisplay = luaL_checkinteger(L, 3);
else if (fastcmp(field,"superringpeak"))
plr->superringpeak = luaL_checkinteger(L, 3);
else if (fastcmp(field,"superringalert"))
plr->superringalert = luaL_checkinteger(L, 3);
else if (fastcmp(field,"nextringaward")) else if (fastcmp(field,"nextringaward"))
plr->nextringaward = luaL_checkinteger(L, 3); plr->nextringaward = luaL_checkinteger(L, 3);
else if (fastcmp(field,"ringvolume")) else if (fastcmp(field,"ringvolume"))

View file

@ -195,3 +195,9 @@ void Obj_AmpAuraThink (mobj_t *amps)
amps->renderflags &= ~RF_DONTDRAW; amps->renderflags &= ~RF_DONTDRAW;
} }
} }
void Obj_AmpBurstThink (mobj_t *amps)
{
amps->renderflags &= ~RF_TRANSMASK;
amps->renderflags |= (NUMTRANSMAPS - amps->fuse) << RF_TRANSSHIFT;
}

View file

@ -677,6 +677,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
} }
player->exp += K_GetExpAdjustment(player); player->exp += K_GetExpAdjustment(player);
K_AwardPlayerRings(player, 10, true);
player->gradingpointnum++; player->gradingpointnum++;
K_UpdatePowerLevels(player, player->laps, false); K_UpdatePowerLevels(player, player->laps, false);

View file

@ -408,7 +408,7 @@ project_icon (mobj_t *part)
K_UpdateMobjItemOverlay(part, K_UpdateMobjItemOverlay(part,
K_ItemResultToType(result), K_ItemResultToType(result),
K_ItemResultToAmount(result)); K_ItemResultToAmount(result, NULL));
center_item_sprite(part, 5*FRACUNIT/4); center_item_sprite(part, 5*FRACUNIT/4);
} }
@ -703,7 +703,7 @@ Obj_MonitorOnDeath
monitor->x, monitor->y, monitor->z + (128 * mapobjectscale * flip), monitor->x, monitor->y, monitor->z + (128 * mapobjectscale * flip),
i * ang, flip, i * ang, flip,
K_ItemResultToType(result), K_ItemResultToType(result),
K_ItemResultToAmount(result))); K_ItemResultToAmount(result, NULL)));
drop->momz /= 2; // This is player-locked, so no need to throw it high drop->momz /= 2; // This is player-locked, so no need to throw it high

View file

@ -8641,6 +8641,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
Obj_AmpAuraThink(mobj); Obj_AmpAuraThink(mobj);
break; break;
} }
case MT_AMPBURST:
{
Obj_AmpBurstThink(mobj);
break;
}
case MT_CHARGEAURA: case MT_CHARGEAURA:
{ {
Obj_ChargeAuraThink(mobj); Obj_ChargeAuraThink(mobj);

View file

@ -501,6 +501,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT16(save->p, players[i].ringboost); WRITEUINT16(save->p, players[i].ringboost);
WRITEUINT8(save->p, players[i].sparkleanim); WRITEUINT8(save->p, players[i].sparkleanim);
WRITEUINT16(save->p, players[i].superring); WRITEUINT16(save->p, players[i].superring);
WRITEUINT16(save->p, players[i].superringdisplay);
WRITEUINT16(save->p, players[i].superringpeak);
WRITEUINT8(save->p, players[i].superringalert);
WRITEUINT8(save->p, players[i].nextringaward); WRITEUINT8(save->p, players[i].nextringaward);
WRITEUINT8(save->p, players[i].ringvolume); WRITEUINT8(save->p, players[i].ringvolume);
WRITEUINT8(save->p, players[i].ringtransparency); WRITEUINT8(save->p, players[i].ringtransparency);
@ -1119,6 +1122,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].ringboost = READUINT16(save->p); players[i].ringboost = READUINT16(save->p);
players[i].sparkleanim = READUINT8(save->p); players[i].sparkleanim = READUINT8(save->p);
players[i].superring = READUINT16(save->p); players[i].superring = READUINT16(save->p);
players[i].superringdisplay = READUINT16(save->p);
players[i].superringpeak = READUINT16(save->p);
players[i].superringalert = READUINT8(save->p);
players[i].nextringaward = READUINT8(save->p); players[i].nextringaward = READUINT8(save->p);
players[i].ringvolume = READUINT8(save->p); players[i].ringvolume = READUINT8(save->p);
players[i].ringtransparency = READUINT8(save->p); players[i].ringtransparency = READUINT8(save->p);

View file

@ -2119,6 +2119,7 @@ static void K_HandleLapIncrement(player_t *player)
} }
player->exp += K_GetExpAdjustment(player); player->exp += K_GetExpAdjustment(player);
K_AwardPlayerRings(player, 10, true);
player->gradingpointnum++; player->gradingpointnum++;
if (player->position == 1 && !(gametyperules & GTR_CHECKPOINTS)) if (player->position == 1 && !(gametyperules & GTR_CHECKPOINTS))