From 825963661b042dc79e479b1260a1fa02b00facc4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 May 2021 00:35:56 +0200 Subject: [PATCH] - migrated volumes to the new storage. --- source/core/g_mapinfo.cpp | 2 +- source/core/gamecontrol.cpp | 22 ++++++++++++++++++---- source/core/mapinfo.cpp | 28 +++++++++++++++++++++++++++- source/core/mapinfo.h | 11 ++++------- source/core/menu/razemenu.cpp | 22 ++++++++++++++-------- source/core/parsefuncs.h | 11 ++++++----- source/core/screenjob.cpp | 20 ++++++-------------- source/core/statusbar2.cpp | 4 +++- source/games/blood/src/levels.cpp | 18 +++++++++++------- source/games/duke/src/gamedef.cpp | 19 ++++++++++++++++++- source/games/sw/src/scrip2.cpp | 10 ++++++++-- wadsrc/static/zscript/razebase.zs | 10 +++++++++- 12 files changed, 125 insertions(+), 52 deletions(-) diff --git a/source/core/g_mapinfo.cpp b/source/core/g_mapinfo.cpp index ef185b236..4100540f7 100644 --- a/source/core/g_mapinfo.cpp +++ b/source/core/g_mapinfo.cpp @@ -372,7 +372,7 @@ DEFINE_MAP_OPTION(clear, true) } -DEFINE_MAP_OPTION(makelevelnum, true) +DEFINE_MAP_OPTION(levelnum, true) { parse.ParseAssign(); parse.sc.MustGetNumber(); diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index cae95b7e5..01d630e8a 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -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) diff --git a/source/core/mapinfo.cpp b/source/core/mapinfo.cpp index cc6f78daf..74ed92fe2 100644 --- a/source/core/mapinfo.cpp +++ b/source/core/mapinfo.cpp @@ -47,7 +47,6 @@ GlobalCutscenes globalCutscenes; TArray clusters; TArray volumes; TArray> 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) diff --git a/source/core/mapinfo.h b/source/core/mapinfo.h index 2d26a290e..67d560f32 100644 --- a/source/core/mapinfo.h +++ b/source/core/mapinfo.h @@ -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) diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 5df1055cc..0e3416d47 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -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 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; diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 175fabb10..ef844c2d9 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -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")) diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 439ccd801..9771ce3a6 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -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); diff --git a/source/core/statusbar2.cpp b/source/core/statusbar2.cpp index a4b9f68e8..cce7f8f90 100644 --- a/source/core/statusbar2.cpp +++ b/source/core/statusbar2.cpp @@ -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, diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index d987a8c44..48195b93d 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -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); diff --git a/source/games/duke/src/gamedef.cpp b/source/games/duke/src/gamedef.cpp index e7943e640..f61e1cee4 100644 --- a/source/games/duke/src/gamedef.cpp +++ b/source/games/duke/src/gamedef.cpp @@ -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()) diff --git a/source/games/sw/src/scrip2.cpp b/source/games/sw/src/scrip2.cpp index d5302df48..8e6759179 100644 --- a/source/games/sw/src/scrip2.cpp +++ b/source/games/sw/src/scrip2.cpp @@ -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: diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index 70a05d590..2e6129596 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -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