- removed gamemission variable because it wasn't used anywhere.

- removed gamemode variable. All it was used for were some checks that
  really should depend on GI_MAPxx.
- Externalized all internal gameinfo definitions.
- added include to MAPINFO parser.
- split IWAD detection code off from d_main.cpp into its own file.
- disabled gamemission based switch filtering because it is not useful.
- added GAMEINFO submission by Blzut3 with significant modifications. There
  is no GAMEINFO lump. Instead all information is placed in MAPINFO, except
  the data that is needed to decide which WADs to autoload.


SVN r1497 (trunk)
This commit is contained in:
Christoph Oelckers 2009-03-22 11:37:56 +00:00
parent 81f834e3f4
commit 505031fa5a
33 changed files with 896 additions and 1729 deletions

View file

@ -1,4 +1,15 @@
March 19, 2009
March 22, 2009 (Changes by Graf Zahl)
- removed gamemode variable. All it was used for were some checks that
really should depend on GI_MAPxx.
- Externalized all internal gameinfo definitions.
- added include to MAPINFO parser.
- split IWAD detection code off from d_main.cpp into its own file.
- disabled gamemission based switch filtering because it is not useful.
- added GAMEINFO submission by Blzut3 with significant modifications. There
is no GAMEINFO lump. Instead all information is placed in MAPINFO, except
the data that is needed to decide which WADs to autoload.
March 19, 2009
- Added the current value of the string buffer to the state saved when
making a function call in ACS. Now you can print inside functions and
also return values from them for the caller to plug directly into

View file

