Merge branch 'staffghost-repair' into 'master'

Staffghost Repair

See merge request KartKrew/Kart!912
This commit is contained in:
Oni 2023-02-07 08:09:22 +00:00
commit 7884bbfed8
24 changed files with 580 additions and 342 deletions

View file

@ -198,6 +198,8 @@ void Environment::loadModule(ACSVM::Module *module)
{
CONS_Printf("No BEHAVIOR lump found.\n");
}
vres_Free(vRes);
}
else
{

View file

@ -2066,7 +2066,7 @@ static void CL_ConnectToServer(void)
CONS_Printf(M_GetText("Contacting the server...\n"));
}
if (cv_currprofile.value == -1)
if (cv_currprofile.value == -1 && !demo.playback)
{
PR_ApplyProfilePretend(cv_ttlprofilen.value, 0);
for (i = 1; i < cv_splitplayers.value; i++)

View file

@ -952,7 +952,7 @@ void D_ClearState(void)
memset(displayplayers, 0, sizeof(displayplayers));
memset(g_localplayers, 0, sizeof g_localplayers);
consoleplayer = 0;
//demosequence = -1;
demo.title = false;
G_SetGametype(GT_RACE); // SRB2kart
paused = false;
@ -968,6 +968,7 @@ void D_ClearState(void)
tutorialmode = false;
G_SetGamestate(GS_NULL);
wipegamestate = GS_NULL;
}
//
@ -975,7 +976,9 @@ void D_ClearState(void)
//
void D_StartTitle(void)
{
S_StopMusic();
if (!demo.title)
S_StopMusic();
D_ClearState();
F_StartTitleScreen();
M_ClearMenus(false);

View file

@ -4894,7 +4894,7 @@ void AltTitle_OnChange(void)
if (!M_SecretUnlocked(SECRET_ALTTITLE, true))
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
CV_StealthSetValue(&cv_itemfinder, 0);
CV_StealthSetValue(&cv_alttitle, 0);
return;
}
}
@ -5784,8 +5784,15 @@ void Command_ExitGame_f(void)
if (!modeattacking)
{
D_ClearState();
M_StartControlPanel();
if (restoreMenu == NULL)
{
D_StartTitle();
}
else
{
D_ClearState();
M_StartControlPanel();
}
}
}

View file

@ -2185,19 +2185,13 @@ void reademblemdata(MYFILE *f, INT32 num)
} while (!myfeof(f));
// Default sprite and color definitions for lazy people like me
if (!emblemlocations[num-1].sprite) switch (emblemlocations[num-1].type)
if (!emblemlocations[num-1].sprite)
{
case ET_TIME:
emblemlocations[num-1].sprite = 'B'; break;
default:
emblemlocations[num-1].sprite = 'A'; break;
emblemlocations[num-1].sprite = 'A';
}
if (!emblemlocations[num-1].color) switch (emblemlocations[num-1].type)
if (!emblemlocations[num-1].color)
{
case ET_TIME: //case ET_NTIME:
emblemlocations[num-1].color = SKINCOLOR_GREY; break;
default:
emblemlocations[num-1].color = SKINCOLOR_GOLD; break;
emblemlocations[num-1].color = SKINCOLOR_GOLD;
}
Z_Free(s);

View file

@ -360,6 +360,14 @@ extern cupheader_t *kartcupheaders; // Start of cup linked list
extern UINT16 numkartcupheaders;
#define MAXMAPLUMPNAME 64 // includes \0, for cleaner savedata
#define MAXSTAFF 3
struct staffbrief_t
{
char name[16];
tic_t time;
tic_t lap;
};
/** Map header information.
*/
@ -374,6 +382,10 @@ struct mapheader_t
void *encoreLump; ///< Lump data for the Encore Mode remap.
void *tweakLump; ///< Lump data for the palette tweak remap.
// Staff Ghost information
UINT8 ghostCount; ///< Count of valid staff ghosts
staffbrief_t *ghostBrief[MAXSTAFF]; ///< Mallocated array of names for each staff ghost
UINT8 mapvisited; ///< A set of flags that says what we've done in the map.
recorddata_t *mainrecord; ///< Stores best time attack data

View file

@ -2194,25 +2194,20 @@ void F_TitleScreenTicker(boolean run)
return;
}
#ifdef STAFFGHOSTS
// is it time?
if (!(--demoIdleLeft))
{
//static boolean use_netreplay = false;
char dname[9];
char *dname2 = dname;
lumpnum_t l;
const char *mapname;
char dname[MAXMAPLUMPNAME+1+8+1];
UINT16 mapnum;
UINT8 numstaff;
static boolean use_netreplay = false;
//@TODO uncomment this when this goes into vanilla
/*if ((use_netreplay = !use_netreplay))*/
if ((use_netreplay = !use_netreplay))
{
numstaff = 1;
while ((l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR)
lumpnum_t l = LUMPERROR;
numstaff = 0;
while (numstaff < 99 && (l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR)
numstaff++;
numstaff--;
if (numstaff)
{
@ -2225,42 +2220,23 @@ void F_TitleScreenTicker(boolean run)
// prevent console spam if failed
demoIdleLeft = demoIdleTime;
if ((l = W_CheckNumForName("MAP01S01")) == LUMPERROR) // gotta have ONE
mapnum = G_RandMap(TOL_RACE|TOL_BATTLE, -2, 2, 0, false, NULL);
if (mapnum == 0) // gotta have ONE
{
F_StartIntro();
return;
}
mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, 0, 0, false, NULL)+1);
numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForLongName(va("%sS%02u",mapname,numstaff+1))) != LUMPERROR)
numstaff++;
numstaff = M_RandomKey(numstaff)+1;
numstaff = M_RandomKey(mapheaderinfo[mapnum]->ghostCount)+1;
// Setup demo name
dname2 = Z_StrDup(va("%sS%02u", mapname, numstaff));
/*if ((l = W_CheckNumForName(dname)) == LUMPERROR) -- we KNOW it exists now
{
CONS_Alert(CONS_ERROR, M_GetText("Demo lump \"%s\" doesn't exist\n"), dname);
F_StartIntro();
return;
}*/
sprintf(dname, "%s/GHOST_%u", mapheaderinfo[mapnum]->lumpname, numstaff);
loadreplay:
demo.title = demo.fromtitle = true;
demo.title = true;
demo.ignorefiles = true;
demo.loadfiles = false;
G_DoPlayDemo(dname2);
if (dname2 != dname)
{
Z_Free(dname2);
}
G_DoPlayDemo(dname);
}
#endif //#ifdef STAFFGHOSTS
}
void F_TitleDemoTicker(void)

