- 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) April 5, 2008 (SBarInfo Update #16)
- Added: fillzeros flag for drawnumber. When set the string will always have - 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. 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. // Catch invalid maps.
mapname = CalcMapName (epsd, map); mapname = CalcMapName (epsd, map);
MapData * mapd = P_OpenMapData(mapname); if (!P_CheckMapData(mapname))
if (mapd == NULL)
return; return;
// So be it. // So be it.
delete mapd;
Printf ("%s\n", GStrings("STSTR_CLEV")); Printf ("%s\n", GStrings("STSTR_CLEV"));
G_DeferedInitNew (mapname); G_DeferedInitNew (mapname);
players[0].health = 0; // Force reset 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. // Just because it's in MAPINFO doesn't mean it's in the wad.
MapData * map = P_OpenMapData(mapname); if (P_CheckMapData(mapname))
if (map != NULL)
{ {
// So be it. // So be it.
delete map;
Printf ("%s\n", GStrings("STSTR_CLEV")); Printf ("%s\n", GStrings("STSTR_CLEV"));
G_DeferedInitNew (mapname); G_DeferedInitNew (mapname);
return; return;
@ -323,14 +319,12 @@ CCMD (changemap)
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
MapData * map = P_OpenMapData(argv[1]); if (!P_CheckMapData(argv[1]))
if (map == NULL)
{ {
Printf ("No map %s\n", argv[1]); Printf ("No map %s\n", argv[1]);
} }
else else
{ {
delete map;
if (argv.argc() > 2) if (argv.argc() > 2)
{ {
Net_WriteByte (DEM_CHANGEMAP2); Net_WriteByte (DEM_CHANGEMAP2);

View file

@ -2184,8 +2184,15 @@ void DoDehPatch (const char *patchfile, bool autoloading)
if (!PatchFile) if (!PatchFile)
{ {
// Couldn't find it on disk, try reading it from a lump // Couldn't find it on disk, try reading it from a lump
FString filebase(ExtractFileBase (patchfile)); lump = Wads.CheckNumForFullName(patchfile, true);
lump = Wads.CheckNumForName (filebase); 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) if (lump >= 0)
{ {
filelen = Wads.LumpLength (lump); 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 // [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. // and name it TITLEMAP. That map will be loaded and used as the title.
MapData * map = P_OpenMapData("TITLEMAP"); if (P_CheckMapData("TITLEMAP"))
if (map != NULL)
{ {
delete map;
G_InitNew ("TITLEMAP", true); G_InitNew ("TITLEMAP", true);
return; return;
} }
@ -2281,14 +2279,12 @@ void D_DoomMain (void)
p = Args->CheckParm ("+map"); p = Args->CheckParm ("+map");
if (p && p < Args->NumArgs()-1) if (p && p < Args->NumArgs()-1)
{ {
MapData * map = P_OpenMapData(Args->GetArg (p+1)); if (!P_CheckMapData(Args->GetArg (p+1)))
if (map == NULL)
{ {
Printf ("Can't find map %s\n", Args->GetArg (p+1)); Printf ("Can't find map %s\n", Args->GetArg (p+1));
} }
else else
{ {
delete map;
strncpy (startmap, Args->GetArg (p+1), 8); strncpy (startmap, Args->GetArg (p+1), 8);
Args->GetArg (p)[0] = '-'; Args->GetArg (p)[0] = '-';
autostart = true; autostart = true;
@ -2355,10 +2351,6 @@ void D_DoomMain (void)
StartScreen->AppendStatusLine(temp); 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 // [RH] Parse through all loaded mapinfo lumps
Printf ("G_ParseMapInfo: Load map definitions.\n"); Printf ("G_ParseMapInfo: Load map definitions.\n");
G_ParseMapInfo (); G_ParseMapInfo ();

View file

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

View file

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

View file

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

View file

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

View file

@ -136,7 +136,7 @@ extern const AInventory *SendItemUse, *SendItemDrop;
void *statcopy; // for statistics driver 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; static TArray<cluster_info_t> wadclusterinfos;
TArray<level_info_t> wadlevelinfos; TArray<level_info_t> wadlevelinfos;
@ -179,6 +179,7 @@ static const char *MapInfoTopLevel[] =
"clearepisodes", "clearepisodes",
"skill", "skill",
"clearskills", "clearskills",
"adddefaultmap",
NULL NULL
}; };
@ -191,6 +192,7 @@ enum
MITL_CLEAREPISODES, MITL_CLEAREPISODES,
MITL_SKILL, MITL_SKILL,
MITL_CLEARSKILLS, MITL_CLEARSKILLS,
MITL_ADDDEFAULTMAP,
}; };
static const char *MapInfoMapLevel[] = static const char *MapInfoMapLevel[] =
@ -336,7 +338,6 @@ enum EMIType
MITYPE_REDIRECT, MITYPE_REDIRECT,
MITYPE_SPECIALACTION, MITYPE_SPECIALACTION,
MITYPE_COMPATFLAG, MITYPE_COMPATFLAG,
MITYPE_F1, // [RC] F1 help
}; };
struct MapInfoHandler struct MapInfoHandler
@ -413,18 +414,18 @@ MapHandlers[] =
{ MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO }, { MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
{ MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO }, { MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL}, { MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 }, { MITYPE_STRING, lioffset(exitpic), 0 },
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 }, { MITYPE_STRING, lioffset(exitpic), 0 },
{ MITYPE_LUMPNAME, lioffset(enterpic), 0 }, { MITYPE_STRING, lioffset(enterpic), 0 },
{ MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) }, { MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) },
{ MITYPE_INT, lioffset(airsupply), 0 }, { MITYPE_INT, lioffset(airsupply), 0 },
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 }, { MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 }, { MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 }, { MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 }, { MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_LUMPNAME, lioffset(sndseq), 0 }, { MITYPE_STRING, lioffset(sndseq), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 }, { MITYPE_STRING, lioffset(soundinfo), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 }, { MITYPE_STRING, lioffset(soundinfo), 0 },
{ MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 }, { MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 },
{ MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 }, { MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 },
{ MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 }, { MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 },
@ -445,7 +446,7 @@ MapHandlers[] =
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL}, { MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
{ MITYPE_COMPATFLAG, COMPATF_INVISIBILITY}, { MITYPE_COMPATFLAG, COMPATF_INVISIBILITY},
{ MITYPE_LUMPNAME, lioffset(bordertexture), 0 }, { MITYPE_LUMPNAME, lioffset(bordertexture), 0 },
{ MITYPE_F1, lioffset(f1), 0, }, { MITYPE_LUMPNAME, lioffset(f1), 0, },
{ MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING }, { MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING },
{ MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)}, { MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)},
{ MITYPE_SCFLAGS, LEVEL_TOTALINFIGHTING, ~LEVEL_NOINFIGHTING }, { 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. // For maps without a BEHAVIOR, this will be cleared.
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION; levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
} }
else
{
levelinfo->flags |= LEVEL_MONSTERFALLINGDAMAGE;
}
levelinfo->airsupply = 10; levelinfo->airsupply = 10;
} }
@ -623,6 +620,48 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *spec)
return 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) static void G_DoParseMapInfo (int lump)
{ {
level_info_t defaultinfo; level_info_t defaultinfo;
@ -647,6 +686,11 @@ static void G_DoParseMapInfo (int lump)
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags); ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
break; 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> case MITL_MAP: // map <MAPNAME> <Nice Name>
levelflags = defaultinfo.flags; levelflags = defaultinfo.flags;
sc.MustGetString (); sc.MustGetString ();
@ -664,7 +708,8 @@ static void G_DoParseMapInfo (int lump)
| LEVEL_FALLDMG_HX | LEVEL_FALLDMG_HX
| LEVEL_ACTOWNSPECIAL | LEVEL_ACTOWNSPECIAL
| LEVEL_MISSILESACTIVATEIMPACT | LEVEL_MISSILESACTIVATEIMPACT
| LEVEL_INFINITE_FLIGHT; | LEVEL_INFINITE_FLIGHT
| LEVEL_MONSTERFALLINGDAMAGE;
} }
levelindex = FindWadLevelInfo (sc.String); levelindex = FindWadLevelInfo (sc.String);
if (levelindex == -1) if (levelindex == -1)
@ -677,18 +722,13 @@ static void G_DoParseMapInfo (int lump)
} }
levelinfo = &wadlevelinfos[levelindex]; levelinfo = &wadlevelinfos[levelindex];
memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo)); memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo));
if (levelinfo->music != NULL) CopyString(levelinfo->music);
{ CopyString(levelinfo->intermusic);
levelinfo->music = copystring (levelinfo->music); CopyString(levelinfo->translator);
} CopyString(levelinfo->enterpic);
if (levelinfo->intermusic != NULL) CopyString(levelinfo->exitpic);
{ CopyString(levelinfo->soundinfo);
levelinfo->intermusic = copystring (levelinfo->intermusic); CopyString(levelinfo->sndseq);
}
if (levelinfo->translator != NULL)
{
levelinfo->translator = copystring (levelinfo->translator);
}
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions); levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
if (HexenHack) if (HexenHack)
{ {
@ -699,13 +739,9 @@ static void G_DoParseMapInfo (int lump)
if (sc.Compare ("lookup")) if (sc.Compare ("lookup"))
{ {
sc.MustGetString (); sc.MustGetString ();
ReplaceString (&levelinfo->level_name, sc.String);
levelflags |= LEVEL_LOOKUPLEVELNAME; levelflags |= LEVEL_LOOKUPLEVELNAME;
} }
else ReplaceString (&levelinfo->level_name, sc.String);
{
ReplaceString (&levelinfo->level_name, sc.String);
}
// Set up levelnum now so that you can use Teleport_NewMap specials // Set up levelnum now so that you can use Teleport_NewMap specials
// to teleport to maps with standard names without needing a levelnum. // to teleport to maps with standard names without needing a levelnum.
if (!strnicmp (levelinfo->mapname, "MAP", 3) && levelinfo->mapname[5] == 0) 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); 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. SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps.
if (levelinfo->pname[0] != 0) if (levelinfo->pname[0] != 0)
{ {
@ -755,22 +787,7 @@ static void G_DoParseMapInfo (int lump)
else else
{ {
clusterinfo = &wadclusterinfos[clusterindex]; clusterinfo = &wadclusterinfos[clusterindex];
if (clusterinfo->entertext != NULL) ClearClusterInfoStrings(clusterinfo);
{
delete[] clusterinfo->entertext;
}
if (clusterinfo->exittext != NULL)
{
delete[] clusterinfo->exittext;
}
if (clusterinfo->messagemusic != NULL)
{
delete[] clusterinfo->messagemusic;
}
if (clusterinfo->clustername != NULL)
{
delete[] clusterinfo->clustername;
}
} }
memset (clusterinfo, 0, sizeof(cluster_info_t)); memset (clusterinfo, 0, sizeof(cluster_info_t));
clusterinfo->cluster = sc.Number; clusterinfo->cluster = sc.Number;
@ -798,60 +815,6 @@ static void G_DoParseMapInfo (int lump)
ClearLevelInfoStrings(&defaultinfo); 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() static void ClearEpisodes()
{ {
for (int i = 0; i < EpiDef.numitems; ++i) for (int i = 0; i < EpiDef.numitems; ++i)
@ -916,13 +879,6 @@ static void ParseMapInfoLower (FScanner &sc,
case MITYPE_REDIRECT: case MITYPE_REDIRECT:
sc.MustGetString (); sc.MustGetString ();
levelinfo->RedirectType = sc.String; 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 // Intentional fall-through
case MITYPE_MAPNAME: { case MITYPE_MAPNAME: {
@ -1077,18 +1033,6 @@ static void ParseMapInfoLower (FScanner &sc,
ReplaceString ((char **)(info + handler->data1), sc.String); ReplaceString ((char **)(info + handler->data1), sc.String);
break; 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: case MITYPE_MUSIC:
sc.MustGetString (); sc.MustGetString ();
{ {
@ -1190,6 +1134,7 @@ static void ParseEpisodeInfo (FScanner &sc)
bool remove = false; bool remove = false;
char key = 0; char key = 0;
bool noskill = false; bool noskill = false;
bool optional = false;
// Get map name // Get map name
sc.MustGetString (); sc.MustGetString ();
@ -1208,7 +1153,12 @@ static void ParseEpisodeInfo (FScanner &sc)
} }
do 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 (); sc.MustGetString ();
ReplaceString (&pic, sc.String); ReplaceString (&pic, sc.String);
@ -1241,6 +1191,17 @@ static void ParseEpisodeInfo (FScanner &sc)
} }
while (sc.GetString ()); 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) for (i = 0; i < EpiDef.numitems; ++i)
{ {
if (strncmp (EpisodeMaps[i], map, 8) == 0) if (strncmp (EpisodeMaps[i], map, 8) == 0)
@ -1408,8 +1369,8 @@ void P_RemoveDefereds (void)
bool CheckWarpTransMap (char mapname[9], bool substitute) bool CheckWarpTransMap (char mapname[9], bool substitute)
{ {
if (mapname[0] == '&' && mapname[1] == 'w' && if (mapname[0] == '&' && (mapname[1]&223) == 'W' &&
mapname[2] == 't' && mapname[3] == '@') (mapname[2]&223) == 'T' && mapname[3] == '@')
{ {
level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4)); level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4));
if (lev != NULL) if (lev != NULL)
@ -1457,12 +1418,12 @@ CCMD (map)
} }
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
MapData * map = P_OpenMapData(argv[1]); if (!P_CheckMapData(argv[1]))
if (map == NULL) {
Printf ("No map %s\n", argv[1]); Printf ("No map %s\n", argv[1]);
}
else else
{ {
delete map;
G_DeferedInitNew (argv[1]); G_DeferedInitNew (argv[1]);
} }
} }
@ -1482,12 +1443,12 @@ CCMD (open)
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
sprintf(d_mapname, "file:%s", argv[1]); sprintf(d_mapname, "file:%s", argv[1]);
MapData * map = P_OpenMapData(d_mapname); if (!P_CheckMapData(d_mapname))
if (map == NULL) {
Printf ("No map %s\n", d_mapname); Printf ("No map %s\n", d_mapname);
}
else else
{ {
delete map;
gameaction = ga_newgame2; gameaction = ga_newgame2;
d_skill = -1; d_skill = -1;
} }
@ -1638,12 +1599,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
} }
// [RH] If this map doesn't exist, bomb out // [RH] If this map doesn't exist, bomb out
MapData * map = P_OpenMapData(mapname); if (!P_CheckMapData(mapname))
if (!map)
{ {
I_Error ("Could not find map %s\n", mapname); I_Error ("Could not find map %s\n", mapname);
} }
delete map;
oldSpeed = GameSpeed; oldSpeed = GameSpeed;
wantFast = !!G_SkillProperty(SKILLP_FastMonsters); wantFast = !!G_SkillProperty(SKILLP_FastMonsters);
@ -1815,10 +1774,8 @@ const char *G_GetSecretExitMap()
if (level.secretmap[0] != 0) if (level.secretmap[0] != 0)
{ {
MapData *map = P_OpenMapData(level.secretmap); if (P_CheckMapData(level.secretmap))
if (map != NULL)
{ {
delete map;
nextmap = level.secretmap; nextmap = level.secretmap;
} }
} }
@ -2061,7 +2018,7 @@ void G_DoLoadLevel (int position, bool autosave)
// DOOM determines the sky texture to be used // DOOM determines the sky texture to be used
// depending on the current episode and the game version. // 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); sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
sky2texture = TexMan.GetTexture (level.skypic2, 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.levelnum = info->levelnum;
level.music = info->music; level.music = info->music;
level.musicorder = info->musicorder; level.musicorder = info->musicorder;
level.f1 = info->f1; // [RC] And import the f1 name
strncpy (level.level_name, info->level_name, 63); strncpy (level.level_name, info->level_name, 63);
G_MaybeLookupLevelName (NULL); G_MaybeLookupLevelName (NULL);
@ -2454,7 +2410,7 @@ void G_InitLevelLocals ()
NormalLight.ChangeFade (level.fadeto); NormalLight.ChangeFade (level.fadeto);
} }
bool level_locals_s::IsJumpingAllowed() const bool FLevelLocals::IsJumpingAllowed() const
{ {
if (dmflags & DF_NO_JUMP) if (dmflags & DF_NO_JUMP)
return false; return false;
@ -2463,7 +2419,7 @@ bool level_locals_s::IsJumpingAllowed() const
return !(level.flags & LEVEL_JUMP_NO); return !(level.flags & LEVEL_JUMP_NO);
} }
bool level_locals_s::IsCrouchingAllowed() const bool FLevelLocals::IsCrouchingAllowed() const
{ {
if (dmflags & DF_NO_CROUCH) if (dmflags & DF_NO_CROUCH)
return false; return false;
@ -2472,7 +2428,7 @@ bool level_locals_s::IsCrouchingAllowed() const
return !(level.flags & LEVEL_CROUCH_NO); return !(level.flags & LEVEL_CROUCH_NO);
} }
bool level_locals_s::IsFreelookAllowed() const bool FLevelLocals::IsFreelookAllowed() const
{ {
if (level.flags & LEVEL_FREELOOK_NO) if (level.flags & LEVEL_FREELOOK_NO)
return false; return false;
@ -2531,10 +2487,8 @@ level_info_t *CheckLevelRedirect (level_info_t *info)
if (playeringame[i] && players[i].mo->FindInventory (type)) if (playeringame[i] && players[i].mo->FindInventory (type))
{ {
// check for actual presence of the map. // check for actual presence of the map.
MapData * map = P_OpenMapData(info->RedirectMap); if (P_CheckMapData(info->RedirectMap))
if (map != NULL)
{ {
delete map;
return FindLevelInfo(info->RedirectMap); return FindLevelInfo(info->RedirectMap);
} }
break; break;
@ -2621,90 +2575,6 @@ const char *G_MaybeLookupLevelName (level_info_t *ininfo)
return info != NULL ? info->level_name : NULL; 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 () void G_AirControlChanged ()
{ {
if (level.aircontrol <= 256) if (level.aircontrol <= 256)
@ -3145,7 +3015,7 @@ void P_ReadACSDefereds (PNGHandle *png)
} }
void level_locals_s::Tick () void FLevelLocals::Tick ()
{ {
// Reset carry sectors // Reset carry sectors
if (Scrolls != NULL) 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) if (secnum < 0)
{ {

View file

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

View file

@ -8,6 +8,7 @@
#include "s_sound.h" #include "s_sound.h"
#include "m_random.h" #include "m_random.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "sbar.h"
#define MORPHTICS (40*TICRATE) #define MORPHTICS (40*TICRATE)
@ -56,6 +57,10 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
{ {
return false; return false;
} }
if (spawntype == p->mo->GetClass())
{
return false;
}
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE)); morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
DObject::StaticPointerSubstitution (actor, morphed); DObject::StaticPointerSubstitution (actor, morphed);
@ -78,6 +83,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
actor->flags |= MF_UNMORPHED; actor->flags |= MF_UNMORPHED;
actor->renderflags |= RF_INVISIBLE; actor->renderflags |= RF_INVISIBLE;
p->morphTics = MORPHTICS; 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->health = morphed->health;
p->mo = morphed; p->mo = morphed;
p->momx = p->momy = 0; p->momx = p->momy = 0;
@ -116,6 +133,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
p->camera = morphed; p->camera = morphed;
} }
morphed->ScoreIcon = actor->ScoreIcon; // [GRB] 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; return true;
} }
@ -182,6 +211,39 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
{ {
player->camera = mo; 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; angle = mo->angle >> ANGLETOFINESHIFT;
Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle], Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle],
pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); 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 //draws an image with the specified flags
void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags) void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
{ {
if (texture == NULL)
{
return;
}
if((flags & DRAWIMAGE_OFFSET_CENTER)) if((flags & DRAWIMAGE_OFFSET_CENTER))
{ {
x -= (texture->GetWidth()/2)-texture->LeftOffset; x -= (texture->GetWidth()/2)-texture->LeftOffset;
@ -1285,16 +1289,20 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++); for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++);
if(currentState != NULL) if(currentState != NULL)
{ {
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, &skins[CPlayer->userinfo.skin], level, angle); FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin];
x += ST_X; FTexture *face = currentState->getCurrentFrameTexture(defaultFace, skin, level, angle);
y += ST_Y; if (face != NULL)
int w = face->GetScaledWidth(); {
int h = face->GetScaledHeight(); x += ST_X;
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); y += ST_Y;
screen->DrawTexture(face, x, y, int w = face->GetScaledWidth();
DTA_DestWidth, w, int h = face->GetScaledHeight();
DTA_DestHeight, h, screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
TAG_DONE); screen->DrawTexture(face, x, y,
DTA_DestWidth, w,
DTA_DestHeight, h,
TAG_DONE);
}
} }
} }

View file

@ -247,6 +247,7 @@ enum
ADEF_PlayerPawn_CrouchSprite, ADEF_PlayerPawn_CrouchSprite,
ADEF_PlayerPawn_DisplayName, ADEF_PlayerPawn_DisplayName,
ADEF_PlayerPawn_SoundClass, ADEF_PlayerPawn_SoundClass,
ADEF_PlayerPawn_Face,
ADEF_PlayerPawn_ScoreIcon, ADEF_PlayerPawn_ScoreIcon,
ADEF_PlayerPawn_MorphWeapon, ADEF_PlayerPawn_MorphWeapon,
ADEF_LastString = 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: case ADEF_PlayerPawn_SoundClass:
sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr); sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr);
break; break;
case ADEF_PlayerPawn_Face:
sgClass->Meta.SetMetaString (APMETA_Face, datastr);
break;
case ADEF_PlayerPawn_ScoreIcon: case ADEF_PlayerPawn_ScoreIcon:
player->ScoreIcon = TexMan.AddPatch (datastr); player->ScoreIcon = TexMan.AddPatch (datastr);
if (player->ScoreIcon <= 0) 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_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_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_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_Face(x) ADD_STRING_PROP(ADEF_PlayerPawn_Face,"\27",x) // Octal - 'tis quaint!
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\30",x) #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_XScale(x) ADD_LONG_PROP(ADEF_XScale,x)
#define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x) #define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x)

