Skip to content

Commit

Permalink
All Games|libcommon: Improved -episode and -warp to support episode IDs
Browse files Browse the repository at this point in the history
One can now specify an episode in textual, id form to both -episode
and -warp from the command line. Note that both options still behave
the same as vanilla if episode numbers are supplied instead.
  • Loading branch information
danij-deng committed Aug 12, 2014
1 parent c920d8f commit 2fddb19
Show file tree
Hide file tree
Showing 14 changed files with 283 additions and 403 deletions.
3 changes: 0 additions & 3 deletions doomsday/plugins/common/include/common.h
Expand Up @@ -51,9 +51,6 @@
# include <doomsday/filesys/lumpindex.h>
#endif

DENG_EXTERN_C dd_bool sc_FileScripts;
DENG_EXTERN_C char const *sc_ScriptsDir;

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
5 changes: 3 additions & 2 deletions doomsday/plugins/common/include/g_common.h
Expand Up @@ -121,8 +121,9 @@ char const *G_InFineBriefing(de::Uri const *mapUri = 0);
char const *G_InFineDebriefing(de::Uri const *mapUri = 0);

/**
* @param mapUri Identifier of the episode to lookup the title of. Can be @c 0 in which
* case the title for the @em current episode will be returned (if set).
* @param episodeId Identifier of the episode to lookup the title of. Can be @c 0 in
* which case the title for the @em current episode will be returned
* (if set).
*/
de::String G_EpisodeTitle(de::String const *episodeId = 0);

Expand Down
3 changes: 2 additions & 1 deletion doomsday/plugins/common/include/g_defs.h
Expand Up @@ -38,12 +38,13 @@ ded_t &Defs();
* better handling of map resources and their references. Instead, use the map URI
* mechanism.
*
* @param episode Episode identifier.
* @param warpNumber Warp number to translate.
*
* @return The unique identifier of the map. If no game session is in progress or the
* warp number is not found, the URI "Maps:" is returned.
*/
de::Uri TranslateMapWarpNumber(uint warpNumber);
de::Uri TranslateMapWarpNumber(de::String const &episodeId, uint warpNumber);

