From e105a29e9944c63fd5a9597e9568b21520a98729 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Apr 2008 12:14:33 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 25 ++ src/c_cmds.cpp | 12 +- src/d_dehacked.cpp | 11 +- src/d_main.cpp | 12 +- src/d_player.h | 2 + src/doomstat.h | 3 - src/f_finale.cpp | 2 +- src/g_game.cpp | 10 +- src/g_level.cpp | 336 ++++++++------------------- src/g_level.h | 22 +- src/g_shared/a_morph.cpp | 62 +++++ src/g_shared/sbarinfo_display.cpp | 28 ++- src/info.h | 1 + src/infodefaults.cpp | 3 + src/infomacros.h | 5 +- src/m_menu.cpp | 12 +- src/p_mobj.cpp | 5 +- src/p_setup.cpp | 33 ++- src/p_setup.h | 1 + src/p_user.cpp | 1 + src/r_defs.h | 2 +- src/r_things.cpp | 16 +- src/s_advsound.cpp | 1 - src/s_sound.cpp | 4 +- src/thingdef/thingdef_properties.cpp | 31 +++ src/v_font.cpp | 20 +- src/wi_stuff.cpp | 2 +- wadsrc/mapinfo/doom1.txt | 19 ++ wadsrc/mapinfo/doom2.txt | 6 + wadsrc/mapinfo/heretic.txt | 23 ++ wadsrc/mapinfo/hexen.txt | 5 + wadsrc/mapinfo/plutonia.txt | 5 + wadsrc/mapinfo/tnt.txt | 5 + wadsrc/zdoom.lst | 2 +- 34 files changed, 409 insertions(+), 318 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index da7859cd40..d78d0ad0a8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 46208a8405..d198022d5d 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -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); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index e0eb7b6ab2..01af1cadf6 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -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 - FString filebase(ExtractFileBase (patchfile)); - lump = Wads.CheckNumForName (filebase); + 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); diff --git a/src/d_main.cpp b/src/d_main.cpp index be3d6e4330..660f274a2b 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -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 (); diff --git a/src/d_player.h b/src/d_player.h index a226779294..f38c10a7b0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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 diff --git a/src/doomstat.h b/src/doomstat.h index 32fbe31d96..a311bd134a 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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? diff --git a/src/f_finale.cpp b/src/f_finale.cpp index a41ead5e39..c91e94187e 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -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; diff --git a/src/g_game.cpp b/src/g_game.cpp index 085990ac92..b873221481 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -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; } diff --git a/src/g_level.cpp b/src/g_level.cpp index 1537e854d7..20814db73f 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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 wadclusterinfos; TArray 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 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); - } + 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) { diff --git a/src/g_level.h b/src/g_level.h index 7d8dd1864c..efd1b8a721 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -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 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); diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 16c60f4696..7ae1e9e52a 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -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(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 (pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 949eab836c..77cb7f7bc1 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -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,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++); if(currentState != NULL) { - FTexture *face = currentState->getCurrentFrameTexture(defaultFace, &skins[CPlayer->userinfo.skin], level, angle); - x += ST_X; - y += ST_Y; - int w = face->GetScaledWidth(); - int h = face->GetScaledHeight(); - screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); - screen->DrawTexture(face, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - TAG_DONE); + 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(); + int h = face->GetScaledHeight(); + screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); + screen->DrawTexture(face, x, y, + DTA_DestWidth, w, + DTA_DestHeight, h, + TAG_DONE); + } } } diff --git a/src/info.h b/src/info.h index 13c6c4da67..f7be057027 100644 --- a/src/info.h +++ b/src/info.h @@ -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, diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp index 93be77539f..a53929d7f0 100644 --- a/src/infodefaults.cpp +++ b/src/infodefaults.cpp @@ -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) diff --git a/src/infomacros.h b/src/infomacros.h index 1c7c2de18e..10fc6761b3 100644 --- a/src/infomacros.h +++ b/src/infomacros.h @@ -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) diff --git a/src/m_menu.cpp b/src/m_menu.cpp index fbb271cbcb..2151a7d24e 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -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) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 101226f688..5ea85736db 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 (); } - mobj->LevelSpawned (); return mobj; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index e33bebac3e..da0eeba88d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -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; } diff --git a/src/p_setup.h b/src/p_setup.h index 31042301cb..a0921e34b7 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -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? // diff --git a/src/p_user.cpp b/src/p_user.cpp index 0090632dc9..3d8a888d0e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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 diff --git a/src/r_defs.h b/src/r_defs.h index 0b33c4e71d..9cca6ac1f4 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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; diff --git a/src/r_things.cpp b/src/r_things.cpp index e4be056ce4..9d33ce6a9a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -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"); - skins[i].face[0] = 'S'; - skins[i].face[1] = 'T'; - skins[i].face[2] = 'F'; + 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; diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index f0bda6aad0..f34b865a29 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -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); diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ff7007bef7..f6fa0beee1 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -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 diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 739b27cbe2..8dd81fe703 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -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) }, diff --git a/src/v_font.cpp b/src/v_font.cpp index 3f83aadca2..44bf06fbbc 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -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; } } - charlumps[i] = lump; + 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; } } diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index e6f2c783ed..fbc8c480f7 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -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); diff --git a/wadsrc/mapinfo/doom1.txt b/wadsrc/mapinfo/doom1.txt index 537a907309..8fa4691418 100644 --- a/wadsrc/mapinfo/doom1.txt +++ b/wadsrc/mapinfo/doom1.txt @@ -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 diff --git a/wadsrc/mapinfo/doom2.txt b/wadsrc/mapinfo/doom2.txt index 0b10f042bb..45a040c17b 100644 --- a/wadsrc/mapinfo/doom2.txt +++ b/wadsrc/mapinfo/doom2.txt @@ -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 diff --git a/wadsrc/mapinfo/heretic.txt b/wadsrc/mapinfo/heretic.txt index 04bcdd190e..0bd8a78898 100644 --- a/wadsrc/mapinfo/heretic.txt +++ b/wadsrc/mapinfo/heretic.txt @@ -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 diff --git a/wadsrc/mapinfo/hexen.txt b/wadsrc/mapinfo/hexen.txt index 80a855ed92..6a621f6dc1 100644 --- a/wadsrc/mapinfo/hexen.txt +++ b/wadsrc/mapinfo/hexen.txt @@ -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 diff --git a/wadsrc/mapinfo/plutonia.txt b/wadsrc/mapinfo/plutonia.txt index 183235dd79..d9ef21076e 100644 --- a/wadsrc/mapinfo/plutonia.txt +++ b/wadsrc/mapinfo/plutonia.txt @@ -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 diff --git a/wadsrc/mapinfo/tnt.txt b/wadsrc/mapinfo/tnt.txt index 099207d784..b826c0b498 100644 --- a/wadsrc/mapinfo/tnt.txt +++ b/wadsrc/mapinfo/tnt.txt @@ -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 diff --git a/wadsrc/zdoom.lst b/wadsrc/zdoom.lst index a48633d1db..5fb2605edb 100644 --- a/wadsrc/zdoom.lst +++ b/wadsrc/zdoom.lst @@ -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