- migrated volumes to the new storage.

This commit is contained in:
Christoph Oelckers 2021-05-02 00:35:56 +02:00
parent 03b9275244
commit 825963661b
12 changed files with 125 additions and 52 deletions

View file

@ -372,7 +372,7 @@ DEFINE_MAP_OPTION(clear, true)
} }
DEFINE_MAP_OPTION(makelevelnum, true) DEFINE_MAP_OPTION(levelnum, true)
{ {
parse.ParseAssign(); parse.ParseAssign();
parse.sc.MustGetNumber(); parse.sc.MustGetNumber();

View file

@ -596,13 +596,17 @@ int GameMain()
void SetDefaultStrings() void SetDefaultStrings()
{ {
// Duke 1.3 does not define its episodes through CON.
if ((g_gameType & GAMEFLAG_DUKE) && fileSystem.FindFile("E4L1.MAP") < 0) if ((g_gameType & GAMEFLAG_DUKE) && fileSystem.FindFile("E4L1.MAP") < 0)
{ {
auto vol0 = AllocateVolume(); vol0->index = 0;
auto vol1 = AllocateVolume(); vol1->index = 1; vol1->flags = VF_SHAREWARELOCK;
auto vol2 = AllocateVolume(); vol2->index = 2; vol1->flags = VF_SHAREWARELOCK;
// Pre-Atomic releases do not define this. // Pre-Atomic releases do not define this.
volumeList[0].name = "$L.A. Meltdown"; vol0->name = "$L.A. Meltdown";
volumeList[1].name = "$Lunar Apocalypse"; vol1->name = "$Lunar Apocalypse";
volumeList[2].name = "$Shrapnel City"; vol2->name = "$Shrapnel City";
if (g_gameType & GAMEFLAG_SHAREWARE) volumeList[3].name = "$The Birth";
gSkillNames[0] = "$Piece of Cake"; gSkillNames[0] = "$Piece of Cake";
gSkillNames[1] = "$Let's Rock"; gSkillNames[1] = "$Let's Rock";
gSkillNames[2] = "$Come get Some"; gSkillNames[2] = "$Come get Some";
@ -1494,6 +1498,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, bcos, bcos)
ACTION_RETURN_INT(bcos(v, shift)); ACTION_RETURN_INT(bcos(v, shift));
} }
DEFINE_ACTION_FUNCTION(_MapRecord, GetCluster)
{
PARAM_SELF_STRUCT_PROLOGUE(MapRecord);
ACTION_RETURN_POINTER(FindCluster(self->cluster));
}
extern bool demoplayback; extern bool demoplayback;
DEFINE_GLOBAL(multiplayer) DEFINE_GLOBAL(multiplayer)
DEFINE_GLOBAL(netgame) DEFINE_GLOBAL(netgame)
@ -1504,6 +1514,9 @@ DEFINE_GLOBAL(consoleplayer)
DEFINE_GLOBAL(currentLevel) DEFINE_GLOBAL(currentLevel)
DEFINE_GLOBAL(paused) DEFINE_GLOBAL(paused)
DEFINE_FIELD_X(ClusterDef, ClusterDef, name)
DEFINE_FIELD_X(ClusterDef, ClusterDef, InterBackground)
DEFINE_FIELD_X(MapRecord, MapRecord, parTime) DEFINE_FIELD_X(MapRecord, MapRecord, parTime)
DEFINE_FIELD_X(MapRecord, MapRecord, designerTime) DEFINE_FIELD_X(MapRecord, MapRecord, designerTime)
DEFINE_FIELD_X(MapRecord, MapRecord, fileName) DEFINE_FIELD_X(MapRecord, MapRecord, fileName)
@ -1518,6 +1531,7 @@ DEFINE_FIELD_X(MapRecord, MapRecord, nextLevel)
DEFINE_FIELD_X(MapRecord, MapRecord, nextSecret) DEFINE_FIELD_X(MapRecord, MapRecord, nextSecret)
//native readonly String messages[MAX_MESSAGES]; //native readonly String messages[MAX_MESSAGES];
DEFINE_FIELD_X(MapRecord, MapRecord, Author) DEFINE_FIELD_X(MapRecord, MapRecord, Author)
DEFINE_FIELD_X(MapRecord, MapRecord, InterBackground)
DEFINE_FIELD_X(SummaryInfo, SummaryInfo, kills) DEFINE_FIELD_X(SummaryInfo, SummaryInfo, kills)
DEFINE_FIELD_X(SummaryInfo, SummaryInfo, maxkills) DEFINE_FIELD_X(SummaryInfo, SummaryInfo, maxkills)

View file

@ -47,7 +47,6 @@ GlobalCutscenes globalCutscenes;
TArray<ClusterDef> clusters; TArray<ClusterDef> clusters;
TArray<VolumeRecord> volumes; TArray<VolumeRecord> volumes;
TArray<TPointer<MapRecord>> mapList; // must be allocated as pointers because it can whack the currentlLevel pointer if this was a flat array. TArray<TPointer<MapRecord>> mapList; // must be allocated as pointers because it can whack the currentlLevel pointer if this was a flat array.
VolumeRecord volumeList[MAXVOLUMES];
MapRecord *currentLevel; // level that is currently played. MapRecord *currentLevel; // level that is currently played.
MapRecord* lastLevel; // Same here, for the last level. MapRecord* lastLevel; // Same here, for the last level.
@ -147,6 +146,33 @@ MapRecord *FindMapByLevelNum(int num)
return nullptr; return nullptr;
} }
VolumeRecord* FindVolume(int index)
{
for (auto& vol : volumes)
{
if (vol.index == index) return &vol;
}
return nullptr;
}
ClusterDef* FindCluster(int index)
{
for (auto& vol : clusters)
{
if (vol.index == index) return &vol;
}
return nullptr;
}
ClusterDef* AllocateCluster()
{
return &clusters[clusters.Reserve(1)];
}
VolumeRecord* AllocateVolume()
{
return &volumes[volumes.Reserve(1)];
}
// return a map whose cluster and map number matches. // return a map whose cluster and map number matches.
// if there's only one map with the given level number return that. // if there's only one map with the given level number return that.
MapRecord* FindMapByClusterAndLevelNum(int cluster, int num) MapRecord* FindMapByClusterAndLevelNum(int cluster, int num)

View file

@ -9,11 +9,9 @@
#undef GetMessage // Windows strikes... #undef GetMessage // Windows strikes...
#endif #endif
enum EMax enum EMax
{ {
MAXSKILLS = 7, MAXSKILLS = 7,
MAXVOLUMES = 7,
MAXMENUGAMEPLAYENTRIES = 7, MAXMENUGAMEPLAYENTRIES = 7,
}; };
@ -203,7 +201,6 @@ struct SummaryInfo
}; };
extern GlobalCutscenes globalCutscenes; extern GlobalCutscenes globalCutscenes;
extern VolumeRecord volumeList[MAXVOLUMES];
extern MapRecord *currentLevel; extern MapRecord *currentLevel;
bool SetMusicForMap(const char* mapname, const char* music, bool namehack = false); bool SetMusicForMap(const char* mapname, const char* music, bool namehack = false);
@ -216,10 +213,10 @@ MapRecord *FindNextMap(MapRecord *thismap);
MapRecord* SetupUserMap(const char* boardfilename, const char *defaultmusic = nullptr); MapRecord* SetupUserMap(const char* boardfilename, const char *defaultmusic = nullptr);
MapRecord* AllocateMap(); MapRecord* AllocateMap();
inline VolumeRecord* FindVolume(int index) { return nullptr; } VolumeRecord* FindVolume(int index);
inline ClusterDef* FindCluster(int index) { return nullptr; } ClusterDef* FindCluster(int index);
inline ClusterDef* AllocateCluster() { return nullptr; } ClusterDef* AllocateCluster();
inline VolumeRecord* AllocateVolume() { return nullptr; } VolumeRecord* AllocateVolume();
void SetLevelNum(MapRecord* info, int num); void SetLevelNum(MapRecord* info, int num);
inline VolumeRecord* MustFindVolume(int index) inline VolumeRecord* MustFindVolume(int index)

