mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-25 13:51:43 +00:00
Allow obtaining ring, time & grade emblems in regular SP gameplay.
This commit is contained in:
parent
13c30ace2e
commit
86b4f93610
10 changed files with 279 additions and 170 deletions
|
@ -2339,7 +2339,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
players[i].score = 0;
|
||||
players[i].score = players[i].recordscore = 0;
|
||||
|
||||
CONS_Printf(M_GetText("Scores have been reset by the server.\n"));
|
||||
}
|
||||
|
|
|
@ -453,7 +453,8 @@ typedef struct player_s
|
|||
INT32 skin;
|
||||
UINT32 availabilities;
|
||||
|
||||
UINT32 score; // player score
|
||||
UINT32 score; // player score (total)
|
||||
UINT32 recordscore; // player score (per life / map)
|
||||
fixed_t dashspeed; // dashing speed
|
||||
|
||||
fixed_t normalspeed; // Normal ground
|
||||
|
|
354
src/g_game.c
354
src/g_game.c
|
@ -519,140 +519,154 @@ UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data)
|
|||
}
|
||||
|
||||
// For easy adding of NiGHTS records
|
||||
void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare)
|
||||
void G_AddTempNightsRecords(player_t *player, UINT32 pscore, tic_t ptime, UINT8 mare)
|
||||
{
|
||||
ntemprecords.score[mare] = pscore;
|
||||
ntemprecords.grade[mare] = P_GetGrade(pscore, gamemap, mare - 1);
|
||||
ntemprecords.time[mare] = ptime;
|
||||
const UINT8 playerID = player - players;
|
||||
|
||||
I_Assert(player != NULL);
|
||||
|
||||
ntemprecords[playerID].score[mare] = pscore;
|
||||
ntemprecords[playerID].grade[mare] = P_GetGrade(pscore, gamemap, mare - 1);
|
||||
ntemprecords[playerID].time[mare] = ptime;
|
||||
|
||||
// Update nummares
|
||||
// Note that mare "0" is overall, mare "1" is the first real mare
|
||||
if (ntemprecords.nummares < mare)
|
||||
ntemprecords.nummares = mare;
|
||||
if (ntemprecords[playerID].nummares < mare)
|
||||
ntemprecords[playerID].nummares = mare;
|
||||
}
|
||||
|
||||
//
|
||||
// G_UpdateRecordReplays
|
||||
// G_SetMainRecords
|
||||
//
|
||||
// Update replay files/data, etc. for Record Attack
|
||||
// See G_SetNightsRecords for NiGHTS Attack.
|
||||
//
|
||||
static void G_UpdateRecordReplays(gamedata_t *data)
|
||||
static void G_SetMainRecords(gamedata_t *data, player_t *player)
|
||||
{
|
||||
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
|
||||
char *gpath;
|
||||
char lastdemo[256], bestdemo[256];
|
||||
UINT8 earnedEmblems;
|
||||
|
||||
I_Assert(player != NULL);
|
||||
|
||||
// Record new best time
|
||||
if (!data->mainrecords[gamemap-1])
|
||||
G_AllocMainRecordData(gamemap-1, data);
|
||||
|
||||
if (players[consoleplayer].score > data->mainrecords[gamemap-1]->score)
|
||||
data->mainrecords[gamemap-1]->score = players[consoleplayer].score;
|
||||
if (player->recordscore > data->mainrecords[gamemap-1]->score)
|
||||
data->mainrecords[gamemap-1]->score = player->recordscore;
|
||||
|
||||
if ((data->mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < data->mainrecords[gamemap-1]->time))
|
||||
data->mainrecords[gamemap-1]->time = players[consoleplayer].realtime;
|
||||
if ((data->mainrecords[gamemap-1]->time == 0) || (player->realtime < data->mainrecords[gamemap-1]->time))
|
||||
data->mainrecords[gamemap-1]->time = player->realtime;
|
||||
|
||||
if ((UINT16)(players[consoleplayer].rings) > data->mainrecords[gamemap-1]->rings)
|
||||
data->mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings);
|
||||
if ((UINT16)(player->rings) > data->mainrecords[gamemap-1]->rings)
|
||||
data->mainrecords[gamemap-1]->rings = (UINT16)(player->rings);
|
||||
|
||||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
lastdemo[255] = '\0';
|
||||
G_SetDemoTime(players[consoleplayer].realtime, players[consoleplayer].score, (UINT16)(players[consoleplayer].rings));
|
||||
G_CheckDemoStatus();
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
||||
if ((gpath = malloc(glen)) == NULL)
|
||||
I_Error("Out of memory for replay filepath\n");
|
||||
|
||||
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
|
||||
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
|
||||
if (FIL_FileExists(lastdemo))
|
||||
if (modeattacking)
|
||||
{
|
||||
UINT8 *buf;
|
||||
size_t len = FIL_ReadFile(lastdemo, &buf);
|
||||
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
|
||||
char *gpath;
|
||||
char lastdemo[256], bestdemo[256];
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
|
||||
{ // Better time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
|
||||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
lastdemo[255] = '\0';
|
||||
G_SetDemoTime(player->realtime, player->recordscore, (UINT16)(player->rings));
|
||||
G_CheckDemoStatus();
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
||||
if ((gpath = malloc(glen)) == NULL)
|
||||
I_Error("Out of memory for replay filepath\n");
|
||||
|
||||
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
|
||||
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
|
||||
if (FIL_FileExists(lastdemo))
|
||||
{
|
||||
UINT8 *buf;
|
||||
size_t len = FIL_ReadFile(lastdemo, &buf);
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
|
||||
{ // Better time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
|
||||
{ // Better score, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2)))
|
||||
{ // Better rings, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW MOST RINGS!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
|
||||
|
||||
Z_Free(buf);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
|
||||
{ // Better score, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2)))
|
||||
{ // Better rings, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW MOST RINGS!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
|
||||
|
||||
Z_Free(buf);
|
||||
free(gpath);
|
||||
}
|
||||
free(gpath);
|
||||
|
||||
// Check emblems when level data is updated
|
||||
if ((earnedEmblems = M_CheckLevelEmblems(data)))
|
||||
{
|
||||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
// Update timeattack menu's replay availability.
|
||||
Nextmap_OnChange();
|
||||
}
|
||||
|
||||
void G_SetNightsRecords(gamedata_t *data)
|
||||
static void G_SetNightsRecords(gamedata_t *data, player_t *player)
|
||||
{
|
||||
INT32 i;
|
||||
nightsdata_t *const ntemprecord = &ntemprecords[player - players];
|
||||
UINT32 totalscore = 0;
|
||||
tic_t totaltime = 0;
|
||||
INT32 i;
|
||||
|
||||
UINT8 earnedEmblems;
|
||||
|
||||
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
|
||||
char *gpath;
|
||||
char lastdemo[256], bestdemo[256];
|
||||
|
||||
if (!ntemprecords.nummares)
|
||||
if (!ntemprecord->nummares)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set overall
|
||||
{
|
||||
UINT8 totalrank = 0, realrank = 0;
|
||||
|
||||
for (i = 1; i <= ntemprecords.nummares; ++i)
|
||||
for (i = 1; i <= ntemprecord->nummares; ++i)
|
||||
{
|
||||
totalscore += ntemprecords.score[i];
|
||||
totalrank += ntemprecords.grade[i];
|
||||
totaltime += ntemprecords.time[i];
|
||||
totalscore += ntemprecord->score[i];
|
||||
totalrank += ntemprecord->grade[i];
|
||||
totaltime += ntemprecord->time[i];
|
||||
}
|
||||
|
||||
// Determine overall grade
|
||||
realrank = (UINT8)((FixedDiv((fixed_t)totalrank << FRACBITS, ntemprecords.nummares << FRACBITS) + (FRACUNIT/2)) >> FRACBITS);
|
||||
realrank = (UINT8)((FixedDiv((fixed_t)totalrank << FRACBITS, ntemprecord->nummares << FRACBITS) + (FRACUNIT/2)) >> FRACBITS);
|
||||
|
||||
// You need ALL rainbow As to get a rainbow A overall
|
||||
if (realrank == GRADE_S && (totalrank / ntemprecords.nummares) != GRADE_S)
|
||||
if (realrank == GRADE_S && (totalrank / ntemprecord->nummares) != GRADE_S)
|
||||
{
|
||||
realrank = GRADE_A;
|
||||
}
|
||||
|
||||
ntemprecords.score[0] = totalscore;
|
||||
ntemprecords.grade[0] = realrank;
|
||||
ntemprecords.time[0] = totaltime;
|
||||
ntemprecord->score[0] = totalscore;
|
||||
ntemprecord->grade[0] = realrank;
|
||||
ntemprecord->time[0] = totaltime;
|
||||
}
|
||||
|
||||
// Now take all temp records and put them in the actual records
|
||||
|
@ -660,71 +674,85 @@ void G_SetNightsRecords(gamedata_t *data)
|
|||
nightsdata_t *maprecords;
|
||||
|
||||
if (!data->nightsrecords[gamemap-1])
|
||||
{
|
||||
G_AllocNightsRecordData(gamemap-1, data);
|
||||
}
|
||||
|
||||
maprecords = data->nightsrecords[gamemap-1];
|
||||
|
||||
if (maprecords->nummares != ntemprecords.nummares)
|
||||
maprecords->nummares = ntemprecords.nummares;
|
||||
|
||||
for (i = 0; i < ntemprecords.nummares + 1; ++i)
|
||||
if (maprecords->nummares != ntemprecord->nummares)
|
||||
{
|
||||
if (maprecords->score[i] < ntemprecords.score[i])
|
||||
maprecords->score[i] = ntemprecords.score[i];
|
||||
if (maprecords->grade[i] < ntemprecords.grade[i])
|
||||
maprecords->grade[i] = ntemprecords.grade[i];
|
||||
if (!maprecords->time[i] || maprecords->time[i] > ntemprecords.time[i])
|
||||
maprecords->time[i] = ntemprecords.time[i];
|
||||
maprecords->nummares = ntemprecord->nummares;
|
||||
}
|
||||
|
||||
for (i = 0; i < ntemprecord->nummares + 1; ++i)
|
||||
{
|
||||
if (maprecords->score[i] < ntemprecord->score[i])
|
||||
maprecords->score[i] = ntemprecord->score[i];
|
||||
if (maprecords->grade[i] < ntemprecord->grade[i])
|
||||
maprecords->grade[i] = ntemprecord->grade[i];
|
||||
if (!maprecords->time[i] || maprecords->time[i] > ntemprecord->time[i])
|
||||
maprecords->time[i] = ntemprecord->time[i];
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ntemprecords, 0, sizeof(nightsdata_t));
|
||||
memset(&ntemprecords[player - players], 0, sizeof(nightsdata_t));
|
||||
|
||||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
lastdemo[255] = '\0';
|
||||
G_SetDemoTime(totaltime, totalscore, 0);
|
||||
G_CheckDemoStatus();
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
||||
if ((gpath = malloc(glen)) == NULL)
|
||||
I_Error("Out of memory for replay filepath\n");
|
||||
|
||||
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
|
||||
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
|
||||
if (FIL_FileExists(lastdemo))
|
||||
if (modeattacking)
|
||||
{
|
||||
UINT8 *buf;
|
||||
size_t len = FIL_ReadFile(lastdemo, &buf);
|
||||
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
|
||||
char *gpath;
|
||||
char lastdemo[256], bestdemo[256];
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);;
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
|
||||
{ // Better time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
|
||||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
lastdemo[255] = '\0';
|
||||
G_SetDemoTime(totaltime, totalscore, 0);
|
||||
G_CheckDemoStatus();
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
||||
if ((gpath = malloc(glen)) == NULL)
|
||||
I_Error("Out of memory for replay filepath\n");
|
||||
|
||||
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
|
||||
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
|
||||
if (FIL_FileExists(lastdemo))
|
||||
{
|
||||
UINT8 *buf;
|
||||
size_t len = FIL_ReadFile(lastdemo, &buf);
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);;
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
|
||||
{ // Better time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
|
||||
{ // Better score, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
|
||||
|
||||
Z_Free(buf);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
|
||||
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
|
||||
{ // Better score, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
|
||||
|
||||
Z_Free(buf);
|
||||
free(gpath);
|
||||
}
|
||||
free(gpath);
|
||||
|
||||
if ((earnedEmblems = M_CheckLevelEmblems(data)))
|
||||
{
|
||||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
// If the mare count changed, this will update the score display
|
||||
Nextmap_OnChange();
|
||||
|
@ -2287,7 +2315,7 @@ void G_Ticker(boolean run)
|
|||
p->lives = startinglivesbalance[0];
|
||||
p->continues = 1;
|
||||
|
||||
p->score = 0;
|
||||
p->score = p->recordscore = 0;
|
||||
|
||||
// The latter two should clear by themselves, but just in case
|
||||
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
|
||||
|
@ -2490,6 +2518,7 @@ static inline void G_PlayerFinishLevel(INT32 player)
|
|||
|
||||
memset(p->powers, 0, sizeof (p->powers));
|
||||
p->ringweapons = 0;
|
||||
p->recordscore = 0;
|
||||
|
||||
p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
|
||||
P_FlashPal(p, 0, 0); // Resets
|
||||
|
@ -2513,6 +2542,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
{
|
||||
player_t *p;
|
||||
INT32 score;
|
||||
INT32 recordscore;
|
||||
INT32 lives;
|
||||
INT32 continues;
|
||||
fixed_t camerascale;
|
||||
|
@ -3165,6 +3195,7 @@ void G_DoReborn(INT32 playernum)
|
|||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
players[i].recordscore = 0;
|
||||
players[i].starpostscale = 0;
|
||||
players[i].starpostangle = 0;
|
||||
players[i].starposttime = 0;
|
||||
|
@ -3844,15 +3875,16 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap)
|
|||
//
|
||||
// G_UpdateVisited
|
||||
//
|
||||
static void G_UpdateVisited(gamedata_t *data, boolean silent)
|
||||
static void G_UpdateVisited(gamedata_t *data, player_t *player, boolean silent)
|
||||
{
|
||||
boolean spec = G_IsSpecialStage(gamemap);
|
||||
// Update visitation flags?
|
||||
if (!demoplayback
|
||||
&& G_CoopGametype() // Campaign mode
|
||||
&& !stagefailed) // Did not fail the stage
|
||||
{
|
||||
UINT8 earnedEmblems;
|
||||
UINT16 totalrings = 0;
|
||||
INT32 i;
|
||||
|
||||
// Update visitation flags
|
||||
data->mapvisited[gamemap-1] |= MV_BEATEN;
|
||||
|
@ -3861,36 +3893,62 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent)
|
|||
if (ultimatemode)
|
||||
data->mapvisited[gamemap-1] |= MV_ULTIMATE;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
totalrings += players[i].rings;
|
||||
}
|
||||
|
||||
// may seem incorrect but IS possible in what the main game uses as mp special stages, and nummaprings will be -1 in NiGHTS
|
||||
if (nummaprings > 0 && players[consoleplayer].rings >= nummaprings)
|
||||
if (nummaprings > 0 && totalrings >= nummaprings)
|
||||
{
|
||||
data->mapvisited[gamemap-1] |= MV_PERFECT;
|
||||
if (modeattacking)
|
||||
data->mapvisited[gamemap-1] |= MV_PERFECTRA;
|
||||
}
|
||||
|
||||
if (!spec)
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
{
|
||||
// not available to special stages because they can only really be done in one order in an unmodified game, so impossible for first six and trivial for seventh
|
||||
if (ALL7EMERALDS(emeralds))
|
||||
data->mapvisited[gamemap-1] |= MV_ALLEMERALDS;
|
||||
}
|
||||
|
||||
if ((earnedEmblems = M_CompletionEmblems(data)) && !silent)
|
||||
{
|
||||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
if (silent)
|
||||
{
|
||||
if (modeattacking)
|
||||
M_CheckLevelEmblems(data);
|
||||
M_CheckLevelEmblems(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (modeattacking == ATTACKING_RECORD)
|
||||
G_UpdateRecordReplays(data);
|
||||
else if (modeattacking == ATTACKING_NIGHTS)
|
||||
G_SetNightsRecords(data);
|
||||
if (mapheaderinfo[gamemap-1]->menuflags & LF2_RECORDATTACK)
|
||||
G_SetMainRecords(data, player);
|
||||
else if (mapheaderinfo[gamemap-1]->menuflags & LF2_NIGHTSATTACK)
|
||||
G_SetNightsRecords(data, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((earnedEmblems = M_CompletionEmblems(data)) && !silent)
|
||||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
static void G_UpdateAllVisited(void)
|
||||
{
|
||||
// Update server
|
||||
G_UpdateVisited(serverGamedata, &players[serverplayer], true);
|
||||
|
||||
// Update client
|
||||
G_UpdateVisited(clientGamedata, &players[consoleplayer], false);
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
// Allow P2 to get emblems too, why not :)
|
||||
G_UpdateVisited(clientGamedata, &players[secondarydisplayplayer], false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3914,6 +3972,9 @@ static boolean CanSaveLevel(INT32 mapnum)
|
|||
|
||||
static void G_HandleSaveLevel(void)
|
||||
{
|
||||
// Update records & emblems
|
||||
G_UpdateAllVisited();
|
||||
|
||||
// do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c
|
||||
if (nextmap >= 1100-1)
|
||||
{
|
||||
|
@ -4092,8 +4153,6 @@ static void G_DoCompleted(void)
|
|||
|
||||
if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none))
|
||||
{
|
||||
G_UpdateVisited(serverGamedata, true);
|
||||
G_UpdateVisited(clientGamedata, false);
|
||||
G_HandleSaveLevel();
|
||||
G_AfterIntermission();
|
||||
}
|
||||
|
@ -4102,8 +4161,6 @@ static void G_DoCompleted(void)
|
|||
G_SetGamestate(GS_INTERMISSION);
|
||||
Y_StartIntermission();
|
||||
Y_LoadIntermissionData();
|
||||
G_UpdateVisited(serverGamedata, true);
|
||||
G_UpdateVisited(clientGamedata, false);
|
||||
G_HandleSaveLevel();
|
||||
}
|
||||
}
|
||||
|
@ -4992,6 +5049,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
players[i].playerstate = PST_REBORN;
|
||||
players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
|
||||
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
|
||||
players[i].recordscore = 0;
|
||||
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
|
|
|
@ -260,8 +260,7 @@ UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data);
|
|||
tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data);
|
||||
UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data);
|
||||
|
||||
void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare);
|
||||
void G_SetNightsRecords(gamedata_t *data);
|
||||
void G_AddTempNightsRecords(player_t *player, UINT32 pscore, tic_t ptime, UINT8 mare);
|
||||
|
||||
FUNCMATH INT32 G_TicsToHours(tic_t tics);
|
||||
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);
|
||||
|
|
|
@ -114,6 +114,7 @@ enum player_e
|
|||
player_skin,
|
||||
player_availabilities,
|
||||
player_score,
|
||||
player_recordscore,
|
||||
player_dashspeed,
|
||||
player_normalspeed,
|
||||
player_runspeed,
|
||||
|
@ -260,6 +261,7 @@ static const char *const player_opt[] = {
|
|||
"skin",
|
||||
"availabilities",
|
||||
"score",
|
||||
"recordscore",
|
||||
"dashspeed",
|
||||
"normalspeed",
|
||||
"runspeed",
|
||||
|
@ -495,6 +497,9 @@ static int player_get(lua_State *L)
|
|||
case player_score:
|
||||
lua_pushinteger(L, plr->score);
|
||||
break;
|
||||
case player_recordscore:
|
||||
lua_pushinteger(L, plr->recordscore);
|
||||
break;
|
||||
case player_dashspeed:
|
||||
lua_pushfixed(L, plr->dashspeed);
|
||||
break;
|
||||
|
@ -957,6 +962,9 @@ static int player_set(lua_State *L)
|
|||
case player_score:
|
||||
plr->score = (UINT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_recordscore:
|
||||
plr->recordscore = (UINT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_dashspeed:
|
||||
plr->dashspeed = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
|
|
|
@ -45,7 +45,7 @@ INT32 numemblems = 0;
|
|||
INT32 numextraemblems = 0;
|
||||
|
||||
// Temporary holding place for nights data for the current map
|
||||
nightsdata_t ntemprecords;
|
||||
nightsdata_t ntemprecords[MAXPLAYERS];
|
||||
|
||||
// Create a new gamedata_t, for start-up
|
||||
gamedata_t *M_NewGameDataStruct(void)
|
||||
|
|
|
@ -181,7 +181,7 @@ typedef struct
|
|||
#define MV_MAX 63 // used in gamedata check, update whenever MV's are added
|
||||
|
||||
// Temporary holding place for nights data for the current map
|
||||
extern nightsdata_t ntemprecords;
|
||||
extern nightsdata_t ntemprecords[MAXPLAYERS];
|
||||
|
||||
// GAMEDATA STRUCTURE
|
||||
// Everything that would get saved in gamedata.dat
|
||||
|
|
|
@ -179,6 +179,7 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEINT32(save_p, players[i].skin);
|
||||
WRITEUINT32(save_p, players[i].availabilities);
|
||||
WRITEUINT32(save_p, players[i].score);
|
||||
WRITEUINT32(save_p, players[i].recordscore);
|
||||
WRITEFIXED(save_p, players[i].dashspeed);
|
||||
WRITESINT8(save_p, players[i].lives);
|
||||
WRITESINT8(save_p, players[i].continues);
|
||||
|
@ -407,6 +408,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].skin = READINT32(save_p);
|
||||
players[i].availabilities = READUINT32(save_p);
|
||||
players[i].score = READUINT32(save_p);
|
||||
players[i].recordscore = READUINT32(save_p);
|
||||
players[i].dashspeed = READFIXED(save_p); // dashing speed
|
||||
players[i].lives = READSINT8(save_p);
|
||||
players[i].continues = READSINT8(save_p); // continues that player has acquired
|
||||
|
@ -4342,8 +4344,6 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
|
||||
WRITEUINT32(save_p, hidetime);
|
||||
|
||||
WRITEUINT32(save_p, unlocktriggers);
|
||||
|
||||
// Is it paused?
|
||||
if (paused)
|
||||
WRITEUINT8(save_p, 0x2f);
|
||||
|
@ -4442,8 +4442,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
|
||||
hidetime = READUINT32(save_p);
|
||||
|
||||
unlocktriggers = READUINT32(save_p);
|
||||
|
||||
// Is it paused?
|
||||
if (READUINT8(save_p) == 0x2f)
|
||||
paused = true;
|
||||
|
@ -4451,7 +4449,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline void P_NetArchiveEmblems(void)
|
||||
{
|
||||
gamedata_t *data = serverGamedata;
|
||||
|
@ -4550,6 +4547,27 @@ static inline void P_NetArchiveEmblems(void)
|
|||
WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]);
|
||||
}
|
||||
}
|
||||
|
||||
// Mid-map stuff
|
||||
WRITEUINT32(save_p, unlocktriggers);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!ntemprecords[i].nummares)
|
||||
{
|
||||
WRITEUINT8(save_p, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
WRITEUINT8(save_p, ntemprecords[i].nummares);
|
||||
|
||||
for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare)
|
||||
{
|
||||
WRITEUINT32(save_p, ntemprecords[i].score[curmare]);
|
||||
WRITEUINT8(save_p, ntemprecords[i].grade[curmare]);
|
||||
WRITEUINT32(save_p, ntemprecords[i].time[curmare]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void P_NetUnArchiveEmblems(void)
|
||||
|
@ -4569,9 +4587,9 @@ static inline void P_NetUnArchiveEmblems(void)
|
|||
savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason.
|
||||
|
||||
if (numemblems != READINT32(save_p))
|
||||
I_Error("numemblems mismatch");
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)");
|
||||
if (numextraemblems != READINT32(save_p))
|
||||
I_Error("numextraemblems mismatch");
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)");
|
||||
|
||||
// This shouldn't happen, but if something really fucked up happens and you transfer
|
||||
// the SERVER player's gamedata over your own CLIENT gamedata,
|
||||
|
@ -4590,7 +4608,7 @@ static inline void P_NetUnArchiveEmblems(void)
|
|||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
|
||||
I_Error("Bad $$$.sav dearchiving Emblems");
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)");
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < MAXEMBLEMS;)
|
||||
|
@ -4634,7 +4652,7 @@ static inline void P_NetUnArchiveEmblems(void)
|
|||
recrings = READUINT16(save_p);
|
||||
|
||||
if (recrings > 10000 || recscore > MAXSCORE)
|
||||
I_Error("Bad $$$.sav dearchiving Emblems");
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (invalid score)");
|
||||
|
||||
if (recscore || rectime || recrings)
|
||||
{
|
||||
|
@ -4661,12 +4679,35 @@ static inline void P_NetUnArchiveEmblems(void)
|
|||
|
||||
if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
|
||||
{
|
||||
I_Error("Bad $$$.sav dearchiving Emblems");
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (invalid grade)");
|
||||
}
|
||||
}
|
||||
|
||||
data->nightsrecords[i]->nummares = recmares;
|
||||
}
|
||||
|
||||
// Mid-map stuff
|
||||
unlocktriggers = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if ((recmares = READUINT8(save_p)) == 0)
|
||||
continue;
|
||||
|
||||
for (curmare = 0; curmare < (recmares+1); ++curmare)
|
||||
{
|
||||
ntemprecords[i].score[curmare] = READUINT32(save_p);
|
||||
ntemprecords[i].grade[curmare] = READUINT8(save_p);
|
||||
ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p);
|
||||
|
||||
if (ntemprecords[i].grade[curmare] > GRADE_S)
|
||||
{
|
||||
I_Error("Bad $$$.sav dearchiving Emblems (invalid temp grade)");
|
||||
}
|
||||
}
|
||||
|
||||
ntemprecords[i].nummares = recmares;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void P_ArchiveLuabanksAndConsistency(void)
|
||||
|
|
|
@ -6985,7 +6985,7 @@ static void P_InitLevelSettings(void)
|
|||
stagefailed = G_IsSpecialStage(gamemap);
|
||||
|
||||
// Reset temporary record data
|
||||
memset(&ntemprecords, 0, sizeof(nightsdata_t));
|
||||
memset(&ntemprecords, 0, sizeof(ntemprecords));
|
||||
|
||||
// earthquake camera
|
||||
memset(&quake,0,sizeof(struct quake));
|
||||
|
|
12
src/p_user.c
12
src/p_user.c
|
@ -882,8 +882,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
}
|
||||
|
||||
// Add score to leaderboards now
|
||||
if (!(netgame||multiplayer) && P_IsLocalPlayer(&players[i]))
|
||||
G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1);
|
||||
G_AddTempNightsRecords(player, players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1);
|
||||
|
||||
// transfer scores anyway
|
||||
players[i].totalmarescore += players[i].marescore;
|
||||
|
@ -909,8 +908,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
player->finishedrings = (INT16)(player->rings);
|
||||
|
||||
// Add score to temp leaderboards
|
||||
if (!(netgame||multiplayer) && P_IsLocalPlayer(player))
|
||||
G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1));
|
||||
G_AddTempNightsRecords(player, player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1));
|
||||
|
||||
// Starting a new mare, transfer scores
|
||||
player->totalmarescore += player->marescore;
|
||||
|
@ -1440,6 +1438,10 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
|
|||
if (player->score > MAXSCORE)
|
||||
player->score = MAXSCORE;
|
||||
|
||||
player->recordscore += amount;
|
||||
if (player->recordscore > MAXSCORE)
|
||||
player->recordscore = MAXSCORE;
|
||||
|
||||
// check for extra lives every 50000 pts
|
||||
if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES))
|
||||
{
|
||||
|
@ -11732,7 +11734,7 @@ void P_PlayerThink(player_t *player)
|
|||
if (player->spectator)
|
||||
{
|
||||
if (!(gametyperules & GTR_CAMPAIGN))
|
||||
player->score = 0;
|
||||
player->score = player->recordscore = 0;
|
||||
}
|
||||
else if ((netgame || multiplayer) && player->lives <= 0 && !G_CoopGametype())
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue