- 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.sc.MustGetNumber();

View file

@ -596,13 +596,17 @@ int GameMain()
void SetDefaultStrings()
{
// Duke 1.3 does not define its episodes through CON.
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.
volumeList[0].name = "$L.A. Meltdown";
volumeList[1].name = "$Lunar Apocalypse";
volumeList[2].name = "$Shrapnel City";
if (g_gameType & GAMEFLAG_SHAREWARE) volumeList[3].name = "$The Birth";
vol0->name = "$L.A. Meltdown";
vol1->name = "$Lunar Apocalypse";
vol2->name = "$Shrapnel City";
gSkillNames[0] = "$Piece of Cake";
gSkillNames[1] = "$Let's Rock";
gSkillNames[2] = "$Come get Some";
@ -1494,6 +1498,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, bcos, bcos)
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;
DEFINE_GLOBAL(multiplayer)
DEFINE_GLOBAL(netgame)
@ -1504,6 +1514,9 @@ DEFINE_GLOBAL(consoleplayer)
DEFINE_GLOBAL(currentLevel)
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, designerTime)
DEFINE_FIELD_X(MapRecord, MapRecord, fileName)
@ -1518,6 +1531,7 @@ DEFINE_FIELD_X(MapRecord, MapRecord, nextLevel)
DEFINE_FIELD_X(MapRecord, MapRecord, nextSecret)
//native readonly String messages[MAX_MESSAGES];
DEFINE_FIELD_X(MapRecord, MapRecord, Author)
DEFINE_FIELD_X(MapRecord, MapRecord, InterBackground)
DEFINE_FIELD_X(SummaryInfo, SummaryInfo, kills)
DEFINE_FIELD_X(SummaryInfo, SummaryInfo, maxkills)

View file

@ -47,7 +47,6 @@ GlobalCutscenes globalCutscenes;
TArray<ClusterDef> clusters;
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.
VolumeRecord volumeList[MAXVOLUMES];
MapRecord *currentLevel; // level that is currently played.
MapRecord* lastLevel; // Same here, for the last level.
@ -147,6 +146,33 @@ MapRecord *FindMapByLevelNum(int num)
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.
// if there's only one map with the given level number return that.
MapRecord* FindMapByClusterAndLevelNum(int cluster, int num)

View file

@ -9,11 +9,9 @@
#undef GetMessage // Windows strikes...
#endif
enum EMax
{
MAXSKILLS = 7,
MAXVOLUMES = 7,
MAXMENUGAMEPLAYENTRIES = 7,
};
@ -203,7 +201,6 @@ struct SummaryInfo
};
extern GlobalCutscenes globalCutscenes;
extern VolumeRecord volumeList[MAXVOLUMES];
extern MapRecord *currentLevel;
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* AllocateMap();
inline VolumeRecord* FindVolume(int index) { return nullptr; }
inline ClusterDef* FindCluster(int index) { return nullptr; }
inline ClusterDef* AllocateCluster() { return nullptr; }
inline VolumeRecord* AllocateVolume() { return nullptr; }
VolumeRecord* FindVolume(int index);
ClusterDef* FindCluster(int index);
ClusterDef* AllocateCluster();
VolumeRecord* AllocateVolume();
void SetLevelNum(MapRecord* info, int num);
inline VolumeRecord* MustFindVolume(int index)

View file

@ -117,11 +117,17 @@ bool M_SetSpecialMenu(FName& menu, int param)
case NAME_StartgameNoSkill:
menu = NAME_Startgame;
NewGameStartupInfo.Skill = param;
if (menu == NAME_StartgameNoSkill) NewGameStartupInfo.Episode = param;
if (menu == NAME_StartgameNoSkill)
{
NewGameStartupInfo.Episode = param;
NewGameStartupInfo.Skill = 1;
}
if (gi->StartGame(NewGameStartupInfo))
{
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();
}
return false;
@ -365,6 +371,7 @@ static DMenuItemBase* CreateCustomListMenuItemText(double x, double y, int heigh
// Creates the episode menu
//
//=============================================================================
extern TArray<VolumeRecord> volumes;
static void BuildEpisodeMenu()
{
@ -385,15 +392,14 @@ static void BuildEpisodeMenu()
ld->mSelectedItem = gDefaultVolume + ld->mItems.Size(); // account for pre-added items
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))
{
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],
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;
ld->mItems.Push(it);
@ -401,7 +407,7 @@ static void BuildEpisodeMenu()
if (vol.subtitle.IsNotEmpty())
{
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;
ld->mItems.Push(it);
textadded = true;

View file

@ -109,20 +109,21 @@ void parseDefineCutscene(FScanner& sc, FScriptPosition& pos)
{
FScanner::SavedPos eblockend;
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);
return;
}
int vol = sc.Number - 1;
int vol = sc.Number;
if (sc.StartBraces(&eblockend)) return;
while (!sc.FoundEndBrace(eblockend))
{
sc.MustGetString();
if (sc.Compare("intro")) parseCutscene(sc, volumeList[vol].intro);
else if (sc.Compare("outro")) parseCutscene(sc, volumeList[vol].outro);
else if (sc.Compare("flags")) sc.GetNumber(volumeList[vol].flags);
auto volume = MustFindVolume(vol);
if (sc.Compare("intro")) parseCutscene(sc, volume->intro);
else if (sc.Compare("outro")) parseCutscene(sc, volume->outro);
else if (sc.Compare("flags")) sc.GetNumber(volume->flags);
}
}
else if (sc.Compare("map"))

View file

@ -461,18 +461,10 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
GC::WriteBarrier(runner);
// retrieve cluster relations for cluster-based cutscenes.
int fromcluster = -1, tocluster = -1;
if (fromMap)
{
fromcluster = fromMap->cluster - 1;
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;
ClusterDef* fromcluster = nullptr, *tocluster = nullptr;
if (fromMap) fromcluster = FindCluster(fromMap->cluster);
if (toMap) tocluster = FindCluster(toMap->cluster);
if (fromcluster == tocluster) fromcluster = tocluster = nullptr;
try
@ -481,7 +473,7 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
{
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);
}
@ -493,7 +485,7 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
{
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.LoadingScreen.Create(runner, toMap, true);

View file

@ -240,7 +240,9 @@ void DBaseStatusBar::PrintAutomapInfo(FLevelStats& stats, bool forcetextfont)
{
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;
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());
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))
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);
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.sound = soundEngine->FindSoundByResID(BloodINI->GetKeyInt(buffer, "CutWavB", -1) + 0x40000000);
@ -181,14 +184,15 @@ void levelLoadDefaults(void)
int j;
for (j = 0; j < kMaxLevels; j++)
{
sprintf(buffer2, "Map%d", j+1);
sprintf(buffer2, "Map%d", j);
if (!BloodINI->KeyExists(buffer, buffer2))
break;
auto pLevelInfo = AllocateMap();
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
CheckSectionAbend(pMap);
pLevelInfo->levelNumber = makelevelnum(i, j);
pLevelInfo->cluster = i + 1;
SetLevelNum(pLevelInfo, makelevelnum(i, j));
pLevelInfo->cluster = i;
pLevelInfo->mapindex = j;
pLevelInfo->labelName = pMap;
pLevelInfo->fileName.Format("%s.map", pMap);
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j);

View file

@ -1644,6 +1644,7 @@ int ConCompiler::parsecommand()
return 0;
case concmd_definevolumename:
{
popscriptvalue();
transnum(LABEL_DEFINE);
j = popscriptvalue();
@ -1658,8 +1659,13 @@ int ConCompiler::parsecommand()
textptr++, i++;
}
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;
}
case concmd_defineskillname:
popscriptvalue();
transnum(LABEL_DEFINE);
@ -1699,6 +1705,11 @@ int ConCompiler::parsecommand()
auto map = FindMapByLevelNum(levnum);
if (!map) map = AllocateMap();
map->SetFileName(parsebuffer.Data());
if (k == 0)
{
auto vol = MustFindVolume(j);
vol->startmap = map->labelName;
}
while (*textptr == ' ' || *textptr == '\t') textptr++;
@ -3177,6 +3188,12 @@ void loadcons()
ScriptCode.Push(0);
ConCompiler comp;
if (fileSystem.FileExists("engine/engine.con"))
{
comp.compilecon("engine/engine.con");
}
comp.compilecon(ConFile()); //Tokenize
if (userConfig.AddCons) for (FString& m : *userConfig.AddCons.get())

View file

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

View file

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