- Externalized all default episode definitions. Added an 'optional' keyword

to handle M4 and 5 in Doom and Heretic.
- Added P_CheckMapData functions and replaced all calls to P_OpenMapData that
  only checked for a map's presence with it.
- Added Martin Howe's player statusbar face submission.
- Added an 'adddefaultmap' option for MAPINFO. This is the same as 'defaultmap'
  but keeps all existing information in the default and just adds to it. This
  is needed because Hexen and Strife set some information in their base
  MAPINFO and using 'defaultmap' in a PWAD would override that.
- Fixed: Using MAPINFO's f1 option could cause memory leaks.
- Added option to load lumps by full name to several places:
  * Finale texts loaded from a text lump
  * Demos
  * Local SNDINFOs
  * Local SNDSEQs
  * Image names in FONTDEFS
  * intermission script names
- Changed the STCFN121 handling. The character is not an 'I' but a '|' so
  instead of discarding it it should be inserted at position 124.
- Renamed indexfont.fon to indexfont so that I could remove a special case
  from V_GetFont that was just added for this one font.
- Added a 'dumpspawnedthings' CVAR that enables a listing of all things in 
  the map and the actor type they spawned.


SVN r882 (trunk)
This commit is contained in:
Christoph Oelckers 2008-04-05 12:14:33 +00:00
parent 7b23f6eb8b
commit e105a29e99
34 changed files with 409 additions and 318 deletions

View file