View file

@ -2987,6 +2987,7 @@ void G_DoPlayDemo(char *defdemoname)
{
snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
Z_Free(pdemoname);
gameaction = ga_nothing;
M_StartMessage(msg, NULL, MM_NOTHING);
return;
@ -2995,18 +2996,68 @@ void G_DoPlayDemo(char *defdemoname)
// load demo resource from WAD
else
{
if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
if (n == defdemoname)
{
snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
gameaction = ga_nothing;
M_StartMessage(msg, NULL, MM_NOTHING);
return;
}
// Raw lump.
if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
{
snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
Z_Free(pdemoname);
gameaction = ga_nothing;
M_StartMessage(msg, NULL, MM_NOTHING);
return;
}
P_SaveBufferFromLump(&demobuf, l);
P_SaveBufferFromLump(&demobuf, l);
}
else
{
// vres GHOST_%u
virtres_t *vRes;
virtlump_t *vLump;
UINT16 mapnum;
size_t step = 0;
step = 0;
while (defdemoname+step < n-1)
{
mapname[step] = defdemoname[step];
step++;
}
mapname[step] = '\0';
mapnum = G_MapNumber(mapname);
if (mapnum >= nummapheaders || mapheaderinfo[mapnum]->lumpnum == LUMPERROR)
{
snprintf(msg, 1024, M_GetText("Failed to read virtlump '%s (couldn't find map %s)'.\n"), defdemoname, mapname);
CONS_Alert(CONS_ERROR, "%s", msg);
Z_Free(pdemoname);
gameaction = ga_nothing;
M_StartMessage(msg, NULL, MM_NOTHING);
return;
}
vRes = vres_GetMap(mapheaderinfo[mapnum]->lumpnum);
vLump = vres_Find(vRes, pdemoname);
if (vLump == NULL)
{
snprintf(msg, 1024, M_GetText("Failed to read virtlump '%s (couldn't find lump %s in %s)'.\n"), defdemoname, pdemoname, mapname);
CONS_Alert(CONS_ERROR, "%s", msg);
Z_Free(pdemoname);
gameaction = ga_nothing;
M_StartMessage(msg, NULL, MM_NOTHING);
return;
}
P_SaveBufferAlloc(&demobuf, vLump->size);
memcpy(demobuf.buffer, vLump->data, vLump->size);
vres_Free(vRes);
}
#if defined(SKIPERRORS) && !defined(DEVELOP)
skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes...
skiperrors = true; // RR: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes...
#endif
}
}
@ -3022,7 +3073,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
demobuf.p += 12; // DEMOHEADER
@ -3042,7 +3092,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
@ -3060,7 +3109,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
demobuf.p += 4; // "PLAY"
@ -3080,7 +3128,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
G_SetGametype(i);
@ -3138,7 +3185,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
}
@ -3153,7 +3199,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
@ -3189,7 +3234,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
@ -3207,7 +3251,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
@ -3262,7 +3305,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
}
@ -3280,7 +3322,6 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(pdemoname);
Z_Free(demobuf.buffer);
demo.playback = false;
demo.title = false;
return;
}
@ -3429,14 +3470,13 @@ void G_DoPlayDemo(char *defdemoname)
demo.deferstart = true;
}
void G_AddGhost(char *defdemoname)
void G_AddGhost(UINT8 *buffer, char *defdemoname)
{
INT32 i;
lumpnum_t l;
char name[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
char name[17], color[MAXCOLORNAME+1], md5[16];
demoghost *gh;
UINT8 flags;
UINT8 *buffer,*p;
UINT8 *p;
mapthing_t *mthing;
UINT16 count, ghostversion;
skin_t *ghskin = &skins[0];
@ -3446,41 +3486,12 @@ void G_AddGhost(char *defdemoname)
name[16] = '\0';
color[16] = '\0';
n = defdemoname+strlen(defdemoname);
while (*n != '/' && *n != '\\' && n != defdemoname)
n--;
if (n != defdemoname)
n++;
pdemoname = ZZ_Alloc(strlen(n)+1);
strcpy(pdemoname,n);
// Internal if no extension, external if one exists
if (FIL_CheckExtension(defdemoname))
{
//FIL_DefaultExtension(defdemoname, ".lmp");
if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL))
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname);
Z_Free(pdemoname);
return;
}
p = buffer;
}
// load demo resource from WAD
else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
Z_Free(pdemoname);
return;
}
else // it's an internal demo
buffer = p = W_CacheLumpNum(l, PU_LEVEL);
p = buffer;
// read demo header
if (memcmp(p, DEMOHEADER, 12))
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), defdemoname);
Z_Free(buffer);
return;
} p += 12; // DEMOHEADER
@ -3495,8 +3506,7 @@ void G_AddGhost(char *defdemoname)
break;
// too old, cannot support.
default:
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), defdemoname);
Z_Free(buffer);
return;
}
@ -3507,16 +3517,14 @@ void G_AddGhost(char *defdemoname)
for (gh = ghosts; gh; gh = gh->next)
if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum?
{ // Don't add another one, then!
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname);
Z_Free(pdemoname);
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", defdemoname);
Z_Free(buffer);
return;
}
if (memcmp(p, "PLAY", 4))
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), defdemoname);
Z_Free(buffer);
return;
} p += 4; // "PLAY"
@ -3528,16 +3536,14 @@ void G_AddGhost(char *defdemoname)
flags = READUINT8(p);
if (!(flags & DF_GHOST))
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), defdemoname);
Z_Free(buffer);
return;
}
if (flags & DF_LUAVARS) // can't be arsed to add support for grinding away ported lua material
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data contains luavars, cannot continue.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data contains luavars, cannot continue.\n"), defdemoname);
Z_Free(buffer);
return;
}
@ -3549,8 +3555,7 @@ void G_AddGhost(char *defdemoname)
skinlist = G_LoadDemoSkins(&p, &worknumskins, true);
if (!skinlist)
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data has invalid skin list, cannot continue.\n"), pdemoname);
Z_Free(pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data has invalid skin list, cannot continue.\n"), defdemoname);
Z_Free(buffer);
return;
}
@ -3578,9 +3583,8 @@ void G_AddGhost(char *defdemoname)
if (*p == DEMOMARKER)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), defdemoname);
Z_Free(skinlist);
Z_Free(pdemoname);
Z_Free(buffer);
return;
}
@ -3591,9 +3595,8 @@ void G_AddGhost(char *defdemoname)
i = READUINT8(p);
if ((i & (DEMO_SPECTATOR|DEMO_BOT)) != 0)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (spectator/bot)\n"), pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (spectator/bot)\n"), defdemoname);
Z_Free(skinlist);
Z_Free(pdemoname);
Z_Free(buffer);
return;
}
@ -3624,9 +3627,8 @@ void G_AddGhost(char *defdemoname)
if (READUINT8(p) != 0xFF)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (bad terminator)\n"), pdemoname);
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (bad terminator)\n"), defdemoname);
Z_Free(skinlist);
Z_Free(pdemoname);
Z_Free(buffer);
return;
}
@ -3693,8 +3695,7 @@ void G_AddGhost(char *defdemoname)
}
gh->oldmo.color = gh->mo->color;
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
Z_Free(pdemoname);
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, defdemoname);
}
// Clean up all ghosts
@ -3711,14 +3712,17 @@ void G_FreeGhosts(void)
}
// A simplified version of G_AddGhost...
void G_UpdateStaffGhostName(lumpnum_t l)
staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
{
UINT8 *buffer,*p;
UINT8 *p = buffer;
UINT16 ghostversion;
UINT8 flags;
INT32 i;
staffbrief_t temp;
staffbrief_t *ret = NULL;
buffer = p = W_CacheLumpNum(l, PU_CACHE);
temp.name[0] = '\0';
temp.time = temp.lap = UINT32_MAX;
// read demo header
if (memcmp(p, DEMOHEADER, 12))
@ -3766,9 +3770,9 @@ void G_UpdateStaffGhostName(lumpnum_t l)
G_SkipDemoSkins(&p);
if (flags & ATTACKING_TIME)
p += 4;
temp.time = READUINT32(p);
if (flags & ATTACKING_LAP)
p += 4;
temp.lap = READUINT32(p);
for (i = 0; i < PRNUMCLASS; i++)
{
@ -3781,7 +3785,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
ghostversion = READUINT16(p);
while (ghostversion--)
{
p += 2;
SKIPSTRING(p);
SKIPSTRING(p);
p++; // stealth
}
@ -3789,13 +3793,18 @@ void G_UpdateStaffGhostName(lumpnum_t l)
// Assert first player is in and then read name
if (READUINT8(p) != 0)
goto fail;
M_Memcpy(dummystaffname, p,16);
dummystaffname[16] = '\0';
if (READUINT8(p) & (DEMO_SPECTATOR|DEMO_BOT))
goto fail;
M_Memcpy(temp.name, p, 16);
ret = Z_Malloc(sizeof(staffbrief_t), PU_STATIC, NULL);
if (ret)
M_Memcpy(ret, &temp, sizeof(staffbrief_t));
// Ok, no longer any reason to care, bye
fail:
Z_Free(buffer);
return;
return ret;
}
//
@ -4009,7 +4018,6 @@ void G_StopDemo(void)
Z_Free(demobuf.buffer);
demobuf.buffer = NULL;
demo.playback = false;
demo.title = false;
demo.timing = false;
singletics = false;

View file

@ -47,7 +47,6 @@ struct demovars_s {
boolean rewinding; // Rewind in progress
boolean loadfiles, ignorefiles; // Demo file loading options
boolean fromtitle; // SRB2Kart: Don't stop the music
boolean inreplayhut; // Go back to replayhut after demos
boolean quitafterplaying; // quit after playing a demo from cmdline
boolean deferstart; // don't start playing demo right away
@ -184,8 +183,8 @@ extern demoghost *ghosts;
void G_DeferedPlayDemo(const char *demo);
void G_DoPlayDemo(char *defdemoname);
void G_TimeDemo(const char *name);
void G_AddGhost(char *defdemoname);
void G_UpdateStaffGhostName(lumpnum_t l);
void G_AddGhost(UINT8 *buffer, char *defdemoname);
staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer);
void G_FreeGhosts(void);
void G_DoneLevelLoad(void);

View file

@ -465,11 +465,6 @@ void G_ClearRecords(void)
Z_Free(mapheaderinfo[i]->mainrecord);
mapheaderinfo[i]->mainrecord = NULL;
}
/*if (nightsrecords[i])
{
Z_Free(nightsrecords[i]);
nightsrecords[i] = NULL;
}*/
}
}
@ -495,31 +490,133 @@ tic_t G_GetBestLap(INT16 map)
}
*/
//
// G_UpdateRecordReplays
//
// Update replay files/data, etc. for Record Attack
//
static void G_UpdateRecordReplays(void)
struct stickermedalinfo stickermedalinfo;
void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord)
{
emblem_t *emblem = M_GetLevelEmblems(map+1);
boolean gonnadrawtime = false;
memset(&stickermedalinfo, 0, sizeof(stickermedalinfo));
stickermedalinfo.timetoreach = UINT32_MAX;
while (emblem != NULL)
{
UINT8 i = 0;
switch (emblem->type)
{
case ET_TIME:
{
break;
}
default:
goto bademblem;
}
if (!gamedata->collected[(emblem-emblemlocations)] && gonnadrawtime)
break;
// Simpler than having two checks
if (stickermedalinfo.visiblecount == MAXMEDALVISIBLECOUNT)
stickermedalinfo.visiblecount--;
// Shuffle along, so [0] is the "main focus"
for (i = stickermedalinfo.visiblecount; i > 0; i--)
{
stickermedalinfo.emblems[i] = stickermedalinfo.emblems[i-1];
}
stickermedalinfo.emblems[0] = emblem;
stickermedalinfo.visiblecount++;
if (!gamedata->collected[(emblem-emblemlocations)] || Playing())
gonnadrawtime = true;
bademblem:
emblem = M_GetLevelEmblems(-1);
}
if (stickermedalinfo.visiblecount > 0)
{
if (emblem != NULL && emblem != stickermedalinfo.emblems[0])
{
// Regenerate the entire array if this is unlocked
stickermedalinfo.regenemblem = emblem;
}
emblem = stickermedalinfo.emblems[0];
if (gonnadrawtime)
{
if (emblem->tag > 0)
{
if (emblem->tag > mapheaderinfo[map]->ghostCount
|| mapheaderinfo[map]->ghostBrief[emblem->tag-1] == NULL)
snprintf(stickermedalinfo.targettext, 9, "Invalid");
else if (mapheaderinfo[map]->ghostBrief[emblem->tag-1]->time == UINT32_MAX)
snprintf(stickermedalinfo.targettext, 9, "DNF");
else
stickermedalinfo.timetoreach = mapheaderinfo[map]->ghostBrief[emblem->tag-1]->time;
}
else
stickermedalinfo.timetoreach = emblem->var;
}
}
if (!gonnadrawtime && showownrecord)
{
stickermedalinfo.timetoreach = G_GetBestTime(map);
}
if (stickermedalinfo.timetoreach != UINT32_MAX)
{
snprintf(stickermedalinfo.targettext, 9, "%i'%02i\"%02i",
G_TicsToMinutes(stickermedalinfo.timetoreach, false),
G_TicsToSeconds(stickermedalinfo.timetoreach),
G_TicsToCentiseconds(stickermedalinfo.timetoreach));
}
}
void G_TickTimeStickerMedals(void)
{
if (stickermedalinfo.jitter)
stickermedalinfo.jitter--;
if (players[consoleplayer].realtime > stickermedalinfo.timetoreach)
{
if (stickermedalinfo.norecord == false)
{
S_StartSound(NULL, sfx_s3k72); //sfx_s26d); -- you STOLE fizzy lifting drinks
stickermedalinfo.norecord = true;
stickermedalinfo.jitter = 4;
}
}
else
{
stickermedalinfo.norecord = false;
}
}
//
// G_UpdateRecords
//
// Update time attack records
//
void G_UpdateRecords(void)
{
char *gpath;
char lastdemo[256], bestdemo[256];
UINT8 earnedEmblems;
// Record new best time
if (!mapheaderinfo[gamemap-1]->mainrecord)
G_AllocMainRecordData(gamemap-1);
if (players[consoleplayer].pflags & PF_NOCONTEST)
{
players[consoleplayer].realtime = UINT32_MAX;
}
if (modeattacking & ATTACKING_TIME)
{
if (((mapheaderinfo[gamemap-1]->mainrecord->time == 0) || (players[consoleplayer].realtime < mapheaderinfo[gamemap-1]->mainrecord->time))
&& (players[consoleplayer].realtime < UINT32_MAX)) // DNF
mapheaderinfo[gamemap-1]->mainrecord->time = players[consoleplayer].realtime;
tic_t time = players[consoleplayer].realtime;
if (players[consoleplayer].pflags & PF_NOCONTEST)
time = UINT32_MAX;
if (((mapheaderinfo[gamemap-1]->mainrecord->time == 0) || (time < mapheaderinfo[gamemap-1]->mainrecord->time))
&& (time < UINT32_MAX)) // DNF
mapheaderinfo[gamemap-1]->mainrecord->time = time;
}
else
{
@ -536,6 +633,38 @@ static void G_UpdateRecordReplays(void)
mapheaderinfo[gamemap-1]->mainrecord->lap = 0;
}
// Check emblems when level data is updated
if ((earnedEmblems = M_CheckLevelEmblems()))
{
if (stickermedalinfo.regenemblem != NULL
&& gamedata->collected[(stickermedalinfo.regenemblem-emblemlocations)])
{
G_UpdateTimeStickerMedals(gamemap-1, false);
}
stickermedalinfo.jitter = 4*earnedEmblems;
S_StartSound(NULL, sfx_ncitem);
}
M_UpdateUnlockablesAndExtraEmblems(true);
G_SaveGameData();
}
//
// G_UpdateRecordReplays
//
// Update replay files/data, etc. for Record Attack
//
static void G_UpdateRecordReplays(void)
{
char *gpath;
char lastdemo[256], bestdemo[256];
if (players[consoleplayer].pflags & PF_NOCONTEST)
{
players[consoleplayer].realtime = UINT32_MAX;
}
// Save demo!
bestdemo[255] = '\0';
lastdemo[255] = '\0';
@ -590,13 +719,6 @@ static void G_UpdateRecordReplays(void)
Z_Free(gpath);
}
// Check emblems when level data is updated
if ((earnedEmblems = M_CheckLevelEmblems()))
CONS_Printf(M_GetText("\x82" "Earned %hu medal%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
M_UpdateUnlockablesAndExtraEmblems(true);
G_SaveGameData();
}
// for consistency among messages: this modifies the game and removes savemoddata.
@ -1339,7 +1461,7 @@ void G_DoLoadLevel(boolean resetplayer)
if (wipegamestate == GS_LEVEL)
wipegamestate = -1; // force a wipe
if (cv_currprofile.value == -1)
if (cv_currprofile.value == -1 && !demo.playback)
{
PR_ApplyProfilePretend(cv_ttlprofilen.value, 0);
for (i = 1; i < cv_splitplayers.value; i++)
@ -3441,6 +3563,10 @@ tryagain:
|| (usehellmaps != (mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU))) // this is bad
continue; //isokmap = false;
if (pprevmap == -2 // title demo hack
&& mapheaderinfo[ix]->ghostCount == 0)
continue;
if (!ignorebuffer)
{
if (extbufsize > 0)
@ -3475,16 +3601,6 @@ tryagain:
continue;
}
#ifdef STAFFGHOSTS
if (pprevmap == -2) // title demo hack
{
lumpnum_t l;
// TODO: Use map header to determine lump name
if ((l = W_CheckNumForLongName(va("%sS01",G_BuildMapName(ix+1)))) == LUMPERROR)
continue;
}
#endif //#ifdef STAFFGHOSTS
okmaps[numokmaps++] = ix;
}