extern "C" {
#endif
Expand Down
15 changes: 5 additions & 10 deletions doomsday/plugins/common/src/common.c
@@ -1,9 +1,7 @@
/**
* @file common.c
* Top-level libcommon routines.
/** @file common.c Top-level libcommon routines.
*
* @authors Copyright &copy; 2012-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright &copy; 2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2012-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2013-2014 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand All @@ -23,9 +21,6 @@
#include "common.h"
#include "g_common.h"

dd_bool sc_FileScripts = false;
char const *sc_ScriptsDir = "";

int Common_GetInteger(int id)
{
switch(id)
Expand All @@ -35,9 +30,9 @@ int Common_GetInteger(int id)
// manually save the game before, e.g., upgrading to a new version.
return G_GameState() == GS_MAP;

default:
break;
default: break;
}

return 0;
}

4 changes: 2 additions & 2 deletions doomsday/plugins/common/src/g_defs.cpp
Expand Up @@ -58,9 +58,9 @@ void GetDefState(char const *def, int *val)
if(*val < 0) *val = 0;
}

de::Uri TranslateMapWarpNumber(uint warpNumber)
de::Uri TranslateMapWarpNumber(String const &episodeId, uint warpNumber)
{
if(Record const *rec = COMMON_GAMESESSION->episodeDef())
if(Record const *rec = Defs().episodes.tryFind("id", episodeId))
{
defn::Episode episodeDef(*rec);
if(Record const *mgNodeRec = episodeDef.tryFindMapGraphNodeByWarpNumber(warpNumber))
Expand Down
147 changes: 137 additions & 10 deletions doomsday/plugins/common/src/g_game.cpp
Expand Up @@ -23,6 +23,17 @@
#include "common.h"
#include "g_common.h"

#include <cctype>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <de/App>
#include <de/NativePath>
#include <de/RecordValue>
#include <doomsday/defs/episode.h>
#include <doomsday/uri.h>

#include "am_map.h"
#include "animdefs.h"
#include "d_net.h"
Expand Down Expand Up @@ -57,16 +68,6 @@
#include "saveslots.h"
#include "x_hair.h"

#include <cctype>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <de/App>
#include <de/NativePath>
#include <doomsday/defs/episode.h>
#include <doomsday/uri.h>

using namespace de;
using namespace common;

Expand Down Expand Up @@ -1026,6 +1027,132 @@ void G_CommonPostInit()
DD_Execute(true, "listmaps");
}

void G_AutoStartOrBeginTitleLoop()
{
CommandLine &cmdLine = DENG2_APP->commandLine();

String startEpisodeId;
de::Uri startMapUri;

// A specific episode?
if(int arg = cmdLine.check("-episode", 1))
{
String episodeId = cmdLine.at(arg + 1);
if(Record const *episodeDef = Defs().episodes.tryFind("id", episodeId))
{
// Ensure this is a playable episode.
de::Uri startMap(episodeDef->gets("startMap"), RC_NULL);
if(P_MapExists(startMap.compose().toUtf8().constData()))
{
startEpisodeId = episodeId;
}
}
}

// A specific map?
if(int arg = cmdLine.check("-warp", 1))
{
bool haveEpisode = (arg + 2 < cmdLine.count() && !cmdLine.isOption(arg + 2));
if(haveEpisode)
{
if(Record const *episodeDef = Defs().episodes.tryFind("id", cmdLine.at(arg + 1)))
{
// Ensure this is a playable episode.
de::Uri startMap(episodeDef->gets("startMap"), RC_NULL);
if(P_MapExists(startMap.compose().toUtf8().constData()))
{
startEpisodeId = episodeDef->gets("id");
}
}
}

// The map.
bool isNumber;
int oldMapNumber = cmdLine.at(arg + (haveEpisode? 2 : 1)).toInt(&isNumber);
#if !__JHEXEN__
if(oldMapNumber > 0) oldMapNumber -= 1; // zero-based.
#endif

if(!isNumber)
{
// It must be a URI, then.
Block rawMapUri = cmdLine.at(arg + (haveEpisode? 2 : 1)).toUtf8();
char *args[1] = { const_cast<char *>(rawMapUri.constData()) };
startMapUri = de::Uri::fromUserInput(args, 1);
if(startMapUri.scheme().isEmpty()) startMapUri.setScheme("Maps");
}
else if(!startEpisodeId.isEmpty())
{
#if __JHEXEN__
// Map numbers must be translated in the context of an episode.
startMapUri = TranslateMapWarpNumber(startEpisodeId, oldMapNumber);
#else
int oldEpisodeNumber = startEpisodeId.toInt(&isNumber);
if(oldEpisodeNumber > 0) oldEpisodeNumber -= 1; // zero-based.
if(isNumber)
{
startMapUri = G_ComposeMapUri(oldEpisodeNumber, oldMapNumber);
}
#endif
}
else
{
startMapUri = G_ComposeMapUri(0, oldMapNumber);
}
}

// Are we attempting an auto-start?
bool autoStart = (IS_NETGAME || !startEpisodeId.isEmpty() || !startMapUri.isEmpty());
if(autoStart)
{
if(startEpisodeId.isEmpty())
{
// Pick the first playable episode.
auto const &episodesById = Defs().episodes.lookup("id").elements();
DENG2_FOR_EACH_CONST(DictionaryValue::Elements, i, episodesById)
{
Record const &episodeDef = *i->second->as<RecordValue>().record();
de::Uri startMap(episodeDef.gets("startMap"), RC_NULL);
if(P_MapExists(startMap.compose().toUtf8().constData()))
{
startEpisodeId = episodeDef.gets("id");
break;
}
}
}

// Ensure that the map exists.
if(!P_MapExists(startMapUri.compose().toUtf8().constData()))
{
startMapUri.clear();

// Pick the start map from the episode, if specified and playable.
if(Record const *episodeDef = Defs().episodes.tryFind("id", startEpisodeId))
{
de::Uri startMap(episodeDef->gets("startMap"), RC_NULL);
if(P_MapExists(startMap.compose().toUtf8().constData()))
{
startMapUri = startMap;
}
}
}
}

// Are we auto-starting?
if(!startEpisodeId.isEmpty() && !startMapUri.isEmpty())
{
LOG_NOTE("Auto-starting episode '%s', map \"%s\", skill %i")
<< startEpisodeId
<< startMapUri
<< ::defaultGameRules.skill;
G_SetGameActionNewSession(::defaultGameRules, startEpisodeId, startMapUri);
}
else
{
COMMON_GAMESESSION->endAndBeginTitle(); // Start up intro loop.
}
}

/**
* Common game shutdown routine.
* @note Game-specific actions should be placed in G_Shutdown rather than here.
Expand Down
6 changes: 6 additions & 0 deletions doomsday/plugins/doom/include/g_game.h
Expand Up @@ -72,6 +72,12 @@ void G_CommonPreInit(void);
*/
void G_CommonPostInit(void);

/**
* To be called post-game initialization, to examine the command line to determine if
* a new game session should be started automatically, or, begin the title loop.
*/
void G_AutoStartOrBeginTitleLoop(void);

void G_CommonShutdown(void);

void R_InitRefresh(void);
Expand Down

0 comments on commit 2fddb19

Please sign in to comment.