diff --git a/docs/rh-log.txt b/docs/rh-log.txt index da7859cd4..d78d0ad0a 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 46208a840..d198022d5 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 e0eb7b6ab..01af1cadf 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 be3d6e433..660f274a2 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 a22677929..f38c10a7b 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 32fbe31d9..a311bd134 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 a41ead5e3..c91e94187 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 085990ac9..b87322148 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 1537e854d..20814db73 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 7d8dd1864..efd1b8a72 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 16c60f469..7ae1e9e52 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 949eab836..77cb7f7bc 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 13c6c4da6..f7be05702 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 93be77539..a53929d7f 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 1c7c2de18..10fc6761b 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 fbb271cbc..2151a7d24 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 101226f68..5ea85736d 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 e33bebac3..da0eeba88 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 31042301c..a0921e34b 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 0090632dc..3d8a888d0 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 0b33c4e71..9cca6ac1f 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 e4be056ce..9d33ce6a9 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 f0bda6aad..f34b865a2 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 ff7007bef..f6fa0beee 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 739b27cbe..8dd81fe70 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 3f83aadca..44bf06fbb 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 e6f2c783e..fbc8c480f 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 537a90730..8fa469141 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 0b10f042b..45a040c17 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 04bcdd190..0bd8a7889 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 80a855ed9..6a621f6dc 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 183235dd7..d9ef21076 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 099207d78..b826c0b49 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 a48633d1d..5fb2605ed 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