@ -117,6 +117,7 @@ extern void R_ExecuteSetViewSize ();
extern void G_NewInit ();
extern void SetupPlayerClasses ();
extern bool CheckCheatmode ();
extern const IWADInfo *D_FindIWAD(const char *basewad);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -124,7 +125,6 @@ void D_CheckNetGame ();
void D_ProcessEvents ();
void G_BuildTiccmd (ticcmd_t* cmd);
void D_DoAdvanceDemo ();
void D_AddFile (const char *file);
void D_AddWildFile (const char *pattern);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
@ -145,22 +145,6 @@ EXTERN_CVAR (Int, screenblocks)
EXTERN_CVAR (Bool, sv_cheats)
EXTERN_CVAR (Bool, sv_unlimited_pickup)
extern gameinfo_t SharewareGameInfo;
extern gameinfo_t RegisteredGameInfo;
extern gameinfo_t RetailGameInfo;
extern gameinfo_t CommercialGameInfo;
extern gameinfo_t HereticGameInfo;
extern gameinfo_t HereticSWGameInfo;
extern gameinfo_t HexenGameInfo;
extern gameinfo_t HexenDKGameInfo;
extern gameinfo_t StrifeGameInfo;
extern gameinfo_t StrifeTeaserGameInfo;
extern gameinfo_t StrifeTeaser2GameInfo;
extern gameinfo_t ChexGameInfo;
extern gameinfo_t Chex3GameInfo;
extern gameinfo_t PlutoniaGameInfo;
extern gameinfo_t TNTGameInfo;
extern int testingmode;
extern bool setmodeneeded;
extern bool netdemo;
@ -194,8 +178,6 @@ CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO)
}
CVAR (Float, timelimit, 0.f, CVAR_SERVERINFO);
CVAR (Bool, queryiwad, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
CVAR (String, defaultiwad, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
CVAR (Int, wipetype, 1, CVAR_ARCHIVE);
CVAR (Int, snd_drawoutput, 0, 0);
@ -219,84 +201,12 @@ FTexture *Advisory;
cycle_t FrameCycles;
// If autoname is NULL, that's either because that game doesn't allow
// loading of external wads or because it's already caught by the
// general game-specific wads section.
const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
{
// banner text, autoname, fg color, bg color
{ "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168) },
{ "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168) },
{ "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24) },
{ "Hexen: Deathkings of the Dark Citadel", "HexenDK", MAKERGB(240,240,240), MAKERGB(139,68,9) },
{ "Hexen: Demo Version", "HexenDemo",MAKERGB(240,240,240), MAKERGB(107,44,24) },
{ "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168) },
{ "Heretic Shareware", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
{ "Heretic: Shadow of the Serpent Riders", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
{ "Heretic", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
{ "DOOM Shareware", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) },
{ "The Ultimate DOOM", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168) },
{ "DOOM Registered", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168) },
{ "Strife: Quest for the Sigil", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) },
{ "Strife: Teaser (Old Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) },
{ "Strife: Teaser (New Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) },
{ "Freedoom", "Freedoom", MAKERGB(50,84,67), MAKERGB(198,220,209) },
{ "Freedoom \"Demo\"", "Freedoom1",MAKERGB(50,84,67), MAKERGB(198,220,209) },
{ "FreeDM", "FreeDM", MAKERGB(50,84,67), MAKERGB(198,220,209) },
{ "Chex(R) Quest", "Chex", MAKERGB(255,255,0), MAKERGB(0,192,0) },
{ "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0) },
};
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static wadlist_t **wadtail = &wadfiles;
static int demosequence;
static int pagetic;
static const char *IWADNames[] =
{
NULL,
"doom2f.wad",
"doom2.wad",
"plutonia.wad",
"tnt.wad",
"doomu.wad", // Hack from original Linux version. Not necessary, but I threw it in anyway.
"doom.wad",
"doom1.wad",
"heretic.wad",
"heretic1.wad",
"hexen.wad",
"hexdd.wad",
"hexendemo.wad",
"hexdemo.wad",
"strife1.wad",
"strife0.wad",
"freedoom.wad", // Freedoom.wad is distributed as Doom2.wad, but this allows to have both in the same directory.
"freedoom1.wad",
"freedm.wad",
"chex.wad",
"chex3.wad",
#ifdef unix
"DOOM2.WAD", // Also look for all-uppercase names
"PLUTONIA.WAD",
"TNT.WAD",
"DOOM.WAD",
"DOOM1.WAD",
"HERETIC.WAD",
"HERETIC1.WAD",
"HEXEN.WAD",
"HEXDD.WAD",
"HEXENDEMO.WAD",
"HEXDEMO.WAD",
"STRIFE1.WAD",
"STRIFE0.WAD",
"FREEDOOM.WAD",
"FREEDOOM1.WAD",
"FREEDM.WAD",
"CHEX.WAD",
"CHEX3.WAD",
#endif
NULL
};
// CODE --------------------------------------------------------------------
@ -1215,11 +1125,8 @@ void D_DoAdvanceDemo (void)
case 2:
pagetic = (int)(gameinfo.pageTime * TICRATE);
gamestate = GS_DEMOSCREEN;
if (pagecount == 0)
pagename = gameinfo.creditPage1;
else
pagename = gameinfo.creditPage2;
pagecount ^= 1;
pagename = gameinfo.creditPages[pagecount];
pagecount = (pagecount+1) % gameinfo.creditPages.Size();
demosequence = 1;
break;
}
@ -1429,555 +1336,6 @@ static void D_AddDirectory (const char *dir)
}
}
//==========================================================================
//
// SetIWAD
//
// Sets parameters for the game using the specified IWAD.
//==========================================================================
static void SetIWAD (const char *iwadpath, EIWADType type)
{
static const struct
{
GameMode_t Mode;
const gameinfo_t *Info;
GameMission_t Mission;
} Datas[NUM_IWAD_TYPES] = {
{ commercial, &TNTGameInfo, pack_tnt }, // Doom2TNT
{ commercial, &PlutoniaGameInfo, pack_plut }, // Doom2Plutonia
{ commercial, &HexenGameInfo, doom2 }, // Hexen
{ commercial, &HexenDKGameInfo, doom2 }, // HexenDK
{ commercial, &HexenGameInfo, doom2 }, // Hexen Demo
{ commercial, &CommercialGameInfo, doom2 }, // Doom2
{ shareware, &HereticSWGameInfo, doom }, // HereticShareware
{ retail, &HereticGameInfo, doom }, // HereticExtended
{ retail, &HereticGameInfo, doom }, // Heretic
{ shareware, &SharewareGameInfo, doom }, // DoomShareware
{ retail, &RetailGameInfo, doom }, // UltimateDoom
{ registered, &RegisteredGameInfo, doom }, // DoomRegistered
{ commercial, &StrifeGameInfo, doom2 }, // Strife
{ commercial, &StrifeTeaserGameInfo, doom2 }, // StrifeTeaser
{ commercial, &StrifeTeaser2GameInfo, doom2 }, // StrifeTeaser2
{ commercial, &CommercialGameInfo, doom2 }, // FreeDoom
{ shareware, &SharewareGameInfo, doom }, // FreeDoom1
{ commercial, &CommercialGameInfo, doom2 }, // FreeDM
{ registered, &ChexGameInfo, doom }, // Chex Quest
{ registered, &Chex3GameInfo, doom }, // Chex Quest 3
};
D_AddFile (iwadpath);
if ((unsigned)type < NUM_IWAD_TYPES)
{
gamemode = Datas[type].Mode;
gameinfo = *Datas[type].Info;
gamemission = Datas[type].Mission;
if (type == IWAD_HereticExtended)
{
gameinfo.flags |= GI_MENUHACK_EXTENDED;
}
}
else
{
gamemode = undetermined;
}
}
//==========================================================================
//
// ScanIWAD
//
// Scan the contents of an IWAD to determine which one it is
//==========================================================================
static EIWADType ScanIWAD (const char *iwad)
{
static const char checklumps[][8] =
{
"E1M1",
"E4M2",
"MAP01",
"MAP40",
"MAP60",
"TITLE",
"REDTNT2",
"CAMO1",
{ 'E','X','T','E','N','D','E','D'},
"ENDSTRF",
"MAP33",
"INVCURS",
{ 'F','R','E','E','D','O','O','M' },
"W94_1",
{ 'P','O','S','S','H','0','M','0' },
"CYCLA1",
"FLMBA1",
"MAPINFO",
"E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
"DPHOOF","BFGGA0","HEADA1","CYBRA1",
{ 'S','P','I','D','A','1','D','1' },
};
#define NUM_CHECKLUMPS (sizeof(checklumps)/8)
enum
{
Check_e1m1,
Check_e4m1,
Check_map01,
Check_map40,
Check_map60,
Check_title,
Check_redtnt2,
Check_cam01,
Check_Extended,
Check_endstrf,
Check_map33,
Check_invcurs,
Check_FreeDoom,
Check_W94_1,
Check_POSSH0M0,
Check_Cycla1,
Check_Flmba1,
Check_Mapinfo,
Check_e2m1
};
int lumpsfound[NUM_CHECKLUMPS];
size_t i;
wadinfo_t header;
FILE *f;
memset (lumpsfound, 0, sizeof(lumpsfound));
if ( (f = fopen (iwad, "rb")) )
{
fread (&header, sizeof(header), 1, f);
if (header.Magic == IWAD_ID || header.Magic == PWAD_ID)
{
header.NumLumps = LittleLong(header.NumLumps);
if (0 == fseek (f, LittleLong(header.InfoTableOfs), SEEK_SET))
{
for (i = 0; i < (size_t)header.NumLumps; i++)
{
wadlump_t lump;
size_t j;
if (0 == fread (&lump, sizeof(lump), 1, f))
break;
for (j = 0; j < NUM_CHECKLUMPS; j++)
if (strnicmp (lump.Name, checklumps[j], 8) == 0)
lumpsfound[j]++;
}
}
}
fclose (f);
}
if (lumpsfound[Check_title] && lumpsfound[Check_map60])
{
return IWAD_HexenDK;
}
else if (lumpsfound[Check_map33] && lumpsfound[Check_endstrf])
{
if (lumpsfound[Check_map01])
{
return IWAD_Strife;
}
else if (lumpsfound[Check_invcurs])
{
return IWAD_StrifeTeaser2;
}
else
{
return IWAD_StrifeTeaser;
}
}
else if (lumpsfound[Check_map01])
{
if (lumpsfound[Check_FreeDoom])
{
// Is there a 100% reliable way to tell FreeDoom and FreeDM
// apart based solely on the lump names?
if (strstr(iwad, "freedm.wad") || strstr(iwad, "FREEDM.WAD"))
{
return IWAD_FreeDM;
}
else
{
return IWAD_FreeDoom;
}
}
else if (lumpsfound[Check_redtnt2])
{
return IWAD_Doom2TNT;
}
else if (lumpsfound[Check_cam01])
{
return IWAD_Doom2Plutonia;
}
else
{
if (lumpsfound[Check_title])
{
if (lumpsfound[Check_map40])
{
return IWAD_Hexen;
}
else
{
return IWAD_HexenDemo;
}
}
else
{
return IWAD_Doom2;
}
}
}
else if (lumpsfound[Check_e1m1])
{
if (lumpsfound[Check_title])
{
if (!lumpsfound[Check_e2m1])
{
return IWAD_HereticShareware;
}
else
{
if (lumpsfound[Check_Extended])
{
return IWAD_HereticExtended;
}
else
{
return IWAD_Heretic;
}
}
}
else if (lumpsfound[Check_Cycla1] && lumpsfound[Check_Flmba1])
{
if (!lumpsfound[Check_Mapinfo])
{
// The original release won't work without its hacked custom EXE.
//I_FatalError("Found an incompatible version of Chex Quest 3");
return NUM_IWAD_TYPES; // Can't use it.
}
return IWAD_ChexQuest3;
}
else
{
if (lumpsfound[Check_FreeDoom])
{
return IWAD_FreeDoom1;
}
for (i = Check_e2m1; i < NUM_CHECKLUMPS; i++)
{
if (!lumpsfound[i])
{
return IWAD_DoomShareware;
}
}
if (i == NUM_CHECKLUMPS)
{
if (lumpsfound[Check_e4m1])
{
if (lumpsfound[Check_W94_1] && lumpsfound[Check_POSSH0M0])
{
return IWAD_ChexQuest;
}
else
{
return IWAD_UltimateDoom;
}
}
else
{
return IWAD_DoomRegistered;
}
}
}
}
return NUM_IWAD_TYPES; // Don't know
}
//==========================================================================
//
// CheckIWAD
//
// Tries to find an IWAD from a set of known IWAD names, and checks the
// contents of each one found to determine which game it belongs to.
// Returns the number of new wads found in this pass (does not count wads
// found from a previous call).
//
//==========================================================================
static int CheckIWAD (const char *doomwaddir, WadStuff *wads)
{
const char *slash;
int i;
int numfound;
numfound = 0;
slash = (doomwaddir[0] && doomwaddir[strlen (doomwaddir)-1] != '/') ? "/" : "";
// Search for a pre-defined IWAD
for (i = IWADNames[0] ? 0 : 1; IWADNames[i]; i++)
{
if (wads[i].Path.IsEmpty())
{
FString iwad;
iwad.Format ("%s%s%s", doomwaddir, slash, IWADNames[i]);
FixPathSeperator (iwad.LockBuffer());
iwad.UnlockBuffer();
if (FileExists (iwad))
{
wads[i].Type = ScanIWAD (iwad);
if (wads[i].Type != NUM_IWAD_TYPES)
{
wads[i].Path = iwad;
numfound++;
}
}
}
}
return numfound;
}
//==========================================================================
//
// CheckIWADinEnvDir
//
// Checks for an IWAD in a path that contains one or more environment
// variables.
//
//==========================================================================
static int CheckIWADinEnvDir (const char *str, WadStuff *wads)
{
FString expanded = ExpandEnvVars (str);
if (!expanded.IsEmpty())
{
char *dir = expanded.LockBuffer ();
FixPathSeperator (dir);
expanded.UnlockBuffer ();
if (expanded[expanded.Len() - 1] != '/')
{
expanded += '/';
}
return CheckIWAD (expanded, wads);
}
return false;
}
//==========================================================================
//
// IdentifyVersion
//
// Tries to find an IWAD in one of four directories under DOS or Win32:
// 1. Current directory
// 2. Executable directory
// 3. $DOOMWADDIR
// 4. $HOME
//
// Under UNIX OSes, the search path is:
// 1. Current directory
// 2. $DOOMWADDIR
// 3. $HOME/.zdoom
// 4. The share directory defined at compile time (/usr/local/share/zdoom)
//
// The search path can be altered by editing the IWADSearch.Directories
// section of the config file.
//
//==========================================================================
static EIWADType IdentifyVersion (const char *zdoom_wad)
{
WadStuff wads[countof(IWADNames)];
size_t foundwads[NUM_IWAD_TYPES] = { 0 };
const char *iwadparm = Args->CheckValue ("-iwad");
size_t numwads;
int pickwad;
size_t i;
bool iwadparmfound = false;
FString custwad;
if (iwadparm)
{
custwad = iwadparm;
FixPathSeperator (custwad.LockBuffer());
if (CheckIWAD (custwad, wads))
{ // -iwad parameter was a directory
iwadparm = NULL;
}
else
{
DefaultExtension (custwad, ".wad");
iwadparm = custwad;
IWADNames[0] = iwadparm;
CheckIWAD ("", wads);
}
}
if (iwadparm == NULL || wads[0].Path.IsEmpty())
{
if (GameConfig->SetSection ("IWADSearch.Directories"))
{
const char *key;
const char *value;
while (GameConfig->NextInSection (key, value))
{
if (stricmp (key, "Path") == 0)
{
if (strchr (value, '$') != NULL)
{
CheckIWADinEnvDir (value, wads);
}
#ifdef unix
else if (*value == '~' && (*(value + 1) == 0 || *(value + 1) == '/'))
{
FString homepath = GetUserFile (*(value + 1) ? value + 2 : value + 1, true);
CheckIWAD (homepath, wads);
}
#endif
else
{
CheckIWAD (value, wads);
}
}
}
}
#ifdef _WIN32
FString steam_path = I_GetSteamPath();
if (steam_path.IsNotEmpty())
{
static const char *const steam_dirs[] =
{
"doom 2/base",
"final doom/base",
"heretic shadow of the serpent riders/base",
"hexen/base",
"hexen deathkings of the dark citadel/base",
"ultimate doom/base"
};
steam_path += "/SteamApps/common/";
for (i = 0; i < countof(steam_dirs); ++i)
{
CheckIWAD (steam_path + steam_dirs[i], wads);
}
}
#endif
}
if (iwadparm != NULL && !wads[0].Path.IsEmpty())
{
iwadparmfound = true;
}
for (i = numwads = 0; i < countof(IWADNames); i++)
{
if (!wads[i].Path.IsEmpty())
{
if (i != numwads)
{
wads[numwads] = wads[i];
}
foundwads[wads[numwads].Type] = numwads + 1;
numwads++;
}
}
if (foundwads[IWAD_HexenDK] && !foundwads[IWAD_Hexen])
{ // Cannot play Hexen DK without Hexen
size_t kill = foundwads[IWAD_HexenDK];
for (i = kill; i < numwads; ++i)
{
wads[i - 1] = wads[i];
}
numwads--;
foundwads[IWAD_HexenDK] = 0;
for (i = 0; i < NUM_IWAD_TYPES; ++i)
{
if (foundwads[i] > kill)
{
foundwads[i]--;
}
}
}
if (numwads == 0)
{
I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n"
"Did you install ZDoom properly? You can do either of the following:\n"
"\n"
"1. Place one or more of these wads in the same directory as ZDoom.\n"
"2. Edit your zdoom-username.ini and add the directories of your iwads\n"
"to the list beneath [IWADSearch.Directories]");
}
pickwad = 0;
if (!iwadparmfound && numwads > 1)
{
int defiwad = 0;
// Locate the user's prefered IWAD, if it was found.
if (defaultiwad[0] != '\0')
{
for (i = 0; i < numwads; ++i)
{
FString basename = ExtractFileBase (wads[i].Path);
if (stricmp (basename, defaultiwad) == 0)
{
defiwad = (int)i;
break;
}
}
}
pickwad = I_PickIWad (wads, (int)numwads, queryiwad, defiwad);
if (pickwad >= 0)
{
// The newly selected IWAD becomes the new default
FString basename = ExtractFileBase (wads[pickwad].Path);
defaultiwad = basename;
}
}
if (pickwad < 0)
exit (0);
// zdoom.pk3 must always be the first file loaded and the IWAD second.
D_AddFile (zdoom_wad);
if (wads[pickwad].Type == IWAD_HexenDK)
{ // load hexen.wad before loading hexdd.wad
D_AddFile (wads[foundwads[IWAD_Hexen]-1].Path);
}
SetIWAD (wads[pickwad].Path, wads[pickwad].Type);
if (wads[pickwad].Type == IWAD_Strife)
{ // Try to load voices.wad along with strife1.wad
long lastslash = wads[pickwad].Path.LastIndexOf ('/');
FString path;
if (lastslash == -1)
{
path = "";// wads[pickwad].Path;
}
else
{
path = FString (wads[pickwad].Path.GetChars(), lastslash + 1);
}
path += "voices.wad";
D_AddFile (path);
}
return wads[pickwad].Type;
}
//==========================================================================
//
@ -2195,7 +1553,6 @@ void D_DoomMain (void)
char *v;
const char *wad;
DArgs *execFiles;
const IWADInfo *iwad_info;
srand(I_MSTime());
@ -2241,13 +1598,11 @@ void D_DoomMain (void)
// Load zdoom.pk3 alone so that we can get access to the internal gameinfos before
// the IWAD is known.
wadlist_t *basewad = (wadlist_t*)M_Malloc(sizeof(wadlist_t) + strlen(wad));
strcpy(basewad->name, wad);
basewad->next = NULL;
Wads.InitMultipleFiles(&basewad);
iwad_info = &IWADInfos[IdentifyVersion(wad)];
I_SetIWADInfo(iwad_info);
const IWADInfo *iwad_info = D_FindIWAD(wad);
gameinfo.gametype = iwad_info->gametype;
gameinfo.flags = iwad_info->flags;
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
if (!(gameinfo.flags & GI_SHAREWARE))
@ -2515,7 +1870,7 @@ void D_DoomMain (void)
// [RH] Parse through all loaded mapinfo lumps
Printf ("G_ParseMapInfo: Load map definitions.\n");
G_ParseMapInfo ();
G_ParseMapInfo (iwad_info->MapInfo);
// [RH] Parse any SNDINFO lumps
Printf ("S_InitData: Load sound definitions.\n");

View file

@ -26,6 +26,7 @@
#define __D_MAIN__
#include "doomtype.h"
#include "gametype.h"
struct event_t;
@ -50,6 +51,7 @@ void D_PageTicker (void);
void D_PageDrawer (void);
void D_AdvanceDemo (void);
void D_StartTitle (void);
void D_AddFile (const char *file);
// [RH] Set this to something to draw an icon during the next screen refresh.
@ -78,6 +80,7 @@ enum EIWADType
IWAD_FreeDM,
IWAD_ChexQuest,
IWAD_ChexQuest3,
IWAD_Custom,
NUM_IWAD_TYPES
};
@ -96,6 +99,9 @@ struct IWADInfo
const char *Autoname; // Name of autoload ini section for this IWAD
DWORD FgColor; // Foreground color for title banner
DWORD BkColor; // Background color for title banner
EGameType gametype; // which game are we playing?
const char *MapInfo; // Base mapinfo to load
int flags;
};
extern const IWADInfo IWADInfos[NUM_IWAD_TYPES];

View file

@ -44,18 +44,6 @@ typedef enum
} GameMode_t;
// Mission packs - might be useful for TC stuff?
typedef enum
{
doom, // DOOM 1
doom2, // DOOM 2
pack_tnt, // TNT mission pack
pack_plut, // Plutonia pack
none
} GameMission_t;
// If rangecheck is undefined, most parameter validation debugging code
// will not be compiled
#ifndef NORANGECHECKING

View file

@ -38,10 +38,6 @@ FStringTable GStrings;
// Game speed
EGameSpeed GameSpeed = SPEED_Normal;
// Game Mode - identify IWAD as shareware, retail etc.
int gamemode = undetermined;
int gamemission = doom;
// Show developer messages if true.
CVAR (Bool, developer, false, 0)

View file

@ -51,9 +51,6 @@ extern bool devparm; // DEBUG: launched with -devparm
// -----------------------------------------------------
// Game Mode - identify IWAD as shareware, retail etc.
//
extern int gamemode;
extern int gamemission;
// -------------------------------------------
// Selected skill type, map etc.
//

View file

@ -89,7 +89,7 @@ void F_AdvanceSlideshow ();
void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat,
const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText, bool ending)
{
bool loopmusic = ending ? !(gameinfo.flags & GI_NOLOOPFINALEMUSIC) : true;
bool loopmusic = ending ? !gameinfo.noloopfinalemusic : true;
gameaction = ga_nothing;
gamestate = GS_FINALE;
viewactive = false;
@ -229,7 +229,7 @@ void F_Ticker ()
if (FinaleStage == 0)
{
if (interrupt ||
((gamemode != commercial || gameinfo.flags & GI_SHAREWARE)
((!(gameinfo.flags & GI_MAPxx) || gameinfo.flags & GI_SHAREWARE)
&& FinaleCount > FinaleTextLen*TEXTSPEED+TEXTWAIT))
{
if (FinaleCount < FinaleTextLen*TEXTSPEED+10)
@ -308,7 +308,7 @@ void F_Ticker ()
case 12: // Pic 2, Text 2
GetFinaleText ("win2msg");
FinaleEndCount = FinaleTextLen*TEXTSPEED+TEXTWAIT;
S_ChangeMusic ("orb", 0, !(gameinfo.flags & GI_NOLOOPFINALEMUSIC));
S_ChangeMusic ("orb", 0, !gameinfo.noloopfinalemusic);
break;
case 13: // Pic 2 -- Fade out
@ -319,7 +319,7 @@ void F_Ticker ()
case 14: // Pic 3 -- Fade in
FinaleEndCount = 71;
FadeDir = -1;
S_ChangeMusic ("chess", 0, !(gameinfo.flags & GI_NOLOOPFINALEMUSIC));
S_ChangeMusic ("chess", 0, !gameinfo.noloopfinalemusic);
break;
case 15: // Pic 3, Text 3
@ -1247,19 +1247,19 @@ void F_Drawer (void)
{
default:
case END_Pic1:
picname = gameinfo.finalePage1;
picname = gameinfo.GetFinalePage(1);
screen->DrawTexture (TexMan[picname], 0, 0,
DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(), TAG_DONE);
break;
case END_Pic2:
picname = gameinfo.finalePage2;
picname = gameinfo.GetFinalePage(2);
screen->DrawTexture (TexMan[picname], 0, 0,
DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(), TAG_DONE);
break;
case END_Pic3:
picname = gameinfo.finalePage3;
picname = gameinfo.GetFinalePage(3);
screen->DrawTexture (TexMan[picname], 0, 0,
DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(), TAG_DONE);

View file

@ -189,7 +189,7 @@ void G_SetForEndGame (char *nextmap)
{
SetEndSequence (nextmap, END_Chess);
}
else if (gamemode == commercial)
else if (gameinfo.gametype == GAME_Doom && (gameinfo.flags & GI_MAPxx))
{
SetEndSequence (nextmap, END_Cast);
}

View file

@ -82,9 +82,10 @@ struct FMapInfoParser
void ParseNextMap(char *mapname);
level_info_t *ParseMapHeader(level_info_t &defaultinfo);
void ParseMapDefinition(level_info_t &leveldef);
void ParseGameInfo();
void ParseEpisodeInfo ();
void ParseSkill ();
void ParseMapInfo (int lump, level_info_t &gamedefaults);
void ParseMapInfo (int lump, level_info_t &gamedefaults, level_info_t &defaultinfo);
void ParseOpenBrace();
bool ParseCloseBrace();
@ -500,7 +501,7 @@ level_info_t *CheckLevelRedirect (level_info_t *info);
FString CalcMapName (int episode, int level);
void G_ParseMapInfo (void);
void G_ParseMapInfo (const char *basemapinfo);
void G_ClearSnapshots (void);
void P_RemoveDefereds ();

View file

@ -1763,10 +1763,8 @@ static void SetLevelNum (level_info_t *info, int num)
//
//==========================================================================
void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults)
void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_info_t &defaultinfo)
{
level_info_t defaultinfo;
sc.OpenLumpNum(lump);
defaultinfo = gamedefaults;
@ -1774,7 +1772,19 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults)
while (sc.GetString ())
{
if (sc.Compare("gamedefaults"))
if (sc.Compare("include"))
{
sc.MustGetString();
int inclump = Wads.CheckNumForFullName(sc.String, true);
if (inclump < 0)
{
sc.ScriptError("include file '%s' not found", sc.String);
}
FScanner saved_sc = sc;
ParseMapInfo(inclump, gamedefaults, defaultinfo);
sc = saved_sc;
}
else if (sc.Compare("gamedefaults"))
{
gamedefaults.Reset();
ParseMapDefinition(gamedefaults);
@ -1825,6 +1835,18 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults)
{
AllSkills.Clear();
}
else if (sc.Compare("gameinfo"))
{
if (format_type != FMT_Old)
{
format_type = FMT_New;
ParseGameInfo();
}
else
{
sc.ScriptError("gameinfo definitions not supported with old MAPINFO syntax");
}
}
else
{
sc.ScriptError("%s: Unknown top level keyword", sc.String);
@ -1841,7 +1863,7 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults)
//
//==========================================================================
void G_ParseMapInfo ()
void G_ParseMapInfo (const char *basemapinfo)
{
int lump, lastlump = 0;
level_info_t gamedefaults;
@ -1849,20 +1871,19 @@ void G_ParseMapInfo ()
atterm(ClearEpisodes);
// Parse the default MAPINFO for the current game.
for(int i=0; i<2; i++)
if (basemapinfo != NULL)
{
if (gameinfo.mapinfo[i] != NULL)
{
FMapInfoParser parse;
parse.ParseMapInfo(Wads.GetNumForFullName(gameinfo.mapinfo[i]), gamedefaults);
}
FMapInfoParser parse;
level_info_t defaultinfo;
parse.ParseMapInfo(Wads.GetNumForFullName(basemapinfo), gamedefaults, defaultinfo);
}
// Parse any extra MAPINFOs.
while ((lump = Wads.FindLump ("MAPINFO", &lastlump)) != -1)
{
FMapInfoParser parse;
parse.ParseMapInfo(lump, gamedefaults);
level_info_t defaultinfo;
parse.ParseMapInfo(lump, gamedefaults, defaultinfo);
}
EndSequences.ShrinkToFit ();

View file

@ -37,6 +37,11 @@
#include "gi.h"
#include "m_fixed.h"
#include "v_palette.h"
#include "sc_man.h"
#include "w_wad.h"
#include "i_system.h"
#include "v_video.h"
#include "g_level.h"
gameinfo_t gameinfo;
@ -70,512 +75,184 @@ static gameborder_t StrifeBorder =
"brdr_bl", "brdr_b", "brdr_br"
};
gameinfo_t HexenGameInfo =
// Custom GAMEINFO ------------------------------------------------------------
const char* GameInfoBoarders[] =
{
GI_PAGESARERAW | GI_MAPxx | GI_NOLOOPFINALEMUSIC | GI_INFOINDEXED | GI_ALWAYSFALLINGDAMAGE,
"TITLE",
"CREDIT",
"CREDIT",
"HEXEN",
280/35,
210/35,
200/35,
"Chat",
"hub",
"-NOFLAT",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "TITLE", {4} } },
NULL,
33,
"F_022",
&HereticBorder,
32*FRACUNIT,
GAME_Hexen,
150,
"F_SKY",
24*FRACUNIT,
"xlat/heretic.txt", // not really correct but this was used before.
{ "mapinfo/hexen.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"BagOfHolding", // Hexen doesn't have a backpack so use Heretic's.
NULL,
"DoomBorder",
"HereticBorder",
"StrifeBorder",
NULL
};
gameinfo_t HexenDKGameInfo =
{
GI_PAGESARERAW | GI_MAPxx | GI_NOLOOPFINALEMUSIC | GI_INFOINDEXED | GI_ALWAYSFALLINGDAMAGE,
"TITLE",
"CREDIT",
"CREDIT",
"HEXEN",
280/35,
210/35,
200/35,
"Chat",
"hub",
"-NOFLAT-",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "TITLE", {4} } },
NULL,
33,
"F_022",
&HereticBorder,
32*FRACUNIT,
GAME_Hexen,
150,
"F_SKY",
24*FRACUNIT,
"xlat/heretic.txt", // not really correct but this was used before.
{ "mapinfo/hexen.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"BagOfHolding",
NULL,
};
#define GAMEINFOKEY_CSTRING(key, variable, length) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetToken(TK_StringConst); \
if(strlen(sc.String) > length) \
{ \
sc.ScriptError("Value for '%s' can not be longer than %d characters.", #key, length); \
} \
strcpy(gameinfo.key, sc.String); \
}
gameinfo_t HereticGameInfo =
{
GI_PAGESARERAW | GI_INFOINDEXED,
"TITLE",
"CREDIT",
"CREDIT",
"MUS_TITL",
280/35,
210/35,
200/35,
"misc/chat",
"MUS_CPTD",
"FLOOR25",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "TITLE", {4} } },
NULL,
17,
"FLAT513",
&HereticBorder,
32*FRACUNIT,
GAME_Heretic,
150,
"F_SKY1",
24*FRACUNIT,
"xlat/heretic.txt",
{ "mapinfo/heretic.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"BagOfHolding",
NULL,
};
#define GAMEINFOKEY_STRINGARRAY(key, variable, length) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
gameinfo.key.Clear(); \
do \
{ \
sc.MustGetToken(TK_StringConst); \
if(strlen(sc.String) > length) \
{ \
sc.ScriptError("Value for '%s' can not be longer than %d characters.", #key, length); \
} \
FName val = sc.String; \
gameinfo.key.Push(val); \
} \
while (sc.CheckToken(',')); \
}
gameinfo_t HereticSWGameInfo =
{
GI_PAGESARERAW | GI_SHAREWARE | GI_INFOINDEXED,
"TITLE",
"CREDIT",
"ORDER",
"MUS_TITL",
280/35,
210/35,
200/35,
"misc/chat",
"MUS_CPTD",
"FLOOR25",
"ORDER",
"CREDIT",
"CREDIT",
{ { "TITLE", {5} } },
NULL,
17,
"FLOOR04",
&HereticBorder,
32*FRACUNIT,
GAME_Heretic,
150,
"F_SKY1",
24*FRACUNIT,
"xlat/heretic.txt",
{ "mapinfo/heretic.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"BagOfHolding",
NULL,
};
#define GAMEINFOKEY_STRING(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetToken(TK_StringConst); \
gameinfo.key = sc.String; \
}
gameinfo_t SharewareGameInfo =
{
GI_SHAREWARE,
"TITLEPIC",
"CREDIT",
"HELP2",
"$MUSIC_INTRO",
5,
0,
200/35,
"misc/chat2",
"$MUSIC_VICTOR",
"FLOOR4_8",
"HELP2",
"VICTORY2",
"HELP2",
{ { "HELP1", "HELP2" } },
"menu/quit1",
1,
"FLOOR7_2",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
#define GAMEINFOKEY_INT(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetNumber(); \
gameinfo.key = sc.Number; \
}
gameinfo_t RegisteredGameInfo =
{
0,
"TITLEPIC",
"CREDIT",
"HELP2",
"$MUSIC_INTRO",
5,
0,
200/35,
"misc/chat2",
"$MUSIC_VICTOR",
"FLOOR4_8",
"HELP2",
"VICTORY2",
"ENDPIC",
{ { "HELP1", "HELP2" } },
"menu/quit1",
2,
"FLOOR7_2",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
#define GAMEINFOKEY_FLOAT(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetFloat(); \
gameinfo.key = static_cast<float> (sc.Float); \
}
gameinfo_t ChexGameInfo =
{
GI_CHEX_QUEST,
"TITLEPIC",
"CREDIT",
"HELP1",
"$MUSIC_INTRO",
5,
0,
200/35,
"misc/chat2",
"$MUSIC_VICTOR",
"FLOOR4_8",
"HELP2",
"VICTORY2",
"ENDPIC",
{ { "HELP1", "CREDIT" } },
"menu/quit1",
2,
"FLOOR7_2",
&DoomBorder,
0,
GAME_Chex,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/chex.txt", NULL },
MAKERGB(63,125,57),
MAKERGB(95,175,87),
"ZorchPack",
"sbarinfo/doom.txt",
};
#define GAMEINFOKEY_FIXED(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetFloat(); \
gameinfo.key = static_cast<int> (sc.Float*FRACUNIT); \
}
gameinfo_t Chex3GameInfo =
{
GI_CHEX_QUEST,
"TITLEPIC",
"ENDPIC",
"VICTORY2",
"$MUSIC_INTRO",
5,
0,
200/35,
"misc/chat2",
"$MUSIC_VICTOR",
"ENDPIC01",
"CREDIT",
"CREDIT",
"ENDPIC",
{ { "HELP1", "CREDIT" } },
"menu/quit1",
2,
"FLOOR7_2",
&DoomBorder,
0,
GAME_Chex,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/chex.txt", NULL },
MAKERGB(63,125,57),
MAKERGB(95,175,87),
"ZorchPack",
"sbarinfo/doom.txt",
};
#define GAMEINFOKEY_COLOR(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetToken(TK_StringConst); \
FString color = sc.String; \
FString colorName = V_GetColorStringByName(color); \
if(!colorName.IsEmpty()) \
color = colorName; \
gameinfo.key = V_GetColorFromString(NULL, color); \
}
gameinfo_t RetailGameInfo =
{
GI_MENUHACK_RETAIL,
"TITLEPIC",
"CREDIT",
"CREDIT",
"$MUSIC_INTRO",
5,
0,
200/35,
"misc/chat2",
"$MUSIC_VICTOR",
"FLOOR4_8",
"CREDIT",
"VICTORY2",
"ENDPIC",
{ { "HELP1", "CREDIT" } },
"menu/quit1",
2,
"FLOOR7_2",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
#define GAMEINFOKEY_BOOL(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
if(sc.CheckToken(TK_False)) \
gameinfo.key = false; \
else \
{ \
sc.MustGetToken(TK_True); \
gameinfo.key = true; \
} \
}
gameinfo_t CommercialGameInfo =
void FMapInfoParser::ParseGameInfo()
{
GI_MAPxx | GI_MENUHACK_COMMERCIAL,
"TITLEPIC",
"CREDIT",
"CREDIT",
"$MUSIC_DM2TTL",
11,
0,
200/35,
"misc/chat",
"$MUSIC_READ_M",
"SLIME16",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "HELP", "CREDIT" } },
"menu/quit2",
3,
"GRNROCK",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/doom2.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
sc.MustGetToken('{');
while(sc.GetToken())
{
if (sc.TokenType == '}') return;
gameinfo_t PlutoniaGameInfo =
{
GI_MAPxx | GI_MENUHACK_COMMERCIAL,
"TITLEPIC",
"CREDIT",
"CREDIT",
"$MUSIC_DM2TTL",
11,
0,
200/35,
"misc/chat",
"$MUSIC_READ_M",
"SLIME16",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "HELP", "CREDIT" } },
"menu/quit2",
3,
"GRNROCK",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/plutonia.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
sc.TokenMustBe(TK_Identifier);
FString nextKey = sc.String;
sc.MustGetToken('=');
gameinfo_t TNTGameInfo =
{
GI_MAPxx | GI_MENUHACK_COMMERCIAL,
"TITLEPIC",
"CREDIT",
"CREDIT",
"$MUSIC_DM2TTL",
11,
0,
200/35,
"misc/chat",
"$MUSIC_READ_M",
"SLIME16",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "HELP", "CREDIT" } },
"menu/quit2",
3,
"GRNROCK",
&DoomBorder,
0,
GAME_Doom,
100,
"F_SKY1",
24*FRACUNIT,
"xlat/doom.txt",
{ "mapinfo/doomcommon.txt", "mapinfo/tnt.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"Backpack",
"sbarinfo/doom.txt",
};
if(nextKey.CompareNoCase("border") == 0)
{
if(sc.CheckToken(TK_Identifier))
{
switch(sc.MustMatchString(GameInfoBoarders))
{
default:
gameinfo.border = &DoomBorder;
break;
case 1:
gameinfo.border = &HereticBorder;
break;
case 2:
gameinfo.border = &StrifeBorder;
break;
}
}
else
{
// border = {size, offset, tr, t, tl, r, l ,br, b, bl};
char *graphics[8] = {DoomBorder.tr, DoomBorder.t, DoomBorder.tl, DoomBorder.r, DoomBorder.l, DoomBorder.br, DoomBorder.b, DoomBorder.bl};
sc.MustGetToken('{');
sc.MustGetToken(TK_IntConst);
DoomBorder.offset = sc.Number;
sc.MustGetToken(',');
sc.MustGetToken(TK_IntConst);
DoomBorder.size = sc.Number;
for(int i = 0;i < 8;i++)
{
sc.MustGetToken(',');
sc.MustGetToken(TK_StringConst);
int len = int(strlen(sc.String));
if(len > 8)
sc.ScriptError("Border graphic can not be more than 8 characters long.\n");
memcpy(graphics[i], sc.String, len);
if(len < 8) // end with a null byte if the string is less than 8 chars.
graphics[i][len] = 0;
}
sc.MustGetToken('}');
}
}
// Insert valid keys here.
GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8)
GAMEINFOKEY_STRINGARRAY(creditPages, "creditPage", 8)
GAMEINFOKEY_STRING(titleMusic, "titleMusic")
GAMEINFOKEY_FLOAT(titleTime, "titleTime")
GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime")
GAMEINFOKEY_FLOAT(pageTime, "pageTime")
GAMEINFOKEY_STRING(chatSound, "chatSound")
GAMEINFOKEY_STRING(finaleMusic, "finaleMusic")
GAMEINFOKEY_CSTRING(finaleFlat, "finaleFlat", 8)
GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8)
GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8)
GAMEINFOKEY_STRING(quitSound, "quitSound")
GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8)
GAMEINFOKEY_FIXED(telefogheight, "telefogheight")
GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8)
GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
GAMEINFOKEY_STRING(backpacktype, "backpacktype")
GAMEINFOKEY_STRING(statusbar, "statusbar")
GAMEINFOKEY_STRING(intermissionMusic, "intermissionMusic")
GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
else
{
// ignore unkown keys.
sc.UnGet();
SkipToNext();
}
}
}
gameinfo_t StrifeGameInfo =
const char *gameinfo_t::GetFinalePage(unsigned int num) const
{
GI_MAPxx | GI_INFOINDEXED | GI_ALWAYSFALLINGDAMAGE,
"TITLEPIC",
"CREDIT",
"CREDIT",
"D_LOGO",
280/35,
0,
200/35,
"misc/chat",
"d_intro",
"-NOFLAT",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "CREDIT", {4} } },
NULL,
49,
"F_PAVE01",
&StrifeBorder,
0,
GAME_Strife,
150,
"F_SKY001",
16*FRACUNIT,
"xlat/strife.txt",
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"AmmoSatchel",
NULL,
};
gameinfo_t StrifeTeaserGameInfo =
{
GI_MAPxx | GI_INFOINDEXED | GI_ALWAYSFALLINGDAMAGE | GI_SHAREWARE,
"TITLEPIC",
"CREDIT",
"CREDIT",
"D_LOGO",
280/35,
0,
200/35,
"misc/chat",
"d_intro",
"-NOFLAT",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "CREDIT", {4} } },
NULL,
49,
"F_PAVE01",
&StrifeBorder,
0,
GAME_Strife,
150,
"F_SKY001",
16*FRACUNIT,
"xlat/strife.txt",
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"AmmoSatchel",
NULL,
};
gameinfo_t StrifeTeaser2GameInfo =
{
GI_MAPxx | GI_INFOINDEXED | GI_ALWAYSFALLINGDAMAGE | GI_SHAREWARE | GI_TEASER2,
"TITLEPIC",
"CREDIT",
"CREDIT",
"D_LOGO",
280/35,
0,
200/35,
"misc/chat",
"d_intro",
"-NOFLAT",
"CREDIT",
"CREDIT",
"CREDIT",
{ { "CREDIT", {4} } },
NULL,
49,
"F_PAVE01",
&StrifeBorder,
0,
GAME_Strife,
150,
"F_SKY001",
16*FRACUNIT,
"xlat/strife.txt",
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
"AmmoSatchel",
NULL,
};
if (finalePages.Size() == 0) return "-NOFLAT-";
else if (num < 1 || num > finalePages.Size()) return finalePages[0];
else return finalePages[num-1];
}

