diff --git a/src/g_game.c b/src/g_game.c index 169933084..95b4c4b8d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -273,6 +273,10 @@ INT16 nospectategrief[MAXPLAYERS]; // Which players spec-scummed, and their powe boolean thwompsactive; // Thwomps activate on lap 2 SINT8 spbplace; // SPB exists, give the person behind better items +// Scrambles +SINT8 speedscramble; +SINT8 encorescramble; + // Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players) boolean legitimateexit; // Did this client actually finish the match? boolean comebackshowninfo; // Have you already seen the "ATTACK OR PROTECT" message? @@ -3194,9 +3198,10 @@ boolean G_BattleGametype(void) // INT16 G_SometimesGetDifferentGametype(void) { - boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype()); + boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE) || encorescramble == 1) && G_RaceGametype()); - if (!cv_kartvoterulechanges.value) // never + if (!cv_kartvoterulechanges.value // never + && encorescramble != 1) // destroying the code for this one instance return gametype; if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3)) @@ -3204,18 +3209,23 @@ INT16 G_SometimesGetDifferentGametype(void) randmapbuffer[NUMMAPS]--; if (encorepossible) { - switch (cv_kartvoterulechanges.value) + if (encorescramble >= 0) + encorepossible = (boolean)encorescramble; + else { - case 3: // always - randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set - break; - case 2: // frequent - encorepossible = M_RandomChance(FRACUNIT>>1); - break; - case 1: // sometimes - default: - encorepossible = M_RandomChance(FRACUNIT>>2); - break; + switch (cv_kartvoterulechanges.value) + { + case 3: // always + randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set + break; + case 2: // frequent + encorepossible = M_RandomChance(FRACUNIT>>1); + break; + case 1: // sometimes + default: + encorepossible = M_RandomChance(FRACUNIT>>2); + break; + } } if (encorepossible != (boolean)cv_kartencore.value) return (gametype|0x80); @@ -3223,6 +3233,9 @@ INT16 G_SometimesGetDifferentGametype(void) return gametype; } + if (!cv_kartvoterulechanges.value) // never (again) + return gametype; + switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv? { case 3: // always diff --git a/src/k_kart.c b/src/k_kart.c index d07afda66..8ff2db66d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6109,6 +6109,39 @@ INT16 K_CalculatePowerLevelInc(INT16 diff) return (INT16)(increment >> FRACBITS); } +INT16 K_CalculatePowerLevelAvg(void) +{ + fixed_t avg = 0; + UINT8 div = 0; + SINT8 t = -1; + UINT8 i; + + if (!netgame || !cv_kartusepwrlv.value) + return 0; // No average. + + if (G_RaceGametype()) + t = 0; + else if (G_BattleGametype()) + t = 1; + + if (t == -1) + return 0; // Hmm?! + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator + || clientpowerlevels[i][t] == 0) + continue; + + avg += clientpowerlevels[i][t]; + div++; + } + + avg /= div; + + return (INT16)(avg >> FRACBITS); +} + void K_PlayerForfeit(UINT8 playernum, boolean pointloss) { UINT8 p = 0; diff --git a/src/k_kart.h b/src/k_kart.h index 0844abc5a..396ebdc55 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -66,6 +66,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground); void K_CalculateBattleWanted(void); void K_CheckBumpers(void); INT16 K_CalculatePowerLevelInc(INT16 diff); +INT16 K_CalculatePowerLevelAvg(void); void K_PlayerForfeit(UINT8 playernum, boolean nopointloss); void K_CheckSpectateStatus(void); diff --git a/src/y_inter.c b/src/y_inter.c index 42a5b0921..67c4b797b 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -710,8 +710,14 @@ dotimer: } // Make it obvious that scrambling is happening next round. - if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!")); + if ((intertic/TICRATE) & 1) + { + /*if (cv_scrambleonchange.value && cv_teamscramble.value) + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!"));*/ + if (speedscramble != -1) + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-12, hilicol|V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, + M_GetText("The next race will be %s Speed!", (speedscramble == 2 ? "Hard" : "Normal"))); + } } // @@ -943,6 +949,78 @@ void Y_StartIntermission(void) powertype = 0; else if (G_BattleGametype()) powertype = 1; + + // Race scrambles + if ((intertype == int_race) && (cv_speedscramble.value || cv_encorescramble.value)) + { + boolean hardmode = false; + boolean encore = false; + INT16 avg = 0, min = 0; + UINT8 i, t = 0; + + avg = K_CalculatePowerLevelAvg(); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (min == 0 || clientpowerlevels[i][0] < min) + min = clientpowerlevels[i][0]; + } + + if (min >= 4000) + { + if (avg >= 5000) + t = 3; + else + t = 2; + } + else if (min >= 2500) + { + if (avg >= 3000) + t = 2; + else + t = 1; + } + else if (min >= 500) + { + if (avg >= 2000) + t = 1; + else + t = 0; + } + else + t = 0; + + switch (t) + { + case 3: + hardmode = true; + encore = M_RandomChance(FRACUNIT>>1); + break; + case 2: + hardmode = M_RandomChance((7<>2); + break; + case 1: + hardmode = M_RandomChance((3<