diff --git a/src/d_player.h b/src/d_player.h index 540c42c2c..d22f6f734 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -50,6 +50,7 @@ typedef enum SF_MACHINE = 1, // Beep boop. Are you a robot? SF_IRONMAN = 1<<1, // Pick a new skin during POSITION. I main Random! SF_BADNIK = 1<<2, // Explodes on death + SF_HIVOLT = 1<<3, // High power TA ringboxes, like 2.0-2.3! // free up to and including 1<<31 } skinflags_t; diff --git a/src/deh_tables.c b/src/deh_tables.c index 0fe01a222..8369624ec 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4727,6 +4727,7 @@ struct int_const_s const INT_CONST[] = { {"SF_MACHINE",SF_MACHINE}, {"SF_IRONMAN",SF_IRONMAN}, {"SF_BADNIK",SF_BADNIK}, + {"SF_HIVOLT",SF_HIVOLT}, // Sound flags {"SF_TOTALLYSINGLE",SF_TOTALLYSINGLE}, diff --git a/src/g_game.c b/src/g_game.c index a24dd3e45..187efc5ca 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -583,6 +583,11 @@ static void G_UpdateRecordReplays(void) modeprefix = "spb-"; } + if (K_LegacyRingboost(&players[consoleplayer])) + { + modeprefix = "classr-"; + } + if (players[consoleplayer].pflags & PF_NOCONTEST) { players[consoleplayer].realtime = UINT32_MAX; diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 8d93c78e8..9dce9c517 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3441,6 +3441,11 @@ static void K_drawRingCounter(boolean gametypeinfoshown) ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); colorring = true; } + else if (K_LegacyRingboost(stplyr) && (leveltime%2)) + { + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_BLUEBERRY, GTC_CACHE); + colorring = true; + } else if (stplyr->hudrings >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); diff --git a/src/k_kart.c b/src/k_kart.c index fea5246fe..4a00a1361 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -292,7 +292,7 @@ void K_TimerInit(void) if (G_TimeAttackStart()) { - starttime = 10*TICRATE; // Longest permitted start. No half-laps in reverse. + starttime = TIMEATTACK_START; // Longest permitted start. No half-laps in reverse. // (Changed on finish line cross later, don't worry.) } @@ -8875,6 +8875,19 @@ static inline BlockItReturn_t PIT_AttractingRings(mobj_t *thing) return BMIT_CONTINUE; // find other rings } +boolean K_LegacyRingboost(player_t *player) +{ + if (netgame) + return false; + if (modeattacking == ATTACKING_SPB) + return false; + if (!modeattacking) + return false; + if (!(skins[player->skin].flags & SF_HIVOLT)) + return false; + return true; +} + /** Looks for rings near a player in the blockmap. * * \param pmo Player object looking for rings to attract @@ -9472,6 +9485,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->superring == 0 || player->stunned) player->ringboost -= max((player->ringboost / roller), 1); + else if (K_LegacyRingboost(player)) + player->ringboost--; else player->ringboost -= min(K_GetFullKartRingPower(player, false) - 1, max(player->ringboost / 2 / roller, 1)); @@ -9758,6 +9773,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) UINT32 existing = (player->lastringboost / K_GetFullKartRingPower(player, true)); // How many rings (effectively) do we have boost credit for right now? + if (K_LegacyRingboost(player)) + existing = 0; + UINT8 ringrate = 3 - min(2, (player->superring + existing) / fastringscaler); // Used to consume fat stacks of cash faster. if (player->stunned) @@ -11769,11 +11787,13 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnDriftSparks(player); } + /* // Magic numbers ahoy! Meant to allow purple drifts to progress past color transition. if ((player->driftcharge + driftadditive) > (dsthree+(32*3)) && K_TimeAttackRules() && leveltime < starttime) { driftadditive = max(0, (dsthree+(32*3)) - player->driftcharge); } + */ if ((player->driftcharge < dsone && player->driftcharge+driftadditive >= dsone) || (player->driftcharge < dstwo && player->driftcharge+driftadditive >= dstwo) @@ -13253,6 +13273,26 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // SPB Attack is hard. award = award / 2; } + else if (K_LegacyRingboost(player)) + { + // An ancient power is revealed once more... + UINT8 accel = 10-player->kartspeed; + UINT8 weight = player->kartweight; + + if (accel > weight) + { + accel *= 10; + weight *= 3; + } + else + { + + accel *= 3; + weight *= 10; + } + + award = (110 + accel + weight) * award / 120; + } else if (modeattacking) { // TA has: diff --git a/src/k_kart.h b/src/k_kart.h index b20d7d59b..ccc32c6f9 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -50,6 +50,8 @@ Make sure this matches the actual number of states #define MINCOMBOFLOAT (mapobjectscale*1) #define MAXCOMBOTIME (TICRATE*4) +#define TIMEATTACK_START (TICRATE*10) + #define OVERDRIVE_STARTUP (0) #define AMPLEVEL (15) @@ -314,6 +316,8 @@ UINT16 K_GetEXP(player_t *player); UINT32 K_GetNumGradingPoints(void); +boolean K_LegacyRingboost(player_t *player); + void K_BotHitPenalty(player_t *player); boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 3a607c40f..7000bd6a6 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2098,6 +2098,7 @@ static void M_DrawCharSelectPreview(UINT8 num) if (p->showextra == true) { INT32 randomskin = 0; + INT32 doping = 0; switch (p->mdepth) { case CSSTEP_ALTS: // Select clone @@ -2108,6 +2109,7 @@ static void M_DrawCharSelectPreview(UINT8 num) V_DrawThinString(x-3, y+12, 0, skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]].name); randomskin = (skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]].flags & SF_IRONMAN); + doping = (skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]].flags & SF_HIVOLT); } else { @@ -2116,7 +2118,8 @@ static void M_DrawCharSelectPreview(UINT8 num) /* FALLTHRU */ case CSSTEP_CHARS: // Character Select grid V_DrawThinString(x-3, y+2, 0, va("Class %c (s %c - w %c)", - ('A' + R_GetEngineClass(p->gridx+1, p->gridy+1, randomskin)), + (doping + ? 'R' : ('A' + R_GetEngineClass(p->gridx+1, p->gridy+1, randomskin))), (randomskin ? '?' : ('1'+p->gridx)), (randomskin @@ -7112,6 +7115,14 @@ void M_DrawCharacterIconAndEngine(INT32 x, INT32 y, UINT8 skin, UINT8 *colormap, } } + else if (skins[baseskin].flags & SF_HIVOLT) + { + UINT32 fucktimer = (gamedata->totalmenutime/2)%8; + UINT8 sq[] = {0, 1, 2, 2, 2, 1, 0, 0}; + UINT8 wq[] = {0, 0, 0, 1, 2, 2, 2, 1}; + s = sq[fucktimer]; + w = wq[fucktimer]; + } else { // The following is a partial duplication of R_GetEngineClass diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 0e455da89..877e39dd1 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -1243,15 +1243,29 @@ void level_tally_t::Draw(void) work_tics % 10 )); - if (modeattacking && !demo.playback && (state == TALLY_ST_DONE || state == TALLY_ST_TEXT_PAUSE) - && !K_IsPlayerLosing(&players[consoleplayer]) && players[consoleplayer].realtime < oldbest) + if (K_LegacyRingboost(&players[consoleplayer])) { drawer_text .x(197.0 * frac) .y(13.0 * frac) .align(srb2::Draw::Align::kCenter) .font(srb2::Draw::Font::kMenu) - .text((leveltime/2 % 2) ? "NEW RECORD!" : "\x82NEW RECORD!"); + .flags(V_TRANSLUCENT) + .text("\"CLASS R\""); + } + else + { + if (modeattacking && !demo.playback && (state == TALLY_ST_DONE || state == TALLY_ST_TEXT_PAUSE) + && !K_IsPlayerLosing(&players[consoleplayer]) && players[consoleplayer].realtime < oldbest) + { + + drawer_text + .x(197.0 * frac) + .y(13.0 * frac) + .align(srb2::Draw::Align::kCenter) + .font(srb2::Draw::Font::kMenu) + .text((leveltime/2 % 2) ? "NEW RECORD!" : "\x82NEW RECORD!"); + } } break; } diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index 7dfb04be6..a0c57ae8c 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -676,6 +676,12 @@ void M_LevelSelectInit(INT32 choice) gt = menugametype; } + if (levellist.levelsearch.timeattack && gt == GT_RACE && skins[R_SkinAvailableEx(cv_skin[0].string, false)].flags & SF_HIVOLT) + { + M_StartMessage("A long-forgotten power...", "You are using a \x82prototype engine\x80.\nRecords will not be saved.", NULL, MM_NOTHING, NULL, NULL); + S_StartSound(NULL, sfx_s3k81); + } + if (!M_LevelListFromGametype(gt)) { S_StartSound(NULL, sfx_s3kb2); diff --git a/src/p_spec.c b/src/p_spec.c index 23cf990ef..db4cc3d4e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2038,7 +2038,25 @@ static void K_HandleLapIncrement(player_t *player) { linecrossed = leveltime; if (starttime > leveltime) // Overlong starts shouldn't reset time on cross + { + // Award some Amps for a fast start, to counterbalance Obvious Rainbow Driftboost + + tic_t starthaste = starttime - leveltime; // How much time we had left to cross + starthaste = TIMEATTACK_START - starthaste; // How much time we wasted before crossing + + tic_t leniency = TICRATE*2; // How long we can take to cross with no penalty to amp payout + + if (starthaste <= leniency) + starthaste = 0; + else + starthaste -= leniency; + + fixed_t ampreward = Easing_OutQuart(starthaste*FRACUNIT/TIMEATTACK_START, 100*FRACUNIT, 0); + K_SpawnAmps(player, ampreward/FRACUNIT, player->mo); + + // And reset our time to 0. starttime = leveltime; + } if (demo.recording) demo_extradata[player-players] |= DXD_START; Music_Stop("position"); diff --git a/src/p_user.c b/src/p_user.c index 925627794..9e811dc01 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1331,7 +1331,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) if (demo.playback == false) { - if (modeattacking) + if (modeattacking && !K_LegacyRingboost(player)) { G_UpdateRecords(); } diff --git a/src/r_skins.c b/src/r_skins.c index 7370d3fde..8ddf839d8 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -379,6 +379,9 @@ engineclass_t R_GetEngineClass(SINT8 speed, SINT8 weight, skinflags_t flags) if (flags & SF_IRONMAN) return ENGINECLASS_J; + if (flags & SF_HIVOLT) + return ENGINECLASS_R; + speed = (speed - 1) / 3; weight = (weight - 1) / 3; @@ -874,6 +877,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(MACHINE) GETFLAG(IRONMAN) GETFLAG(BADNIK) + GETFLAG(HIVOLT) #undef GETFLAG else // let's check if it's a sound, otherwise error out diff --git a/src/r_skins.h b/src/r_skins.h index 9a05129f9..2f32c9fbe 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -92,7 +92,8 @@ typedef enum { ENGINECLASS_H, ENGINECLASS_I, - ENGINECLASS_J + ENGINECLASS_J, + ENGINECLASS_R = 17, } engineclass_t;