View file

@ -35,37 +35,15 @@
#define __GI_H__
#include "basictypes.h"
#include "zstring.h"
// Flags are not user configurable and only depend on the standard IWADs
#define GI_MAPxx 0x00000001
#define GI_PAGESARERAW 0x00000002
#define GI_SHAREWARE 0x00000004
#define GI_NOLOOPFINALEMUSIC 0x00000008
#define GI_INFOINDEXED 0x00000010
#define GI_MENUHACK 0x00000060
#define GI_MENUHACK_RETAIL 0x00000020
#define GI_MENUHACK_EXTENDED 0x00000040 // (Heretic)
#define GI_MENUHACK_COMMERCIAL 0x00000060
#define GI_ALWAYSFALLINGDAMAGE 0x00000080
#define GI_TEASER2 0x00000100 // Alternate version of the Strife Teaser
#define GI_CHEX_QUEST 0x00000200
#define GI_SHAREWARE 0x00000002
#define GI_MENUHACK_EXTENDED 0x00000004 // (Heretic)
#define GI_TEASER2 0x00000008 // Alternate version of the Strife Teaser
#ifndef EGAMETYPE
#define EGAMETYPE
enum EGameType
{
GAME_Any = 0,
GAME_Doom = 1,
GAME_Heretic = 2,
GAME_Hexen = 4,
GAME_Strife = 8,
GAME_Chex = 16, //Chex is basically Doom, but we need to have a different set of actors.
GAME_Raven = GAME_Heretic|GAME_Hexen,
GAME_DoomStrife = GAME_Doom|GAME_Strife,
GAME_DoomChex = GAME_Doom|GAME_Chex,
GAME_DoomStrifeChex = GAME_Doom|GAME_Strife|GAME_Chex
};
#endif
#include "gametype.h"
extern const char *GameNames[17];
@ -86,45 +64,39 @@ typedef struct
typedef struct
{
int flags;
EGameType gametype;
char titlePage[9];
char creditPage1[9];
char creditPage2[9];
char titleMusic[16];
bool drawreadthis;
bool noloopfinalemusic;
TArray<FName> creditPages;
TArray<FName> finalePages;
TArray<FName> infoPages;
FString titleMusic;
float titleTime;
float advisoryTime;
float pageTime;
char chatSound[16];
char finaleMusic[16];
FString chatSound;
FString finaleMusic;
char finaleFlat[9];
char finalePage1[9];
char finalePage2[9];
char finalePage3[9];
union
{
char infoPage[2][9];
struct
{
char basePage[9];
char numPages;
} indexed;
} info;
const char *quitSound;
int maxSwitch;
FString quitSound;
char borderFlat[9];
gameborder_t *border;
int telefogheight;
EGameType gametype;
int defKickback;
char SkyFlatName[9];
fixed_t StepHeight;
const char *translator;
const char *mapinfo[2];
FString translator;
DWORD defaultbloodcolor;
DWORD defaultbloodparticlecolor;
const char *backpacktype;
const char *statusbar;
FString backpacktype;
FString statusbar;
FString intermissionMusic;
const char *GetFinalePage(unsigned int num) const;
} gameinfo_t;
extern gameinfo_t gameinfo;
#endif //__GI_H__