@ -1,3 +1,28 @@
April 5, 2008 (Changes by Graf Zahl)
- Externalized all default episode definitions. Added an 'optional' keyword
to handle M4 and 5 in Doom and Heretic.
- Added P_CheckMapData function and replaced all calls to P_OpenMapData that
only checked for a map's presence with it.
- Added Martin Howe's player statusbar face submission.
- Added an 'adddefaultmap' option for MAPINFO. This is the same as 'defaultmap'
but keeps all existing information in the default and just adds to it. This
is needed because Hexen and Strife set some information in their base
MAPINFO and using 'defaultmap' in a PWAD would override that.
- Fixed: Using MAPINFO's f1 option could cause memory leaks.
- Added option to load lumps by full name to several places:
* Finale texts loaded from a text lump
* Demos
* Local SNDINFOs
* Local SNDSEQs
* Image names in FONTDEFS
* intermission script names
- Changed the STCFN121 handling. The character is not an 'I' but a '|' so
instead of discarding it it should be inserted at position 124.
- Renamed indexfont.fon to indexfont so that I could remove a special case
from V_GetFont that was just added for this one font.
- Added a 'dumpspawnedthings' CVAR that enables a listing of all things in
the map and the actor type they spawned.
April 5, 2008 (SBarInfo Update #16)
- Added: fillzeros flag for drawnumber. When set the string will always have
a length of the specified size and zeros will fill in for the missing places.

View file

@ -266,12 +266,10 @@ CCMD (idclev)
// Catch invalid maps.
mapname = CalcMapName (epsd, map);
MapData * mapd = P_OpenMapData(mapname);
if (mapd == NULL)
if (!P_CheckMapData(mapname))
return;
// So be it.
delete mapd;
Printf ("%s\n", GStrings("STSTR_CLEV"));
G_DeferedInitNew (mapname);
players[0].health = 0; // Force reset
@ -293,11 +291,9 @@ CCMD (hxvisit)
{
// Just because it's in MAPINFO doesn't mean it's in the wad.
MapData * map = P_OpenMapData(mapname);
if (map != NULL)
if (P_CheckMapData(mapname))
{
// So be it.
delete map;
Printf ("%s\n", GStrings("STSTR_CLEV"));
G_DeferedInitNew (mapname);
return;
@ -323,14 +319,12 @@ CCMD (changemap)
if (argv.argc() > 1)
{
MapData * map = P_OpenMapData(argv[1]);
if (map == NULL)
if (!P_CheckMapData(argv[1]))
{
Printf ("No map %s\n", argv[1]);
}
else
{
delete map;
if (argv.argc() > 2)
{
Net_WriteByte (DEM_CHANGEMAP2);

View file

@ -2184,8 +2184,15 @@ void DoDehPatch (const char *patchfile, bool autoloading)
if (!PatchFile)
{
// Couldn't find it on disk, try reading it from a lump
lump = Wads.CheckNumForFullName(patchfile, true);
if (lump == -1)
{
// Compatibility fallback. It's just here because
// some WAD may need it. Should be deleted it it can
// be confirmed that nothing uses this case.
FString filebase(ExtractFileBase (patchfile));
lump = Wads.CheckNumForName (filebase);
}
if (lump >= 0)
{
filelen = Wads.LumpLength (lump);

View file

@ -1013,10 +1013,8 @@ void D_DoAdvanceDemo (void)
// [RH] If you want something more dynamic for your title, create a map
// and name it TITLEMAP. That map will be loaded and used as the title.
MapData * map = P_OpenMapData("TITLEMAP");
if (map != NULL)
if (P_CheckMapData("TITLEMAP"))
{
delete map;
G_InitNew ("TITLEMAP", true);
return;
}
@ -2281,14 +2279,12 @@ void D_DoomMain (void)
p = Args->CheckParm ("+map");
if (p && p < Args->NumArgs()-1)
{
MapData * map = P_OpenMapData(Args->GetArg (p+1));
if (map == NULL)
if (!P_CheckMapData(Args->GetArg (p+1)))
{
Printf ("Can't find map %s\n", Args->GetArg (p+1));
}
else
{
delete map;
strncpy (startmap, Args->GetArg (p+1), 8);
Args->GetArg (p)[0] = '-';
autostart = true;
@ -2355,10 +2351,6 @@ void D_DoomMain (void)
StartScreen->AppendStatusLine(temp);
}
// [RH] Now that all text strings are set up,
// insert them into the level and cluster data.
G_MakeEpisodes ();
// [RH] Parse through all loaded mapinfo lumps
Printf ("G_ParseMapInfo: Load map definitions.\n");
G_ParseMapInfo ();

View file

@ -51,6 +51,7 @@ enum
APMETA_DisplayName, // display name (used in menus etc.)
APMETA_SoundClass, // sound class
APMETA_Face, // doom status bar face (when used)
APMETA_ColorRange, // skin color range
APMETA_InvulMode,
APMETA_HealingRadius,
@ -252,6 +253,7 @@ public:
int fixedcolormap; // can be set to REDCOLORMAP, etc.
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
int morphTics; // player is a chicken/pig if > 0
BYTE MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed
AWeapon *PremorphWeapon; // ready weapon before morphing
int chickenPeck; // chicken peck countdown
int jumpTics; // delay the next jump for a moment

View file

@ -149,9 +149,6 @@ extern int viewangleoffset;
extern int consoleplayer;
extern level_locals_t level;
// --------------------------------------
// DEMO playback/recording related stuff.
// No demo, there is a human player in charge?

View file

@ -1314,7 +1314,7 @@ static void GetFinaleText (const char *msgLumpName)
{
int msgLump;
msgLump = Wads.CheckNumForName(msgLumpName);
msgLump = Wads.CheckNumForFullName(msgLumpName, true);
if (msgLump != -1)
{
char *textbuf;

View file

@ -2291,11 +2291,11 @@ void G_BeginRecording (const char *startmap)
// G_PlayDemo
//
char defdemoname[128];
FString defdemoname;
void G_DeferedPlayDemo (char *name)
{
strncpy (defdemoname, name, 127);
defdemoname = name;
gameaction = ga_playdemo;
}
@ -2457,7 +2457,7 @@ void G_DoPlayDemo (void)
gameaction = ga_nothing;
// [RH] Allow for demos not loaded as lumps
demolump = Wads.CheckNumForName (defdemoname);
demolump = Wads.CheckNumForFullName (defdemoname, true);
if (demolump >= 0)
{
int demolen = Wads.LumpLength (demolump);
@ -2472,7 +2472,7 @@ void G_DoPlayDemo (void)
}
demo_p = demobuffer;
Printf ("Playing demo %s\n", defdemoname);
Printf ("Playing demo %s\n", defdemoname.GetChars());
C_BackupCVars (); // [RH] Save cvars that might be affected by demo
@ -2520,7 +2520,7 @@ void G_TimeDemo (char* name)
timingdemo = true;
singletics = true;
strncpy (defdemoname, name, 128);
defdemoname = name;
gameaction = ga_playdemo;
}

View file

@ -136,7 +136,7 @@ extern const AInventory *SendItemUse, *SendItemDrop;
void *statcopy; // for statistics driver
level_locals_t level; // info about current level
FLevelLocals level; // info about current level
static TArray<cluster_info_t> wadclusterinfos;
TArray<level_info_t> wadlevelinfos;
@ -179,6 +179,7 @@ static const char *MapInfoTopLevel[] =
"clearepisodes",
"skill",
"clearskills",
"adddefaultmap",
NULL
};
@ -191,6 +192,7 @@ enum
MITL_CLEAREPISODES,
MITL_SKILL,
MITL_CLEARSKILLS,
MITL_ADDDEFAULTMAP,
};
static const char *MapInfoMapLevel[] =
@ -336,7 +338,6 @@ enum EMIType
MITYPE_REDIRECT,
MITYPE_SPECIALACTION,
MITYPE_COMPATFLAG,
MITYPE_F1, // [RC] F1 help
};
struct MapInfoHandler
@ -413,18 +414,18 @@ MapHandlers[] =
{ MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
{ MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
{ MITYPE_LUMPNAME, lioffset(enterpic), 0 },
{ MITYPE_STRING, lioffset(exitpic), 0 },
{ MITYPE_STRING, lioffset(exitpic), 0 },
{ MITYPE_STRING, lioffset(enterpic), 0 },
{ MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) },
{ MITYPE_INT, lioffset(airsupply), 0 },
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_LUMPNAME, lioffset(sndseq), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
{ MITYPE_STRING, lioffset(sndseq), 0 },
{ MITYPE_STRING, lioffset(soundinfo), 0 },
{ MITYPE_STRING, lioffset(soundinfo), 0 },
{ MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 },
{ MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 },
{ MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 },
@ -445,7 +446,7 @@ MapHandlers[] =
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
{ MITYPE_COMPATFLAG, COMPATF_INVISIBILITY},
{ MITYPE_LUMPNAME, lioffset(bordertexture), 0 },
{ MITYPE_F1, lioffset(f1), 0, },
{ MITYPE_LUMPNAME, lioffset(f1), 0, },
{ MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING },
{ MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)},
{ MITYPE_SCFLAGS, LEVEL_TOTALINFIGHTING, ~LEVEL_NOINFIGHTING },
@ -536,10 +537,6 @@ static void SetLevelDefaults (level_info_t *levelinfo)
// For maps without a BEHAVIOR, this will be cleared.
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
}
else
{
levelinfo->flags |= LEVEL_MONSTERFALLINGDAMAGE;
}
levelinfo->airsupply = 10;
}
@ -623,6 +620,48 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *spec)
return spec;
}
static void CopyString (char *& string)
{
if (string != NULL)
string = copystring(string);
}
static void SafeDelete(char *&string)
{
if (string != NULL)
{
delete[] string;
string = NULL;
}
}
static void ClearLevelInfoStrings(level_info_t *linfo)
{
SafeDelete(linfo->music);
SafeDelete(linfo->intermusic);
SafeDelete(linfo->level_name);
SafeDelete(linfo->translator);
SafeDelete(linfo->enterpic);
SafeDelete(linfo->exitpic);
SafeDelete(linfo->soundinfo);
SafeDelete(linfo->sndseq);
for (FSpecialAction *spac = linfo->specialactions; spac != NULL; )
{
FSpecialAction *next = spac->Next;
delete spac;
spac = next;
}
}
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
{
SafeDelete(cinfo->exittext);
SafeDelete(cinfo->entertext);
SafeDelete(cinfo->messagemusic);
SafeDelete(cinfo->clustername);
}
static void G_DoParseMapInfo (int lump)
{
level_info_t defaultinfo;
@ -647,6 +686,11 @@ static void G_DoParseMapInfo (int lump)
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
break;
case MITL_ADDDEFAULTMAP:
// Same as above but adds to the existing definitions instead of replacing them completely
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
break;
case MITL_MAP: // map <MAPNAME> <Nice Name>
levelflags = defaultinfo.flags;
sc.MustGetString ();
@ -664,7 +708,8 @@ static void G_DoParseMapInfo (int lump)
| LEVEL_FALLDMG_HX
| LEVEL_ACTOWNSPECIAL
| LEVEL_MISSILESACTIVATEIMPACT
| LEVEL_INFINITE_FLIGHT;
| LEVEL_INFINITE_FLIGHT
| LEVEL_MONSTERFALLINGDAMAGE;
}
levelindex = FindWadLevelInfo (sc.String);
if (levelindex == -1)
@ -677,18 +722,13 @@ static void G_DoParseMapInfo (int lump)
}
levelinfo = &wadlevelinfos[levelindex];
memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo));
if (levelinfo->music != NULL)
{
levelinfo->music = copystring (levelinfo->music);
}
if (levelinfo->intermusic != NULL)
{
levelinfo->intermusic = copystring (levelinfo->intermusic);
}
if (levelinfo->translator != NULL)
{
levelinfo->translator = copystring (levelinfo->translator);
}
CopyString(levelinfo->music);
CopyString(levelinfo->intermusic);
CopyString(levelinfo->translator);
CopyString(levelinfo->enterpic);
CopyString(levelinfo->exitpic);
CopyString(levelinfo->soundinfo);
CopyString(levelinfo->sndseq);
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
if (HexenHack)
{
@ -699,13 +739,9 @@ static void G_DoParseMapInfo (int lump)
if (sc.Compare ("lookup"))
{
sc.MustGetString ();
ReplaceString (&levelinfo->level_name, sc.String);
levelflags |= LEVEL_LOOKUPLEVELNAME;
}
else
{
ReplaceString (&levelinfo->level_name, sc.String);
}
// Set up levelnum now so that you can use Teleport_NewMap specials
// to teleport to maps with standard names without needing a levelnum.
if (!strnicmp (levelinfo->mapname, "MAP", 3) && levelinfo->mapname[5] == 0)
@ -730,10 +766,6 @@ static void G_DoParseMapInfo (int lump)
{
strcpy (levelinfo->skypic2, levelinfo->skypic1);
}
if (levelinfo->f1 != NULL)
{
levelinfo->f1 = copystring (levelinfo->f1);
}
SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps.
if (levelinfo->pname[0] != 0)
{
@ -755,22 +787,7 @@ static void G_DoParseMapInfo (int lump)
else
{
clusterinfo = &wadclusterinfos[clusterindex];
if (clusterinfo->entertext != NULL)
{
delete[] clusterinfo->entertext;
}
if (clusterinfo->exittext != NULL)
{
delete[] clusterinfo->exittext;
}
if (clusterinfo->messagemusic != NULL)
{
delete[] clusterinfo->messagemusic;
}
if (clusterinfo->clustername != NULL)
{
delete[] clusterinfo->clustername;
}
ClearClusterInfoStrings(clusterinfo);
}
memset (clusterinfo, 0, sizeof(cluster_info_t));
clusterinfo->cluster = sc.Number;
@ -798,60 +815,6 @@ static void G_DoParseMapInfo (int lump)
ClearLevelInfoStrings(&defaultinfo);
}
static void ClearLevelInfoStrings(level_info_t *linfo)
{
if (linfo->music != NULL)
{
delete[] linfo->music;
linfo->music = NULL;
}
if (linfo->intermusic != NULL)
{
delete[] linfo->intermusic;
linfo->intermusic = NULL;
}
if (linfo->level_name != NULL)
{
delete[] linfo->level_name;
linfo->level_name = NULL;
}
if (linfo->translator != NULL)
{
delete[] linfo->translator;
linfo->translator = NULL;
}
for (FSpecialAction *spac = linfo->specialactions; spac != NULL; )
{
FSpecialAction *next = spac->Next;
delete spac;
spac = next;
}
}
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
{
if (cinfo->exittext != NULL)
{
delete[] cinfo->exittext;
cinfo->exittext = NULL;
}
if (cinfo->entertext != NULL)
{
delete[] cinfo->entertext;
cinfo->entertext = NULL;
}
if (cinfo->messagemusic != NULL)
{
delete[] cinfo->messagemusic;
cinfo->messagemusic = NULL;
}
if (cinfo->clustername != NULL)
{
delete[] cinfo->clustername;
cinfo->clustername = NULL;
}
}
static void ClearEpisodes()
{
for (int i = 0; i < EpiDef.numitems; ++i)
@ -916,13 +879,6 @@ static void ParseMapInfoLower (FScanner &sc,
case MITYPE_REDIRECT:
sc.MustGetString ();
levelinfo->RedirectType = sc.String;
/*
if (levelinfo->RedirectType == NULL ||
!(levelinfo->RedirectType->IsDescendantOf (RUNTIME_CLASS(AInventory))))
{
SC_ScriptError ("%s is not an inventory item", sc.String);
}
*/
// Intentional fall-through
case MITYPE_MAPNAME: {
@ -1077,18 +1033,6 @@ static void ParseMapInfoLower (FScanner &sc,
ReplaceString ((char **)(info + handler->data1), sc.String);
break;
case MITYPE_F1:
sc.MustGetString ();
{
char *colon = strchr (sc.String, ':');
if (colon)
{
*colon = 0;
}
ReplaceString ((char **)(info + handler->data1), sc.String);
}
break;
case MITYPE_MUSIC:
sc.MustGetString ();
{
@ -1190,6 +1134,7 @@ static void ParseEpisodeInfo (FScanner &sc)
bool remove = false;
char key = 0;
bool noskill = false;
bool optional = false;
// Get map name
sc.MustGetString ();
@ -1208,7 +1153,12 @@ static void ParseEpisodeInfo (FScanner &sc)
}
do
{
if (sc.Compare ("name"))
if (sc.Compare ("optional"))
{
// For M4 in Doom and M4 and M5 in Heretic
optional = true;
}
else if (sc.Compare ("name"))
{
sc.MustGetString ();
ReplaceString (&pic, sc.String);
@ -1241,6 +1191,17 @@ static void ParseEpisodeInfo (FScanner &sc)
}
while (sc.GetString ());
if (optional && !remove)
{
if (!P_CheckMapData(map))
{
// If the episode is optional and the map does not exist
// just ignore this episode definition.
return;
}
}
for (i = 0; i < EpiDef.numitems; ++i)
{
if (strncmp (EpisodeMaps[i], map, 8) == 0)
@ -1408,8 +1369,8 @@ void P_RemoveDefereds (void)
bool CheckWarpTransMap (char mapname[9], bool substitute)
{
if (mapname[0] == '&' && mapname[1] == 'w' &&
mapname[2] == 't' && mapname[3] == '@')
if (mapname[0] == '&' && (mapname[1]&223) == 'W' &&
(mapname[2]&223) == 'T' && mapname[3] == '@')
{
level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4));
if (lev != NULL)
@ -1457,12 +1418,12 @@ CCMD (map)
}
if (argv.argc() > 1)
{
MapData * map = P_OpenMapData(argv[1]);
if (map == NULL)
if (!P_CheckMapData(argv[1]))
{
Printf ("No map %s\n", argv[1]);
}
else
{
delete map;
G_DeferedInitNew (argv[1]);
}
}
@ -1482,12 +1443,12 @@ CCMD (open)
if (argv.argc() > 1)
{
sprintf(d_mapname, "file:%s", argv[1]);
MapData * map = P_OpenMapData(d_mapname);
if (map == NULL)
if (!P_CheckMapData(d_mapname))
{
Printf ("No map %s\n", d_mapname);
}
else
{
delete map;
gameaction = ga_newgame2;
d_skill = -1;
}
@ -1638,12 +1599,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
}
// [RH] If this map doesn't exist, bomb out
MapData * map = P_OpenMapData(mapname);
if (!map)
if (!P_CheckMapData(mapname))
{
I_Error ("Could not find map %s\n", mapname);
}
delete map;
oldSpeed = GameSpeed;
wantFast = !!G_SkillProperty(SKILLP_FastMonsters);
@ -1815,10 +1774,8 @@ const char *G_GetSecretExitMap()
if (level.secretmap[0] != 0)
{
MapData *map = P_OpenMapData(level.secretmap);
if (map != NULL)
if (P_CheckMapData(level.secretmap))
{
delete map;
nextmap = level.secretmap;
}
}
@ -2061,7 +2018,7 @@ void G_DoLoadLevel (int position, bool autosave)
// DOOM determines the sky texture to be used
// depending on the current episode and the game version.
// [RH] Fetch sky parameters from level_locals_t.
// [RH] Fetch sky parameters from FLevelLocals.
sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
@ -2421,7 +2378,6 @@ void G_InitLevelLocals ()
level.levelnum = info->levelnum;
level.music = info->music;
level.musicorder = info->musicorder;
level.f1 = info->f1; // [RC] And import the f1 name
strncpy (level.level_name, info->level_name, 63);
G_MaybeLookupLevelName (NULL);
@ -2454,7 +2410,7 @@ void G_InitLevelLocals ()
NormalLight.ChangeFade (level.fadeto);
}
bool level_locals_s::IsJumpingAllowed() const
bool FLevelLocals::IsJumpingAllowed() const
{
if (dmflags & DF_NO_JUMP)
return false;
@ -2463,7 +2419,7 @@ bool level_locals_s::IsJumpingAllowed() const
return !(level.flags & LEVEL_JUMP_NO);
}
bool level_locals_s::IsCrouchingAllowed() const
bool FLevelLocals::IsCrouchingAllowed() const
{
if (dmflags & DF_NO_CROUCH)
return false;
@ -2472,7 +2428,7 @@ bool level_locals_s::IsCrouchingAllowed() const
return !(level.flags & LEVEL_CROUCH_NO);
}
bool level_locals_s::IsFreelookAllowed() const
bool FLevelLocals::IsFreelookAllowed() const
{
if (level.flags & LEVEL_FREELOOK_NO)
return false;
@ -2531,10 +2487,8 @@ level_info_t *CheckLevelRedirect (level_info_t *info)
if (playeringame[i] && players[i].mo->FindInventory (type))
{
// check for actual presence of the map.
MapData * map = P_OpenMapData(info->RedirectMap);
if (map != NULL)
if (P_CheckMapData(info->RedirectMap))
{
delete map;
return FindLevelInfo(info->RedirectMap);
}
break;
@ -2621,90 +2575,6 @@ const char *G_MaybeLookupLevelName (level_info_t *ininfo)
return info != NULL ? info->level_name : NULL;
}
void G_MakeEpisodes ()
{
int i;
// Set the default episodes
if (EpiDef.numitems == 0)
{
static const char eps[5][8] =
{
"E1M1", "E2M1", "E3M1", "E4M1", "E5M1"
};
static const char depinames[4][7] =
{
"M_EPI1", "M_EPI2", "M_EPI3", "M_EPI4"
};
static const char depikeys[4] = { 'k', 't', 'i', 't' };
static const char *hepinames[5] =
{
"$MNU_COTD",
"$MNU_HELLSMAW",
"$MNU_DOME",
"$MNU_OSSUARY",
"$MNU_DEMESNE",
};
static const char hepikeys[5] = { 'c', 'h', 'd', 'o', 's' };
if (gameinfo.flags & GI_MAPxx)
{
if (gameinfo.gametype == GAME_Hexen)
{
// "&wt@01" is a magic name that will become whatever map has
// warptrans 1.
strcpy (EpisodeMaps[0], "&wt@01");
EpisodeMenu[0].name = copystring ("Hexen");
}
else
{
strcpy (EpisodeMaps[0], "MAP01");
EpisodeMenu[0].name = copystring ("Hell on Earth");
}
EpisodeMenu[0].alphaKey = 'h';
EpisodeMenu[0].fulltext = true;
EpiDef.numitems = 1;
}
else if (gameinfo.gametype == GAME_Doom)
{
memcpy (EpisodeMaps, eps, 4*8);
for (i = 0; i < 4; ++i)
{
EpisodeMenu[i].name = copystring (depinames[i]);
EpisodeMenu[i].fulltext = false;
EpisodeMenu[i].alphaKey = depikeys[i];
}
if (gameinfo.flags & GI_MENUHACK_RETAIL)
{
EpiDef.numitems = 4;
}
else
{
EpiDef.numitems = 3;
}
}
else
{
memcpy (EpisodeMaps, eps, 5*8);
for (i = 0; i < 5; ++i)
{
EpisodeMenu[i].name = copystring (hepinames[i]);
EpisodeMenu[i].fulltext = true;
EpisodeMenu[i].alphaKey = hepikeys[i];
}
if (gameinfo.flags & GI_MENUHACK_EXTENDED)
{
EpiDef.numitems = 5;
}
else
{
EpiDef.numitems = 3;
}
}
}
}
void G_AirControlChanged ()
{
if (level.aircontrol <= 256)
@ -3145,7 +3015,7 @@ void P_ReadACSDefereds (PNGHandle *png)
}
void level_locals_s::Tick ()
void FLevelLocals::Tick ()
{
// Reset carry sectors
if (Scrolls != NULL)
@ -3154,7 +3024,7 @@ void level_locals_s::Tick ()
}
}
void level_locals_s::AddScroller (DScroller *scroller, int secnum)
void FLevelLocals::AddScroller (DScroller *scroller, int secnum)
{
if (secnum < 0)
{

View file

@ -130,7 +130,7 @@ struct FSpecialAction
FSpecialAction *Next;
};
struct level_info_s
struct level_info_t
{
char mapname[9];
int levelnum;
@ -146,7 +146,7 @@ struct level_info_s
char *level_name;
char fadetable[9];
SBYTE WallVertLight, WallHorizLight;
const char *f1;
char f1[9];
// TheDefaultLevelInfo initializes everything above this line.
int musicorder;
FCompressedMemFile *snapshot;
@ -172,13 +172,13 @@ struct level_info_s
FName RedirectType;
char RedirectMap[9];
char enterpic[9];
char exitpic[9];
char *enterpic;
char *exitpic;
char *intermusic;
int intermusicorder;
char soundinfo[9];
char sndseq[9];
char *soundinfo;
char *sndseq;
char bordertexture[9];
int fogdensity;
@ -187,8 +187,8 @@ struct level_info_s
FSpecialAction * specialactions;
float teamdamage;
};
typedef struct level_info_s level_info_t;
// [RH] These get zeroed every tic and are updated by thinkers.
struct FSectorScrollValues
@ -196,7 +196,7 @@ struct FSectorScrollValues
fixed_t ScrollX, ScrollY;
};
struct level_locals_s
struct FLevelLocals
{
void Tick ();
void AddScroller (DScroller *, int secnum);
@ -254,15 +254,12 @@ struct level_locals_s
bool FromSnapshot; // The current map was restored from a snapshot
const char *f1;
float teamdamage;
bool IsJumpingAllowed() const;
bool IsCrouchingAllowed() const;
bool IsFreelookAllowed() const;
};
typedef struct level_locals_s level_locals_t;
enum EndTypes
{
@ -310,7 +307,7 @@ typedef struct cluster_info_s cluster_info_t;
#define CLUSTER_LOOKUPEXITTEXT 0x00000010 // Exit text is the name of a language string
#define CLUSTER_LOOKUPENTERTEXT 0x00000020 // Enter text is the name of a language string
extern level_locals_t level;
extern FLevelLocals level;
extern TArray<level_info_t> wadlevelinfos;
@ -360,7 +357,6 @@ void G_InitLevelLocals (void);
void G_AirControlChanged ();
void G_MakeEpisodes (void);
const char *G_MaybeLookupLevelName (level_info_t *level);
cluster_info_t *FindClusterInfo (int cluster);

View file

@ -8,6 +8,7 @@
#include "s_sound.h"
#include "m_random.h"
#include "a_sharedglobal.h"
#include "sbar.h"
#define MORPHTICS (40*TICRATE)
@ -56,6 +57,10 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
{
return false;
}
if (spawntype == p->mo->GetClass())
{
return false;
}
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
DObject::StaticPointerSubstitution (actor, morphed);
@ -78,6 +83,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
actor->flags |= MF_UNMORPHED;
actor->renderflags |= RF_INVISIBLE;
p->morphTics = MORPHTICS;
// [MH] Used by SBARINFO to speed up face drawing
p->MorphedPlayerClass = 0;
for (unsigned int i = 1; i < PlayerClasses.Size (); i++)
{
if (PlayerClasses[i].Type == spawntype)
{
p->MorphedPlayerClass = i;
break;
}
}
p->health = morphed->health;
p->mo = morphed;
p->momx = p->momy = 0;
@ -116,6 +133,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
p->camera = morphed;
}
morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
// [MH]
// If the player that was morphed is the one
// taking events, set up the face, if any;
// this is only needed for old-skool skins
// and for the original DOOM status bar.
if ((p == &players[consoleplayer]) &&
(strcmp(spawntype->Meta.GetMetaString (APMETA_Face), "None") != 0))
{
StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
}
return true;
}
@ -182,6 +211,39 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
{
player->camera = mo;
}
// [MH]
// If the player that was morphed is the one
// taking events, reset up the face, if any;
// this is only needed for old-skool skins
// and for the original DOOM status bar.
if ((player == &players[consoleplayer]) &&
(strcmp(pmo->GetClass()->Meta.GetMetaString (APMETA_Face), "None") != 0))
{
// Assume root-level base skin to begin with
size_t skinindex = 0;
// If a custom skin was in use, then reload it
// or else the base skin for the player class.
if ((unsigned int)player->userinfo.skin >= PlayerClasses.Size () &&
(size_t)player->userinfo.skin < numskins)
{
skinindex = player->userinfo.skin;
}
else if (PlayerClasses.Size () > 1)
{
const PClass *whatami = player->mo->GetClass();
for (unsigned int i = 0; i < PlayerClasses.Size (); ++i)
{
if (PlayerClasses[i].Type == whatami)
{
skinindex = i;
break;
}
}
}
StatusBar->SetFace(&skins[skinindex]);
}
angle = mo->angle >> ANGLETOFINESHIFT;
Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle],
pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);

View file

@ -1178,6 +1178,10 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
//draws an image with the specified flags
void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
{
if (texture == NULL)
{
return;
}
if((flags & DRAWIMAGE_OFFSET_CENTER))
{
x -= (texture->GetWidth()/2)-texture->LeftOffset;
@ -1285,7 +1289,10 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++);
if(currentState != NULL)
{
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, &skins[CPlayer->userinfo.skin], level, angle);
FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin];
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, skin, level, angle);
if (face != NULL)
{
x += ST_X;
y += ST_Y;
int w = face->GetScaledWidth();
@ -1297,6 +1304,7 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
TAG_DONE);
}
}
}
int DSBarInfo::updateState(bool xdth, bool animatedgodmode)
{

View file

@ -247,6 +247,7 @@ enum
ADEF_PlayerPawn_CrouchSprite,
ADEF_PlayerPawn_DisplayName,
ADEF_PlayerPawn_SoundClass,
ADEF_PlayerPawn_Face,
ADEF_PlayerPawn_ScoreIcon,
ADEF_PlayerPawn_MorphWeapon,
ADEF_LastString = ADEF_PlayerPawn_MorphWeapon,

View file

@ -328,6 +328,9 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_PlayerPawn_SoundClass:
sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr);
break;
case ADEF_PlayerPawn_Face:
sgClass->Meta.SetMetaString (APMETA_Face, datastr);
break;
case ADEF_PlayerPawn_ScoreIcon:
player->ScoreIcon = TexMan.AddPatch (datastr);
if (player->ScoreIcon <= 0)

