- transitioned Blood to the common mapinfo system.

This commit is contained in:
Christoph Oelckers 2019-12-11 00:57:53 +01:00
parent cc33c6a0ed
commit 5c0cd5114d
11 changed files with 75 additions and 87 deletions

View file

@ -542,6 +542,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
return; return;
} }
char levelName[BMAX_PATH]; char levelName[BMAX_PATH];
currentLevel = &mapList[gGameOptions.nEpisode * kMaxLevels + gGameOptions.nLevel];
STAT_NewLevel(gameOptions->zLevelName); STAT_NewLevel(gameOptions->zLevelName);
G_LoadMapHack(levelName, gameOptions->zLevelName); G_LoadMapHack(levelName, gameOptions->zLevelName);
wsrand(gameOptions->uMapCRC); wsrand(gameOptions->uMapCRC);
@ -1444,9 +1445,8 @@ static int32_t S_DefineMusic(const char *ID, const char *name)
return -1; return -1;
} }
int nEpisode = sel/kMaxLevels; quoteMgr.InitializeQuote(sel, name);
int nLevel = sel%kMaxLevels; return 0;
return S_DefineAudioIfSupported(gEpisodeInfo[nEpisode].at28[nLevel].atd0, name);
} }
static int parsedefinitions_game(scriptfile *, int); static int parsedefinitions_game(scriptfile *, int);
@ -1988,9 +1988,7 @@ bool fileExistsRFF(int id, const char *ext) {
int sndTryPlaySpecialMusic(int nMusic) int sndTryPlaySpecialMusic(int nMusic)
{ {
int nEpisode = nMusic/kMaxLevels; if (Mus_Play(nullptr, quoteMgr.GetQuote(nMusic), true))
int nLevel = nMusic%kMaxLevels;
if (Mus_Play(gEpisodeInfo[nEpisode].at28[nLevel].at0, gEpisodeInfo[nEpisode].at28[nLevel].atd0, true))
{ {
return 0; return 0;
} }

View file

@ -146,48 +146,48 @@ void CheckKeyAbend(const char *pzSection, const char *pzKey)
ThrowError("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection); ThrowError("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection);
} }
LEVELINFO * levelGetInfoPtr(int nEpisode, int nLevel) MapRecord * levelGetInfoPtr(int nEpisode, int nLevel)
{ {
dassert(nEpisode >= 0 && nEpisode < gEpisodeCount); dassert(nEpisode >= 0 && nEpisode < gEpisodeCount);
EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode]; EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode];
dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels); dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels);
return &pEpisodeInfo->at28[nLevel]; return &pEpisodeInfo->levels[nLevel];
} }
char * levelGetFilename(int nEpisode, int nLevel) const char * levelGetFilename(int nEpisode, int nLevel)
{ {
dassert(nEpisode >= 0 && nEpisode < gEpisodeCount); dassert(nEpisode >= 0 && nEpisode < gEpisodeCount);
EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode]; EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode];
dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels); dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels);
return pEpisodeInfo->at28[nLevel].at0; return pEpisodeInfo->levels[nLevel].labelName;
} }
char * levelGetMessage(int nMessage) const char * levelGetMessage(int nMessage)
{ {
int nEpisode = gGameOptions.nEpisode; int nEpisode = gGameOptions.nEpisode;
int nLevel = gGameOptions.nLevel; int nLevel = gGameOptions.nLevel;
dassert(nMessage < kMaxMessages); dassert(nMessage < kMaxMessages);
char *pMessage = gEpisodeInfo[nEpisode].at28[nLevel].atec[nMessage]; const char *pMessage = gEpisodeInfo[nEpisode].levels[nLevel].GetMessage(nMessage);
if (*pMessage == 0) if (*pMessage == 0)
return NULL; return NULL;
return pMessage; return pMessage;
} }
char * levelGetTitle(void) const char * levelGetTitle(void)
{ {
int nEpisode = gGameOptions.nEpisode; int nEpisode = gGameOptions.nEpisode;
int nLevel = gGameOptions.nLevel; int nLevel = gGameOptions.nLevel;
char *pTitle = gEpisodeInfo[nEpisode].at28[nLevel].at90; const char *pTitle = gEpisodeInfo[nEpisode].levels[nLevel].DisplayName();
if (*pTitle == 0) if (*pTitle == 0)
return NULL; return NULL;
return pTitle; return pTitle;
} }
char * levelGetAuthor(void) const char * levelGetAuthor(void)
{ {
int nEpisode = gGameOptions.nEpisode; int nEpisode = gGameOptions.nEpisode;
int nLevel = gGameOptions.nLevel; int nLevel = gGameOptions.nLevel;
char *pAuthor = gEpisodeInfo[nEpisode].at28[nLevel].atb0; const char *pAuthor = gEpisodeInfo[nEpisode].levels[nLevel].author;
if (*pAuthor == 0) if (*pAuthor == 0)
return NULL; return NULL;
return pAuthor; return pAuthor;
@ -197,26 +197,27 @@ void levelSetupOptions(int nEpisode, int nLevel)
{ {
gGameOptions.nEpisode = nEpisode; gGameOptions.nEpisode = nEpisode;
gGameOptions.nLevel = nLevel; gGameOptions.nLevel = nLevel;
strcpy(gGameOptions.zLevelName, gEpisodeInfo[nEpisode].at28[nLevel].at0); strcpy(gGameOptions.zLevelName, gEpisodeInfo[nEpisode].levels[nLevel].labelName);
gGameOptions.uMapCRC = dbReadMapCRC(gGameOptions.zLevelName); gGameOptions.uMapCRC = dbReadMapCRC(gGameOptions.zLevelName);
gGameOptions.nTrackNumber = gEpisodeInfo[nEpisode].at28[nLevel].ate0; gGameOptions.nTrackNumber = gEpisodeInfo[nEpisode].levels[nLevel].cdSongId;
} }
void levelLoadMapInfo(IniFile *pIni, LEVELINFO *pLevelInfo, const char *pzSection) void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSection, int epinum, int mapnum)
{ {
char buffer[16]; char buffer[16];
strncpy(pLevelInfo->at90, pIni->GetKeyString(pzSection, "Title", pLevelInfo->at0), 31); pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName));
strncpy(pLevelInfo->atb0, pIni->GetKeyString(pzSection, "Author", ""), 31); pLevelInfo->author = pIni->GetKeyString(pzSection, "Author", "");
strncpy(pLevelInfo->atd0, pIni->GetKeyString(pzSection, "Song", ""), BMAX_PATH); pLevelInfo->music.Format("%s.%s", pIni->GetKeyString(pzSection, "Song", ""), ".mid");
pLevelInfo->ate0 = pIni->GetKeyInt(pzSection, "Track", -1); pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1);
pLevelInfo->ate4 = pIni->GetKeyInt(pzSection, "EndingA", -1); pLevelInfo->nextLevel = pIni->GetKeyInt(pzSection, "EndingA", -1); //if (pLevelInfo->nextLevel >= 0) pLevelInfo->nextLevel +epinum * kMaxLevels;
pLevelInfo->ate8 = pIni->GetKeyInt(pzSection, "EndingB", -1); pLevelInfo->nextSecret = pIni->GetKeyInt(pzSection, "EndingB", -1); //if (pLevelInfo->nextSecret >= 0) pLevelInfo->nextSecret + epinum * kMaxLevels;
pLevelInfo->at8ec = pIni->GetKeyInt(pzSection, "Fog", -0); pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0);
pLevelInfo->at8ed = pIni->GetKeyInt(pzSection, "Weather", -0); pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0);
pLevelInfo->messageStart = 1024 + ((epinum * kMaxLevels) + mapnum) * kMaxMessages;
for (int i = 0; i < kMaxMessages; i++) for (int i = 0; i < kMaxMessages; i++)
{ {
sprintf(buffer, "Message%d", i+1); sprintf(buffer, "Message%d", i+1);
strncpy(pLevelInfo->atec[i], pIni->GetKeyString(pzSection, buffer, ""), 63); quoteMgr.InitializeQuote(pLevelInfo->messageStart + i, pIni->GetKeyString(pzSection, buffer, ""), true);
} }
} }
@ -226,7 +227,7 @@ void levelLoadDefaults(void)
char buffer2[16]; char buffer2[16];
levelInitINI(G_ConFile()); // This doubles for the INI in the global code. levelInitINI(G_ConFile()); // This doubles for the INI in the global code.
memset(gEpisodeInfo, 0, sizeof(gEpisodeInfo)); memset(gEpisodeInfo, 0, sizeof(gEpisodeInfo));
strncpy(gEpisodeInfo[MUS_INTRO/kMaxLevels].at28[MUS_INTRO%kMaxLevels].atd0, "PESTIS", BMAX_PATH); quoteMgr.InitializeQuote(MUS_INTRO, "PESTIS.MID");
int i; int i;
for (i = 0; i < kMaxEpisodes; i++) for (i = 0; i < kMaxEpisodes; i++)
{ {
@ -253,17 +254,19 @@ void levelLoadDefaults(void)
pEpisodeInfo->cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0); pEpisodeInfo->cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0);
if (pEpisodeInfo->cutALevel > 0) if (pEpisodeInfo->cutALevel > 0)
pEpisodeInfo->cutALevel--; pEpisodeInfo->cutALevel--;
pEpisodeInfo->levels = mapList + i * kMaxLevels;
int j; int j;
for (j = 0; j < kMaxLevels; j++) for (j = 0; j < kMaxLevels; j++)
{ {
LEVELINFO *pLevelInfo = &pEpisodeInfo->at28[j]; auto pLevelInfo = &pEpisodeInfo->levels[j];
sprintf(buffer2, "Map%d", j+1); sprintf(buffer2, "Map%d", j+1);
if (!BloodINI->KeyExists(buffer, buffer2)) if (!BloodINI->KeyExists(buffer, buffer2))
break; break;
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL); const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
CheckSectionAbend(pMap); CheckSectionAbend(pMap);
strncpy(pLevelInfo->at0, pMap, BMAX_PATH); pLevelInfo->labelName = pMap;
levelLoadMapInfo(BloodINI, pLevelInfo, pMap); pLevelInfo->fileName.Format("%s.map", pMap);
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j);
} }
pEpisodeInfo->nLevels = j; pEpisodeInfo->nLevels = j;
} }
@ -289,24 +292,24 @@ void levelAddUserMap(const char *pzMap)
} }
nLevel = pEpisodeInfo->nLevels++; nLevel = pEpisodeInfo->nLevels++;
} }
LEVELINFO *pLevelInfo = &pEpisodeInfo->at28[nLevel]; auto pLevelInfo = &pEpisodeInfo->levels[nLevel];
ChangeExtension(buffer, ""); ChangeExtension(buffer, "");
strncpy(pLevelInfo->at0, buffer, BMAX_PATH); pLevelInfo->name = buffer;
levelLoadMapInfo(&UserINI, pLevelInfo, NULL); levelLoadMapInfo(&UserINI, pLevelInfo, NULL, nEpisode, nLevel);
gGameOptions.nEpisode = nEpisode; gGameOptions.nEpisode = nEpisode;
gGameOptions.nLevel = nLevel; gGameOptions.nLevel = nLevel;
gGameOptions.uMapCRC = dbReadMapCRC(pLevelInfo->at0); gGameOptions.uMapCRC = dbReadMapCRC(pLevelInfo->name);
strcpy(gGameOptions.zLevelName, pLevelInfo->at0); strcpy(gGameOptions.zLevelName, pLevelInfo->name);
} }
void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB) void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB)
{ {
dassert(pnEndingA != NULL && pnEndingB != NULL); dassert(pnEndingA != NULL && pnEndingB != NULL);
LEVELINFO *pLevelInfo = &gEpisodeInfo[nEpisode].at28[nLevel]; auto pLevelInfo = &gEpisodeInfo[nEpisode].levels[nLevel];
int nEndingA = pLevelInfo->ate4; int nEndingA = pLevelInfo->nextLevel;
if (nEndingA >= 0) if (nEndingA >= 0)
nEndingA--; nEndingA--;
int nEndingB = pLevelInfo->ate8; int nEndingB = pLevelInfo->nextSecret;
if (nEndingB >= 0) if (nEndingB >= 0)
nEndingB--; nEndingB--;
*pnEndingA = nEndingA; *pnEndingA = nEndingA;
@ -396,14 +399,14 @@ int levelGetMusicIdx(const char *str)
bool levelTryPlayMusic(int nEpisode, int nLevel, bool bSetLevelSong) bool levelTryPlayMusic(int nEpisode, int nLevel, bool bSetLevelSong)
{ {
char buffer[BMAX_PATH]; char buffer[BMAX_PATH];
if (mus_redbook && gEpisodeInfo[nEpisode].at28[nLevel].ate0 > 0) if (mus_redbook && gEpisodeInfo[nEpisode].levels[nLevel].cdSongId > 0)
snprintf(buffer, BMAX_PATH, "blood%02i.ogg", gEpisodeInfo[nEpisode].at28[nLevel].ate0); snprintf(buffer, BMAX_PATH, "blood%02i.ogg", gEpisodeInfo[nEpisode].levels[nLevel].cdSongId);
else else
{ {
strncpy(buffer, gEpisodeInfo[nEpisode].at28[nLevel].atd0, BMAX_PATH); strncpy(buffer, gEpisodeInfo[nEpisode].levels[nLevel].music, BMAX_PATH);
} }
if (!strchr(buffer, '.')) strcat(buffer, ".mid"); if (!strchr(buffer, '.')) strcat(buffer, ".mid");
return !!Mus_Play(gEpisodeInfo[nEpisode].at28[nLevel].at0, buffer, true); return !!Mus_Play(gEpisodeInfo[nEpisode].levels[nLevel].labelName, buffer, true);
} }
void levelTryPlayMusicOrNothing(int nEpisode, int nLevel) void levelTryPlayMusicOrNothing(int nEpisode, int nLevel)

View file

@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#pragma once #pragma once
#include "common_game.h" #include "common_game.h"
#include "inifile.h" #include "inifile.h"
#include "mapinfo.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -68,27 +69,13 @@ enum {
MUS_LOADING = MUS_FIRST_SPECIAL + 1, MUS_LOADING = MUS_FIRST_SPECIAL + 1,
}; };
struct LEVELINFO
{
char at0[BMAX_PATH]; // Filename
char at90[32]; // Title
char atb0[32]; // Author
char atd0[BMAX_PATH]; // Song;
int ate0; // SongId
int ate4; // EndingA
int ate8; // EndingB
char atec[kMaxMessages][64]; // Messages
char at8ec; // Fog
char at8ed; // Weather
}; // 0x8ee bytes
struct EPISODEINFO struct EPISODEINFO
{ {
//char at0[32]; removed, so that the global episode name table can be used for consistency //char at0[32]; removed, so that the global episode name table can be used for consistency
int nLevels; int nLevels;
unsigned int bloodbath : 1; unsigned int bloodbath : 1;
unsigned int cutALevel : 4; unsigned int cutALevel : 4;
LEVELINFO at28[kMaxLevels]; MapRecord* levels; // points into the global table.
char at8f08[BMAX_PATH]; char at8f08[BMAX_PATH];
char at8f98[BMAX_PATH]; char at8f98[BMAX_PATH];
int at9028; int at9028;
@ -118,13 +105,12 @@ void levelSetupSecret(int nCount);
void levelTriggerSecret(int nSecret); void levelTriggerSecret(int nSecret);
void CheckSectionAbend(const char *pzSection); void CheckSectionAbend(const char *pzSection);
void CheckKeyAbend(const char *pzSection, const char *pzKey); void CheckKeyAbend(const char *pzSection, const char *pzKey);
LEVELINFO * levelGetInfoPtr(int nEpisode, int nLevel); MapRecord * levelGetInfoPtr(int nEpisode, int nLevel);
char * levelGetFilename(int nEpisode, int nLevel); const char * levelGetFilename(int nEpisode, int nLevel);
char * levelGetMessage(int nMessage); const char * levelGetMessage(int nMessage);
char * levelGetTitle(void); const char * levelGetTitle(void);
char * levelGetAuthor(void); const char * levelGetAuthor(void);
void levelSetupOptions(int nEpisode, int nLevel); void levelSetupOptions(int nEpisode, int nLevel);
void levelLoadMapInfo(IniFile *pIni, LEVELINFO *pLevelInfo, const char *pzSection);
void levelLoadDefaults(void); void levelLoadDefaults(void);
void levelAddUserMap(const char *pzMap); void levelAddUserMap(const char *pzMap);
// EndingA is normal ending, EndingB is secret level // EndingA is normal ending, EndingB is secret level

View file

@ -209,13 +209,6 @@ bool GameInterface::SaveGame(FSaveGameNode* node)
Printf(TEXTCOLOR_RED "%s\n", err.what()); Printf(TEXTCOLOR_RED "%s\n", err.what());
return false; return false;
} }
auto & li = gEpisodeInfo[gGameOptions.nEpisode].at28[gGameOptions.nLevel];
// workaround until the level info here has been transitioned.
MapRecord mr;
mr.name = li.at90;
mr.labelName = li.at0;
mr.fileName.Format("%s.map", li.at0);
currentLevel = &mr;
G_WriteSaveHeader(node->SaveTitle); G_WriteSaveHeader(node->SaveTitle);
LoadSave::hSFile = NULL; LoadSave::hSFile = NULL;