View file

@ -142,23 +142,7 @@ struct FStateLabels
FArchive &operator<< (FArchive &arc, FState *&state);
#ifndef EGAMETYPE
#define EGAMETYPE
enum EGameType
{
GAME_Any = 0,
GAME_Doom = 1,
GAME_Heretic = 2,
GAME_Hexen = 4,
GAME_Strife = 8,
GAME_Chex = 16,
GAME_Raven = GAME_Heretic|GAME_Hexen,
GAME_DoomStrife = GAME_Doom|GAME_Strife,
GAME_DoomChex = GAME_Doom|GAME_Chex,
GAME_DoomStrifeChex = GAME_Doom|GAME_Strife|GAME_Chex
};
#endif
#include "gametype.h"
typedef TMap<FName, fixed_t> DmgFactors;
typedef TMap<FName, BYTE> PainChanceList;

View file

@ -1460,36 +1460,23 @@ void M_DrawReadThis ()
FTexture *tex = NULL, *prevpic = NULL;
fixed_t alpha;
if (gameinfo.flags & GI_INFOINDEXED)
// Did the mapper choose a custom help page via MAPINFO?
if ((level.info != NULL) && level.info->f1[0] != 0)
{
char name[9];
name[8] = 0;
Wads.GetLumpName (name, Wads.GetNumForName (gameinfo.info.indexed.basePage, ns_graphics) + InfoType);
tex = TexMan[name];
if (InfoType > 1)
{
Wads.GetLumpName (name, Wads.GetNumForName (gameinfo.info.indexed.basePage, ns_graphics) + InfoType - 1);
prevpic = TexMan[name];
}
tex = TexMan.FindTexture(level.info->f1);
InfoType = 1;
}
else
if (tex == NULL)
{
// Did the mapper choose a custom help page via MAPINFO?
if ((level.info != NULL) && level.info->f1[0] != 0)
{
tex = TexMan.FindTexture(level.info->f1);
}
if (tex == NULL)
{
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
}
if (InfoType > 1)
{
prevpic = TexMan[gameinfo.info.infoPage[InfoType-2]];
}
tex = TexMan[gameinfo.infoPages[InfoType-1].GetChars()];
}
if (InfoType > 1)
{
prevpic = TexMan[gameinfo.infoPages[InfoType-2].GetChars()];
}
alpha = MIN<fixed_t> (Scale (gametic - InfoTic, OPAQUE, TICRATE/3), OPAQUE);
if (alpha < OPAQUE && prevpic != NULL)
{
@ -1975,14 +1962,7 @@ void M_ReadThisMore (int choice)
{
InfoType++;
InfoTic = gametic;
if (gameinfo.flags & GI_INFOINDEXED)
{
if (InfoType >= gameinfo.info.indexed.numPages)
{
M_FinishReadThis (0);
}
}
else if (InfoType > 2)
if ((level.info != NULL && level.info->f1[0] != 0) || InfoType > int(gameinfo.infoPages.Size()))
{
M_FinishReadThis (0);
}
@ -3504,19 +3484,15 @@ void M_Init (void)
LINEHEIGHT = 20;
}
switch (gameinfo.flags & GI_MENUHACK)
if (!gameinfo.drawreadthis)
{
case GI_MENUHACK_COMMERCIAL:
MainMenu[MainDef.numitems-2] = MainMenu[MainDef.numitems-1];
MainDef.numitems--;
MainDef.y += 8;
ReadDef.routine = M_DrawReadThis;
ReadDef.x = 330;
ReadDef.y = 165;
ReadMenu[0].routine = M_FinishReadThis;
break;
default:
break;
//ReadMenu[0].routine = M_FinishReadThis;
}
M_OptInit ();

View file

@ -162,16 +162,21 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos
}
void P_GetFloorCeilingZ(FCheckPosition &tmf)
void P_GetFloorCeilingZ(FCheckPosition &tmf, bool get)
{
sector_t *sec = P_PointInSector (tmf.x, tmf.y);
tmf.floorsector = sec;
tmf.ceilingsector = sec;
sector_t *sec;
if (get)
{
sec = P_PointInSector (tmf.x, tmf.y);
tmf.floorsector = sec;
tmf.ceilingsector = sec;
tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint (tmf.x, tmf.y);
tmf.ceilingz = sec->ceilingplane.ZatPoint (tmf.x, tmf.y);
tmf.floorpic = sec->GetTexture(sector_t::floor);
tmf.ceilingpic = sec->GetTexture(sector_t::ceiling);
tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint (tmf.x, tmf.y);
tmf.ceilingz = sec->ceilingplane.ZatPoint (tmf.x, tmf.y);
tmf.floorpic = sec->GetTexture(sector_t::floor);
tmf.ceilingpic = sec->GetTexture(sector_t::ceiling);
}
else sec = tmf.thing->Sector;
#ifdef _3DFLOORS
for(unsigned int i=0;i<sec->e->XFloor.ffloors.Size();i++)
@ -217,14 +222,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos)
if (!onlyspawnpos)
{
P_GetFloorCeilingZ(tmf);
actor->floorz = tmf.floorz;
actor->dropoffz = tmf.dropoffz;
actor->ceilingz = tmf.ceilingz;
actor->floorpic = tmf.floorpic;
actor->floorsector = tmf.floorsector;
actor->ceilingpic = tmf.ceilingpic;
actor->ceilingsector = tmf.ceilingsector;
P_GetFloorCeilingZ(tmf, true);
}
else
{
@ -234,7 +232,15 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos)
tmf.ceilingz = actor->ceilingz;
tmf.floorpic = actor->floorpic;
tmf.ceilingpic = actor->ceilingpic;
P_GetFloorCeilingZ(tmf, false);
}
actor->floorz = tmf.floorz;
actor->dropoffz = tmf.dropoffz;
actor->ceilingz = tmf.ceilingz;
actor->floorpic = tmf.floorpic;
actor->floorsector = tmf.floorsector;
actor->ceilingpic = tmf.ceilingpic;
actor->ceilingsector = tmf.ceilingsector;
FBoundingBox box(tmf.x, tmf.y, actor->radius);
@ -293,7 +299,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
tmf.x = x;
tmf.y = y;
tmf.z = z;
P_GetFloorCeilingZ(tmf);
P_GetFloorCeilingZ(tmf, true);
spechit.Clear ();