View file

@ -218,8 +218,9 @@ public:
#define PROP_PlayerPawn_CrouchSprite(x) ADD_STRING_PROP(ADEF_PlayerPawn_CrouchSprite,"\24",x)
#define PROP_PlayerPawn_DisplayName(x) ADD_STRING_PROP(ADEF_PlayerPawn_DisplayName,"\25",x)
#define PROP_PlayerPawn_SoundClass(x) ADD_STRING_PROP(ADEF_PlayerPawn_SoundClass,"\26",x)
#define PROP_PlayerPawn_ScoreIcon(x) ADD_STRING_PROP(ADEF_PlayerPawn_ScoreIcon,"\27",x)
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\30",x)
#define PROP_PlayerPawn_Face(x) ADD_STRING_PROP(ADEF_PlayerPawn_Face,"\27",x) // Octal - 'tis quaint!
#define PROP_PlayerPawn_ScoreIcon(x) ADD_STRING_PROP(ADEF_PlayerPawn_ScoreIcon,"\30",x)
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\31",x)
#define PROP_XScale(x) ADD_LONG_PROP(ADEF_XScale,x)
#define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x)

View file

@ -1446,7 +1446,7 @@ void M_QuickLoad ()
//
void M_DrawReadThis ()
{
FTexture *tex, *prevpic = NULL;
FTexture *tex = NULL, *prevpic = NULL;
fixed_t alpha;
if (gameinfo.flags & GI_INFOINDEXED)
@ -1463,11 +1463,15 @@ void M_DrawReadThis ()
}
else
{
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
// Did the mapper choose a custom help page via MAPINFO?
if((level.f1 != NULL) && (strlen(level.f1) > 0))
if (level.info->f1[0] != 0)
{
tex = TexMan.FindTexture(level.f1);
tex = TexMan.FindTexture(level.info->f1);
}
if (tex == NULL)
{
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
}
if (InfoType > 1)

View file

@ -4052,11 +4052,10 @@ AActor *P_SpawnMapThing (mapthing2_t *mthing, int position)
mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360);
mobj->BeginPlay ();
if (mobj->ObjectFlags & OF_EuthanizeMe)
if (!(mobj->ObjectFlags & OF_EuthanizeMe))
{
return NULL;
}
mobj->LevelSpawned ();
}
return mobj;
}

