diff --git a/src/d_player.h b/src/d_player.h index 64547b348..0c89b7fef 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 44195a340..41218ae0a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4712,6 +4712,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 392d6f72b..a5b4abf52 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 ec93ed554..2874532a9 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3318,6 +3318,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 5173fa3eb..e1c95929a 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.) } @@ -8844,6 +8844,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 @@ -9409,6 +9422,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->superring == 0) 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)); @@ -9690,6 +9705,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->nextringaward >= ringrate) @@ -11698,11 +11716,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) @@ -13178,6 +13198,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 00b0e44c3..c9a57607d 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) @@ -312,6 +314,8 @@ UINT16 K_GetDisplayEXP(player_t *player); UINT32 K_GetNumGradingPoints(void); +boolean K_LegacyRingboost(player_t *player); + #ifdef __cplusplus } // extern "C" #endif 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 6c4489528..e3d11ba67 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -1244,15 +1244,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 2d5707d37..b8abed3a4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2038,7 +2038,21 @@ 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 + starthaste = max(0, 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 c29b5e84d..b388b9592 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;