View file

@ -3370,7 +3370,7 @@ void P_SetupLevel (char *lumpname, int position)
{
// We need translators only for Doom format maps.
// If none has been defined in a map use the game's default.
P_LoadTranslator(!level.info->Translator.IsEmpty()? level.info->Translator.GetChars() : gameinfo.translator);
P_LoadTranslator(!level.info->Translator.IsEmpty()? level.info->Translator.GetChars() : gameinfo.translator.GetChars());
}
CheckCompatibility(map);

View file

@ -143,10 +143,9 @@ void P_InitSwitchList ()
Printf ("Switch %s in SWITCHES has the same 'on' state\n", list_p);
continue;
}
// [RH] Skip this switch if its texture can't be found.
if (((gameinfo.maxSwitch & 15) >= (list_p[18] & 15)) &&
((gameinfo.maxSwitch & ~15) == (list_p[18] & ~15)) &&
TexMan.CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags).Exists())
// [RH] Skip this switch if its textures can't be found.
if (TexMan.CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags).Exists() &&
TexMan.CheckForTexture (list_p + 9 /* .name2 */, FTexture::TEX_Wall, texflags).Exists())
{
def1 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef));
def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef));
@ -204,42 +203,40 @@ void P_ProcessSwitchDef (FScanner &sc)
FString picname;
FSwitchDef *def1, *def2;
FTextureID picnum;
BYTE max;
int gametype;
bool quest = false;
def1 = def2 = NULL;
sc.MustGetString ();
if (sc.Compare ("doom"))
{
max = 0;
gametype = GAME_DoomChex;
sc.CheckNumber(); // skip the gamemission filter
}
else if (sc.Compare ("heretic"))
{
max = 17;
gametype = GAME_Heretic;
}
else if (sc.Compare ("hexen"))
{
max = 33;
gametype = GAME_Hexen;
}
else if (sc.Compare ("strife"))
{
max = 49;
gametype = GAME_Strife;
}
else if (sc.Compare ("any"))
{
max = 240;
gametype = GAME_Any;
}
else
{
// There is no game specified; just treat as any
max = 240;
//max = 240;
gametype = GAME_Any;
sc.UnGet ();
}
if (max == 0)
{
sc.MustGetNumber ();
max |= sc.Number & 15;
}
sc.MustGetString ();
picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
picname = sc.String;
@ -271,16 +268,9 @@ void P_ProcessSwitchDef (FScanner &sc)
break;
}
}
/*
if (def1 == NULL)
{
sc.ScriptError ("Switch must have an on state");
}
*/
if (def1 == NULL || !picnum.Exists() ||
((max & 240) != 240 &&
((gameinfo.maxSwitch & 240) != (max & 240) ||
(gameinfo.maxSwitch & 15) < (max & 15))))
(gametype != GAME_Any && !(gametype & gameinfo.gametype)))
{
if (def2 != NULL)
{

View file

@ -302,7 +302,7 @@ int FWadCollection::AddExternalFile(const char *filename)
//
//-----------------------------------------------------------------------
static DWORD Zip_FindCentralDir(FileReader * fin)
DWORD Zip_FindCentralDir(FileReader * fin)
{
unsigned char buf[BUFREADCOMMENT + 4];
DWORD FileSize;

View file

@ -103,6 +103,9 @@ void uppercopy (char *to, const char *from);
// Perform Blood encryption/decryption.
void BloodCrypt (void *data, int key, int len);
// Locate central directory in a zip file.
DWORD Zip_FindCentralDir(FileReader * fin);
// A very loose reference to a lump on disk. This is really just a wrapper
// around the main wad's FILE object with a different length recorded. Since
// two lumps from the same wad share the same FILE, you cannot read from

View file

@ -312,7 +312,7 @@ void WI_LoadBackground(bool isenterpic)
{
case GAME_Chex:
case GAME_Doom:
if (gamemode != commercial)
if (!(gameinfo.flags & GI_MAPxx))
{
const char *level = isenterpic ? wbs->next : wbs->current;
if (IsExMy(level))
@ -332,7 +332,7 @@ void WI_LoadBackground(bool isenterpic)
if (level.info->ExitPic.IsNotEmpty()) return;
// E1-E3 need special treatment when playing Doom 1.
if (gamemode!=commercial)
if (!(gameinfo.flags & GI_MAPxx))
{
// not if the last level is not from the first 3 episodes
if (!IsExMy(wbs->current)) return;
@ -1881,16 +1881,8 @@ void WI_Ticker(void)
// intermission music - use the defaults if none specified
if (level.info->InterMusic.IsNotEmpty())
S_ChangeMusic(level.info->InterMusic, level.info->intermusicorder);
else if (gameinfo.gametype == GAME_Heretic)
S_ChangeMusic ("mus_intr");
else if (gameinfo.gametype == GAME_Hexen)
S_ChangeMusic ("hub");
else if (gameinfo.gametype == GAME_Strife) // Strife also needs a default
S_ChangeMusic ("d_slide");
else if (gamemode == commercial)
S_ChangeMusic ("$MUSIC_DM2INT");
else
S_ChangeMusic ("$MUSIC_INTER");
S_ChangeMusic (gameinfo.intermissionMusic.GetChars());
}

View file

@ -1,5 +1,32 @@
// MAPINFO for Chex Quest
gameinfo
{
titlepage = "TITLEPIC"
creditpage = "CREDIT", "HELP1"
titlemusic = "$MUSIC_INTRO"
titletime = 5
advisorytime = 0
pagetime = 5
chatsound = "misc/chat2"
finalemusic = "$MUSIC_VICTOR"
finaleflat = "FLOOR4_8"
finalepage = "HELP2", "VICTORY2", "ENDPIC"
infopage = "HELP1", "CREDIT"
quitsound = "menu/quit1"
borderflat = "FLOOR7_2"
border = DoomBorder
telefogheight = 0
defkickback = 100
skyflatname = "F_SKY1"
translator = "xlat/doom.txt"
defaultbloodcolor = "3f 7d 39"
defaultbloodparticlecolor = "5f af 57"
backpacktype = "ZorchPack"
statusbar = "sbarinfo/doom.txt"
intermissionmusic = "$MUSIC_INTER"
}
skill baby
{
AutoUseHealth

View file

@ -0,0 +1,10 @@
include "mapinfo/chex.txt"
// Chex Quest 3 gameinfo
gameinfo
{
creditpage = "ENDPIC", "VICTORY2"
finaleflat = "ENDPIC01"
finalepage = "CREDIT", "CREDIT", "ENDPIC"
}

View file

@ -1,4 +1,19 @@
// MAPINFO for Doom 1 (Shareware, Registered, and Retail)
include "mapinfo/doomcommon.txt"
gameinfo
{
creditpage = "CREDIT", "HELP2"
titlemusic = "$MUSIC_INTRO"
titletime = 5
finalemusic = "$MUSIC_VICTOR"
finaleflat = "FLOOR4_8"
finalepage = "HELP2", "VICTORY2", "ENDPIC"
infopage = "HELP1", "HELP2"
quitsound = "menu/quit1"
borderflat = "FLOOR7_2"
drawreadthis = true
}
clearepisodes
episode e1m1

View file

@ -1,4 +1,5 @@
// MAPINFO for Doom 2
include "mapinfo/doomcommon.txt"
clearepisodes
episode map01

View file

@ -1,3 +1,32 @@
gameinfo
{
titlepage = "TITLEPIC"
creditpage = "CREDIT"
titlemusic = "$MUSIC_DM2TTL"
titletime = 11
advisorytime = 0
pagetime = 5
chatsound = "misc/chat"
finalemusic = "$MUSIC_READ_M"
finaleflat = "SLIME16"
finalepage = "CREDIT"
infopage = "HELP", "CREDIT"
quitsound = "menu/quit2"
borderflat = "GRNROCK"
border = DoomBorder
telefogheight = 0
defkickback = 100
skyflatname = "F_SKY1"
translator = "xlat/doom.txt"
mapinfo = "mapinfo/doom2.txt"
defaultbloodcolor = "68 00 00"
defaultbloodparticlecolor = "ff 00 00"
backpacktype = "Backpack"
statusbar = "sbarinfo/doom.txt"
intermissionmusic = "$MUSIC_INTER"
}
skill baby
{
AutoUseHealth

View file

@ -1,5 +1,32 @@
// MAPINFO for Heretic (Shareware and Retail)
gameinfo
{
titlepage = "TITLE"
creditpage = "CREDIT"
titlemusic = "MUS_TITL"
titletime = 8
advisorytime = 6
pagetime = 5
chatsound = "misc/chat"
finalemusic = "MUS_CPTD"
finaleflat = "FLOOR25"
finalepage = "CREDIT"
infopage = "HELP1", "HELP2", "CREDIT"
quitsound = ""
borderflat = "FLAT513"
border = HereticBorder
telefogheight = 32
defkickback = 150
skyflatname = "F_SKY1"
translator = "xlat/heretic.txt"
defaultbloodcolor = "68 00 00"
defaultbloodparticlecolor = "ff 00 00"
backpacktype = "BagOfHolding"
statusbar = ""
intermissionmusic = "mus_intr"
}
skill baby
{
AutoUseHealth

View file

@ -0,0 +1,8 @@
include "mapinfo/heretic.txt"
gameinfo
{
finalepage = "ORDER"
infopage = "ORDER", "HELP1", "HELP2", "CREDIT"
}

View file

@ -2,6 +2,34 @@
// Most of the MAPINFO is still in hexen.wad.
gameinfo
{
noloopfinalemusic = true
titlepage = "TITLE"
creditpage = "CREDIT"
titlemusic = "HEXEN"
titletime = 8
advisorytime = 6
pagetime = 5
chatsound = "Chat"
finalemusic = "hub"
finaleflat = "-NOFLAT-"
finalepage = "CREDIT"
infopage = "HELP1", "HELP2", "CREDIT"
quitsound = ""
borderflat = "F_022"
border = HereticBorder
telefogheight = 32
defkickback = 150
skyflatname = "F_SKY"
translator = "xlat/heretic.txt" // not really correct but this was used before.
defaultbloodcolor = "68 00 00"
defaultbloodparticlecolor = "ff 00 00"
backpacktype = "BagOfHolding" // Hexen doesn't have a backpack so use Heretic's.
statusbar = ""
intermissionmusic = "hub"
}
skill baby
{
AutoUseHealth

View file

@ -1,7 +1,8 @@
// MAPINFO for Plutonia. Exactly the same as Doom 2, except it
// has different map names and cluster messages.
include "mapinfo/doomcommon.txt"
clearepisodes
episode map01
{

View file

@ -1,5 +1,32 @@
// MAPINFO for Strife (full version and teaser)
gameinfo
{
titlepage = "TITLEPIC"
creditpage = "CREDIT"
titlemusic = "D_LOGO"
titletime = 8
advisorytime = 0
pagetime = 5
chatsound = "misc/chat"
finalemusic = "d_intro"
finaleflat = "-NOFLAT-"
finalepage = "CREDIT"
infopage = "HELP1", "HELP2", "HELP3"
quitsound = ""
borderflat = "F_PAVE01"
border = StrifeBorder
telefogheight = 0
defkickback = 150
skyflatname = "F_SKY001"
translator = "xlat/strife.txt"
defaultbloodcolor = "68 00 00"
defaultbloodparticlecolor = "ff 00 00"
backpacktype = "AmmoSatchel"
statusbar = ""
intermissionmusic = "d_slide"
}
skill baby
{
AutoUseHealth

View file

@ -1,7 +1,8 @@
// MAPINFO for TNT. Exactly the same as Doom 2, except it
// has different map names and cluster messages.
include "mapinfo/doomcommon.txt"
clearepisodes
episode map01
{

View file

@ -0,0 +1,10 @@
include "mapinfo/doom1.txt"
gameinfo
{
creditpage = "CREDIT"
chatsound = "misc/chat2"
finalepage = "CREDIT", "VICTORY2", "ENDPIC"
infopage = "HELP1", "CREDIT"
}

File diff suppressed because it is too large Load diff