View file

@ -201,6 +201,22 @@ void G_UseContinue(void);
void G_AfterIntermission(void);
void G_EndGame(void); // moved from y_inter.c/h and renamed
#define MAXMEDALVISIBLECOUNT 3
extern struct stickermedalinfo
{
UINT8 visiblecount;
UINT8 jitter;
boolean norecord;
tic_t timetoreach;
emblem_t *emblems[MAXMEDALVISIBLECOUNT];
emblem_t *regenemblem;
char targettext[9];
} stickermedalinfo;
void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord);
void G_TickTimeStickerMedals(void);
void G_UpdateRecords(void);
void G_Ticker(boolean run);
boolean G_Responder(event_t *ev);

View file

@ -1466,7 +1466,7 @@ static void K_drawKartItem(void)
}
}
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode)
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, UINT8 mode)
{
// TIME_X = BASEVIDWIDTH-124; // 196
// TIME_Y = 6; // 6
@ -1550,77 +1550,60 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
V_DrawKartString(TX+84, TY+3-jitter, splitflags, va("%d", worktime%10));
}
if (emblemmap && (modeattacking || (mode == 1)) && !demo.playback) // emblem time!
// Medal data!
if ((modeattacking || (mode == 1))
&& !demo.playback)
{
INT32 workx = TX + 96, worky = TY+18;
SINT8 curemb = 0;
patch_t *emblempic[3] = {NULL, NULL, NULL};
UINT8 *emblemcol[3] = {NULL, NULL, NULL};
UINT8 i = stickermedalinfo.visiblecount;
emblem_t *emblem = M_GetLevelEmblems(emblemmap);
while (emblem)
if (stickermedalinfo.targettext[0] != '\0')
{
char targettext[9];
switch (emblem->type)
if (!mode)
{
case ET_TIME:
{
static boolean canplaysound = true;
tic_t timetoreach = emblem->var;
if (stickermedalinfo.jitter)
{
jitter = stickermedalinfo.jitter+3;
if (jitter & 2)
workx += jitter/4;
else
workx -= jitter/4;
}
if (gamedata->collected[(emblem-emblemlocations)])
{
emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE);
emblemcol[curemb] = R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE);
if (++curemb == 3)
break;
goto bademblem;
}
snprintf(targettext, 9, "%i'%02i\"%02i",
G_TicsToMinutes(timetoreach, false),
G_TicsToSeconds(timetoreach),
G_TicsToCentiseconds(timetoreach));
if (!mode)
{
if (stplyr->realtime > timetoreach)
{
splitflags = (splitflags &~ V_HUDTRANS)|V_HUDTRANSHALF;
if (canplaysound)
{
S_StartSound(NULL, sfx_s3k72); //sfx_s26d); -- you STOLE fizzy lifting drinks
canplaysound = false;
}
}
else if (!canplaysound)
canplaysound = true;
}
targettext[8] = 0;
}
break;
default:
goto bademblem;
if (stickermedalinfo.norecord == true)
{
splitflags = (splitflags &~ V_HUDTRANS)|V_HUDTRANSHALF;
}
}
V_DrawRightAlignedString(workx, worky, splitflags|V_6WIDTHSPACE, targettext);
workx -= 67;
V_DrawSmallScaledPatch(workx + 4, worky, splitflags, W_CachePatchName("NEEDIT", PU_CACHE));
break;
bademblem:
emblem = M_GetLevelEmblems(-1);
workx -= V_ThinStringWidth(stickermedalinfo.targettext, splitflags|V_6WIDTHSPACE);
V_DrawThinString(workx, worky, splitflags|V_6WIDTHSPACE, stickermedalinfo.targettext);
}
workx -= (6 + (i*5));
if (!mode)
splitflags = (splitflags &~ V_HUDTRANSHALF)|V_HUDTRANS;
while (curemb--)
while (i > 0)
{
workx -= 12;
V_DrawSmallMappedPatch(workx + 4, worky, splitflags, emblempic[curemb], emblemcol[curemb]);
i--;
if (gamedata->collected[(stickermedalinfo.emblems[i]-emblemlocations)])
{
V_DrawSmallMappedPatch(workx, worky, splitflags,
W_CachePatchName(M_GetEmblemPatch(stickermedalinfo.emblems[i], false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(stickermedalinfo.emblems[i]), GTC_CACHE)
);
}
else
{
V_DrawSmallMappedPatch(workx, worky, splitflags,
W_CachePatchName("NEEDIT", PU_CACHE),
NULL
);
}
workx += 6;
}
}
}
@ -5054,7 +5037,7 @@ void K_drawKartHUD(void)
{
// Draw the timestamp
if (LUA_HudEnabled(hud_time))
K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, 0);
K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, 0);
islonesome = K_drawKartPositionFaces();
}
@ -5063,17 +5046,17 @@ void K_drawKartHUD(void)
{
if (demo.title) // Draw title logo instead in demo.titles
{
INT32 x = BASEVIDWIDTH - 32, y = 128, snapflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
INT32 x = BASEVIDWIDTH - 8, y = BASEVIDHEIGHT-8, snapflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SLIDEIN;
patch_t *pat = W_CachePatchName((cv_alttitle.value ? "MTSJUMPR1" : "MTSBUMPR1"), PU_CACHE);
if (r_splitscreen == 3)
{
x = BASEVIDWIDTH/2 + 10;
y = BASEVIDHEIGHT/2 - 30;
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
snapflags = 0;
}
V_DrawTinyScaledPatch(x-54, y, snapflags|V_SLIDEIN, W_CachePatchName("TTKBANNR", PU_CACHE));
V_DrawTinyScaledPatch(x-54, y+25, snapflags|V_SLIDEIN, W_CachePatchName("TTKART", PU_CACHE));
V_DrawScaledPatch(x-(SHORT(pat->width)), y-(SHORT(pat->height)), snapflags, pat);
}
else
{

View file

@ -40,7 +40,7 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny);
void K_LoadKartHUDGraphics(void);
void K_drawKartHUD(void);
void K_drawKartFreePlay(void);
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, UINT8 mode);
void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol);
void K_DrawMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, UINT16 map, UINT8 *colormap);
void K_DrawLikeMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, patch_t *patch, UINT8 *colormap);