View file

@ -197,8 +197,8 @@ void CViewMap::sub_25C74(void)
videoClearScreen(0); videoClearScreen(0);
renderDrawMapView(x,y,nZoom>>2,angle); renderDrawMapView(x,y,nZoom>>2,angle);
sub_2541C(x,y,nZoom>>2,angle); sub_2541C(x,y,nZoom>>2,angle);
char *pTitle = levelGetTitle(); const char *pTitle = levelGetTitle();
char *pFilename = levelGetFilename(gGameOptions.nEpisode, gGameOptions.nLevel); const char *pFilename = levelGetFilename(gGameOptions.nEpisode, gGameOptions.nLevel);
if (pTitle) if (pTitle)
sprintf(pBuffer, "%s: %s", pFilename, pTitle); sprintf(pBuffer, "%s: %s", pFilename, pTitle);
else else

View file

@ -4769,7 +4769,7 @@ void trInit(void)
void trTextOver(int nId) void trTextOver(int nId)
{ {
char *pzMessage = levelGetMessage(nId); const char *pzMessage = levelGetMessage(nId);
if (pzMessage) if (pzMessage)
viewSetMessage(pzMessage, VanillaMode() ? 0 : 8, MESSAGE_PRIORITY_INI); // 8: gold viewSetMessage(pzMessage, VanillaMode() ? 0 : 8, MESSAGE_PRIORITY_INI); // 8: gold
} }