View file

@ -46,6 +46,7 @@
#include "p_lnspec.h"
#include "v_palette.h"
#include "c_console.h"
#include "c_cvars.h"
#include "p_acs.h"
#include "vectors.h"
#include "announcer.h"
@ -279,7 +280,7 @@ MapData *P_OpenMapData(const char * mapname)
if (lumpfile != nextfile)
{
// The following lump is from a different file so whatever this is,
// it is not a multi-lump Doom level.
// it is not a multi-lump Doom level so let's assume it is a Build map.
return map;
}
@ -379,6 +380,13 @@ MapData *P_OpenMapData(const char * mapname)
return map;
}
bool P_CheckMapData(const char *mapname)
{
MapData *mapd = P_OpenMapData(mapname);
if (mapd == NULL) return false;
delete mapd;
return true;
}
//===========================================================================
//
@ -1207,6 +1215,23 @@ void P_LoadNodes (MapData * map)
delete[] mnp;
}
//===========================================================================
//
// SpawnMapThing
//
//===========================================================================
CVAR(Bool, dumpspawnedthings, false, 0)
static void SpawnMapThing(int index, mapthing2_t *mt, int position)
{
AActor *spawned = P_SpawnMapThing(mt, position);
if (dumpspawnedthings)
{
Printf("%5d: (%5d, %5d, %5d), doomednum = %5d, flags = %04x, type = %s\n",
index, mt->x, mt->y, mt->z, mt->type, mt->flags,
spawned? spawned->GetClass()->TypeName.GetChars() : "(none)");
}
}
//===========================================================================
//
@ -1268,7 +1293,7 @@ void P_LoadThings (MapData * map, int position)
mt2.angle = LittleShort(mt->angle);
mt2.type = LittleShort(mt->type);
P_SpawnMapThing (&mt2, position);
SpawnMapThing (i, &mt2, position);
}
delete [] mtp;
}
@ -1712,7 +1737,7 @@ void P_LoadThings2 (MapData * map, int position)
for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++)
{
P_SpawnMapThing (mt, position);
SpawnMapThing (i, mt, position);
}
delete[] mtp;
}
@ -3792,7 +3817,7 @@ void P_SetupLevel (char *lumpname, int position)
{
for (i = 0; i < numbuildthings; ++i)
{
P_SpawnMapThing (&buildthings[i], 0);
SpawnMapThing (i, &buildthings[i], 0);
}
delete[] buildthings;
}