View file

@ -1446,7 +1446,7 @@ void M_QuickLoad ()
// //
void M_DrawReadThis () void M_DrawReadThis ()
{ {
FTexture *tex, *prevpic = NULL; FTexture *tex = NULL, *prevpic = NULL;
fixed_t alpha; fixed_t alpha;
if (gameinfo.flags & GI_INFOINDEXED) if (gameinfo.flags & GI_INFOINDEXED)
@ -1463,11 +1463,15 @@ void M_DrawReadThis ()
} }
else else
{ {
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
// Did the mapper choose a custom help page via MAPINFO? // 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) 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->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360);
mobj->BeginPlay (); mobj->BeginPlay ();
if (mobj->ObjectFlags & OF_EuthanizeMe) if (!(mobj->ObjectFlags & OF_EuthanizeMe))
{ {
return NULL; mobj->LevelSpawned ();
} }
mobj->LevelSpawned ();
return mobj; return mobj;
} }

View file

@ -46,6 +46,7 @@
#include "p_lnspec.h" #include "p_lnspec.h"
#include "v_palette.h" #include "v_palette.h"
#include "c_console.h" #include "c_console.h"
#include "c_cvars.h"
#include "p_acs.h" #include "p_acs.h"
#include "vectors.h" #include "vectors.h"
#include "announcer.h" #include "announcer.h"
@ -279,7 +280,7 @@ MapData *P_OpenMapData(const char * mapname)
if (lumpfile != nextfile) if (lumpfile != nextfile)
{ {
// The following lump is from a different file so whatever this is, // 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; return map;
} }
@ -379,6 +380,13 @@ MapData *P_OpenMapData(const char * mapname)
return map; 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; 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.angle = LittleShort(mt->angle);
mt2.type = LittleShort(mt->type); mt2.type = LittleShort(mt->type);
P_SpawnMapThing (&mt2, position); SpawnMapThing (i, &mt2, position);
} }
delete [] mtp; delete [] mtp;
} }
@ -1712,7 +1737,7 @@ void P_LoadThings2 (MapData * map, int position)
for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++) for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++)
{ {
P_SpawnMapThing (mt, position); SpawnMapThing (i, mt, position);
} }
delete[] mtp; delete[] mtp;
} }
@ -3792,7 +3817,7 @@ void P_SetupLevel (char *lumpname, int position)
{ {
for (i = 0; i < numbuildthings; ++i) for (i = 0; i < numbuildthings; ++i)
{ {
P_SpawnMapThing (&buildthings[i], 0); SpawnMapThing (i, &buildthings[i], 0);
} }
delete[] buildthings; delete[] buildthings;
} }

