- handle Blood's level progression by the actual level data, not some episode/level pair.

This should allow loading user maps again.
This commit is contained in:
Christoph Oelckers 2020-08-16 13:26:57 +02:00
parent 598ea99441
commit 9700b8435b
11 changed files with 63 additions and 154 deletions

View file

@ -60,13 +60,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "secrets.h"
#include "gamestate.h"
#include "screenjob.h"
#include "mapinfo.h"
BEGIN_BLD_NS
void LocalKeys(void);
void InitCheats();
char bAddUserMap = false;
bool bNoDemo = false;
bool bQuickStart = true;
@ -359,50 +359,32 @@ int gHealthTemp[kMaxPlayers];
vec3_t startpos;
int16_t startang, startsectnum;
void StartLevel(GAMEOPTIONS *gameOptions)
void StartLevel(MapRecord *level)
{
if (!level) return;
STAT_Update(0);
EndLevel();
gInput = {};
gStartNewGame = 0;
gStartNewGame = nullptr;
ready2send = 0;
netWaitForEveryone(0);
currentLevel = FindMapByLevelNum(levelnum(gGameOptions.nEpisode, gGameOptions.nLevel));
currentLevel = level;
if (gGameOptions.nGameType == 0)
{
if (!(gGameOptions.uGameFlags&1))
levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel);
///////
gGameOptions.weaponsV10x = gWeaponsV10x;
///////
}
#if 0
else if (gGameOptions.nGameType > 0 && !(gGameOptions.uGameFlags&1))
{
gGameOptions.nEpisode = gPacketStartGame.episodeId;
gGameOptions.nLevel = gPacketStartGame.levelId;
gGameOptions.nGameType = gPacketStartGame.gameType;
gGameOptions.nDifficulty = gPacketStartGame.difficulty;
gGameOptions.nMonsterSettings = gPacketStartGame.monsterSettings;
gGameOptions.nWeaponSettings = gPacketStartGame.weaponSettings;
gGameOptions.nItemSettings = gPacketStartGame.itemSettings;
gGameOptions.nRespawnSettings = gPacketStartGame.respawnSettings;
gGameOptions.bFriendlyFire = gPacketStartGame.bFriendlyFire;
gGameOptions.bKeepKeysOnRespawn = gPacketStartGame.bKeepKeysOnRespawn;
if (gPacketStartGame.userMap)
levelAddUserMap(gPacketStartGame.userMapName);
else
levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel);
///////
gGameOptions.weaponsV10x = gPacketStartGame.weaponsV10x;
///////
// todo
gBlueFlagDropped = false;
gRedFlagDropped = false;
}
if (gameOptions->uGameFlags&1)
#endif
if (gGameOptions.uGameFlags&1)
{
for (int i = connecthead; i >= 0; i = connectpoint2[i])
{
@ -435,9 +417,9 @@ void StartLevel(GAMEOPTIONS *gameOptions)
if (pSprite->statnum < kMaxStatus && pSprite->extra > 0) {
XSPRITE *pXSprite = &xsprite[pSprite->extra];
if ((pXSprite->lSkill & (1 << gameOptions->nDifficulty)) || (pXSprite->lS && gameOptions->nGameType == 0)
|| (pXSprite->lB && gameOptions->nGameType == 2) || (pXSprite->lT && gameOptions->nGameType == 3)
|| (pXSprite->lC && gameOptions->nGameType == 1)) {
if ((pXSprite->lSkill & (1 << gGameOptions.nDifficulty)) || (pXSprite->lS && gGameOptions.nGameType == 0)
|| (pXSprite->lB && gGameOptions.nGameType == 2) || (pXSprite->lT && gGameOptions.nGameType == 3)
|| (pXSprite->lC && gGameOptions.nGameType == 1)) {
DeleteSprite(i);
continue;
@ -487,7 +469,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
evInit();
for (int i = connecthead; i >= 0; i = connectpoint2[i])
{
if (!(gameOptions->uGameFlags&1))
if (!(gGameOptions.uGameFlags&1))
{
if (numplayers == 1)
{
@ -499,7 +481,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
}
playerStart(i, 1);
}
if (gameOptions->uGameFlags&1)
if (gGameOptions.uGameFlags&1)
{
for (int i = connecthead; i >= 0; i = connectpoint2[i])
{
@ -516,7 +498,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
pPlayer->nextWeapon = gPlayerTemp[i].nextWeapon;
}
}
gameOptions->uGameFlags &= ~3;
gGameOptions.uGameFlags &= ~3;
PreloadCache();
InitMirrors();
gFrameClock = 0;
@ -534,6 +516,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
totalclock = 0;
paused = 0;
ready2send = 1;
levelTryPlayMusic();
}
@ -664,7 +647,7 @@ void ProcessFrame(void)
if (gGameOptions.uGameFlags&8)
{
levelPlayEndScene(gGameOptions.nEpisode, completion);
levelPlayEndScene(volfromlevelnum(currentLevel->levelNumber), completion);
}
else completion(false);
}
@ -787,11 +770,6 @@ static void app_init()
registerinputcommands();
gChoke.sub_83ff0(518, sub_84230);
if (bAddUserMap)
{
levelAddUserMap(gUserMapFilename);
gStartNewGame = 1;
}
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
UpdateDacs(0, true);
}
@ -888,31 +866,37 @@ static void commonTicker(bool &playvideo)
}
if (gStartNewGame)
{
gStartNewGame = false;
auto sng = gStartNewGame;
gStartNewGame = nullptr;
gQuitGame = false;
auto completion = [](bool = false)
auto completion = [=](bool = false)
{
StartLevel(&gGameOptions);
levelTryPlayMusic();
StartLevel(sng);
gNetFifoClock = gFrameClock = totalclock;
gamestate = GS_LEVEL;
};
if (gEpisodeInfo[gGameOptions.nEpisode].cutALevel == gGameOptions.nLevel
&& gEpisodeInfo[gGameOptions.nEpisode].cutsceneAName[0])
levelPlayIntroScene(gGameOptions.nEpisode, completion);
else
completion(false);
bool startedCutscene = false;
if (!(sng->flags & MI_USERMAP))
{
int episode = volfromlevelnum(sng->levelNumber);
int level = mapfromlevelnum(sng->levelNumber);
if (gEpisodeInfo[episode].cutALevel == level && gEpisodeInfo[episode].cutsceneAName[0])
{
levelPlayIntroScene(episode, completion);
startedCutscene = true;
}
}
if (!startedCutscene) completion(false);
}
if (gRestartGame)
else if (gRestartGame)
{
Mus_Stop();
soundEngine->StopAllChannels();
gQuitGame = 0;
gQuitRequest = 0;
gRestartGame = 0;
levelSetupOptions(0, 0);
if (gGameOptions.nGameType != 0)

View file

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "levels.h"
#include "misc.h"
#include "db.h"
#include "mapinfo.h"
BEGIN_BLD_NS
@ -96,7 +97,7 @@ extern int gQuitRequest;
void QuitGame(void);
void PreloadCache(void);
void StartLevel(GAMEOPTIONS *gameOptions);
void StartLevel(MapRecord *gameOptions);
void ProcessFrame(void);
void ScanINIFiles(void);
bool DemoRecordStatus(void);

View file

@ -242,10 +242,8 @@ void GameInterface::StartGame(FNewGameStartup& gs)
{
sfxKillAllSounds();
gGameOptions.nDifficulty = gs.Skill;
gGameOptions.nEpisode = gs.Episode;
gSkill = gs.Skill;
gGameOptions.nLevel = gs.Level;
gStartNewGame = true;
gStartNewGame = FindMapByLevelNum(levelnum(gs.Episode, gs.Level));
cheatReset();
}

View file

@ -149,17 +149,14 @@ void CEndGameMgr::Setup(void)
inputState.keyFlushScans();
}
//int gNextLevel;
extern int gInitialNetPlayers;
extern bool gStartNewGame;
void CEndGameMgr::Finish(void)
{
levelSetupOptions(gGameOptions.nEpisode, gNextLevel);
int ep = volfromlevelnum(currentLevel->levelNumber);
gStartNewGame = FindMapByLevelNum(levelnum(ep, gNextLevel));
gInitialNetPlayers = numplayers;
soundEngine->StopAllChannels();
gStartNewGame = 1;
at0 = 0;
}

View file

@ -46,14 +46,14 @@ BEGIN_BLD_NS
GAMEOPTIONS gGameOptions;
GAMEOPTIONS gSingleGameOptions = {
0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200
0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200
};
EPISODEINFO gEpisodeInfo[kMaxEpisodes+1];
int gSkill = 2;
int gEpisodeCount;
int gNextLevel;
int gNextLevel; // fixme: let this contain a full level number.
int gLevelTime;
@ -110,12 +110,6 @@ void CheckKeyAbend(const char *pzSection, const char *pzKey)
}
void levelSetupOptions(int nEpisode, int nLevel)
{
gGameOptions.nEpisode = nEpisode;
gGameOptions.nLevel = nLevel;
}
void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSection, int epinum, int mapnum)
{
char buffer[16];
@ -193,46 +187,13 @@ void levelLoadDefaults(void)
gEpisodeCount = i;
}
void levelAddUserMap(const char *pzMap)
{
// FIXME: Make this work with the reworked map system
#if 0
char buffer[BMAX_PATH];
strncpy(buffer, pzMap, BMAX_PATH);
ChangeExtension(buffer, ".DEF");
IniFile UserINI(buffer);
int nEpisode = ClipRange(UserINI.GetKeyInt(NULL, "Episode", 0), 0, 5);
EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode];
int nLevel = ClipRange(UserINI.GetKeyInt(NULL, "Level", pEpisodeInfo->nLevels), 0, 15);
if (nLevel >= pEpisodeInfo->nLevels)
{
if (pEpisodeInfo->nLevels == 0)
{
gEpisodeCount++;
gVolumeNames[nEpisode].Format("Episode %d", nEpisode+1);
}
nLevel = pEpisodeInfo->nLevels++;
}
auto pLevelInfo = &pEpisodeInfo->levels[nLevel];
ChangeExtension(buffer, "");
pLevelInfo->name = buffer;
levelLoadMapInfo(&UserINI, pLevelInfo, NULL, nEpisode, nLevel);
gGameOptions.nEpisode = nEpisode;
gGameOptions.nLevel = nLevel;
#else
auto map = SetupUserMap(pzMap);
#endif
}
void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB)
void levelGetNextLevels(int *pnEndingA, int *pnEndingB)
{
dassert(pnEndingA != NULL && pnEndingB != NULL);
auto pLevelInfo = FindMapByLevelNum(levelnum(nEpisode, nLevel));
int nEndingA = pLevelInfo->nextLevel;
int nEndingA = currentLevel->nextLevel;
if (nEndingA >= 0)
nEndingA--;
int nEndingB = pLevelInfo->nextSecret;
int nEndingB = currentLevel->nextSecret;
if (nEndingB >= 0)
nEndingB--;
*pnEndingA = nEndingA;
@ -242,9 +203,10 @@ void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB
void levelEndLevel(int arg)
{
int nEndingA, nEndingB;
EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[gGameOptions.nEpisode];
auto episode = volfromlevelnum(currentLevel->levelNumber);
EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[episode];
gGameOptions.uGameFlags |= 1;
levelGetNextLevels(gGameOptions.nEpisode, gGameOptions.nLevel, &nEndingA, &nEndingB);
levelGetNextLevels(&nEndingA, &nEndingB);
switch (arg)
{
case 0:
@ -252,7 +214,6 @@ void levelEndLevel(int arg)
{
if (pEpisodeInfo->cutsceneBName[0])
gGameOptions.uGameFlags |= 8;
gGameOptions.nLevel = 0;
gGameOptions.uGameFlags |= 2;
}
else
@ -261,16 +222,14 @@ void levelEndLevel(int arg)
case 1:
if (nEndingB == -1)
{
if (gGameOptions.nEpisode + 1 < gEpisodeCount)
if (episode + 1 < gEpisodeCount)
{
if (pEpisodeInfo->cutsceneBName[0])
gGameOptions.uGameFlags |= 8;
gGameOptions.nLevel = 0;
gGameOptions.uGameFlags |= 2;
}
else
{
gGameOptions.nLevel = 0;
gGameOptions.uGameFlags |= 1;
}
}
@ -282,11 +241,10 @@ void levelEndLevel(int arg)
void levelRestart(void)
{
levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel);
gStartNewGame = true;
gStartNewGame = currentLevel;
}
bool levelTryPlayMusic()
void levelTryPlayMusic()
{
FString buffer;
if (mus_redbook && currentLevel->cdSongId > 0)
@ -294,7 +252,7 @@ bool levelTryPlayMusic()
else
{
buffer = currentLevel->music;
if (Mus_Play(currentLevel->labelName, buffer, true)) return true;
if (Mus_Play(currentLevel->labelName, buffer, true)) return;
DefaultExtension(buffer, ".mid");
}
if (!Mus_Play(currentLevel->labelName, buffer, true))

View file

@ -38,8 +38,6 @@ BEGIN_BLD_NS
struct GAMEOPTIONS {
unsigned char nGameType;
unsigned char nDifficulty;
int nEpisode;
int nLevel;
short nSaveGameSlot;
int picEntry;
char nMonsterSettings;
@ -98,14 +96,10 @@ void levelSetupSecret(int nCount);
void levelTriggerSecret(int nSecret);
void CheckSectionAbend(const char *pzSection);
void CheckKeyAbend(const char *pzSection, const char *pzKey);
void levelSetupOptions(int nEpisode, int nLevel);
void levelLoadDefaults(void);
void levelAddUserMap(const char *pzMap);
// EndingA is normal ending, EndingB is secret level
void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB);
// arg: 0 is normal exit, 1 is secret level
void levelEndLevel(int arg);
void levelRestart(void);
bool levelTryPlayMusic();
void levelTryPlayMusic();
END_BLD_NS

View file

@ -272,9 +272,8 @@ void ToggleDelirium(void)
void LevelWarp(int nEpisode, int nLevel)
{
levelSetupOptions(nEpisode, nLevel);
StartLevel(&gGameOptions);
levelTryPlayMusic();
auto map = FindMapByLevelNum(levelnum(nEpisode, nLevel));
if (map) StartLevel(map);
}
bool bPlayerCheated = false;

View file

@ -41,7 +41,7 @@ extern bool gHaveNetworking;
BEGIN_BLD_NS
char packet[576];
bool gStartNewGame = 0;
MapRecord *gStartNewGame = 0;
PACKETMODE gPacketMode = PACKETMODE_1;
ClockTicks gNetFifoClock = 0;
int gNetFifoTail = 0;
@ -72,8 +72,6 @@ int gNetPort = kNetDefaultPort;
const short word_1328AC = 0x214;
PKT_STARTGAME gPacketStartGame;
void netResetToSinglePlayer(void)
{
myconnectindex = connecthead = 0;

View file

@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "compat.h"
#include "build.h"
#include "controls.h"
#include "mapinfo.h"
BEGIN_BLD_NS
@ -43,7 +44,7 @@ enum NETWORKMODE {
#define kNetDefaultPort 23513
extern char packet[576];
extern bool gStartNewGame;
extern MapRecord *gStartNewGame;
extern PACKETMODE gPacketMode;
extern ClockTicks gNetFifoClock;
extern int gNetFifoTail;
@ -71,20 +72,6 @@ extern char gNetAddress[32];
extern int gNetPort;
struct PKT_STARTGAME {
short version;
char gameType, difficulty, monsterSettings, weaponSettings, itemSettings, respawnSettings;
char episodeId, levelId;
int unk;
char userMap, userMapName[13];
int weaponsV10x;
bool bFriendlyFire;
bool bKeepKeysOnRespawn;
};
extern PKT_STARTGAME gPacketStartGame;
inline void PutPacketByte(char *&p, int a2)
{
//dassert(p - packet + 1 < sizeof(packet));

View file

@ -5174,7 +5174,6 @@ void levelEndLevelCustom(int nLevel) {
if (nLevel >= 16 || nLevel < 0) {
gGameOptions.uGameFlags |= 2;
gGameOptions.nLevel = 0;
return;
}

View file

@ -60,19 +60,13 @@ static int osdcmd_map(CCmdFuncPtr parm)
auto maprec = FindMapByName(mapname);
if (maprec)
{
int e = volfromlevelnum(maprec->levelNumber);
int m = mapfromlevelnum(maprec->levelNumber);
LevelWarp(e, m);
return CCMD_OK;
StartLevel(maprec);
}
else
{
// Map has not been defined. Treat as user map.
StartLevel(SetupUserMap(mapname));
}
// Map has not been defined. Treat as user map.
#if 0 // this doesn't work yet because map progression is hardwired to the level number.
levelAddUserMap(mapname);
levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel);
StartLevel(&gGameOptions);
#endif
return CCMD_OK;
}