View file

@ -469,7 +469,6 @@ void Moviemode_option_Onchange(void);
extern menu_t *currentMenu;
extern menu_t *restoreMenu;
extern char dummystaffname[22];
extern consvar_t cv_dummystaff;
extern INT16 itemOn; // menu item skull is on, Hack by Tails 09-18-2002
@ -576,7 +575,7 @@ boolean M_MenuButtonPressed(UINT8 pid, UINT32 bt);
boolean M_MenuButtonHeld(UINT8 pid, UINT32 bt);
boolean M_ChangeStringCvar(INT32 choice);
void M_ChangeCvarDirect(INT32 choice, consvar_t *cv);
boolean M_NextOpt(void);
boolean M_PrevOpt(void);

View file

@ -2240,7 +2240,6 @@ void M_DrawTimeAttack(void)
INT32 w;
patch_t *minimap = NULL;
UINT8 i;
consvar_t *cv;
M_DrawLevelSelectBlock(0, 2, map, true, false);
@ -2267,7 +2266,7 @@ void M_DrawTimeAttack(void)
&& (mapheaderinfo[map]->numlaps != 1))
{
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST LAP:");
K_drawKartTimestamp(laprec, 162+t, timeheight+6, 0, 2);
K_drawKartTimestamp(laprec, 162+t, timeheight+6, 2);
timeheight += 30;
}
else
@ -2276,7 +2275,7 @@ void M_DrawTimeAttack(void)
}
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST TIME:");
K_drawKartTimestamp(timerec, 162+t, timeheight+6, map, 1);
K_drawKartTimestamp(timerec, 162+t, timeheight+6, 1);
}
else
opty = 80;
@ -2303,19 +2302,56 @@ void M_DrawTimeAttack(void)
opty += 10;
// Cvar specific handling
if (currentMenu->menuitems[i].status & IT_CVAR)
{
cv = currentMenu->menuitems[i].itemaction.cvar;
const char *str = NULL;
INT32 optflags = f;
boolean drawarrows = (i == itemOn);
w = V_StringWidth(cv->string, 0);
V_DrawString(leftedge, opty, f, cv->string);
if (i == itemOn)
if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS)
{
V_DrawCharacter(leftedge - 10 - (skullAnimCounter/5), opty, '\x1C' | f, false); // left arrow
V_DrawCharacter(leftedge + w + 2+ (skullAnimCounter/5), opty, '\x1D' | f, false); // right arrow
// Currently assumes M_HandleStaffReplay
if (mapheaderinfo[levellist.choosemap]->ghostCount <= 1)
drawarrows = false;
optflags |= V_ALLOWLOWERCASE;
if (mapheaderinfo[levellist.choosemap] == NULL)
str = "Invalid map";
else if (cv_dummystaff.value > mapheaderinfo[levellist.choosemap]->ghostCount)
str = va("%u - Invalid ID", cv_dummystaff.value+1);
else if (mapheaderinfo[levellist.choosemap]->ghostBrief[cv_dummystaff.value] == NULL)
str = va("%u - Invalid brief", cv_dummystaff.value+1);
else
{
const char *th = "th";
if (cv_dummystaff.value+1 == 1)
th = "st";
else if (cv_dummystaff.value+1 == 2)
th = "nd";
else if (cv_dummystaff.value+1 == 3)
th = "rd";
str = va("%u%s - %s",
cv_dummystaff.value+1,
th,
mapheaderinfo[levellist.choosemap]->ghostBrief[cv_dummystaff.value]->name
);
}
}
else if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR)
{
str = currentMenu->menuitems[i].itemaction.cvar->string;
}
if (str)
{
w = V_StringWidth(str, optflags);
V_DrawString(leftedge+12, opty, optflags, str);
if (drawarrows)
{
V_DrawCharacter(leftedge+12 - 10 - (skullAnimCounter/5), opty, '\x1C' | f, false); // left arrow
V_DrawCharacter(leftedge+12 + w + 2+ (skullAnimCounter/5), opty, '\x1D' | f, false); // right arrow
}
opty += 10;
}
opty += 10;
}
break;

