Implement new nextmap logic for the enhanced lastmap

This commit is contained in:
Mia McMahill 2025-06-30 19:26:37 -05:00
parent 5f8ea94caa
commit 74701da267
6 changed files with 42 additions and 33 deletions

View file

@ -20,9 +20,9 @@
//
//-----------------------------------------------------------------------------
#ifndef __C_MAPLIST__
#define __C_MAPLIST__
#pragma once
#include <nonstd/expected.hpp>
// Maplist statuses
enum maplist_status_t
@ -50,11 +50,13 @@ inline auto format_as(maplist_status_t eStatus)
}
struct maplist_lastmaps_t {
std::vector<std::pair<OLumpName, OLumpName>> entries;
std::vector<std::pair<std::string, std::string>> entries;
bool empty() const {
return entries.empty();
}
static nonstd::expected<maplist_lastmaps_t, std::string> parse(const std::string& lastmaps);
};
// Map list entry structure
@ -90,5 +92,3 @@ inline auto format_as(const maplist_lastmaps_t& lastmaps)
// Query result
typedef std::pair<size_t, maplist_entry_t*> maplist_qrow_t;
typedef std::vector<maplist_qrow_t> maplist_qrows_t;
#endif

View file

@ -368,7 +368,7 @@ StringTokens TokenizeString(const std::string& str, const std::string& delim) {
while (delimPos != std::string::npos) {
delimPos = str.find(delim, prevDelim);
tokens.push_back(str.substr(prevDelim, delimPos - prevDelim));
prevDelim = delimPos + 1;
prevDelim = delimPos + delim.length();
}
return tokens;

View file

@ -30,6 +30,7 @@
#include "c_console.h"
#include "c_dispatch.h"
#include "c_maplist.h"
#include "d_event.h"
#include "d_main.h"
#include "g_game.h"
@ -46,7 +47,7 @@
#include "w_ident.h"
level_locals_t level; // info about current level
std::string forcedlastmap; // forced last map for the current wad
maplist_lastmaps_t forcedlastmaps; // forced last map for the current wad
level_pwad_info_t g_EmptyLevel;
cluster_info_t g_EmptyCluster;
@ -394,7 +395,7 @@ const char *ParseString2(const char *data);
// Takes a string of random wads and patches, which is sorted through and
// trampolined to the implementation of G_LoadWad.
//
bool G_LoadWadString(const std::string& str, const std::string& mapname, const std::string& lastmap)
bool G_LoadWadString(const std::string& str, const std::string& mapname, const maplist_lastmaps_t& lastmaps)
{
const std::vector<std::string>& wad_exts = M_FileTypeExts(OFILE_WAD);
const std::vector<std::string>& deh_exts = M_FileTypeExts(OFILE_DEH);
@ -452,7 +453,7 @@ bool G_LoadWadString(const std::string& str, const std::string& mapname, const s
continue;
}
forcedlastmap = StdStringToUpper(lastmap);
forcedlastmaps = lastmaps;
return G_LoadWad(newwadfiles, newpatchfiles, mapname);
}

View file

@ -24,6 +24,7 @@
#pragma once
#include "cmdlib.h"
#include "c_maplist.h"
#include "m_fixed.h"
#include "m_resfile.h"
#include "olumpname.h"
@ -489,7 +490,7 @@ void P_RemoveDefereds();
bool G_LoadWad(const OWantFiles& newwadfiles, const OWantFiles& newpatchfiles,
const std::string& mapname = "");
bool G_LoadWadString(const std::string& str, const std::string& mapname = "", const std::string& lastmap = "");
bool G_LoadWadString(const std::string& str, const std::string& mapname = "", const maplist_lastmaps_t& lastmaps = {});
LevelInfos& getLevelInfos();
ClusterInfos& getClusterInfos();

View file

@ -75,7 +75,7 @@ EXTERN_CVAR (sv_teamsinplay)
EXTERN_CVAR(g_resetinvonexit)
extern int mapchange;
extern std::string forcedlastmap;
extern maplist_lastmaps_t forcedlastmaps;
// [AM] Stores the reset snapshot
FLZOMemFile *reset_snapshot = NULL;
@ -165,16 +165,20 @@ BEGIN_COMMAND (wad) // denis - changes wads
}
std::string lastmap = argv[argc-1];
maplist_lastmaps_t lastmaps;
if (lastmap.rfind("lastmap=", 0) == 0)
{
lastmap = lastmap.substr(8);
auto lastmap_result = maplist_lastmaps_t::parse(lastmap.substr(8));
if (!lastmap_result) {
PrintFmt(PRINT_HIGH, "Failed to parse lastmap: {}\n", lastmap_result.error());
return;
}
lastmaps = lastmap_result.value();
argc--;
}
else
lastmap = "";
std::string wadstr = C_EscapeWadList(VectorArgs(argc, argv));
G_LoadWadString(wadstr, "", lastmap);
G_LoadWadString(wadstr, "", lastmaps);
}
END_COMMAND (wad)
@ -184,7 +188,12 @@ EXTERN_CVAR(sv_shufflemaplist)
bool isLastMap()
{
return level.nextmap == "" || level.mapname == forcedlastmap;
return level.nextmap.empty() ||
std::any_of(
forcedlastmaps.entries.begin(), forcedlastmaps.entries.end(),
[&](const auto& entry) {
return entry.first == level.mapname && (entry.second.empty() || entry.second == level.nextmap);
});
}
// Returns the next map, assuming there is no maplist.
@ -193,7 +202,7 @@ OLumpName G_NextMap()
{
OLumpName next = level.nextmap;
if (gamestate == GS_STARTUP || (sv_gametype != GM_COOP && forcedlastmap.empty()) || next.empty())
if (gamestate == GS_STARTUP || (sv_gametype != GM_COOP && forcedlastmaps.empty()) || next.empty())
{
// if not coop, and lastmap is not specified, stay on same level
// [ML] 1/25/10: OR if next is empty
@ -207,9 +216,9 @@ OLumpName G_NextMap()
// NES - exiting a Doom 1 episode moves to the next episode,
// rather than always going back to E1M1
if (level.nextmap == "" || level.mapname == forcedlastmap ||
(next.substr(0, 7) == "EndGame") ||
(gamemode == retail_chex && (level.nextmap == "E1M6")))
if (isLastMap() ||
(next.substr(0, 7) == "EndGame") ||
(gamemode == retail_chex && (level.nextmap == "E1M6")))
{
if (gameinfo.flags & GI_MAPxx || gamemode == shareware ||
(((gamemode == registered && level.cluster == 3) ||
@ -247,7 +256,7 @@ void G_ChangeMap()
else
{
size_t next_index;
if ((!forcedlastmap.empty() && !isLastMap()) || !Maplist::instance().get_next_index(next_index))
if ((!forcedlastmaps.empty() && !isLastMap()) || !Maplist::instance().get_next_index(next_index))
{
// We don't have a maplist, so grab the next 'natural' map lump.
G_DeferedInitNew(G_NextMap());
@ -258,7 +267,7 @@ void G_ChangeMap()
Maplist::instance().get_map_by_index(next_index, maplist_entry);
std::string wadstr = C_EscapeWadList(maplist_entry.wads);
G_LoadWadString(wadstr, maplist_entry.map, maplist_entry.lastmap);
G_LoadWadString(wadstr, maplist_entry.map, maplist_entry.lastmaps);
// Set the new map as the current map
Maplist::instance().set_index(next_index);
@ -284,7 +293,7 @@ void G_ChangeMap(size_t index) {
}
std::string wadstr = C_EscapeWadList(maplist_entry.wads);
G_LoadWadString(wadstr, maplist_entry.map, maplist_entry.lastmap);
G_LoadWadString(wadstr, maplist_entry.map, maplist_entry.lastmaps);
// Set the new map as the current map
Maplist::instance().set_index(index);

View file

@ -25,7 +25,6 @@
#include <algorithm>
#include <sstream>
#include <nonstd/expected.hpp>
#include "c_maplist.h"
#include "sv_maplist.h"
@ -641,21 +640,20 @@ void Maplist_Disconnect(player_t &player) {
//////// CONSOLE COMMANDS ////////
// TODO: since this is needed for the wad command too, move this to c_maplist.h or smth and make it a static method
nonstd::expected<maplist_lastmaps_t, std::string> ParseLastmaps(const std::string& lastmaps) {
nonstd::expected<maplist_lastmaps_t, std::string> maplist_lastmaps_t::parse(const std::string& lastmaps) {
StringTokens entries = TokenizeString(lastmaps, ",");
maplist_lastmaps_t result;
for (const auto& entry : entries) {
if (entry.empty()) {
return nonstd::make_unexpected("Empty lastmap entry found.");
return nonstd::make_unexpected(fmt::format("Empty lastmap entry found in {}", lastmaps));
}
StringTokens maps = TokenizeString(entry, "->");
if (maps.size() == 1)
result.entries.push_back({ entry, "" });
StringTokens maps = TokenizeString(StdStringToUpper(entry), "->");
if (maps.size() == 1 && maps[0].find("->") == std::string::npos)
result.entries.push_back({ maps[0], "" });
else if (maps.size() == 2)
result.entries.push_back({ maps[0], maps[1] });
else {
return nonstd::make_unexpected(fmt::format("Invalid lastmap entry: {}", entry));
return nonstd::make_unexpected(fmt::format("Invalid lastmap entry: {} in {}", entry, lastmaps));
}
}
return result;
@ -701,7 +699,7 @@ BEGIN_COMMAND (addmap) {
std::string lastmap = argv[argc-1];
if (lastmap.rfind("lastmap=", 0) == 0)
{
auto lastmap_result = ParseLastmaps(lastmap.substr(8));
auto lastmap_result = maplist_lastmaps_t::parse(lastmap.substr(8));
if (!lastmap_result) {
PrintFmt(PRINT_HIGH, "Failed to parse lastmap: {}\n", lastmap_result.error());
return;
@ -740,7 +738,7 @@ BEGIN_COMMAND(insertmap) {
std::string lastmap = argv[argc-1];
if (lastmap.rfind("lastmap=", 0) == 0)
{
auto lastmap_result = ParseLastmaps(lastmap.substr(8));
auto lastmap_result = maplist_lastmaps_t::parse(lastmap.substr(8));
if (!lastmap_result) {
PrintFmt(PRINT_HIGH, "Failed to parse lastmap: {}\n", lastmap_result.error());
return;