View file

@ -2,6 +2,10 @@
#include "gstrings.h" #include "gstrings.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "quotemgr.h"
#ifdef GetMessage
#undef GetMessage // Windows strikes...
#endif
// Localization capable replacement of the game specific solutions. // Localization capable replacement of the game specific solutions.
@ -18,21 +22,21 @@ enum
struct MapRecord struct MapRecord
{ {
int parTime; int parTime = -1;
int designerTime; int designerTime = -1;
FString fileName; FString fileName;
FString labelName; FString labelName;
FString name; FString name;
FString music; FString music;
int cdSongId; int cdSongId = -1;
int flags = -1;
// The rest is only used by Blood // The rest is only used by Blood
int nextLevel; int nextLevel = -1;
int nextSecret; int nextSecret = -1;
int messageStart; // messages are stored in the quote array to reduce clutter. int messageStart = 0; // messages are stored in the quote array to reduce clutter.
FString author; FString author;
// bool fog, weather; // Blood defines these but they aren't used. int8_t fog = -1, weather = -1; // Blood defines these but they aren't used.
int flags;
const char *DisplayName() const char *DisplayName()
{ {
@ -49,6 +53,10 @@ struct MapRecord
fileName = n; fileName = n;
labelName = ExtractFileBase(n); labelName = ExtractFileBase(n);
} }
const char* GetMessage(int num)
{
return quoteMgr.GetQuote(messageStart + num);
}
}; };

