mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 08:52:00 +00:00
- adapted Blood to the new level progression features and simplified several parts, particularly the clumsy retrieval of the next level.
Some cheats in Duke will not work correctly with this commit!
This commit is contained in:
parent
93bfc35ad6
commit
e9385ed4e8
11 changed files with 100 additions and 105 deletions
|
@ -294,7 +294,7 @@ static MapRecord* levelwarp_common(FCommandLine& argv, const char *cmdname, cons
|
|||
Printf(PRINT_BOLD, "Invalid level! Numbers must be > 0\n");
|
||||
return nullptr;
|
||||
}
|
||||
auto map = FindMapByLevelNum(numparm == 1 ? m : makelevelnum(e - 1, m - 1));
|
||||
auto map = FindMapByLevelNum(numparm == 1 ? m : makelevelnum(e, m));
|
||||
if (!map)
|
||||
{
|
||||
if (numparm == 2) Printf(PRINT_BOLD, "Level E%s L%s not found!\n", argv[1], argv[2]);
|
||||
|
|
|
@ -84,10 +84,10 @@ CCMD(mapinfo)
|
|||
if (clus.intro.isdefined() || clus.outro.isdefined())
|
||||
{
|
||||
Printf("Cluster %d\n\tName = '%s'\n", clus.index, clus.name.GetChars());
|
||||
if (clus.intro.function.IsNotEmpty()) Printf("\tIntro function = %d\n", clus.intro.function.GetChars());
|
||||
if (clus.intro.video.IsNotEmpty()) Printf("\tIntro video = %d\n", clus.intro.video.GetChars());
|
||||
if (clus.outro.function.IsNotEmpty()) Printf("\tOutro function = %d\n", clus.outro.function.GetChars());
|
||||
if (clus.outro.video.IsNotEmpty()) Printf("\tOutro video = %d\n", clus.outro.video.GetChars());
|
||||
if (clus.intro.function.IsNotEmpty()) Printf("\tIntro function = %s\n", clus.intro.function.GetChars());
|
||||
if (clus.intro.video.IsNotEmpty()) Printf("\tIntro video = %s\n", clus.intro.video.GetChars());
|
||||
if (clus.outro.function.IsNotEmpty()) Printf("\tOutro function = %s\n", clus.outro.function.GetChars());
|
||||
if (clus.outro.video.IsNotEmpty()) Printf("\tOutro video = %s\n", clus.outro.video.GetChars());
|
||||
Printf("}\n");
|
||||
}
|
||||
}
|
||||
|
@ -108,10 +108,10 @@ CCMD(mapinfo)
|
|||
if (map->cdSongId > 0) Printf("\tCD track = %d\n", map->cdSongId);
|
||||
if (map->parTime) Printf("\tPar Time = %d\n", map->parTime);
|
||||
if (map->designerTime) Printf("\tPar Time = %d\n", map->designerTime);
|
||||
if (map->intro.function.IsNotEmpty()) Printf("\tIntro function = %d\n", map->intro.function.GetChars());
|
||||
if (map->intro.video.IsNotEmpty()) Printf("\tIntro video = %d\n", map->intro.video.GetChars());
|
||||
if (map->outro.function.IsNotEmpty()) Printf("\tOutro function = %d\n", map->outro.function.GetChars());
|
||||
if (map->outro.video.IsNotEmpty()) Printf("\tOutro video = %d\n", map->outro.video.GetChars());
|
||||
if (map->intro.function.IsNotEmpty()) Printf("\tIntro function = %s\n", map->intro.function.GetChars());
|
||||
if (map->intro.video.IsNotEmpty()) Printf("\tIntro video = %s\n", map->intro.video.GetChars());
|
||||
if (map->outro.function.IsNotEmpty()) Printf("\tOutro function = %s\n", map->outro.function.GetChars());
|
||||
if (map->outro.video.IsNotEmpty()) Printf("\tOutro video = %s\n", map->outro.video.GetChars());
|
||||
Printf("}\n");
|
||||
}
|
||||
else
|
||||
|
@ -173,6 +173,41 @@ VolumeRecord* AllocateVolume()
|
|||
{
|
||||
return &volumes[volumes.Reserve(1)];
|
||||
}
|
||||
|
||||
MapRecord* FindMapByIndexOnly(int cluster, int num)
|
||||
{
|
||||
for (auto& map : mapList)
|
||||
{
|
||||
if (map->mapindex == num && map->cluster == cluster) return map.Data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MapRecord* FindMapByIndex(int cluster, int num)
|
||||
{
|
||||
auto map = FindMapByLevelNum(num);
|
||||
if (!map) map = FindMapByIndexOnly(cluster, num); // modern definitions take precedence.
|
||||
return map;
|
||||
}
|
||||
|
||||
MapRecord* FindNextMap(MapRecord* thismap)
|
||||
{
|
||||
MapRecord* next = nullptr;
|
||||
if (!thismap->NextMap.Compare("-")) return nullptr; // '-' means to forcibly end the game here.
|
||||
if (thismap->NextMap.IsNotEmpty()) next = FindMapByName(thismap->NextMap);
|
||||
if (!next) next = FindMapByLevelNum(thismap->levelNumber);
|
||||
return next;
|
||||
}
|
||||
|
||||
MapRecord* FindNextSecretMap(MapRecord* thismap)
|
||||
{
|
||||
MapRecord* next = nullptr;
|
||||
if (!thismap->NextSecret.Compare("-")) return nullptr; // '-' means to forcibly end the game here.
|
||||
if (thismap->NextSecret.IsNotEmpty()) next = FindMapByName(thismap->NextSecret);
|
||||
return next? next : FindNextMap(thismap);
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
|
@ -195,12 +230,6 @@ MapRecord* FindMapByClusterAndLevelNum(int cluster, int num)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
MapRecord *FindNextMap(MapRecord *thismap)
|
||||
{
|
||||
if (thismap->nextLevel != -1) return FindMapByLevelNum(thismap->nextLevel);
|
||||
return FindMapByLevelNum(thismap->levelNumber+1);
|
||||
}
|
||||
|
||||
bool SetMusicForMap(const char* mapname, const char* music, bool namehack)
|
||||
{
|
||||
static const char* specials[] = { "intro", "briefing", "loading" };
|
||||
|
|
|
@ -205,9 +205,11 @@ bool SetMusicForMap(const char* mapname, const char* music, bool namehack = fals
|
|||
|
||||
MapRecord *FindMapByName(const char *nm);
|
||||
MapRecord *FindMapByLevelNum(int num);
|
||||
MapRecord* FindMapByIndexOnly(int clst, int num); // this is for map setup where fallbacks are undesirable.
|
||||
MapRecord* FindMapByIndex(int clst, int num);
|
||||
MapRecord* FindMapByClusterAndLevelNum(int clst, int num);
|
||||
inline MapRecord* FindMapByIndexOnly(int clst, int num) { return FindMapByClusterAndLevelNum(clst, num); }
|
||||
MapRecord *FindNextMap(MapRecord *thismap);
|
||||
MapRecord* FindNextSecretMap(MapRecord* thismap);
|
||||
MapRecord* SetupUserMap(const char* boardfilename, const char *defaultmusic = nullptr);
|
||||
MapRecord* AllocateMap();
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ void EndLevel(void)
|
|||
seqKillAll();
|
||||
}
|
||||
|
||||
void StartLevel(MapRecord* level)
|
||||
void StartLevel(MapRecord* level, bool newgame)
|
||||
{
|
||||
if (!level) return;
|
||||
gFrameCount = 0;
|
||||
|
@ -97,14 +97,14 @@ void StartLevel(MapRecord* level)
|
|||
///////
|
||||
}
|
||||
#if 0
|
||||
else if (gGameOptions.nGameType > 0 && !(gGameOptions.uGameFlags & GF_AdvanceLevel))
|
||||
else if (gGameOptions.nGameType > 0 && newgame)
|
||||
{
|
||||
// todo
|
||||
gBlueFlagDropped = false;
|
||||
gRedFlagDropped = false;
|
||||
}
|
||||
#endif
|
||||
if (gGameOptions.uGameFlags & GF_AdvanceLevel)
|
||||
if (!newgame)
|
||||
{
|
||||
for (int i = connecthead; i >= 0; i = connectpoint2[i])
|
||||
{
|
||||
|
@ -182,13 +182,13 @@ void StartLevel(MapRecord* level)
|
|||
evInit();
|
||||
for (int i = connecthead; i >= 0; i = connectpoint2[i])
|
||||
{
|
||||
if (!(gGameOptions.uGameFlags & GF_AdvanceLevel))
|
||||
if (newgame)
|
||||
{
|
||||
playerInit(i, 0);
|
||||
}
|
||||
playerStart(i, 1);
|
||||
}
|
||||
if (gGameOptions.uGameFlags & GF_AdvanceLevel)
|
||||
if (!newgame)
|
||||
{
|
||||
for (int i = connecthead; i >= 0; i = connectpoint2[i])
|
||||
{
|
||||
|
@ -205,7 +205,6 @@ void StartLevel(MapRecord* level)
|
|||
pPlayer->nextWeapon = gPlayerTemp[i].nextWeapon;
|
||||
}
|
||||
}
|
||||
gGameOptions.uGameFlags &= ~(GF_AdvanceLevel|GF_EndGame);
|
||||
PreloadCache();
|
||||
InitMirrors();
|
||||
trInit();
|
||||
|
@ -224,11 +223,11 @@ void StartLevel(MapRecord* level)
|
|||
}
|
||||
|
||||
|
||||
void NewLevel(MapRecord *sng, int skill)
|
||||
void NewLevel(MapRecord *sng, int skill, bool newgame)
|
||||
{
|
||||
if (skill != -1) gGameOptions.nDifficulty = skill;
|
||||
gSkill = gGameOptions.nDifficulty;
|
||||
StartLevel(sng);
|
||||
StartLevel(sng, newgame);
|
||||
gameaction = ga_level;
|
||||
}
|
||||
|
||||
|
@ -236,13 +235,12 @@ void GameInterface::NewGame(MapRecord *sng, int skill, bool)
|
|||
{
|
||||
gGameOptions.uGameFlags = 0;
|
||||
cheatReset();
|
||||
NewLevel(sng, skill);
|
||||
NewLevel(sng, skill, true);
|
||||
}
|
||||
|
||||
void GameInterface::NextLevel(MapRecord *map, int skill)
|
||||
{
|
||||
gGameOptions.uGameFlags = GF_AdvanceLevel;
|
||||
NewLevel(map, skill);
|
||||
NewLevel(map, skill, false);
|
||||
}
|
||||
|
||||
void GameInterface::Ticker()
|
||||
|
@ -313,25 +311,12 @@ void GameInterface::Ticker()
|
|||
team_ticker[i] = 0;
|
||||
}
|
||||
|
||||
int gf = gGameOptions.uGameFlags;
|
||||
|
||||
if (gf & GF_AdvanceLevel)
|
||||
if (gGameOptions.uGameFlags & GF_AdvanceLevel)
|
||||
{
|
||||
gGameOptions.uGameFlags &= ~GF_AdvanceLevel;
|
||||
seqKillAll();
|
||||
|
||||
if (gf & GF_EndGame)
|
||||
{
|
||||
STAT_Update(true);
|
||||
CompleteLevel(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
STAT_Update(false);
|
||||
// Fixme: Link maps, not episode/level pairs.
|
||||
int ep = volfromlevelnum(currentLevel->levelNumber);
|
||||
auto map = FindMapByLevelNum(makelevelnum(ep, gNextLevel));
|
||||
CompleteLevel(map);
|
||||
}
|
||||
STAT_Update(gNextLevel == nullptr);
|
||||
CompleteLevel(gNextLevel);
|
||||
}
|
||||
r_NoInterpolate = false;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ void GameInterface::LevelCompleted(MapRecord *map, int skill)
|
|||
{
|
||||
soundEngine->StopAllChannels();
|
||||
gameaction = map? ga_nextlevel : ga_creditsmenu;
|
||||
if (!map) gGameOptions.uGameFlags &= ~(GF_AdvanceLevel | GF_EndGame);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ GAMEOPTIONS gSingleGameOptions = {
|
|||
};
|
||||
|
||||
int gSkill = 2;
|
||||
int gNextLevel; // fixme: let this contain a full level number.
|
||||
MapRecord* gNextLevel;
|
||||
|
||||
char BloodIniFile[BMAX_PATH] = "BLOOD.INI";
|
||||
bool bINIOverride = false;
|
||||
|
@ -91,15 +91,16 @@ void CheckKeyAbend(const char *pzSection, const char *pzKey)
|
|||
}
|
||||
|
||||
|
||||
void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSection, int epinum, int mapnum)
|
||||
|
||||
void levelLoadMapInfo(IniFile* pIni, MapRecord* pLevelInfo, const char* pzSection, int epinum, int mapnum, int* nextmap, int* nextsecret)
|
||||
{
|
||||
char buffer[16];
|
||||
pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName));
|
||||
pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", "");
|
||||
pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); DefaultExtension(pLevelInfo->music, ".mid");
|
||||
pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1);
|
||||
pLevelInfo->nextLevel = pIni->GetKeyInt(pzSection, "EndingA", -1);
|
||||
pLevelInfo->nextSecret = pIni->GetKeyInt(pzSection, "EndingB", -1);
|
||||
*nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0);
|
||||
*nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0);
|
||||
pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0);
|
||||
pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0);
|
||||
for (int i = 0; i < kMaxMessages; i++)
|
||||
|
@ -178,11 +179,11 @@ void levelLoadDefaults(void)
|
|||
csB.sound = soundEngine->FindSound(cleanPath(BloodINI->GetKeyString(buffer, "CutWavB", "")));
|
||||
|
||||
//pEpisodeInfo->bloodbath = BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0);
|
||||
cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0) - 1;
|
||||
if (cutALevel < 0) cutALevel = 0;
|
||||
cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0);
|
||||
if (cutALevel < 1) cutALevel = 1;
|
||||
|
||||
int j;
|
||||
for (j = 1; j <= kMaxLevels; j++)
|
||||
int nextmaps[kMaxLevels]{}, nextsecrets[kMaxLevels]{};
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
sprintf(buffer2, "Map%d", j);
|
||||
if (!BloodINI->KeyExists(buffer, buffer2))
|
||||
|
@ -190,13 +191,13 @@ void levelLoadDefaults(void)
|
|||
auto pLevelInfo = AllocateMap();
|
||||
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
|
||||
CheckSectionAbend(pMap);
|
||||
SetLevelNum(pLevelInfo, makelevelnum(i-1, j-1));
|
||||
SetLevelNum(pLevelInfo, makelevelnum(i, j));
|
||||
pLevelInfo->cluster = i;
|
||||
pLevelInfo->mapindex = j;
|
||||
pLevelInfo->labelName = pMap;
|
||||
if (j == 1) volume->startmap = pLevelInfo->labelName;
|
||||
pLevelInfo->fileName.Format("%s.map", pMap);
|
||||
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j);
|
||||
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j, &nextmaps[j - 1], &nextsecrets[j - 1]);
|
||||
if (j == cutALevel)
|
||||
{
|
||||
CutsceneDef& csA = pLevelInfo->intro;
|
||||
|
@ -206,47 +207,34 @@ void levelLoadDefaults(void)
|
|||
csA.sound = soundEngine->FindSound(cleanPath(BloodINI->GetKeyString(buffer, "CutWavA", "")));
|
||||
}
|
||||
}
|
||||
// Now resolve the level links
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
auto map = FindMapByIndexOnly(i, j);
|
||||
if (map)
|
||||
{
|
||||
if (nextmaps[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextmaps[j - 1]);
|
||||
if (nmap) map->NextMap = nmap->labelName;
|
||||
else map->NextMap = "-";
|
||||
}
|
||||
if (nextsecrets[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]);
|
||||
if (nmap) map->NextSecret = nmap->labelName;
|
||||
else map->NextSecret = "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void levelGetNextLevels(int *pnEndingA, int *pnEndingB)
|
||||
{
|
||||
assert(pnEndingA != NULL && pnEndingB != NULL);
|
||||
int nEndingA = currentLevel->nextLevel;
|
||||
if (nEndingA >= 0)
|
||||
nEndingA--;
|
||||
int nEndingB = currentLevel->nextSecret;
|
||||
if (nEndingB >= 0)
|
||||
nEndingB--;
|
||||
*pnEndingA = nEndingA;
|
||||
*pnEndingB = nEndingB;
|
||||
}
|
||||
|
||||
void levelEndLevel(int secret)
|
||||
{
|
||||
int nEndingA, nEndingB;
|
||||
auto episode = volfromlevelnum(currentLevel->levelNumber);
|
||||
gGameOptions.uGameFlags |= GF_AdvanceLevel;
|
||||
levelGetNextLevels(&nEndingA, &nEndingB);
|
||||
switch (secret)
|
||||
{
|
||||
case 0:
|
||||
if (nEndingA == -1)
|
||||
{
|
||||
gGameOptions.uGameFlags |= GF_EndGame;
|
||||
}
|
||||
else
|
||||
gNextLevel = nEndingA;
|
||||
break;
|
||||
case 1:
|
||||
if (nEndingB == -1)
|
||||
{
|
||||
gGameOptions.uGameFlags |= GF_EndGame;
|
||||
}
|
||||
else
|
||||
gNextLevel = nEndingB;
|
||||
break;
|
||||
}
|
||||
if (!secret) gNextLevel = FindNextMap(currentLevel);
|
||||
else gNextLevel = FindNextSecretMap(currentLevel);
|
||||
}
|
||||
|
||||
void levelTryPlayMusic()
|
||||
|
|
|
@ -41,7 +41,6 @@ enum
|
|||
enum EGameFlag
|
||||
{
|
||||
GF_AdvanceLevel = 1,
|
||||
GF_EndGame = 2,
|
||||
// 4 was for playing intro cutscenes but is no longer used.
|
||||
GF_PlayCutscene = 8,
|
||||
};
|
||||
|
@ -72,7 +71,7 @@ extern GAMEOPTIONS gGameOptions;
|
|||
extern int gSkill;
|
||||
extern char BloodIniFile[];
|
||||
extern bool bINIOverride;
|
||||
extern int gNextLevel;
|
||||
extern MapRecord* gNextLevel;
|
||||
extern bool gGameStarted;
|
||||
|
||||
void levelInitINI(const char *pzIni);
|
||||
|
|
|
@ -641,7 +641,6 @@ void SerializeState(FSerializer& arc)
|
|||
("modern", gModernMap)
|
||||
#endif
|
||||
("cheating", bPlayerCheated)
|
||||
("nextlevel", gNextLevel)
|
||||
("skyhoriz", pSky->horizfrac)
|
||||
("skyy", pSky->yoffs)
|
||||
("scale", pSky->yscale)
|
||||
|
|
|
@ -268,7 +268,7 @@ static int parseArgs(char *pzArgs, int *nArg1, int *nArg2)
|
|||
if (!nArg1 || !nArg2 || strlen(pzArgs) < 3)
|
||||
return -1;
|
||||
*nArg1 = pzArgs[0] - '0';
|
||||
*nArg2 = (pzArgs[1] - '0')*10+(pzArgs[2]-'0') - 1;
|
||||
*nArg2 = (pzArgs[1] - '0')*10+(pzArgs[2]-'0');
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ static bool cheatMario(cheatseq_t* c)
|
|||
int nEpisode, nLevel;
|
||||
if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2)
|
||||
{
|
||||
auto map = FindMapByLevelNum(makelevelnum(nEpisode, nLevel));
|
||||
auto map = FindMapByIndex(nEpisode, nLevel);
|
||||
if (map) DeferedStartGame(map, -1);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -5215,13 +5215,7 @@ void seqSpawnerOffSameTx(XSPRITE* pXSource) {
|
|||
void levelEndLevelCustom(int nLevel) {
|
||||
|
||||
gGameOptions.uGameFlags |= GF_AdvanceLevel;
|
||||
|
||||
if (nLevel >= 16 || nLevel < 0) {
|
||||
gGameOptions.uGameFlags |= GF_EndGame;
|
||||
return;
|
||||
}
|
||||
|
||||
gNextLevel = nLevel;
|
||||
gNextLevel = FindMapByIndex(currentLevel->cluster, nLevel + 1);
|
||||
}
|
||||
|
||||
void callbackUniMissileBurst(int nSprite) // 22
|
||||
|
|
|
@ -292,11 +292,11 @@ static bool cheatItems(int player)
|
|||
static bool cheatLevel(cheatseq_t *s)
|
||||
{
|
||||
int volnume,levnume;
|
||||
volnume = s->Args[0] - '0' - 1;
|
||||
levnume = (s->Args[1] - '0')*10+(s->Args[2]-'0') - 1;
|
||||
volnume = s->Args[0] - '0';
|
||||
levnume = (s->Args[1] - '0')*10+(s->Args[2]-'0');
|
||||
|
||||
// Instead of hard coded range checks on volume and level, let's just check if the level is defined.
|
||||
auto map = FindMapByLevelNum(makelevelnum(volnume, levnume));
|
||||
auto map = FindMapByIndex(volnume, levnume);
|
||||
if (map)
|
||||
{
|
||||
ChangeLevel(map, -1);
|
||||
|
|
Loading…
Reference in a new issue