View file

@ -117,11 +117,17 @@ bool M_SetSpecialMenu(FName& menu, int param)
case NAME_StartgameNoSkill: case NAME_StartgameNoSkill:
menu = NAME_Startgame; menu = NAME_Startgame;
NewGameStartupInfo.Skill = param; NewGameStartupInfo.Skill = param;
if (menu == NAME_StartgameNoSkill) NewGameStartupInfo.Episode = param; if (menu == NAME_StartgameNoSkill)
{
NewGameStartupInfo.Episode = param;
NewGameStartupInfo.Skill = 1;
}
if (gi->StartGame(NewGameStartupInfo)) if (gi->StartGame(NewGameStartupInfo))
{ {
M_ClearMenus(); M_ClearMenus();
STAT_StartNewGame(volumeList[NewGameStartupInfo.Episode].name, NewGameStartupInfo.Skill); int ep = NewGameStartupInfo.Episode;
auto vol = FindVolume(ep);
if (vol) STAT_StartNewGame(vol->name, NewGameStartupInfo.Skill);
inputState.ClearAllInput(); inputState.ClearAllInput();
} }
return false; return false;
@ -365,6 +371,7 @@ static DMenuItemBase* CreateCustomListMenuItemText(double x, double y, int heigh
// Creates the episode menu // Creates the episode menu
// //
//============================================================================= //=============================================================================
extern TArray<VolumeRecord> volumes;
static void BuildEpisodeMenu() static void BuildEpisodeMenu()
{ {
@ -385,15 +392,14 @@ static void BuildEpisodeMenu()
ld->mSelectedItem = gDefaultVolume + ld->mItems.Size(); // account for pre-added items ld->mSelectedItem = gDefaultVolume + ld->mItems.Size(); // account for pre-added items
int y = ld->mYpos; int y = ld->mYpos;
for (int i = 0; i < MAXVOLUMES; i++) // Volume definitions should be sorted by intended menu order.
for (auto &vol : volumes)
{ {
auto& vol = volumeList[i];
if (vol.name.IsNotEmpty() && !(vol.flags & VF_HIDEFROMSP)) if (vol.name.IsNotEmpty() && !(vol.flags & VF_HIDEFROMSP))
{ {
int isShareware = ((g_gameType & GAMEFLAG_DUKE) && (g_gameType & GAMEFLAG_SHAREWARE) && i > 0); int isShareware = ((g_gameType & GAMEFLAG_DUKE) && (g_gameType & GAMEFLAG_SHAREWARE) && (vol.flags & VF_SHAREWARELOCK));
auto it = CreateCustomListMenuItemText(ld->mXpos, y, ld->mLinespacing, vol.name[0], auto it = CreateCustomListMenuItemText(ld->mXpos, y, ld->mLinespacing, vol.name[0],
vol.name, ld->mFont, CR_UNTRANSLATED, isShareware, NAME_Skillmenu, i); // font colors are not used, so hijack one for the shareware flag. vol.name, ld->mFont, CR_UNTRANSLATED, isShareware, NAME_Skillmenu, vol.index); // font colors are not used, so hijack one for the shareware flag.
y += ld->mLinespacing; y += ld->mLinespacing;
ld->mItems.Push(it); ld->mItems.Push(it);
@ -401,7 +407,7 @@ static void BuildEpisodeMenu()
if (vol.subtitle.IsNotEmpty()) if (vol.subtitle.IsNotEmpty())
{ {
auto it = CreateCustomListMenuItemText(ld->mXpos, y, ld->mLinespacing * 6 / 10, 1, auto it = CreateCustomListMenuItemText(ld->mXpos, y, ld->mLinespacing * 6 / 10, 1,
vol.subtitle, SmallFont, CR_GRAY, false, NAME_None, i); vol.subtitle, SmallFont, CR_GRAY, false, NAME_None, vol.index);
y += ld->mLinespacing * 6 / 10; y += ld->mLinespacing * 6 / 10;
ld->mItems.Push(it); ld->mItems.Push(it);
textadded = true; textadded = true;

View file

@ -109,20 +109,21 @@ void parseDefineCutscene(FScanner& sc, FScriptPosition& pos)
{ {
FScanner::SavedPos eblockend; FScanner::SavedPos eblockend;
sc.MustGetNumber(); sc.MustGetNumber();
if (sc.Number < 1 || sc.Number > MAXVOLUMES) if (sc.Number < 1)
{ {
sc.ScriptError("episode number %d out of range. Must be positive", sc.Number); sc.ScriptError("episode number %d out of range. Must be positive", sc.Number);
return; return;
} }
int vol = sc.Number - 1; int vol = sc.Number;
if (sc.StartBraces(&eblockend)) return; if (sc.StartBraces(&eblockend)) return;
while (!sc.FoundEndBrace(eblockend)) while (!sc.FoundEndBrace(eblockend))
{ {
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("intro")) parseCutscene(sc, volumeList[vol].intro); auto volume = MustFindVolume(vol);
else if (sc.Compare("outro")) parseCutscene(sc, volumeList[vol].outro); if (sc.Compare("intro")) parseCutscene(sc, volume->intro);
else if (sc.Compare("flags")) sc.GetNumber(volumeList[vol].flags); else if (sc.Compare("outro")) parseCutscene(sc, volume->outro);
else if (sc.Compare("flags")) sc.GetNumber(volume->flags);
} }
} }
else if (sc.Compare("map")) else if (sc.Compare("map"))

View file

@ -461,18 +461,10 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
GC::WriteBarrier(runner); GC::WriteBarrier(runner);
// retrieve cluster relations for cluster-based cutscenes. // retrieve cluster relations for cluster-based cutscenes.
int fromcluster = -1, tocluster = -1; ClusterDef* fromcluster = nullptr, *tocluster = nullptr;
if (fromMap) if (fromMap) fromcluster = FindCluster(fromMap->cluster);
{ if (toMap) tocluster = FindCluster(toMap->cluster);
fromcluster = fromMap->cluster - 1; if (fromcluster == tocluster) fromcluster = tocluster = nullptr;
if (fromcluster < 0 || fromcluster >= MAXVOLUMES) fromcluster = -1;
}
if (toMap)
{
tocluster = toMap->cluster - 1;
if (tocluster < 0 || tocluster >= MAXVOLUMES) tocluster = -1;
}
if (fromcluster == tocluster) fromcluster = tocluster = -1;
try try
@ -481,7 +473,7 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
{ {
if (!fromMap->outro.Create(runner, fromMap, !!toMap)) if (!fromMap->outro.Create(runner, fromMap, !!toMap))
{ {
if (fromcluster != -1 && !volumeList[fromcluster].outro.Create(runner, fromMap, !!toMap)) if (fromcluster != nullptr && !fromcluster->outro.Create(runner, fromMap, !!toMap))
globalCutscenes.DefaultMapOutro.Create(runner, fromMap, !!toMap); globalCutscenes.DefaultMapOutro.Create(runner, fromMap, !!toMap);
} }
@ -493,7 +485,7 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
{ {
if (!toMap->intro.Create(runner, toMap, !!fromMap)) if (!toMap->intro.Create(runner, toMap, !!fromMap))
{ {
if (tocluster != -1 && !volumeList[tocluster].intro.Create(runner, toMap, !!fromMap)) if (tocluster != nullptr && !tocluster->intro.Create(runner, toMap, !!fromMap))
globalCutscenes.DefaultMapIntro.Create(runner, toMap, !!fromMap); globalCutscenes.DefaultMapIntro.Create(runner, toMap, !!fromMap);
} }
globalCutscenes.LoadingScreen.Create(runner, toMap, true); globalCutscenes.LoadingScreen.Create(runner, toMap, true);

View file

@ -240,7 +240,9 @@ void DBaseStatusBar::PrintAutomapInfo(FLevelStats& stats, bool forcetextfont)
{ {
y = 200 - stats.screenbottomspace - spacing; y = 200 - stats.screenbottomspace - spacing;
} }
const auto &volname = volumeList[volfromlevelnum(lev->levelNumber)].name; auto cluster = FindCluster(lev->cluster);
FString volname;
if (cluster) volname = cluster->name;
if (volname.IsEmpty() && am_nameontop) y = 1; if (volname.IsEmpty() && am_nameontop) y = 1;
DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, mapname, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, mapname, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,

View file

@ -160,14 +160,17 @@ void levelLoadDefaults(void)
levelInitINI(DefFile()); levelInitINI(DefFile());
int i; int i;
for (i = 0; i < kMaxEpisodes; i++) for (i = 1; i <= kMaxEpisodes; i++)
{ {
sprintf(buffer, "Episode%d", i+1); sprintf(buffer, "Episode%d", i);
if (!BloodINI->SectionExists(buffer)) if (!BloodINI->SectionExists(buffer))
break; break;
CutsceneDef &csB = volumeList[i].outro; auto cluster = MustFindCluster(i);
auto volume = MustFindVolume(i);
CutsceneDef &csB = cluster->outro;
auto ep_str = BloodINI->GetKeyString(buffer, "Title", buffer); auto ep_str = BloodINI->GetKeyString(buffer, "Title", buffer);
volumeList[i].name = ep_str; cluster->name = volume->name = ep_str;
if (i > 1) volume->flags |= VF_SHAREWARELOCK;
csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", "")); csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", ""));
csB.sound = soundEngine->FindSoundByResID(BloodINI->GetKeyInt(buffer, "CutWavB", -1) + 0x40000000); csB.sound = soundEngine->FindSoundByResID(BloodINI->GetKeyInt(buffer, "CutWavB", -1) + 0x40000000);
@ -181,14 +184,15 @@ void levelLoadDefaults(void)
int j; int j;
for (j = 0; j < kMaxLevels; j++) for (j = 0; j < kMaxLevels; j++)
{ {
sprintf(buffer2, "Map%d", j+1); sprintf(buffer2, "Map%d", j);
if (!BloodINI->KeyExists(buffer, buffer2)) if (!BloodINI->KeyExists(buffer, buffer2))
break; break;
auto pLevelInfo = AllocateMap(); auto pLevelInfo = AllocateMap();
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL); const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
CheckSectionAbend(pMap); CheckSectionAbend(pMap);
pLevelInfo->levelNumber = makelevelnum(i, j); SetLevelNum(pLevelInfo, makelevelnum(i, j));
pLevelInfo->cluster = i + 1; pLevelInfo->cluster = i;
pLevelInfo->mapindex = j;
pLevelInfo->labelName = pMap; pLevelInfo->labelName = pMap;
pLevelInfo->fileName.Format("%s.map", pMap); pLevelInfo->fileName.Format("%s.map", pMap);
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j); levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j);

View file

@ -1644,6 +1644,7 @@ int ConCompiler::parsecommand()
return 0; return 0;
case concmd_definevolumename: case concmd_definevolumename:
{
popscriptvalue(); popscriptvalue();
transnum(LABEL_DEFINE); transnum(LABEL_DEFINE);
j = popscriptvalue(); j = popscriptvalue();
@ -1658,8 +1659,13 @@ int ConCompiler::parsecommand()
textptr++, i++; textptr++, i++;
} }
parsebuffer.Push(0); parsebuffer.Push(0);
volumeList[j].name = FStringTable::MakeMacro(parsebuffer.Data(), i); // We need both a volume and a cluster for this new episode.
auto vol = MustFindVolume(j);
auto clust = MustFindCluster(j + 1);
vol->name = clust->name = FStringTable::MakeMacro(parsebuffer.Data(), i);
if (j > 0) vol->flags |= VF_SHAREWARELOCK;
return 0; return 0;
}
case concmd_defineskillname: case concmd_defineskillname:
popscriptvalue(); popscriptvalue();
transnum(LABEL_DEFINE); transnum(LABEL_DEFINE);
@ -1699,6 +1705,11 @@ int ConCompiler::parsecommand()
auto map = FindMapByLevelNum(levnum); auto map = FindMapByLevelNum(levnum);
if (!map) map = AllocateMap(); if (!map) map = AllocateMap();
map->SetFileName(parsebuffer.Data()); map->SetFileName(parsebuffer.Data());
if (k == 0)
{
auto vol = MustFindVolume(j);
vol->startmap = map->labelName;
}
while (*textptr == ' ' || *textptr == '\t') textptr++; while (*textptr == ' ' || *textptr == '\t') textptr++;
@ -3177,6 +3188,12 @@ void loadcons()
ScriptCode.Push(0); ScriptCode.Push(0);
ConCompiler comp; ConCompiler comp;
if (fileSystem.FileExists("engine/engine.con"))
{
comp.compilecon("engine/engine.con");
}
comp.compilecon(ConFile()); //Tokenize comp.compilecon(ConFile()); //Tokenize
if (userConfig.AddCons) for (FString& m : *userConfig.AddCons.get()) if (userConfig.AddCons) for (FString& m : *userConfig.AddCons.get())

View file

@ -524,13 +524,19 @@ void LoadCustomInfoFromScript(const char *filename)
case CM_TITLE: case CM_TITLE:
{ {
sc.MustGetString(); sc.MustGetString();
if (curep != -1) volumeList[curep].name = sc.String; auto vol = MustFindVolume(curep);
auto clust = MustFindCluster(curep);
vol->name = clust->name = sc.String;
break; break;
} }
case CM_SUBTITLE: case CM_SUBTITLE:
{ {
sc.MustGetString(); sc.MustGetString();
if (curep != -1) volumeList[curep].subtitle = sc.String; if (curep != -1)
{
auto vol = MustFindVolume(curep);
vol->subtitle = sc.String;
}
break; break;
} }
default: default:

View file

@ -65,7 +65,7 @@ struct MapRecord native
native readonly int flags; native readonly int flags;
native readonly int levelNumber; native readonly int levelNumber;
native readonly int cluster; native readonly int cluster;
native readonly String InterBackground;
// The rest is only used by Blood // The rest is only used by Blood
native readonly int nextLevel; native readonly int nextLevel;
native readonly int nextSecret; native readonly int nextSecret;
@ -82,6 +82,14 @@ struct MapRecord native
if (name == "") return labelName; if (name == "") return labelName;
return name; return name;
} }
native ClusterDef GetCluster();
}
struct ClusterDef
{
native readonly String name;
native readonly String InterBackground;
} }
struct SummaryInfo native struct SummaryInfo native