Profiles handle power level properly now

Overwriting the global power level all the time and not updating any code to use the profile was extremely yikes. This also allows for splitscreen players with power levels.
This commit is contained in:
Sally Coolatta 2022-08-30 03:51:35 -04:00
parent d22c7edd30
commit d5a4954dd3
11 changed files with 99 additions and 61 deletions

View file

@ -1538,7 +1538,6 @@ void D_SRB2Main(void)
// Load Profiles now that default controls have been defined // Load Profiles now that default controls have been defined
PR_LoadProfiles(); // load control profiles PR_LoadProfiles(); // load control profiles
PR_SaveProfiles(); // Test @TODO: remove this lol
M_Init(); M_Init();

View file

@ -1886,21 +1886,23 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum)
void D_SendPlayerConfig(UINT8 n) void D_SendPlayerConfig(UINT8 n)
{ {
const profile_t *pr = PR_GetProfile(cv_lastprofile[n].value);
UINT8 buf[4]; UINT8 buf[4];
UINT8 *p = buf; UINT8 *p = buf;
SendNameAndColor(n); SendNameAndColor(n);
SendWeaponPref(n); SendWeaponPref(n);
if (n == 0) if (pr != NULL)
{ {
// Send it over // Send it over
WRITEUINT16(p, vspowerlevel[PWRLV_RACE]); WRITEUINT16(p, pr->powerlevels[PWRLV_RACE]);
WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]); WRITEUINT16(p, pr->powerlevels[PWRLV_BATTLE]);
} }
else else
{ {
// Splitscreen players have invalid powerlevel // Guest players have no power level
WRITEUINT16(p, 0); WRITEUINT16(p, 0);
WRITEUINT16(p, 0); WRITEUINT16(p, 0);
} }

View file

@ -3984,9 +3984,6 @@ void G_LoadGameData(void)
totalplaytime = 0; // total play time (separate from all) totalplaytime = 0; // total play time (separate from all)
matchesplayed = 0; // SRB2Kart: matches played & finished matchesplayed = 0; // SRB2Kart: matches played & finished
for (i = 0; i < PWRLV_NUMTYPES; i++) // SRB2Kart: online rank system
vspowerlevel[i] = PWRLVRECORD_START;
if (M_CheckParm("-nodata")) if (M_CheckParm("-nodata"))
return; // Don't load. return; // Don't load.
@ -4022,13 +4019,6 @@ void G_LoadGameData(void)
totalplaytime = READUINT32(save_p); totalplaytime = READUINT32(save_p);
matchesplayed = READUINT32(save_p); matchesplayed = READUINT32(save_p);
for (i = 0; i < PWRLV_NUMTYPES; i++)
{
vspowerlevel[i] = READUINT16(save_p);
if (vspowerlevel[i] < PWRLVRECORD_MIN || vspowerlevel[i] > PWRLVRECORD_MAX)
goto datacorrupt;
}
modded = READUINT8(save_p); modded = READUINT8(save_p);
// Aha! Someone's been screwing with the save file! // Aha! Someone's been screwing with the save file!
@ -4145,9 +4135,6 @@ void G_SaveGameData(void)
WRITEUINT32(save_p, totalplaytime); WRITEUINT32(save_p, totalplaytime);
WRITEUINT32(save_p, matchesplayed); WRITEUINT32(save_p, matchesplayed);
for (i = 0; i < PWRLV_NUMTYPES; i++)
WRITEUINT16(save_p, vspowerlevel[i]);
WRITEUINT8(save_p, (UINT8)savemoddata); WRITEUINT8(save_p, (UINT8)savemoddata);
// TODO put another cipher on these things? meh, I don't care... // TODO put another cipher on these things? meh, I don't care...

View file