View file

@ -37,8 +37,6 @@ boolean fromlevelselect = false;
menu_t *currentMenu = &MAIN_ProfilesDef;
menu_t *restoreMenu = NULL;
char dummystaffname[22];
INT16 itemOn = 0; // menu item skull is on, Hack by Tails 09-18-2002
INT16 skullAnimCounter = 8; // skull animation counter
struct menutransition_s menutransition; // Menu transition properties
@ -77,7 +75,7 @@ consvar_t cv_tutorialprompt = CVAR_INIT ("tutorialprompt", "On", CV_SAVE, CV_OnO
static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}};
static CV_PossibleValue_t dummyspectate_cons_t[] = {{0, "Spectator"}, {1, "Playing"}, {0, NULL}};
static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}};
static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}};
static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {MAXSTAFF-1, "MAX"}, {0, NULL}};
static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL);
//static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL);
@ -92,39 +90,15 @@ consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN,
static void Dummystaff_OnChange(void)
{
#ifdef STAFFGHOSTS
lumpnum_t l;
if (mapheaderinfo[levellist.choosemap] == NULL || mapheaderinfo[levellist.choosemap]->ghostCount <= 0)
return;
dummystaffname[0] = '\0';
if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) == LUMPERROR)
dummystaff_cons_t[1].value = mapheaderinfo[levellist.choosemap]->ghostCount-1;
if (cv_dummystaff.value > dummystaff_cons_t[1].value)
{
CV_StealthSetValue(&cv_dummystaff, 0);
return;
}
else
{
char *temp = dummystaffname;
UINT8 numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value),numstaff+1))) != LUMPERROR)
numstaff++;
if (cv_dummystaff.value < 1)
CV_StealthSetValue(&cv_dummystaff, numstaff);
else if (cv_dummystaff.value > numstaff)
CV_StealthSetValue(&cv_dummystaff, 1);
if ((l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value), cv_dummystaff.value))) == LUMPERROR)
return; // shouldn't happen but might as well check...
G_UpdateStaffGhostName(l);
while (*temp)
temp++;
sprintf(temp, " - %d", cv_dummystaff.value);
}
#endif //#ifdef STAFFGHOSTS
}
@ -132,10 +106,8 @@ static void Dummystaff_OnChange(void)
// BASIC MENU HANDLING
// =========================================================================
static void M_ChangeCvar(INT32 choice)
void M_ChangeCvarDirect(INT32 choice, consvar_t *cv)
{
consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar;
// Backspace sets values to default value
if (choice == -1)
{
@ -143,7 +115,7 @@ static void M_ChangeCvar(INT32 choice)
return;
}
choice = (choice<<1) - 1;
choice = (choice == 0 ? -1 : 1);
if (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_SLIDER)
|| ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER)
@ -170,6 +142,11 @@ static void M_ChangeCvar(INT32 choice)
}
}
static void M_ChangeCvar(INT32 choice)
{
M_ChangeCvarDirect(choice, currentMenu->menuitems[itemOn].itemaction.cvar);
}
boolean M_NextOpt(void)
{
INT16 oldItemOn = itemOn; // prevent infinite loop
@ -466,7 +443,7 @@ void M_StartControlPanel(void)
}
// intro might call this repeatedly
if (menuactive && gamestate != GS_NULL)
if (mapchangepending || (menuactive && gamestate != GS_NULL))
{
CON_ToggleOff(); // move away console
return;
@ -939,7 +916,7 @@ static void M_HandleMenuInput(void)
{
case IT_CVAR:
case IT_ARROWS:
routine(1); // right arrow
routine(2); // usually right arrow
break;
case IT_CALL:
routine(itemOn);
@ -965,19 +942,17 @@ static void M_HandleMenuInput(void)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{
consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar;
/*consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar;
// Make these CVar options?
if (cv == &cv_chooseskin
|| cv == &cv_dummystaff
/*
|| cv == &cv_nextmap
|| cv == &cv_newgametype
*/
)
{
return;
}
}*/
S_StartSound(NULL, sfx_s3k5b);

View file

@ -949,6 +949,7 @@ UINT8 M_CheckLevelEmblems(void)
{
INT32 i;
INT32 valToReach;
INT16 tag;
INT16 levelnum;
UINT8 res;
UINT8 somethingUnlocked = 0;
@ -968,11 +969,23 @@ UINT8 M_CheckLevelEmblems(void)
levelnum = checkLevel;
valToReach = emblemlocations[i].var;
tag = emblemlocations[i].tag;
switch (emblemlocations[i].type)
{
case ET_TIME: // Requires time on map <= x
res = (G_GetBestTime(levelnum) <= (unsigned)valToReach);
if (tag > 0)
{
if (tag > mapheaderinfo[checkLevel]->ghostCount
|| mapheaderinfo[checkLevel]->ghostBrief[tag-1] == NULL)
continue;
res = (G_GetBestTime(levelnum) <= mapheaderinfo[checkLevel]->ghostBrief[tag-1]->time);
}
else
{
res = (G_GetBestTime(levelnum) <= (unsigned)valToReach);
}
break;
default: // unreachable but shuts the compiler up.
continue;
@ -998,7 +1011,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
{
INT32 checkLevel;
if (emblemlocations[i].type < ET_TIME || gamedata->collected[i])
if (emblemlocations[i].type != ET_MAP || gamedata->collected[i])
continue;
checkLevel = M_EmblemMapNum(&emblemlocations[i]);

View file

@ -56,7 +56,7 @@ menuitem_t PLAY_TAReplay[] =
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
{IT_STRING | IT_CALL, "Replay Last", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0},
{IT_STRING | IT_CALL, "Replay Guest", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0},
{IT_STRING | IT_CALL, "Replay Staff", NULL, NULL, {.routine = M_HandleStaffReplay}, 0, 0},
{IT_STRING | IT_ARROWS, "Replay Staff", NULL, NULL, {.routine = M_HandleStaffReplay}, 0, 0},
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
{IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0},
@ -178,6 +178,7 @@ void M_PrepareTimeAttack(INT32 choice)
{
(void) choice;
// Gametype guess
if (levellist.guessgt != MAXGAMETYPES)
{
levellist.newgametype = levellist.guessgt;
@ -189,6 +190,10 @@ void M_PrepareTimeAttack(INT32 choice)
}
}
// Time-sticker Medals
G_UpdateTimeStickerMedals(levellist.choosemap, false);
// Menu options
{
// see also p_setup.c's P_LoadRecordGhosts
char *gpath = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1)));
@ -197,8 +202,6 @@ void M_PrepareTimeAttack(INT32 choice)
if (!gpath)
return;
CV_StealthSetValue(&cv_dummystaff, 0);
active = false;
PLAY_TimeAttack[ta_guest].status = IT_DISABLED;
PLAY_TimeAttack[ta_replay].status = IT_DISABLED;
@ -257,16 +260,13 @@ void M_PrepareTimeAttack(INT32 choice)
PLAY_TAReplay[tareplay_staff].status =
PLAY_TAGhosts[taghost_staff].status = IT_DISABLED;
#ifdef STAFFGHOSTS
CV_SetValue(&cv_dummystaff, 1);
if (cv_dummystaff.value)
if (mapheaderinfo[levellist.choosemap]->ghostCount > 0)
{
PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_KEYHANDLER;
PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_ARROWS;
PLAY_TAGhosts[taghost_staff].status = IT_STRING|IT_CVAR;
CV_StealthSetValue(&cv_dummystaff, 1);
CV_SetValue(&cv_dummystaff, 0);
active |= 1|4;
}
#endif //#ifdef STAFFGHOSTS
if (active & 1)
PLAY_TimeAttack[ta_replay].status = IT_STRING|IT_SUBMENU;
@ -287,8 +287,19 @@ void M_PrepareTimeAttack(INT32 choice)
void M_HandleStaffReplay(INT32 choice)
{
// @TODO:
(void) choice;
if (choice == 2)
{
restoreMenu = &PLAY_TimeAttackDef;
M_ClearMenus(true);
demo.loadfiles = false;
demo.ignorefiles = true; // Just assume that record attack replays have the files needed
G_DoPlayDemo(va("%s/GHOST_%u", mapheaderinfo[levellist.choosemap]->lumpname, cv_dummystaff.value+1));
return;
}
M_ChangeCvarDirect(choice, &cv_dummystaff);
}
void M_ReplayTimeAttack(INT32 choice)
@ -457,4 +468,6 @@ void M_StartTimeAttack(INT32 choice)
M_ClearMenus(true);
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false);
G_UpdateTimeStickerMedals(levellist.choosemap, true);
}

