G_AddGhost, G_LoadRecordGhosts: Re-add support for loading staff ghosts.

- UINT8 *buffer for AddGhost must now be allocated and filled externally.
- Introduce P_TryAddExternalGhost helper function for existing external ghosts.
- Call vRes_Free(curmapvirt) later, and NULL to make incorrect usage immediately obvious.
This commit is contained in:
toaster 2023-02-04 15:46:15 +00:00
parent 3e0ba74003
commit 59f9609160
3 changed files with 59 additions and 76 deletions

View file

@ -3030,7 +3030,7 @@ void G_DoPlayDemo(char *defdemoname)
mapnum = G_MapNumber(mapname);
if (mapnum >= nummapheaders || mapheaderinfo[mapnum]->lumpnum == LUMPERROR)
{
snprintf(msg, 1024, M_GetText("Failed to read lump '%s (couldn't find map %s)'.\n"), defdemoname, mapname);
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;
@ -3043,7 +3043,7 @@ void G_DoPlayDemo(char *defdemoname)
if (vLump == NULL)
{
snprintf(msg, 1024, M_GetText("Failed to read lump '%s (couldn't find lump %s in %s)'.\n"), defdemoname, pdemoname, mapname);
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;
@ -3480,14 +3480,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];
@ -3497,41 +3496,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
@ -3546,8 +3516,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;
}
@ -3558,16 +3527,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"
@ -3579,16 +3546,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;
}
@ -3600,8 +3565,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;
}
@ -3629,9 +3593,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;
}
@ -3642,9 +3605,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;
}
@ -3675,9 +3637,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;
}
@ -3744,8 +3705,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

View file

@ -184,7 +184,7 @@ 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_AddGhost(UINT8 *buffer, char *defdemoname);
staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer);
void G_FreeGhosts(void);
void G_DoneLevelLoad(void);

View file

@ -6908,8 +6908,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;
}
@ -7138,6 +7136,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
@ -7156,8 +7171,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));
}
}
}
@ -7172,8 +7186,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));
}
}
}
@ -7186,29 +7199,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);
}
@ -7802,6 +7821,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();