View file

@ -81,6 +81,7 @@ struct MapData
}; };
MapData * P_OpenMapData(const char * mapname); MapData * P_OpenMapData(const char * mapname);
bool P_CheckMapData(const char * mapname);
// NOT called by W_Ticker. Fixme. [RH] Is that bad? // 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_SideMove2 (FRACUNIT)
PROP_PlayerPawn_ColorRange (0, 0) PROP_PlayerPawn_ColorRange (0, 0)
PROP_PlayerPawn_SoundClass ("player") PROP_PlayerPawn_SoundClass ("player")
PROP_PlayerPawn_Face ("None")
PROP_PlayerPawn_MorphWeapon ("None") PROP_PlayerPawn_MorphWeapon ("None")
END_DEFAULTS END_DEFAULTS

View file

@ -1046,7 +1046,7 @@ class FPlayerSkin
{ {
public: public:
char name[17]; // 16 chars + NULL 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 gender; // This skin's gender (not really used)
BYTE range0start; BYTE range0start;
BYTE range0end; BYTE range0end;

View file

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

View file

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

View file

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

View file

@ -2184,6 +2184,36 @@ static void PlayerSoundClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
bag.Info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp); 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.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) },
{ "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) }, { "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
{ "player.displayname", (apf)PlayerDisplayName, 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.forwardmove", (apf)PlayerForwardMove, RUNTIME_CLASS(APlayerPawn) },
{ "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) }, { "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
{ "player.hexenarmor", (apf)PlayerHexenArmor, 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; int lump = -1;
lump = Wads.CheckNumForFullName(name, true); 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) if (lump != -1)
{ {
@ -293,6 +287,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
double *luminosity; double *luminosity;
int maxyoffs; int maxyoffs;
bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false; bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
bool stcfn121 = false;
Chars = new CharData[count]; Chars = new CharData[count];
charlumps = new int[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); lump = Wads.CheckNumForName (buffer, ns_graphics);
if (doomtemplate && lump >= 0 && i + start == 121) if (doomtemplate && lump >= 0 && i + start == 121)
{ // HACKHACK: Don't load STCFN121 in doom(2), because { // 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 // 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. // provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load.
if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 || if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 ||
Wads.CheckNumForName ("STCFN122", 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; lump = -1;
stcfn121 = true;
} }
} }
charlumps[i] = lump; if (lump != -1 || i != 124-start || !stcfn121)
charlumps[i] = lump;
if (lump >= 0) if (lump >= 0)
{ {
FTexture *pic = TexMan[buffer]; FTexture *pic = TexMan[buffer];
@ -1691,7 +1691,7 @@ void V_InitCustomFonts()
if (format == 1) goto wrong; if (format == 1) goto wrong;
int *p = &lumplist[*(unsigned char*)sc.String]; int *p = &lumplist[*(unsigned char*)sc.String];
sc.MustGetString(); sc.MustGetString();
*p = Wads.CheckNumForName (sc.String); *p = Wads.CheckNumForFullName (sc.String, true);
format=2; format=2;
} }
} }

View file

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

View file

@ -1,5 +1,24 @@
// MAPINFO for Doom 1 (Shareware, Registered, and Retail) // 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 // Registered/Retail Episode 1
map E1M1 lookup HUSTR_E1M1 map E1M1 lookup HUSTR_E1M1

View file

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

View file

@ -31,6 +31,29 @@ skill nightmare
SpawnFilter "Hard" SpawnFilter "Hard"
Name "$MNU_BLACKPLAGUE" 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 // Episode 1

View file

@ -48,6 +48,10 @@ skill nightmare
PlayerClassName "cleric" "$MNU_POPE" PlayerClassName "cleric" "$MNU_POPE"
PlayerClassName "mage" "$MNU_ARCHMAGE" PlayerClassName "mage" "$MNU_ARCHMAGE"
clearepisodes
episode "&wt@01"
name "Hexen"
key h
clusterdef 1 clusterdef 1
hub hub
@ -84,6 +88,7 @@ defaultmap
nointermission nointermission
noautosequences noautosequences
missilesactivateimpactlines missilesactivateimpactlines
monsterfallingdamage
// There is also support for showing a clus5msg after cluster 5, but // 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 // 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 // MAPINFO for Plutonia. Exactly the same as Doom 2, except it
// has different map names and cluster messages. // has different map names and cluster messages.
clearepisodes
episode map01
name "The Plutonia Experiment"
key t
map MAP01 lookup PHUSTR_1 map MAP01 lookup PHUSTR_1
titlepatch CWILV00 titlepatch CWILV00
next MAP02 next MAP02

View file

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

View file

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