View file

@ -50,15 +50,13 @@ menu_t PAUSE_PlaybackMenuDef = {
void M_EndModeAttackRun(void)
{
boolean dotitle = demo.title;
G_CheckDemoStatus(); // Cancel recording
Command_ExitGame_f(); // Clear a bunch of state
modeattacking = ATTACKING_NONE; // Kept until now because of Command_ExitGame_f
if (dotitle)
if (demo.title == true)
{
D_StartTitle();
}
@ -210,7 +208,14 @@ void M_PlaybackSetViews(INT32 choice)
}
else if (r_splitscreen)
{
r_splitscreen--;
if (choice == 0)
{
r_splitscreen--;
}
else
{
r_splitscreen = 0;
}
R_ExecuteSetViewSize();
}
}

View file

@ -471,6 +471,7 @@ void P_AllocMapHeader(INT16 i)
mapheaderinfo[i]->lumpname = NULL;
mapheaderinfo[i]->thumbnailPic = NULL;
mapheaderinfo[i]->minimapPic = NULL;
mapheaderinfo[i]->ghostCount = 0;
mapheaderinfo[i]->cup = NULL;
mapheaderinfo[i]->mainrecord = NULL;
mapheaderinfo[i]->flickies = NULL;
@ -6909,8 +6910,6 @@ static boolean P_LoadMapFromFile(void)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(curmapvirt, &mapmd5);
vres_Free(curmapvirt);
return true;
}
@ -7139,6 +7138,23 @@ static void P_ResetSpawnpoints(void)
skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
}
static void P_TryAddExternalGhost(char *defdemoname)
{
UINT8 *buffer = NULL;
if (FIL_FileExists(defdemoname))
{
if (FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL))
{
G_AddGhost(buffer, defdemoname);
}
else
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname);
}
}
}
static void P_LoadRecordGhosts(void)
{
// see also /menus/play-local-race-time-attack.c's M_PrepareTimeAttack
@ -7157,8 +7173,7 @@ static void P_LoadRecordGhosts(void)
if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name));
P_TryAddExternalGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name));
}
}
}
@ -7173,8 +7188,7 @@ static void P_LoadRecordGhosts(void)
if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name));
P_TryAddExternalGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name));
}
}
}
@ -7187,29 +7201,35 @@ static void P_LoadRecordGhosts(void)
if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name));
P_TryAddExternalGhost(va("%s-%s-last.lmp", gpath, skins[i].name));
}
}
// Guest ghost
if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath)))
G_AddGhost(va("%s-guest.lmp", gpath));
if (cv_ghost_guest.value)
P_TryAddExternalGhost(va("%s-guest.lmp", gpath));
#ifdef STAFFGHOSTS
// Staff Attack ghosts
if (cv_ghost_staff.value)
{
lumpnum_t l;
UINT8 j = 1;
// TODO: Use vres for lumps
while (j <= 99 && (l = W_CheckNumForLongName(va("%sS%02u",G_BuildMapName(gamemap),j))) != LUMPERROR)
char *defdemoname;
virtlump_t *vLump;
UINT8 *buffer = NULL;
for (i = mapheaderinfo[gamemap-1]->ghostCount; i > 0; i--)
{
G_AddGhost(va("%sS%02u",G_BuildMapName(gamemap),j));
j++;
defdemoname = va("GHOST_%u", i);
vLump = vres_Find(curmapvirt, defdemoname);
if (vLump == NULL)
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read virtlump '%s'.\n"), defdemoname);
continue;
}
buffer = Z_Malloc(vLump->size, PU_LEVEL, NULL);
memcpy(buffer, vLump->data, vLump->size);
G_AddGhost(buffer, defdemoname);
}
}
#endif //#ifdef STAFFGHOSTS
Z_Free(gpath);
}
@ -7803,6 +7823,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (!fromnetsave)
P_InitGametype();
// Now safe to free.
vres_Free(curmapvirt);
curmapvirt = NULL;
if (!reloadinggamestate)
{
P_InitCamera();
@ -8020,11 +8044,13 @@ INT16 wadnamemap = 0; // gamemap based
UINT8 P_InitMapData(boolean existingmapheaders)
{
UINT8 ret = 0;
INT32 i;
INT32 i, j;
lumpnum_t maplump;
virtres_t *virtmap;
virtlump_t *minimap, *thumbnailPic;
virtlump_t *minimap, *thumbnailPic, *ghost;
char *name;
char buffer[9];
sprintf(buffer, "GHOST_x");
for (i = 0; i < nummapheaders; ++i)
{
@ -8036,7 +8062,6 @@ UINT8 P_InitMapData(boolean existingmapheaders)
if (maplump != LUMPERROR || mapheaderinfo[i]->lumpnum != LUMPERROR)
{
cupheader_t *cup = kartcupheaders;
INT32 j;
while (cup)
{
@ -8118,16 +8143,46 @@ UINT8 P_InitMapData(boolean existingmapheaders)
}
// Now apply the new ones!
if (thumbnailPic)
if (thumbnailPic != NULL)
{
mapheaderinfo[i]->thumbnailPic = vres_GetPatch(thumbnailPic, PU_STATIC);
}
if (minimap)
if (minimap != NULL)
{
mapheaderinfo[i]->minimapPic = vres_GetPatch(minimap, PU_STATIC);
}
// Staff ghosts.
// The trouble with staff ghosts is that they're too large to cache.
// So we store extra information about them, and load later.
while (mapheaderinfo[i]->ghostCount > 0)
{
mapheaderinfo[i]->ghostCount--;
Z_Free(mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount]);
mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount] = NULL;
}
while (mapheaderinfo[i]->ghostCount < MAXSTAFF)
{
buffer[6] = '1' + mapheaderinfo[i]->ghostCount;
ghost = vres_Find(virtmap, buffer);
if (ghost == NULL)
break;
mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount] = G_GetStaffGhostBrief(ghost->data);
if (mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount] == NULL)
break;
/*CONS_Printf("name is %s, time is %d, lap is %d\n",
mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount]->name,
mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount]->time/TICRATE,
mapheaderinfo[i]->ghostBrief[mapheaderinfo[i]->ghostCount]->lap/TICRATE);*/
mapheaderinfo[i]->ghostCount++;
}
vres_Free(virtmap);
}
}