View file

@ -601,7 +601,7 @@ CCMD(printstats)
ADD_STAT(statistics) ADD_STAT(statistics)
{ {
if (*StartEpisode == 0 || *LevelName == 0) return; if (*StartEpisode == 0 || *LevelName == 0) return "";
StoreLevelStats(); // Refresh the current level's results. StoreLevelStats(); // Refresh the current level's results.
return GetStatString(); return GetStatString();
} }

View file

@ -419,7 +419,7 @@ void G_CacheMapData(void)
if (ud.recstat == 2) if (ud.recstat == 2)
return; return;
S_TryPlaySpecialMusic(MUS_LOADING); //S_TryPlaySpecialMusic(MUS_LOADING);
uint32_t const cacheStartTime = timerGetTicks(); uint32_t const cacheStartTime = timerGetTicks();

View file

@ -149,7 +149,7 @@ void S_PlayLevelMusicOrNothing(unsigned int m)
{ {
// Thanks to scripting that stupid slot hijack cannot be refactored - but we'll store the real data elsewhere anyway! // Thanks to scripting that stupid slot hijack cannot be refactored - but we'll store the real data elsewhere anyway!
auto &mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m]; auto &mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m];
Mus_Play(mr.fileName, mr.music, true); Mus_Play(mr.labelName, mr.music, true);
S_SetMusicIndex(m); S_SetMusicIndex(m);
} }
} }

View file

@ -125,7 +125,7 @@ void S_MenuSound(void)
void S_PlayLevelMusicOrNothing(unsigned int m) void S_PlayLevelMusicOrNothing(unsigned int m)
{ {
Mus_Play(mapList[m].fileName, RR ? nullptr : mapList[m].music, true); Mus_Play(mapList[m].labelName, RR ? nullptr : mapList[m].music, true);
} }
int S_TryPlaySpecialMusic(unsigned int m) int S_TryPlaySpecialMusic(unsigned int m)