From ebb34ff9d4ad8526e16ded14baa13805d9ebd17f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 14 Aug 2022 06:00:37 -0400 Subject: [PATCH] Lap based power level --- src/command.c | 24 +--- src/d_netcmd.c | 50 +++----- src/d_netcmd.h | 1 - src/d_player.h | 1 + src/doomstat.h | 1 + src/g_demo.c | 17 ++- src/g_game.c | 6 + src/hu_stuff.c | 2 +- src/k_hud.c | 14 +-- src/k_kart.c | 2 +- src/k_pwrlv.c | 291 ++++++++++++++++++++++++++++++++++++++++---- src/k_pwrlv.h | 29 ++++- src/lua_playerlib.c | 4 + src/lua_script.c | 2 +- src/m_menu.c | 10 +- src/p_inter.c | 9 +- src/p_local.h | 3 + src/p_saveg.c | 12 +- src/p_setup.c | 34 +++--- src/p_spec.c | 42 ++++--- src/p_user.c | 3 +- src/y_inter.c | 175 +++----------------------- 22 files changed, 415 insertions(+), 317 deletions(-) diff --git a/src/command.c b/src/command.c index a0f2967bf..6bbf58c44 100644 --- a/src/command.c +++ b/src/command.c @@ -1641,34 +1641,14 @@ void CV_SaveVars(UINT8 **p, boolean in_demo) // the client will reset all netvars to default before loading WRITEUINT16(*p, 0x0000); for (cvar = consvar_vars; cvar; cvar = cvar->next) - if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (in_demo && cvar->netid == cv_numlaps.netid)) + if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) { if (in_demo) WRITESTRING(*p, cvar->name); else WRITEUINT16(*p, cvar->netid); - // UGLY HACK: Save proper lap count in net replays - if (in_demo && cvar->netid == cv_numlaps.netid) - { - if (cv_basenumlaps.value && - (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) - || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value)) - ) - { - WRITESTRING(*p, cv_basenumlaps.string); - } - else - { - char buf[9]; - sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps); - WRITESTRING(*p, buf); - } - } - else - { - WRITESTRING(*p, cvar->string); - } + WRITESTRING(*p, cvar->string); WRITEUINT8(*p, false); ++count; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 99fcbded3..7e8143427 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -102,7 +102,6 @@ static void Got_DiscordInfo(UINT8 **cp, INT32 playernum); static void PointLimit_OnChange(void); static void TimeLimit_OnChange(void); static void NumLaps_OnChange(void); -static void BaseNumLaps_OnChange(void); static void Mute_OnChange(void); static void AutoBalance_OnChange(void); @@ -141,7 +140,6 @@ static void Color4_OnChange(void); static void DummyConsvar_OnChange(void); static void SoundTest_OnChange(void); -static void BaseNumLaps_OnChange(void); static void KartFrantic_OnChange(void); static void KartSpeed_OnChange(void); static void KartEncore_OnChange(void); @@ -467,10 +465,9 @@ static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}}; consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); -static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; -consvar_t cv_numlaps = CVAR_INIT ("numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); -static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); + +static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {MAX_LAPS, "MAX"}, {0, "Map default"}, {0, NULL}}; +consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, numlaps_cons_t, NumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -691,7 +688,6 @@ void D_RegisterServerCommands(void) // misc CV_RegisterVar(&cv_pointlimit); CV_RegisterVar(&cv_numlaps); - CV_RegisterVar(&cv_basenumlaps); CV_RegisterVar(&cv_autobalance); CV_RegisterVar(&cv_teamscramble); @@ -4480,24 +4476,6 @@ static void PointLimit_OnChange(void) CONS_Printf(M_GetText("Point limit disabled\n")); } -static void NumLaps_OnChange(void) -{ - if (K_CanChangeRules() == false) - { - return; - } - - if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) - && (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps)) - { - CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps); - } - - // Just don't be verbose - if (gametyperules & GTR_CIRCUIT) - CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value); -} - static void NetTimeout_OnChange(void) { connectiontimeout = (tic_t)cv_nettimeout.value; @@ -5759,22 +5737,24 @@ static void Command_ShowTime_f(void) } // SRB2Kart: On change messages -static void BaseNumLaps_OnChange(void) +static void NumLaps_OnChange(void) { - if (K_CanChangeRules() == true) + if (K_CanChangeRules() == false) { - const char *str = va("%d", cv_basenumlaps.value); + return; + } - if (cv_basenumlaps.value == 0) - { - str = "map defaults"; - } - - CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str); + if (leveltime < starttime) + { + CONS_Printf(M_GetText("Number of laps have been set to %d.\n"), cv_numlaps.value); + numlaps = (UINT8)cv_numlaps.value; + } + else + { + CONS_Printf(M_GetText("Number of laps will be set to %d next round.\n"), cv_numlaps.value); } } - static void KartFrantic_OnChange(void) { if (K_CanChangeRules() == false) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index f6d172bcc..e84342795 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -42,7 +42,6 @@ extern consvar_t cv_itemrespawn; extern consvar_t cv_pointlimit; extern consvar_t cv_timelimit; extern consvar_t cv_numlaps; -extern consvar_t cv_basenumlaps; extern UINT32 timelimitintics; extern consvar_t cv_allowexitlevel; diff --git a/src/d_player.h b/src/d_player.h index e81e4b6f1..e1971cf1c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -537,6 +537,7 @@ typedef struct player_s INT16 totalring; // Total number of rings obtained for GP tic_t realtime; // integer replacement for leveltime UINT8 laps; // Number of laps (optional) + UINT8 latestlap; INT32 starpostnum; // The number of the last starpost you hit UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue diff --git a/src/doomstat.h b/src/doomstat.h index 4e782e59c..791504815 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -700,6 +700,7 @@ extern INT16 scramblecount; //for CTF team scramble extern INT32 cheats; // SRB2kart +extern UINT8 numlaps; extern UINT8 gamespeed; extern boolean franticitems; extern boolean encoremode, prevencoremode; diff --git a/src/g_demo.c b/src/g_demo.c index a5f658a62..24ee6cd4e 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1999,6 +1999,7 @@ void G_BeginRecording(void) WRITEUINT8(demo_p, demoflags); WRITEUINT8(demo_p, gametype & 0xFF); + WRITEUINT8(demo_p, numlaps); // file list m = demo_p;/* file count */ @@ -2429,6 +2430,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 16; // map md5 flags = READUINT8(p); // demoflags p++; // gametype + p++; // numlaps G_SkipDemoExtraFiles(&p); aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); @@ -2486,6 +2488,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 16; // mapmd5 flags = READUINT8(p); p++; // gametype + p++; // numlaps G_SkipDemoExtraFiles(&p); if (!(flags & aflags)) { @@ -2600,6 +2603,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) } pdemo->gametype = READUINT8(info_p); + pdemo->numlaps = READUINT8(info_p); pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); info_p += 4; // RNG seed @@ -2626,20 +2630,11 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) pdemo->kartspeed = kartspeed_cons_t[j].value; } - else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) - pdemo->numlaps = atoi(svalue); } if (pdemoflags & DF_ENCORE) pdemo->kartspeed |= DF_ENCORE; - /*// Temporary info until this is actually present in replays. - (void)extrainfo_p; - sprintf(pdemo->winnername, "transrights420"); - pdemo->winnerskin = 1; - pdemo->winnercolor = SKINCOLOR_MOONSET; - pdemo->winnertime = 6666;*/ - // Read standings! count = 0; @@ -2835,6 +2830,7 @@ void G_DoPlayDemo(char *defdemoname) demoflags = READUINT8(demo_p); gametype = READUINT8(demo_p); G_SetGametype(gametype); + numlaps = READUINT8(demo_p); if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. G_SkipDemoExtraFiles(&demo_p); @@ -3258,6 +3254,7 @@ void G_AddGhost(char *defdemoname) } p++; // gametype + p++; // numlaps G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) @@ -3475,7 +3472,7 @@ void G_UpdateStaffGhostName(lumpnum_t l) } p++; // Gametype - + p++; // numlaps G_SkipDemoExtraFiles(&p); switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) diff --git a/src/g_game.c b/src/g_game.c index 2939dee2e..50dd18713 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -303,6 +303,7 @@ INT32 cheats; //for multiplayer cheat commands // SRB2Kart // Cvars that we don't want changed mid-game +UINT8 numlaps; // Removed from Cvar hell UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard boolean encoremode = false; // Encore Mode currently enabled? boolean prevencoremode; @@ -2198,6 +2199,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) INT32 khudcardanimation; INT16 totalring; UINT8 laps; + UINT8 latestlap; UINT16 skincolor; INT32 skin; UINT32 availabilities; @@ -2284,6 +2286,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) khudfault = 0; nocontrol = 0; laps = 0; + latestlap = 0; totalring = 0; roundscore = 0; exiting = 0; @@ -2324,6 +2327,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) nocontrol = players[player].nocontrol; laps = players[player].laps; + latestlap = players[player].latestlap; + totalring = players[player].totalring; roundscore = players[player].roundscore; @@ -2380,6 +2385,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->karthud[khud_cardanimation] = khudcardanimation; p->laps = laps; + p->latestlap = latestlap; p->totalring = totalring; p->bot = bot; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 194f1de0b..f4f52f5cf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2421,7 +2421,7 @@ static void HU_DrawRankings(void) if (circuitmap) { V_DrawCenteredString(64, 8, 0, "LAP COUNT"); - V_DrawCenteredString(64, 16, hilicol, va("%d", cv_numlaps.value)); + V_DrawCenteredString(64, 16, hilicol, va("%d", numlaps)); } V_DrawCenteredString(256, 8, 0, "GAME SPEED"); diff --git a/src/k_hud.c b/src/k_hud.c index 2f0a43b24..efb2cda3a 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1706,7 +1706,7 @@ static void K_DrawKartPositionNum(INT32 num) { localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3]; } - else if (stplyr->laps >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won + else if (stplyr->laps >= numlaps || stplyr->exiting) // Check for the final lap, or won { boolean useRedNums = K_IsPlayerLosing(stplyr); @@ -2337,7 +2337,7 @@ static void K_drawKartLapsAndRings(void) V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_splitlapflag); V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|V_SLIDEIN|splitflags, frameslash); - if (cv_numlaps.value >= 10) + if (numlaps >= 10) { UINT8 ln[2]; ln[0] = ((stplyr->laps / 10) % 10); @@ -2346,8 +2346,8 @@ static void K_drawKartLapsAndRings(void) V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]); V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]); - ln[0] = ((abs(cv_numlaps.value) / 10) % 10); - ln[1] = (abs(cv_numlaps.value) % 10); + ln[0] = ((abs(numlaps) / 10) % 10); + ln[1] = (abs(numlaps) % 10); V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]); V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]); @@ -2355,7 +2355,7 @@ static void K_drawKartLapsAndRings(void) else { V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->laps) % 10]); - V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(cv_numlaps.value) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(numlaps) % 10]); } // Rings @@ -2393,7 +2393,7 @@ static void K_drawKartLapsAndRings(void) { // Laps V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_lapsticker); - V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, cv_numlaps.value), cv_numlaps.value)); + V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps)); // Rings if (!uselives) @@ -4367,7 +4367,7 @@ static void K_drawLapStartAnim(void) kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL); } - if (stplyr->laps == (UINT8)(cv_numlaps.value)) + if (stplyr->laps == (UINT8)(numlaps)) { newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT; oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT; diff --git a/src/k_kart.c b/src/k_kart.c index 043507b92..becb9f56c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8261,7 +8261,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) // distance calculation to work easily if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == 0U) { - const UINT8 numfulllapsleft = ((UINT8)cv_numlaps.value - player->laps); + const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps); player->distancetofinish += numfulllapsleft * K_GetCircuitLength(); diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 22c386191..a08487110 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -1,5 +1,12 @@ -/// \file k_pwrlv.c -/// \brief SRB2Kart Power Levels +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2022 by Sally Cochenour +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +// \brief Power Level system #include "k_pwrlv.h" #include "d_netcmd.h" @@ -19,9 +26,12 @@ UINT16 vspowerlevel[PWRLV_NUMTYPES]; // This is done so that clients will never be able to hack someone else's score over the server. UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES]; -// Which players spec-scummed, and their power level before scumming. -// On race finish, everyone is considered to have "won" against these people. -INT16 nospectategrief[MAXPLAYERS]; +// Total calculated power add during the match, +// totalled at the end of the round. +INT16 clientPowerAdd[MAXPLAYERS]; + +// Players who spectated mid-race +UINT8 spectateGriefed = 0; // Game setting scrambles based on server Power Level SINT8 speedscramble = -1; @@ -52,8 +62,14 @@ void K_ClearClientPowerLevels(void) { UINT8 i, j; for (i = 0; i < MAXPLAYERS; i++) + { + clientPowerAdd[i] = 0; + for (j = 0; j < PWRLV_NUMTYPES; j++) + { clientpowerlevels[i][j] = 0; + } + } } // Adapted from this: http://wiki.tockdom.com/wiki/Player_Rating @@ -143,7 +159,206 @@ INT16 K_CalculatePowerLevelAvg(void) return (INT16)(avg >> FRACBITS); } -// -- K_UpdatePowerLevels could not be moved here due to usage of y_data, unfortunately. -- +void K_UpdatePowerLevels(player_t *player) +{ + const UINT8 playerNum = player - players; + const boolean exitBonus = ((player->laps > numlaps) || (player->pflags & PF_NOCONTEST)); + + SINT8 powerType = K_UsingPowerLevels(); + + INT16 yourScore = 0; + UINT16 yourPower = 0; + + UINT8 i; + + // Compare every single player against each other for power level increases. + // Every player you won against gives you more points, and vice versa. + // The amount of points won per match-up depends on the difference between the loser's power and the winner's power. + // See K_CalculatePowerLevelInc for more info. + + if (powerType == PWRLV_DISABLED) + { + return; + } + + if (!playeringame[playerNum] || player->spectator) + { + return; + } + + CONS_Printf("Power Level Gain for player %d:\n", playerNum); + + yourPower = clientpowerlevels[playerNum][powerType]; + if (yourPower == 0) + { + // Guests don't record power level changes. + return; + } + + CONS_Printf("Player %d's PWR.LV: %d\n", playerNum, yourPower); + + if (gametyperules & GTR_CIRCUIT) + { + yourScore = MAXPLAYERS - player->position; + } + else + { + yourScore = player->score; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT16 theirScore = 0; + INT16 theirPower = PWRLVRECORD_DEF; + + INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV + INT16 inc = 0; // Total pt increment + + boolean won = false; + + if (i == playerNum) // Same person + { + continue; + } + + if (!playeringame[i] || players[i].spectator) + { + continue; + } + + CONS_Printf("Player %d VS Player %d:\n", playerNum, i); + + theirPower = clientpowerlevels[i][powerType]; + if (theirPower == 0) + { + // No power level (splitscreen guests, bots) + continue; + } + + CONS_Printf("Player %d's PWR.LV: %d\n", i, theirPower); + + if (gametyperules & GTR_CIRCUIT) + { + theirScore = MAXPLAYERS - players[i].position; + } + else + { + theirScore = players[i].score; + } + + if (yourScore == theirScore) // Tie -- neither get any points for this match up. + { + CONS_Printf("TIE, no change.\n"); + continue; + } + + won = (yourScore > theirScore); + + if (won) // This player won! + { + diff = theirPower - yourPower; + inc += K_CalculatePowerLevelInc(diff); + CONS_Printf("WON! Diff is %d, total increment is %d\n", diff, inc); + } + else // This player lost... + { + diff = yourPower - theirPower; + inc -= K_CalculatePowerLevelInc(diff); + CONS_Printf("LOST... Diff is %d, total increment is %d\n", diff, inc); + } + + if (exitBonus == false) + { + CONS_Printf("Reduced (%d / %d = %d) because it's not the end of the race\n", inc, numlaps, inc/numlaps); + inc /= numlaps; + } + + if (inc == 0) + { + CONS_Printf("Total Result: No increment, no change.\n"); + continue; + } + + CONS_Printf("Total Result: Increment of %d.\n", inc); + + clientPowerAdd[playerNum] += inc; + clientPowerAdd[i] -= inc; + } +} + +INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 increment) +{ + INT16 inc = increment; + UINT8 numPlayers = 0; + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + continue; + } + + numPlayers++; + } + + if (inc <= 0) + { + if (player->position == 1) + { + // Won the whole match? + // Get at least one point. + inc = 1; + } + else + { + // You trade points in 1v1s, + // but is more lenient in bigger lobbies. + inc /= max(1, numPlayers-1); + } + } + + if (yourPower + inc > PWRLVRECORD_MAX) + { + inc -= ((yourPower + inc) - PWRLVRECORD_MAX); + } + + if (yourPower + inc < PWRLVRECORD_MIN) + { + inc -= ((yourPower + inc) - PWRLVRECORD_MIN); + } + + return inc; +} + +void K_CashInPowerLevels(void) +{ + SINT8 powerType = K_UsingPowerLevels(); + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (powerType != PWRLV_DISABLED) + { + INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]); + clientpowerlevels[i][powerType] += inc; + + if (!demo.playback && i == consoleplayer) + { + vspowerlevel[powerType] = clientpowerlevels[i][powerType]; + + if (M_UpdateUnlockablesAndExtraEmblems()) + { + S_StartSound(NULL, sfx_ncitem); + } + + G_SaveGameData(); + } + } + + clientPowerAdd[i] = 0; + } +} void K_SetPowerLevelScrambles(SINT8 powertype) { @@ -227,7 +442,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype) { case 5: speed = KARTSPEED_HARD; - encore = true; + encore = P_RandomChance(FRACUNIT>>1); break; case 4: speed = P_RandomChance((7<>2); break; case 2: - speed = 1; + speed = KARTSPEED_NORMAL; encore = P_RandomChance(FRACUNIT>>3); break; case 1: default: @@ -254,7 +469,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype) CONS_Debug(DBG_GAMELOGIC, "Rolled speed: %d\n", speed); CONS_Debug(DBG_GAMELOGIC, "Rolled encore: %s\n", (encore ? "true" : "false")); - if (cv_kartspeed.value == -1) + if (cv_kartspeed.value == KARTSPEED_AUTO) speedscramble = speed; else speedscramble = -1; @@ -278,16 +493,13 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) UINT16 theirpower = PWRLVRECORD_DEF; INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV INT16 inc = 0; + UINT8 lapsLeft = 0; UINT8 i; // power level & spectating is netgames only if (!netgame) return; - // This server isn't using power levels anyway! - if (!cv_kartusepwrlv.value) - return; - // Hey, I just got here! if (players[playernum].jointime <= 1) return; @@ -296,14 +508,25 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) if (gamestate != GS_LEVEL || leveltime <= starttime+(20*TICRATE)) return; + spectateGriefed++; + + // This server isn't using power levels, so don't mess with them. + if (!cv_kartusepwrlv.value) + return; + for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator) + if ((playeringame[i] && !players[i].spectator) + || (i == playernum)) + { p++; + } } if (p < 2) // no players + { return; + } if ((gametyperules & GTR_CIRCUIT)) powertype = PWRLV_RACE; @@ -317,14 +540,12 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) return; yourpower = clientpowerlevels[playernum][powertype]; - // Set up the point compensation. - nospectategrief[playernum] = yourpower; - - if (!pointloss) // This is set for stuff like sync-outs, which shouldn't be so harsh on the victim! - return; + lapsLeft = (numlaps - players[playernum].latestlap); for (i = 0; i < MAXPLAYERS; i++) { + INT16 thisInc = 0; + if (i == playernum) continue; @@ -334,24 +555,40 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) theirpower = clientpowerlevels[i][powertype]; diff = yourpower - theirpower; - inc -= K_CalculatePowerLevelInc(diff); + thisInc = K_CalculatePowerLevelInc(diff); + + if (thisInc == 0) + { + continue; + } + + thisInc *= lapsLeft; + clientPowerAdd[i] += thisInc; + inc -= thisInc; } - if (inc == 0) // No change. + if (inc >= 0) + { + // No change. Also don't award points. return; + } - if (yourpower + inc > PWRLVRECORD_MAX) // I mean... we're subtracting... but y'know how it is :V + if (yourpower + inc > PWRLVRECORD_MAX) // I mean... we're always subtracting... but y'know how it is :V inc -= ((yourpower + inc) - PWRLVRECORD_MAX); if (yourpower + inc < PWRLVRECORD_MIN) inc -= ((yourpower + inc) - PWRLVRECORD_MIN); - clientpowerlevels[playernum][powertype] += inc; - - if (!demo.playback && playernum == consoleplayer) + // pointloss isn't set for stuff like sync-outs, + // which shouldn't be so harsh on the victim! + if (!demo.playback && pointloss == true && playernum == consoleplayer) { - vspowerlevel[powertype] = clientpowerlevels[playernum][powertype]; + vspowerlevel[powertype] = clientpowerlevels[playernum][powertype] + inc; + if (M_UpdateUnlockablesAndExtraEmblems()) + { S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(); // save your punishment! + } + + G_SaveGameData(); } } diff --git a/src/k_pwrlv.h b/src/k_pwrlv.h index 579e298af..2c582dd21 100644 --- a/src/k_pwrlv.h +++ b/src/k_pwrlv.h @@ -1,13 +1,27 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2022 by Sally Cochenour +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +// \brief Power Level system + #ifndef __K_PWRLV__ #define __K_PWRLV__ #include "doomtype.h" #include "doomdef.h" +#include "d_player.h" -#define PWRLV_DISABLED -1 -#define PWRLV_RACE 0 -#define PWRLV_BATTLE 1 -#define PWRLV_NUMTYPES 2 +typedef enum +{ + PWRLV_DISABLED = -1, + PWRLV_RACE = 0, + PWRLV_BATTLE = 1, + PWRLV_NUMTYPES = 2, +} pwrlv_type_t; #define PWRLVRECORD_START 1000 #define PWRLVRECORD_DEF 5000 @@ -19,13 +33,16 @@ extern SINT8 encorescramble; extern UINT16 vspowerlevel[PWRLV_NUMTYPES]; extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES]; -extern INT16 nospectategrief[MAXPLAYERS]; +extern INT16 clientPowerAdd[MAXPLAYERS]; +extern UINT8 spectateGriefed; SINT8 K_UsingPowerLevels(void); void K_ClearClientPowerLevels(void); INT16 K_CalculatePowerLevelInc(INT16 diff); INT16 K_CalculatePowerLevelAvg(void); -//void K_UpdatePowerLevels(void); +void K_UpdatePowerLevels(player_t *player); +INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 increment); +void K_CashInPowerLevels(void); void K_SetPowerLevelScrambles(SINT8 powertype); void K_PlayerForfeit(UINT8 playernum, boolean nopointloss); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 4b2bad33d..c448a287a 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -446,6 +446,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->realtime); else if (fastcmp(field,"laps")) lua_pushinteger(L, plr->laps); + else if (fastcmp(field,"latestlap")) + lua_pushinteger(L, plr->latestlap); else if (fastcmp(field,"ctfteam")) lua_pushinteger(L, plr->ctfteam); else if (fastcmp(field,"checkskip")) @@ -786,6 +788,8 @@ static int player_set(lua_State *L) plr->realtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"laps")) plr->laps = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"latestlap")) + plr->latestlap = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"ctfteam")) plr->ctfteam = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"checkskip")) diff --git a/src/lua_script.c b/src/lua_script.c index 8aea589db..1511fdf0d 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -391,7 +391,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushinteger(L, mapobjectscale); return 1; } else if (fastcmp(word,"numlaps")) { - lua_pushinteger(L, cv_numlaps.value); + lua_pushinteger(L, numlaps); return 1; } else if (fastcmp(word,"racecountdown")) { lua_pushinteger(L, racecountdown); diff --git a/src/m_menu.c b/src/m_menu.c index b7299fc9b..58a40176e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1478,17 +1478,17 @@ static menuitem_t OP_GameOptionsMenu[] = {IT_STRING | IT_SUBMENU, NULL, "Random Item Toggles...", {.submenu = &OP_MonitorToggleDef}, 10}, {IT_STRING | IT_CVAR, NULL, "Game Speed", {.cvar = &cv_kartspeed}, 30}, - {IT_STRING | IT_CVAR, NULL, "Frantic Items", {.cvar = &cv_kartfrantic}, 40}, + {IT_STRING | IT_CVAR, NULL, "Frantic Items", {.cvar = &cv_kartfrantic}, 40}, {IT_SECRET, NULL, "Encore Mode", {.cvar = &cv_kartencore}, 50}, - {IT_STRING | IT_CVAR, NULL, "Number of Laps", {.cvar = &cv_basenumlaps}, 70}, + {IT_STRING | IT_CVAR, NULL, "Number of Laps", {.cvar = &cv_numlaps}, 70}, {IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", {.cvar = &cv_countdowntime}, 80}, {IT_STRING | IT_CVAR, NULL, "Time Limit", {.cvar = &cv_timelimit}, 100}, - {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", {.cvar = &cv_kartbumpers}, 110}, - {IT_STRING | IT_CVAR, NULL, "Karma Comeback", {.cvar = &cv_kartcomeback}, 120}, + {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", {.cvar = &cv_kartbumpers}, 110}, + {IT_STRING | IT_CVAR, NULL, "Karma Comeback", {.cvar = &cv_kartcomeback}, 120}, - {IT_STRING | IT_CVAR, NULL, "Track Power Levels", {.cvar = &cv_kartusepwrlv}, 140}, + {IT_STRING | IT_CVAR, NULL, "Track Power Levels", {.cvar = &cv_kartusepwrlv}, 140}, }; static menuitem_t OP_ServerOptionsMenu[] = diff --git a/src/p_inter.c b/src/p_inter.c index 83a6eb83c..0974e11d7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -792,16 +792,11 @@ boolean P_CheckRacers(void) boolean eliminatelast = cv_karteliminatelast.value; boolean everyonedone = true; boolean eliminatebots = false; - boolean griefed = false; + const boolean griefed = (spectateGriefed > 0); // Check if all the players in the race have finished. If so, end the level. for (i = 0; i < MAXPLAYERS; i++) { - if (nospectategrief[i] != -1) // prevent spectate griefing - { - griefed = true; - } - if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing { // Y'all aren't even playing @@ -922,7 +917,7 @@ boolean P_CheckRacers(void) // We're still playing, but no one else is, so we need to reset spectator griefing. if (numplayersingame <= 1) { - memset(nospectategrief, -1, sizeof (nospectategrief)); + spectateGriefed = 0; } // Turns out we're still having a good time & playing the game, we didn't have to do anything :) diff --git a/src/p_local.h b/src/p_local.h index bb0d02fb2..0e03b8482 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -28,6 +28,9 @@ //#define VIEWHEIGHTS "41" +// Maximum laps per map. +#define MAX_LAPS 99 + // Maximum player score. #define MAXSCORE 99999990 // 999999990 diff --git a/src/p_saveg.c b/src/p_saveg.c index 554be67d2..81adeca60 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -106,6 +106,7 @@ static void P_NetArchivePlayers(void) { WRITEINT16(save_p, clientpowerlevels[i][j]); } + WRITEINT16(save_p, clientPowerAdd[i]); if (!playeringame[i]) continue; @@ -167,6 +168,7 @@ static void P_NetArchivePlayers(void) WRITEINT16(save_p, players[i].totalring); WRITEUINT32(save_p, players[i].realtime); WRITEUINT8(save_p, players[i].laps); + WRITEUINT8(save_p, players[i].latestlap); WRITEINT32(save_p, players[i].starpostnum); WRITEUINT8(save_p, players[i].ctfteam); @@ -404,6 +406,7 @@ static void P_NetUnArchivePlayers(void) { clientpowerlevels[i][j] = READINT16(save_p); } + clientPowerAdd[i] = READINT16(save_p); // Do NOT memset player struct to 0 // other areas may initialize data elsewhere @@ -466,6 +469,7 @@ static void P_NetUnArchivePlayers(void) players[i].totalring = READINT16(save_p); // Total number of rings obtained for GP players[i].realtime = READUINT32(save_p); // integer replacement for leveltime players[i].laps = READUINT8(save_p); // Number of laps (optional) + players[i].latestlap = READUINT8(save_p); players[i].starpostnum = READINT32(save_p); players[i].ctfteam = READUINT8(save_p); // 1 == Red, 2 == Blue @@ -4495,6 +4499,7 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT8(save_p, battlecapsules); WRITEUINT8(save_p, gamespeed); + WRITEUINT8(save_p, numlaps); WRITEUINT8(save_p, franticitems); WRITEUINT8(save_p, comeback); @@ -4515,8 +4520,7 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT32(save_p, indirectitemcooldown); WRITEUINT32(save_p, mapreset); - for (i = 0; i < MAXPLAYERS; i++) - WRITEINT16(save_p, nospectategrief[i]); + WRITEUINT8(save_p, spectateGriefed); WRITEUINT8(save_p, thwompsactive); WRITEUINT8(save_p, lastLowestLap); @@ -4644,6 +4648,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) battlecapsules = (boolean)READUINT8(save_p); gamespeed = READUINT8(save_p); + numlaps = READUINT8(save_p); franticitems = (boolean)READUINT8(save_p); comeback = (boolean)READUINT8(save_p); @@ -4664,8 +4669,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) indirectitemcooldown = READUINT32(save_p); mapreset = READUINT32(save_p); - for (i = 0; i < MAXPLAYERS; i++) - nospectategrief[i] = READINT16(save_p); + spectateGriefed = READUINT8(save_p); thwompsactive = (boolean)READUINT8(save_p); lastLowestLap = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index a9701511b..20d45052c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4063,25 +4063,37 @@ static void P_InitPlayers(void) static void P_InitGametype(void) { + spectateGriefed = 0; + K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped + P_InitPlayers(); if (modeattacking && !demo.playback) P_LoadRecordGhosts(); - if ((gametyperules & GTR_CIRCUIT) && server) + numlaps = 0; + if (gametyperules & GTR_CIRCUIT) { - if ((netgame || multiplayer) && cv_basenumlaps.value + if ((netgame || multiplayer) && cv_numlaps.value && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) - || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))) + || (mapheaderinfo[gamemap - 1]->numlaps > cv_numlaps.value))) { - CV_StealthSetValue(&cv_numlaps, cv_basenumlaps.value); + numlaps = cv_numlaps.value; } else { - CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps); + numlaps = mapheaderinfo[gamemap - 1]->numlaps; } } + wantedcalcdelay = wantedfrequency*2; + indirectitemcooldown = 0; + mapreset = 0; + + thwompsactive = false; + lastLowestLap = 0; + spbplace = -1; + // Start recording replay in multiplayer with a temp filename //@TODO I'd like to fix dedis crashing when recording replays for the future too... if (!demo.playback && multiplayer && !dedicated) @@ -4117,6 +4129,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Map header should always be in place at this point INT32 i, ranspecialwipe = 0; sector_t *ss; + levelloading = true; // This is needed. Don't touch. @@ -4430,17 +4443,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) K_InitDirector(); } - wantedcalcdelay = wantedfrequency*2; - indirectitemcooldown = 0; - mapreset = 0; - - for (i = 0; i < MAXPLAYERS; i++) - nospectategrief[i] = -1; - - thwompsactive = false; - lastLowestLap = 0; - spbplace = -1; - // clear special respawning que iquehead = iquetail = 0; diff --git a/src/p_spec.c b/src/p_spec.c index ccb31d447..9bf655483 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1917,14 +1917,6 @@ static void K_HandleLapIncrement(player_t *player) player->karthud[khud_laphand] = 0; // No hands in FREE PLAY player->karthud[khud_lapanimation] = 80; - - // save best lap for record attack - if (player == &players[consoleplayer]) - { - if (curlap < bestlap || bestlap == 0) - bestlap = curlap; - curlap = 0; - } } if (rainbowstartavailable == true) @@ -1938,18 +1930,18 @@ static void K_HandleLapIncrement(player_t *player) rainbowstartavailable = false; } - if (netgame && player->laps >= (UINT8)cv_numlaps.value) + if (netgame && player->laps >= numlaps) CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players])); player->starpostnum = 0; if (P_IsDisplayPlayer(player)) { - if (player->laps == (UINT8)(cv_numlaps.value)) // final lap + if (player->laps == numlaps) // final lap S_StartSound(NULL, sfx_s3k68); - else if ((player->laps > 1) && (player->laps < (UINT8)(cv_numlaps.value))) // non-final lap + else if ((player->laps > 1) && (player->laps < numlaps)) // non-final lap S_StartSound(NULL, sfx_s221); - else if (player->laps > (UINT8)(cv_numlaps.value)) + else if (player->laps > numlaps) { // finished S_StartSound(NULL, sfx_s3k6a); @@ -1958,7 +1950,7 @@ static void K_HandleLapIncrement(player_t *player) } else { - if ((player->laps > (UINT8)(cv_numlaps.value)) && (player->position == 1)) + if ((player->laps > numlaps) && (player->position == 1)) { // opponent finished S_StartSound(NULL, sfx_s253); @@ -1966,12 +1958,34 @@ static void K_HandleLapIncrement(player_t *player) } // finished race exit setup - if (player->laps > (unsigned)cv_numlaps.value) + if (player->laps > numlaps) { P_DoPlayerExit(player); P_SetupSignExit(player); } + if (player->laps > player->latestlap) + { + if (player->laps > 1) + { + // save best lap for record attack + if (modeattacking && player == &players[consoleplayer]) + { + if (curlap < bestlap || bestlap == 0) + { + bestlap = curlap; + } + + curlap = 0; + } + + // Update power levels for this lap. + K_UpdatePowerLevels(player); + } + + player->latestlap = player->laps; + } + thwompsactive = true; // Lap 2 effects lowestLap = P_FindLowestLap(); diff --git a/src/p_user.c b/src/p_user.c index ffc53012b..aafcbe4ea 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -873,7 +873,7 @@ void P_RestoreMusic(player_t *player) #if 0 // Event - Final Lap // Still works for GME, but disabled for consistency - if ((gametyperules & GTR_CIRCUIT) && player->laps >= (UINT8)(cv_numlaps.value)) + if ((gametyperules & GTR_CIRCUIT) && player->laps >= numlaps) S_SpeedMusic(1.2f); #endif if (mapmusresume && cv_resume.value) @@ -3851,6 +3851,7 @@ void P_DoTimeOver(player_t *player) } player->pflags |= PF_NOCONTEST; + K_UpdatePowerLevels(player); if (G_GametypeUsesLives()) { diff --git a/src/y_inter.c b/src/y_inter.c index d612f0e75..fe5c5ba90 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -214,7 +214,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) { INT32 i, j; boolean completed[MAXPLAYERS]; - INT32 numplayersingame = 0, numgriefers = 0; + INT32 numplayersingame = 0; // Initialize variables if (rankingsmode > 1) @@ -273,9 +273,6 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) { data.val[i] = UINT32_MAX; - if (nospectategrief[i] != -1) - numgriefers++; - if (!playeringame[i] || players[i].spectator) { data.increase[i] = INT16_MIN; @@ -324,10 +321,10 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) { if ((powertype == PWRLV_DISABLED) && !(players[i].pflags & PF_NOCONTEST) - && (data.pos[data.numplayers] < (numplayersingame + numgriefers))) + && (data.pos[data.numplayers] < (numplayersingame + spectateGriefed))) { // Online rank is handled further below in this file. - data.increase[i] = K_CalculateGPRankPoints(data.pos[data.numplayers], numplayersingame + numgriefers); + data.increase[i] = K_CalculateGPRankPoints(data.pos[data.numplayers], numplayersingame + spectateGriefed); players[i].score += data.increase[i]; } @@ -890,157 +887,6 @@ void Y_Ticker(void) } } -static void K_UpdatePowerLevels(void) -{ - INT32 i, j; - INT32 numplayersingame = 0, numgriefers = 0; - INT16 increment[MAXPLAYERS]; - - // Compare every single player against each other for power level increases. - // Every player you won against gives you more points, and vice versa. - // The amount of points won per match-up depends on the difference between the loser's power and the winner's power. - // See K_CalculatePowerLevelInc for more info. - - for (i = 0; i < MAXPLAYERS; i++) - { - increment[i] = 0; - - if (nospectategrief[i] != -1) - numgriefers++; - - if (!playeringame[i] || players[i].spectator) - continue; - - numplayersingame++; - } - - for (i = 0; i < numplayersingame; i++) - { - UINT16 yourpower = PWRLVRECORD_DEF; - UINT16 theirpower = PWRLVRECORD_DEF; - INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV - INT16 inc = 0; // Total pt increment - UINT8 ipnum = data.num[i]; - UINT8 jpnum; - - CONS_Debug(DBG_GAMELOGIC, "Power Level Gain for player %d:\n", ipnum); - - if (clientpowerlevels[ipnum][powertype] == 0) // splitscreen guests don't record power level changes - continue; - yourpower = clientpowerlevels[ipnum][powertype]; - - CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", ipnum, yourpower); - - for (j = 0; j < numplayersingame; j++) - { - boolean won = false; - - jpnum = data.num[j]; - - if (i == j || ipnum == jpnum) // Same person - continue; - - CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d:\n", ipnum, jpnum); - - if (data.val[i] == data.val[j]) // Tie -- neither get any points for this match up. - { - CONS_Debug(DBG_GAMELOGIC, "TIE, no change.\n"); - continue; - } - - if (clientpowerlevels[jpnum][powertype] == 0) // No power level (splitscreen guests, bots) - continue; - - theirpower = clientpowerlevels[jpnum][powertype]; - - CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower); - - if ((gametyperules & GTR_CIRCUIT)) - { - if (data.val[i] < data.val[j]) - won = true; - } - else - { - if (data.val[i] > data.val[j]) - won = true; - } - - if (won) // This player won! - { - diff = theirpower - yourpower; - inc += K_CalculatePowerLevelInc(diff); - CONS_Debug(DBG_GAMELOGIC, "WON! Diff is %d, total increment is %d\n", diff, inc); - } - else // This player lost... - { - diff = yourpower - theirpower; - inc -= K_CalculatePowerLevelInc(diff); - CONS_Debug(DBG_GAMELOGIC, "LOST... Diff is %d, total increment is %d\n", diff, inc); - } - } - - if (numgriefers != 0) // Automatic win against quitters. - { - for (jpnum = 0; jpnum < MAXPLAYERS; jpnum++) - { - if (nospectategrief[jpnum] == -1) // Empty slot - continue; - - if (ipnum == jpnum) // Same person - continue; - - CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d (griefer):\n", ipnum, jpnum); - - if (nospectategrief[jpnum] == 0) // No power level (splitscreen guests, bots) - continue; - - theirpower = nospectategrief[jpnum]; - - CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower); - - diff = theirpower - yourpower; - inc += K_CalculatePowerLevelInc(diff); - CONS_Debug(DBG_GAMELOGIC, "AUTO-WON! Diff is %d, total increment is %d\n", diff, inc); - } - } - - if (inc == 0) - { - data.increase[ipnum] = INT16_MIN; - CONS_Debug(DBG_GAMELOGIC, "Total Result: No increment, no change.\n"); - continue; - } - - if (yourpower + inc > PWRLVRECORD_MAX) - inc -= ((yourpower + inc) - PWRLVRECORD_MAX); - if (yourpower + inc < PWRLVRECORD_MIN) - inc -= ((yourpower + inc) - PWRLVRECORD_MIN); - - CONS_Debug(DBG_GAMELOGIC, "Total Result: Increment of %d.\n", inc); - increment[ipnum] = inc; - } - - CONS_Debug(DBG_GAMELOGIC, "Setting final power levels...\n"); - for (i = 0; i < MAXPLAYERS; i++) - { - if (increment[i] == 0) - continue; - - data.increase[i] = increment[i]; - clientpowerlevels[i][powertype] += data.increase[i]; - - if (!demo.playback && i == consoleplayer) - { - CONS_Debug(DBG_GAMELOGIC, "Player %d is you! Saving...\n", i); - vspowerlevel[powertype] = clientpowerlevels[i][powertype]; - if (M_UpdateUnlockablesAndExtraEmblems()) - S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(); - } - } -} - // // Y_DetermineIntermissionType // @@ -1121,7 +967,7 @@ void Y_StartIntermission(void) //if (dedicated) return; // This should always exist, but just in case... - if(!mapheaderinfo[prevmap]) + if (!mapheaderinfo[prevmap]) P_AllocMapHeader(prevmap); switch (intertype) @@ -1157,7 +1003,18 @@ void Y_StartIntermission(void) if (powertype != PWRLV_DISABLED) { - K_UpdatePowerLevels(); + for (i = 0; i < nump; i++) + { + // Kind of a hack to do this here, + // but couldn't think of a better way. + data.increase[i] = K_FinalPowerIncrement( + &players[data.num[i]], + clientpowerlevels[data.num[i]][powertype], + clientPowerAdd[data.num[i]] + ); + } + + K_CashInPowerLevels(); } //if (intertype == int_race || intertype == int_battle)