View file

@ -81,6 +81,7 @@ struct MapData
};
MapData * P_OpenMapData(const char * mapname);
bool P_CheckMapData(const char * mapname);
// NOT called by W_Ticker. Fixme. [RH] Is that bad?
//

View file

@ -416,6 +416,7 @@ BEGIN_STATELESS_DEFAULTS (APlayerPawn, Any, -1, 0)
PROP_PlayerPawn_SideMove2 (FRACUNIT)
PROP_PlayerPawn_ColorRange (0, 0)
PROP_PlayerPawn_SoundClass ("player")
PROP_PlayerPawn_Face ("None")
PROP_PlayerPawn_MorphWeapon ("None")
END_DEFAULTS

View file

@ -1046,7 +1046,7 @@ class FPlayerSkin
{
public:
char name[17]; // 16 chars + NULL
char face[3];
char face[4]; // 3 chars ([MH] + NULL so can use as a C string)
BYTE gender; // This skin's gender (not really used)
BYTE range0start;
BYTE range0end;

View file

@ -501,6 +501,7 @@ void R_InitSkins (void)
{
for (j = 2; j >= 0; j--)
skins[i].face[j] = toupper (sc.String[j]);
skins[i].face[3] = '\0';
}
else if (0 == stricmp (key, "gender"))
{
@ -886,11 +887,20 @@ void R_InitSprites ()
for (i = 0; i < PlayerClasses.Size (); i++)
{
const PClass *basetype = PlayerClasses[i].Type;
const char *pclassface = basetype->Meta.GetMetaString (APMETA_Face);
strcpy (skins[i].name, "Base");
if (strcmp(pclassface, "None") == 0)
{
skins[i].face[0] = 'S';
skins[i].face[1] = 'T';
skins[i].face[2] = 'F';
skins[i].face[3] = '\0';
}
else
{
strcpy(skins[i].face, pclassface);
}
skins[i].range0start = basetype->Meta.GetMetaInt (APMETA_ColorRange) & 255;
skins[i].range0end = basetype->Meta.GetMetaInt (APMETA_ColorRange) >> 8;
skins[i].Scale = GetDefaultByType (basetype)->scaleX;

View file

@ -561,7 +561,6 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid,
if (lumpname)
{
lump = Wads.CheckNumForFullName (lumpname, true, ns_sounds);
if (lump == -1) lump = Wads.CheckNumForName (lumpname, ns_sounds);
}
return S_AddPlayerSound (pclass, gender, refid, lump);

View file

@ -379,7 +379,7 @@ void S_Start ()
if (*LocalSndInfo)
{
// Now parse the local SNDINFO
int j = Wads.CheckNumForName(LocalSndInfo);
int j = Wads.CheckNumForFullName(LocalSndInfo, true);
if (j>=0) S_AddLocalSndInfo(j);
}
@ -392,7 +392,7 @@ void S_Start ()
}
if (parse_ss)
{
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForName(LocalSndSeq) : -1);
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForFullName(LocalSndSeq, true) : -1);
}
else

