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
PR_LoadProfiles(); // load control profiles
PR_SaveProfiles(); // Test @TODO: remove this lol
M_Init();

View file

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

View file

@ -3984,9 +3984,6 @@ void G_LoadGameData(void)
totalplaytime = 0; // total play time (separate from all)
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"))
return; // Don't load.
@ -4022,13 +4019,6 @@ void G_LoadGameData(void)
totalplaytime = 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);
// Aha! Someone's been screwing with the save file!
@ -4145,9 +4135,6 @@ void G_SaveGameData(void)
WRITEUINT32(save_p, totalplaytime);
WRITEUINT32(save_p, matchesplayed);
for (i = 0; i < PWRLV_NUMTYPES; i++)
WRITEUINT16(save_p, vspowerlevel[i]);
WRITEUINT8(save_p, (UINT8)savemoddata);
// 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;
UINT8 maxp = PR_GetNumProfiles();
for (i=0; i < maxp; i++)
for (i = 0; i < maxp; i++)
{
profile_t *pr = PR_GetProfile(i);
INT16 dist = abs(p->profilen - i);

View file

@ -330,8 +330,6 @@ void Addons_option_Onchange(void)
static void M_EraseDataResponse(INT32 ch)
{
UINT8 i;
if (ch == MA_NO)
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
totalplaytime = 0;
matchesplayed = 0;
for (i = 0; i < PWRLV_NUMTYPES; i++)
vspowerlevel[i] = PWRLVRECORD_START;
}
if (optionsmenu.erasecontext != 1)
G_ClearRecords();

View file

@ -16,8 +16,8 @@
#include "r_skins.h"
// List of all the profiles.
static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile.
static UINT8 numprofiles = 0; // # of loaded profiles
static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile.
static UINT8 numprofiles = 0; // # of loaded profiles
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
for (i = 0; i < PWRLV_NUMTYPES; i++)
{
new->powerlevels[i] = PWRLVRECORD_START;
}
return new;
}
@ -89,8 +91,11 @@ profile_t* PR_GetProfile(INT32 num)
boolean PR_DeleteProfile(INT32 num)
{
UINT8 i, j;
if (num <= 0 || num > numprofiles)
{
return false;
}
// If we're deleting inbetween profiles, move everything.
if (num < numprofiles)
@ -103,10 +108,15 @@ boolean PR_DeleteProfile(INT32 num)
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
{
if (cv_lastprofile[j].value == num)
CV_StealthSetValue(&cv_lastprofile[j], 0); // 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.
{
// If we were on the deleted profile, default back to guest.
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);
}
}
}
}
@ -158,14 +168,6 @@ void PR_SaveProfiles(void)
{
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");
if (f != NULL)
{
@ -192,11 +194,11 @@ void PR_LoadProfiles(void)
if (f != NULL)
{
INT32 i;
INT32 i, j;
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);
fread(profilesList[i], sizeof(profile_t), 1, f);
@ -223,12 +225,22 @@ void PR_LoadProfiles(void)
{
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);
// Overwrite the first profile for the default profile to avoid letting anyone tamper with it.
profilesList[0] = dprofile;
profilesList[PROFILE_GUEST] = dprofile;
}
else
{
@ -286,12 +298,9 @@ void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum)
CV_StealthSetValue(&cv_lastprofile[playernum], profilenum);
// If we're doing this on P1, also change current profile.
// and update the powerlevel local array.
if (!playernum)
if (playernum == 0)
{
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 prn = PR_GetProfileNum(p);
for (i=0; i < MAXSPLITSCREENPLAYERS; i++)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (prn == cv_lastprofile[i].value)
return i;
}
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 MAXPROFILES 16
#define PROFILESFILE "ringprofiles.cfg"
#define PROFILE_GUEST 0
#define PROFILEDEFAULTNAME "guest"
#define PROFILEDEFAULTPNAME "Player"
@ -58,7 +59,7 @@ typedef struct profile_s
char follower[SKINNAMESIZE+1]; // Follower
UINT16 followercolor; // Follower color
UINT16 powerlevels[PWRLV_NUMTYPES]; // PWRLV for race & battle.
UINT16 powerlevels[PWRLV_NUMTYPES]; // PWRLV for each gametype.
// Player-specific consvars.
// @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
SINT8 PR_ProfileUsedBy(profile_t *p);
profile_t *PR_GetPlayerProfile(player_t *player);
#endif

View file

@ -17,10 +17,7 @@
#include "p_tick.h" // leveltime
#include "k_grandprix.h"
#include "k_boss.h"
// Online rankings for the main gametypes.
// This array is saved to the gamedata.
UINT16 vspowerlevel[PWRLV_NUMTYPES];
#include "k_profiles.h"
// 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.
@ -370,6 +367,7 @@ INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc)
// Get at least one point.
inc = 1;
}
#if 0
else
{
// 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)
@ -416,14 +415,16 @@ void K_CashInPowerLevels(void)
{
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]);
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())
{
@ -567,6 +568,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
{
profile_t *pr;
UINT8 p = 0;
SINT8 powerType = PWRLV_DISABLED;
@ -631,17 +633,22 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
K_UpdatePowerLevelsOnFailure(&players[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;
}
// 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)
if (inc < 0 && pointLoss == false)
{
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())
{

View file

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

View file

@ -20,7 +20,9 @@
#include "g_game.h" // record info
#include "r_skins.h" // numskins
#include "r_draw.h" // R_GetColorByName
#include "k_pwrlv.h"
#include "k_profiles.h"
// Map triggers for linedef executors
// 32 triggers, one bit each
@ -108,7 +110,20 @@ UINT8 M_CheckCondition(condition_t *cn)
case UC_MATCHESPLAYED: // Requires any level completed >= x times
return (matchesplayed >= (unsigned)cn->requirement);
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
return (timesBeaten >= (unsigned)cn->requirement);
case UC_OVERALLTIME: // Requires overall time <= x

View file

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