@ -1340,7 +1340,7 @@ static void M_DrawCharSelectPreview(UINT8 num)
INT16 py = y+48 - p->profilen*12; INT16 py = y+48 - p->profilen*12;
UINT8 maxp = PR_GetNumProfiles(); UINT8 maxp = PR_GetNumProfiles();
for (i=0; i < maxp; i++) for (i = 0; i < maxp; i++)
{ {
profile_t *pr = PR_GetProfile(i); profile_t *pr = PR_GetProfile(i);
INT16 dist = abs(p->profilen - i); INT16 dist = abs(p->profilen - i);

View file

@ -330,8 +330,6 @@ void Addons_option_Onchange(void)
static void M_EraseDataResponse(INT32 ch) static void M_EraseDataResponse(INT32 ch)
{ {
UINT8 i;
if (ch == MA_NO) if (ch == MA_NO)
return; return;
@ -343,8 +341,6 @@ static void M_EraseDataResponse(INT32 ch)
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets // SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
totalplaytime = 0; totalplaytime = 0;
matchesplayed = 0; matchesplayed = 0;
for (i = 0; i < PWRLV_NUMTYPES; i++)
vspowerlevel[i] = PWRLVRECORD_START;
} }
if (optionsmenu.erasecontext != 1) if (optionsmenu.erasecontext != 1)
G_ClearRecords(); G_ClearRecords();

View file

@ -16,8 +16,8 @@
#include "r_skins.h" #include "r_skins.h"
// List of all the profiles. // List of all the profiles.
static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile. static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile.
static UINT8 numprofiles = 0; // # of loaded profiles static UINT8 numprofiles = 0; // # of loaded profiles
INT32 PR_GetNumProfiles(void) INT32 PR_GetNumProfiles(void)
{ {
@ -47,7 +47,9 @@ profile_t* PR_MakeProfile(const char *prname, const char *pname, const char *sna
// Init both power levels // Init both power levels
for (i = 0; i < PWRLV_NUMTYPES; i++) for (i = 0; i < PWRLV_NUMTYPES; i++)
{
new->powerlevels[i] = PWRLVRECORD_START; new->powerlevels[i] = PWRLVRECORD_START;
}
return new; return new;
} }
@ -89,8 +91,11 @@ profile_t* PR_GetProfile(INT32 num)
boolean PR_DeleteProfile(INT32 num) boolean PR_DeleteProfile(INT32 num)
{ {
UINT8 i, j; UINT8 i, j;
if (num <= 0 || num > numprofiles) if (num <= 0 || num > numprofiles)
{
return false; return false;
}
// If we're deleting inbetween profiles, move everything. // If we're deleting inbetween profiles, move everything.
if (num < numprofiles) if (num < numprofiles)
@ -103,10 +108,15 @@ boolean PR_DeleteProfile(INT32 num)
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
{ {
if (cv_lastprofile[j].value == num) if (cv_lastprofile[j].value == num)
CV_StealthSetValue(&cv_lastprofile[j], 0); // If we were on the deleted profile, default back to guest. {
// If we were on the deleted profile, default back to guest.
else if (cv_lastprofile[j].value == i+1) // Otherwise, shift our lastprofile number down to match the new order. CV_StealthSetValue(&cv_lastprofile[j], PROFILE_GUEST);
}
else if (cv_lastprofile[j].value == i+1)
{
// Otherwise, shift our lastprofile number down to match the new order.
CV_StealthSetValue(&cv_lastprofile[j], cv_lastprofile[j].value-1); CV_StealthSetValue(&cv_lastprofile[j], cv_lastprofile[j].value-1);
}
} }
} }
} }
@ -158,14 +168,6 @@ void PR_SaveProfiles(void)
{ {
FILE *f = NULL; FILE *f = NULL;
// save powerlevel in the current profile.
// granted we're using a profile that isn't guest, that is.
if (cv_currprofile.value > 0)
{
profile_t *pr = PR_GetProfile(cv_currprofile.value);
memcpy(&pr->powerlevels, vspowerlevel, sizeof(vspowerlevel));
}
f = fopen(va(pandf, srb2home, PROFILESFILE), "w"); f = fopen(va(pandf, srb2home, PROFILESFILE), "w");
if (f != NULL) if (f != NULL)
{ {
@ -192,11 +194,11 @@ void PR_LoadProfiles(void)
if (f != NULL) if (f != NULL)
{ {
INT32 i; INT32 i, j;
fread(&numprofiles, sizeof numprofiles, 1, f); fread(&numprofiles, sizeof numprofiles, 1, f);
for (i = 1; i < numprofiles; ++i) for (i = PROFILE_GUEST+1; i < numprofiles; ++i)
{ {
profilesList[i] = Z_Malloc(sizeof(profile_t), PU_STATIC, NULL); profilesList[i] = Z_Malloc(sizeof(profile_t), PU_STATIC, NULL);
fread(profilesList[i], sizeof(profile_t), 1, f); fread(profilesList[i], sizeof(profile_t), 1, f);
@ -223,12 +225,22 @@ void PR_LoadProfiles(void)
{ {
profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR; profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR;
} }
for (j = 0; j < PWRLV_NUMTYPES; j++)
{
if (profilesList[i]->powerlevels[j] < PWRLVRECORD_MIN
|| profilesList[i]->powerlevels[j] > PWRLVRECORD_MAX)
{
// invalid, reset
profilesList[i]->powerlevels[j] = PWRLVRECORD_START;
}
}
} }
fclose(f); fclose(f);
// Overwrite the first profile for the default profile to avoid letting anyone tamper with it. // Overwrite the first profile for the default profile to avoid letting anyone tamper with it.
profilesList[0] = dprofile; profilesList[PROFILE_GUEST] = dprofile;
} }
else else
{ {
@ -286,12 +298,9 @@ void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum)
CV_StealthSetValue(&cv_lastprofile[playernum], profilenum); CV_StealthSetValue(&cv_lastprofile[playernum], profilenum);
// If we're doing this on P1, also change current profile. // If we're doing this on P1, also change current profile.
// and update the powerlevel local array. if (playernum == 0)
if (!playernum)
{ {
CV_StealthSetValue(&cv_currprofile, profilenum); CV_StealthSetValue(&cv_currprofile, profilenum);
memcpy(&vspowerlevel, p->powerlevels, sizeof(p->powerlevels));
} }
} }
@ -325,11 +334,32 @@ SINT8 PR_ProfileUsedBy(profile_t *p)
UINT8 i; UINT8 i;
UINT8 prn = PR_GetProfileNum(p); UINT8 prn = PR_GetProfileNum(p);
for (i=0; i < MAXSPLITSCREENPLAYERS; i++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{ {
if (prn == cv_lastprofile[i].value) if (prn == cv_lastprofile[i].value)
return i; return i;
} }
return -1; return -1;
} }
profile_t *PR_GetPlayerProfile(player_t *player)
{
const UINT8 playerNum = (player - players);
UINT8 i;
if (demo.playback)
{
return NULL;
}
for (i = 0; i <= splitscreen; i++)
{
if (playerNum == g_localplayers[i])
{
return PR_GetProfile(cv_lastprofile[i].value);
}
}
return NULL;
}

View file

@ -30,6 +30,7 @@
#define PROFILEVER 1 #define PROFILEVER 1
#define MAXPROFILES 16 #define MAXPROFILES 16
#define PROFILESFILE "ringprofiles.cfg" #define PROFILESFILE "ringprofiles.cfg"
#define PROFILE_GUEST 0
#define PROFILEDEFAULTNAME "guest" #define PROFILEDEFAULTNAME "guest"
#define PROFILEDEFAULTPNAME "Player" #define PROFILEDEFAULTPNAME "Player"
@ -58,7 +59,7 @@ typedef struct profile_s
char follower[SKINNAMESIZE+1]; // Follower char follower[SKINNAMESIZE+1]; // Follower
UINT16 followercolor; // Follower color UINT16 followercolor; // Follower color
UINT16 powerlevels[PWRLV_NUMTYPES]; // PWRLV for race & battle. UINT16 powerlevels[PWRLV_NUMTYPES]; // PWRLV for each gametype.
// Player-specific consvars. // Player-specific consvars.
// @TODO: List all of those // @TODO: List all of those
@ -134,4 +135,6 @@ UINT8 PR_GetProfileNum(profile_t *p);
// If the profile belongs to no player, then this returns -1 // If the profile belongs to no player, then this returns -1
SINT8 PR_ProfileUsedBy(profile_t *p); SINT8 PR_ProfileUsedBy(profile_t *p);
profile_t *PR_GetPlayerProfile(player_t *player);
#endif #endif

View file

@ -17,10 +17,7 @@
#include "p_tick.h" // leveltime #include "p_tick.h" // leveltime
#include "k_grandprix.h" #include "k_grandprix.h"
#include "k_boss.h" #include "k_boss.h"
#include "k_profiles.h"
// Online rankings for the main gametypes.
// This array is saved to the gamedata.
UINT16 vspowerlevel[PWRLV_NUMTYPES];
// Client-sided calculations done for Power Levels. // Client-sided calculations done for Power Levels.
// This is done so that clients will never be able to hack someone else's score over the server. // This is done so that clients will never be able to hack someone else's score over the server.
@ -370,6 +367,7 @@ INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc)
// Get at least one point. // Get at least one point.
inc = 1; inc = 1;
} }
#if 0
else else
{ {
// You trade points in 1v1s, // You trade points in 1v1s,
@ -388,6 +386,7 @@ INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc)
} }
} }
} }
#endif
} }
if (yourPower + inc > PWRLVRECORD_MAX) if (yourPower + inc > PWRLVRECORD_MAX)
@ -416,14 +415,16 @@ void K_CashInPowerLevels(void)
{ {
if (playeringame[i] == true && powerType != PWRLV_DISABLED) if (playeringame[i] == true && powerType != PWRLV_DISABLED)
{ {
profile_t *pr = PR_GetPlayerProfile(&players[i]);
INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]); INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]);
clientpowerlevels[i][powerType] += inc; clientpowerlevels[i][powerType] += inc;
//CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc); //CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc);
if (!demo.playback && i == consoleplayer && inc != 0) if (pr != NULL && inc != 0)
{ {
vspowerlevel[powerType] = clientpowerlevels[i][powerType]; pr->powerlevels[powerType] = clientpowerlevels[i][powerType];
if (M_UpdateUnlockablesAndExtraEmblems()) if (M_UpdateUnlockablesAndExtraEmblems())
{ {
@ -567,6 +568,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss) void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
{ {
profile_t *pr;
UINT8 p = 0; UINT8 p = 0;
SINT8 powerType = PWRLV_DISABLED; SINT8 powerType = PWRLV_DISABLED;
@ -631,17 +633,22 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
K_UpdatePowerLevelsOnFailure(&players[playerNum]); K_UpdatePowerLevelsOnFailure(&players[playerNum]);
inc = K_FinalPowerIncrement(&players[playerNum], yourPower, clientPowerAdd[playerNum]); inc = K_FinalPowerIncrement(&players[playerNum], yourPower, clientPowerAdd[playerNum]);
if (inc >= 0) if (inc == 0)
{ {
// Don't record no change or increases. // No change
return; return;
} }
// pointLoss isn't set for stuff like sync-outs, if (inc < 0 && pointLoss == false)
// which shouldn't be so harsh on the victim!
if (!demo.playback && pointLoss == true && playerNum == consoleplayer)
{ {
vspowerlevel[powerType] = yourPower + inc; // Don't record point losses for sync-out / crashes.
return;
}
pr = PR_GetPlayerProfile(&players[playerNum]);
if (pr != NULL)
{
pr->powerlevels[powerType] = yourPower + inc;
if (M_UpdateUnlockablesAndExtraEmblems()) if (M_UpdateUnlockablesAndExtraEmblems())
{ {

View file

@ -31,7 +31,6 @@ typedef enum
extern SINT8 speedscramble; extern SINT8 speedscramble;
extern SINT8 encorescramble; extern SINT8 encorescramble;
extern UINT16 vspowerlevel[PWRLV_NUMTYPES];
extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES]; extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
extern INT16 clientPowerAdd[MAXPLAYERS]; extern INT16 clientPowerAdd[MAXPLAYERS];
extern UINT8 spectateGriefed; extern UINT8 spectateGriefed;

View file

@ -20,7 +20,9 @@
#include "g_game.h" // record info #include "g_game.h" // record info
#include "r_skins.h" // numskins #include "r_skins.h" // numskins
#include "r_draw.h" // R_GetColorByName #include "r_draw.h" // R_GetColorByName
#include "k_pwrlv.h" #include "k_pwrlv.h"
#include "k_profiles.h"
// Map triggers for linedef executors // Map triggers for linedef executors
// 32 triggers, one bit each // 32 triggers, one bit each
@ -108,7 +110,20 @@ UINT8 M_CheckCondition(condition_t *cn)
case UC_MATCHESPLAYED: // Requires any level completed >= x times case UC_MATCHESPLAYED: // Requires any level completed >= x times
return (matchesplayed >= (unsigned)cn->requirement); return (matchesplayed >= (unsigned)cn->requirement);
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
return (vspowerlevel[cn->extrainfo1] >= (unsigned)cn->requirement); {
UINT8 i;
for (i = PROFILE_GUEST; i < PR_GetNumProfiles(); i++)
{
profile_t *p = PR_GetProfile(i);
if (p->powerlevels[cn->extrainfo1] >= (unsigned)cn->requirement)
{
return true;
}
}
return false;
}
case UC_GAMECLEAR: // Requires game beaten >= x times case UC_GAMECLEAR: // Requires game beaten >= x times
return (timesBeaten >= (unsigned)cn->requirement); return (timesBeaten >= (unsigned)cn->requirement);
case UC_OVERALLTIME: // Requires overall time <= x case UC_OVERALLTIME: // Requires overall time <= x

View file

@ -1099,7 +1099,7 @@ boolean P_IsMachineLocalPlayer(player_t *player)
return false; return false;
} }
for (i = 0; i <= r_splitscreen; i++) for (i = 0; i <= splitscreen; i++)
{ {
if (player == &players[g_localplayers[i]]) if (player == &players[g_localplayers[i]])
return true; return true;