View file

@ -2184,6 +2184,36 @@ static void PlayerSoundClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
bag.Info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
}
//==========================================================================
//
//==========================================================================
static void PlayerFace (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
{
FString tmp;
sc.MustGetString ();
tmp = sc.String;
if (tmp.Len() != 3)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
sc.String, bag.Info->Class->TypeName.GetChars ());
}
tmp.ToUpper();
bool valid = (
(((tmp[0] >= 'A') && (tmp[0] <= 'Z')) || ((tmp[0] >= '0') && (tmp[0] <= '9'))) &&
(((tmp[1] >= 'A') && (tmp[1] <= 'Z')) || ((tmp[1] >= '0') && (tmp[1] <= '9'))) &&
(((tmp[2] >= 'A') && (tmp[2] <= 'Z')) || ((tmp[2] >= '0') && (tmp[2] <= '9')))
);
if (!valid)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
sc.String, bag.Info->Class->TypeName.GetChars ());
}
bag.Info->Class->Meta.SetMetaString (APMETA_Face, tmp);
}
//==========================================================================
//
//==========================================================================
@ -2552,6 +2582,7 @@ static const ActorProps props[] =
{ "player.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) },
{ "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
{ "player.displayname", (apf)PlayerDisplayName, RUNTIME_CLASS(APlayerPawn) },
{ "player.face", (apf)PlayerFace, RUNTIME_CLASS(APlayerPawn) },
{ "player.forwardmove", (apf)PlayerForwardMove, RUNTIME_CLASS(APlayerPawn) },
{ "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
{ "player.hexenarmor", (apf)PlayerHexenArmor, RUNTIME_CLASS(APlayerPawn) },

View file

@ -218,12 +218,6 @@ FFont *V_GetFont(const char *name)
int lump = -1;
lump = Wads.CheckNumForFullName(name, true);
if (lump < 0 && strlen(name) > 8)
{
FString fullname;
fullname.Format("%s.fon", name);
lump = Wads.CheckNumForFullName(fullname);
}
if (lump != -1)
{
@ -293,6 +287,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
double *luminosity;
int maxyoffs;
bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
bool stcfn121 = false;
Chars = new CharData[count];
charlumps = new int[count];
@ -314,17 +309,22 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
lump = Wads.CheckNumForName (buffer, ns_graphics);
if (doomtemplate && lump >= 0 && i + start == 121)
{ // HACKHACK: Don't load STCFN121 in doom(2), because
// it's not really a lower-case 'y' but an upper-case 'I'.
// it's not really a lower-case 'y' but a '|'.
// Because a lot of wads with their own font seem to foolishly
// copy STCFN121 and make it an 'I' themselves, wads must
// copy STCFN121 and make it a '|' themselves, wads must
// provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load.
if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 ||
Wads.CheckNumForName ("STCFN122", ns_graphics) == -1)
{
// insert the incorrectly named '|' graphic in its correct position.
if (count > 124-start) charlumps[124-start] = lump;
lump = -1;
stcfn121 = true;
}
}
if (lump != -1 || i != 124-start || !stcfn121)
charlumps[i] = lump;
if (lump >= 0)
{
FTexture *pic = TexMan[buffer];
@ -1691,7 +1691,7 @@ void V_InitCustomFonts()
if (format == 1) goto wrong;
int *p = &lumplist[*(unsigned char*)sc.String];
sc.MustGetString();
*p = Wads.CheckNumForName (sc.String);
*p = Wads.CheckNumForFullName (sc.String, true);
format=2;
}
}

View file

@ -395,7 +395,7 @@ void WI_LoadBackground(bool isenterpic)
}
else
{
int lumpnum=Wads.GetNumForName(lumpname+1);
int lumpnum=Wads.CheckNumForFullName(lumpname+1, true);
if (lumpnum>=0)
{
FScanner sc(lumpnum);

View file

@ -1,5 +1,24 @@
// MAPINFO for Doom 1 (Shareware, Registered, and Retail)
clearepisodes
episode e1m1
picname "M_EPI1"
key k
episode e2m1
picname "M_EPI2"
key t
episode e3m1
picname "M_EPI3"
key i
episode e4m1
picname "M_EPI4"
key t
optional
// Registered/Retail Episode 1
map E1M1 lookup HUSTR_E1M1

View file

@ -1,5 +1,11 @@
// MAPINFO for Doom 2
clearepisodes
episode map01
name "Hell On Earth"
key h
map MAP01 lookup HUSTR_1
titlepatch CWILV00
next MAP02

View file

@ -31,6 +31,29 @@ skill nightmare
SpawnFilter "Hard"
Name "$MNU_BLACKPLAGUE"
clearepisodes
episode e1m1
name "$MNU_COTD"
key c
episode e2m1
name "$MNU_HELLSMAW"
key h
episode e3m1
name "$MNU_DOME"
key d
episode e4m1
name "$MNU_OSSUARY"
key o
optional
episode e5m1
name "$MNU_DEMESNE"
key s
optional
// Episode 1

View file

@ -48,6 +48,10 @@ skill nightmare
PlayerClassName "cleric" "$MNU_POPE"
PlayerClassName "mage" "$MNU_ARCHMAGE"
clearepisodes
episode "&wt@01"
name "Hexen"
key h
clusterdef 1
hub
@ -84,6 +88,7 @@ defaultmap
nointermission
noautosequences
missilesactivateimpactlines
monsterfallingdamage
// There is also support for showing a clus5msg after cluster 5, but
// since it isn't used, and it would intefere with the finale if I

View file

@ -1,6 +1,11 @@
// MAPINFO for Plutonia. Exactly the same as Doom 2, except it
// has different map names and cluster messages.
clearepisodes
episode map01
name "The Plutonia Experiment"
key t
map MAP01 lookup PHUSTR_1
titlepatch CWILV00
next MAP02

View file

@ -1,6 +1,11 @@
// MAPINFO for TNT. Exactly the same as Doom 2, except it
// has different map names and cluster messages.
clearepisodes
episode map01
name "TNT: Evilution"
key t
map MAP01 lookup THUSTR_1
titlepatch CWILV00
next MAP02

View file

@ -255,7 +255,7 @@ acs/strfhelp.o strfhelp.o
# Font color ranges
textcolors.txt textcolors.txt
fontdefs.txt fontdefs.txt
indexfont.fon indexfont.fon
indexfont indexfont.fon
========
# Decorate stuff