View file

@ -766,7 +766,11 @@ void P_Ticker(boolean run)
}
if (modeattacking)
{
G_GhostTicker();
if (!demo.playback)
G_TickTimeStickerMedals();
}
if (mapreset > 1
&& --mapreset <= 1

View file

@ -1367,6 +1367,9 @@ void P_DoPlayerExit(player_t *player)
}
}
if (modeattacking)
G_UpdateRecords();
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
if (player == &players[consoleplayer])

View file

@ -1761,6 +1761,10 @@ UINT32 S_GetMusicLoopPoint(void)
boolean S_SetMusicPosition(UINT32 position)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return false;
return I_SetSongPosition(position);
}
@ -1962,7 +1966,13 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
UINT32 newpos = 0;
boolean mapmuschanged = false;
musicstack_t *result;
musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
musicstack_t *entry;
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return false;
entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
if (status)
result = S_GetMusicStackEntry(status, fromfirst, -1);
@ -2387,6 +2397,10 @@ void S_StopFadingMusic(void)
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return false;
if (source_volume < 0)
return I_FadeSong(target_volume, ms, NULL);
else
@ -2395,6 +2409,10 @@ boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 m
boolean S_FadeOutStopMusic(UINT32 ms)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return false;
return I_FadeSong(0, ms, &S_StopMusic);
}

View file

@ -113,6 +113,7 @@ TYPEDEF (textprompt_t);
TYPEDEF (mappoint_t);
TYPEDEF (customoption_t);
TYPEDEF (gametype_t);
TYPEDEF (staffbrief_t);
TYPEDEF (mapheader_t);
TYPEDEF (tolinfo_t);
TYPEDEF (cupheader_t);