2006-02-24 04:48:15 +00:00
|
|
|
/*
|
|
|
|
** gi.cpp
|
|
|
|
** Holds same game-dependant info
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
2006-06-11 01:37:00 +00:00
|
|
|
** Copyright 1998-2006 Randy Heit
|
2006-02-24 04:48:15 +00:00
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "info.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "m_fixed.h"
|
2008-08-26 18:32:17 +00:00
|
|
|
#include "v_palette.h"
|
2009-03-22 11:37:56 +00:00
|
|
|
#include "sc_man.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "g_level.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
gameinfo_t gameinfo;
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
const char *GameNames[17] =
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex"
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static gameborder_t DoomBorder =
|
|
|
|
{
|
|
|
|
8, 8,
|
|
|
|
"brdr_tl", "brdr_t", "brdr_tr",
|
|
|
|
"brdr_l", "brdr_r",
|
|
|
|
"brdr_bl", "brdr_b", "brdr_br"
|
|
|
|
};
|
|
|
|
|
|
|
|
static gameborder_t HereticBorder =
|
|
|
|
{
|
|
|
|
4, 16,
|
|
|
|
"bordtl", "bordt", "bordtr",
|
|
|
|
"bordl", "bordr",
|
|
|
|
"bordbl", "bordb", "bordbr"
|
|
|
|
};
|
|
|
|
|
|
|
|
static gameborder_t StrifeBorder =
|
|
|
|
{
|
|
|
|
8, 8,
|
|
|
|
"brdr_tl", "brdr_t", "brdr_tr",
|
|
|
|
"brdr_l", "brdr_r",
|
|
|
|
"brdr_bl", "brdr_b", "brdr_br"
|
|
|
|
};
|
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
// Custom GAMEINFO ------------------------------------------------------------
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-12-14 00:50:02 +00:00
|
|
|
const char* GameInfoBorders[] =
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-03-22 11:37:56 +00:00
|
|
|
"DoomBorder",
|
|
|
|
"HereticBorder",
|
|
|
|
"StrifeBorder",
|
|
|
|
NULL
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#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); \
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#define GAMEINFOKEY_STRINGARRAY(key, variable, length) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
gameinfo.key.Clear(); \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
sc.MustGetToken(TK_StringConst); \
|
2010-09-14 17:28:18 +00:00
|
|
|
if(length > 0 && strlen(sc.String) > length) \
|
2009-03-22 11:37:56 +00:00
|
|
|
{ \
|
|
|
|
sc.ScriptError("Value for '%s' can not be longer than %d characters.", #key, length); \
|
|
|
|
} \
|
2010-09-14 17:28:18 +00:00
|
|
|
gameinfo.key[gameinfo.key.Reserve(1)] = sc.String; \
|
2009-03-22 11:37:56 +00:00
|
|
|
} \
|
|
|
|
while (sc.CheckToken(',')); \
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#define GAMEINFOKEY_STRING(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetToken(TK_StringConst); \
|
|
|
|
gameinfo.key = sc.String; \
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#define GAMEINFOKEY_INT(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetNumber(); \
|
|
|
|
gameinfo.key = sc.Number; \
|
|
|
|
}
|
2008-08-26 18:32:17 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#define GAMEINFOKEY_FLOAT(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetFloat(); \
|
|
|
|
gameinfo.key = static_cast<float> (sc.Float); \
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#define GAMEINFOKEY_FIXED(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetFloat(); \
|
|
|
|
gameinfo.key = static_cast<int> (sc.Float*FRACUNIT); \
|
|
|
|
}
|
2008-09-13 19:19:53 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#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); \
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
#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; \
|
|
|
|
} \
|
|
|
|
}
|
2008-08-26 18:32:17 +00:00
|
|
|
|
2010-11-06 09:28:17 +00:00
|
|
|
#define GAMEINFOKEY_FONT(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetToken(TK_StringConst); \
|
|
|
|
gameinfo.key.fontname = sc.String; \
|
|
|
|
if (sc.CheckToken(',')) { \
|
|
|
|
sc.MustGetToken(TK_StringConst); \
|
|
|
|
gameinfo.key.color = sc.String; \
|
|
|
|
} else { \
|
|
|
|
gameinfo.key.color = NAME_None; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GAMEINFOKEY_PATCH(key, variable) \
|
|
|
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
|
|
|
{ \
|
|
|
|
sc.MustGetToken(TK_StringConst); \
|
|
|
|
gameinfo.key.fontname = sc.String; \
|
|
|
|
gameinfo.key.color = NAME_Null; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
void FMapInfoParser::ParseGameInfo()
|
2008-08-26 18:32:17 +00:00
|
|
|
{
|
2009-03-22 11:37:56 +00:00
|
|
|
sc.MustGetToken('{');
|
|
|
|
while(sc.GetToken())
|
|
|
|
{
|
|
|
|
if (sc.TokenType == '}') return;
|
2008-08-26 18:32:17 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
sc.TokenMustBe(TK_Identifier);
|
|
|
|
FString nextKey = sc.String;
|
|
|
|
sc.MustGetToken('=');
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-04-04 17:46:33 +00:00
|
|
|
if (nextKey.CompareNoCase("weaponslot") == 0)
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_IntConst);
|
|
|
|
if (sc.Number < 0 || sc.Number >= 10)
|
|
|
|
{
|
|
|
|
sc.ScriptError("Weapon slot index must be in range [0..9].\n");
|
|
|
|
}
|
|
|
|
int i = sc.Number;
|
|
|
|
gameinfo.DefaultWeaponSlots[i].Clear();
|
|
|
|
sc.MustGetToken(',');
|
|
|
|
do
|
|
|
|
{
|
|
|
|
sc.MustGetString();
|
|
|
|
FName val = sc.String;
|
|
|
|
gameinfo.DefaultWeaponSlots[i].Push(val);
|
|
|
|
|
|
|
|
}
|
|
|
|
while (sc.CheckToken(','));
|
|
|
|
}
|
|
|
|
else if(nextKey.CompareNoCase("border") == 0)
|
2009-03-22 11:37:56 +00:00
|
|
|
{
|
|
|
|
if(sc.CheckToken(TK_Identifier))
|
|
|
|
{
|
2010-12-14 00:50:02 +00:00
|
|
|
switch(sc.MustMatchString(GameInfoBorders))
|
2009-03-22 11:37:56 +00:00
|
|
|
{
|
|
|
|
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(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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-07 19:46:54 +00:00
|
|
|
else if(nextKey.CompareNoCase("armoricons") == 0)
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
strncpy(gameinfo.ArmorIcon1, sc.String, 8);
|
|
|
|
gameinfo.ArmorIcon1[8] = 0;
|
|
|
|
if (sc.CheckToken(','))
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_FloatConst);
|
|
|
|
gameinfo.Armor2Percent = FLOAT2FIXED(sc.Float);
|
|
|
|
sc.MustGetToken(',');
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
strncpy(gameinfo.ArmorIcon2, sc.String, 8);
|
|
|
|
gameinfo.ArmorIcon2[8] = 0;
|
|
|
|
}
|
|
|
|
}
|
2010-10-16 22:37:30 +00:00
|
|
|
else if(nextKey.CompareNoCase("maparrow") == 0)
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
gameinfo.mMapArrow = sc.String;
|
|
|
|
if (sc.CheckToken(','))
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
gameinfo.mCheatMapArrow = sc.String;
|
|
|
|
}
|
|
|
|
else gameinfo.mCheatMapArrow = "";
|
|
|
|
}
|
2009-03-22 11:37:56 +00:00
|
|
|
// Insert valid keys here.
|
|
|
|
GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8)
|
|
|
|
GAMEINFOKEY_STRINGARRAY(creditPages, "creditPage", 8)
|
2010-09-19 08:27:20 +00:00
|
|
|
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0)
|
2009-03-22 11:37:56 +00:00
|
|
|
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)
|
2010-09-19 10:39:34 +00:00
|
|
|
GAMEINFOKEY_CSTRING(PauseSign, "pausesign", 8)
|
2009-03-22 11:37:56 +00:00
|
|
|
GAMEINFOKEY_STRING(quitSound, "quitSound")
|
|
|
|
GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8)
|
|
|
|
GAMEINFOKEY_FIXED(telefogheight, "telefogheight")
|
2010-09-19 10:39:34 +00:00
|
|
|
GAMEINFOKEY_FIXED(gibfactor, "gibfactor")
|
2009-03-22 11:37:56 +00:00
|
|
|
GAMEINFOKEY_INT(defKickback, "defKickback")
|
|
|
|
GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8)
|
|
|
|
GAMEINFOKEY_STRING(translator, "translator")
|
2010-08-14 06:25:38 +00:00
|
|
|
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
|
2009-03-22 11:37:56 +00:00
|
|
|
GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
|
|
|
|
GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
|
|
|
|
GAMEINFOKEY_STRING(backpacktype, "backpacktype")
|
|
|
|
GAMEINFOKEY_STRING(statusbar, "statusbar")
|
|
|
|
GAMEINFOKEY_STRING(intermissionMusic, "intermissionMusic")
|
2010-09-26 05:31:52 +00:00
|
|
|
GAMEINFOKEY_STRING(CursorPic, "CursorPic")
|
2009-03-22 11:37:56 +00:00
|
|
|
GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
|
|
|
|
GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
|
2010-09-26 06:53:40 +00:00
|
|
|
GAMEINFOKEY_BOOL(swapmenu, "swapmenu")
|
2009-04-23 22:49:38 +00:00
|
|
|
GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
|
2010-09-19 10:39:34 +00:00
|
|
|
GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
|
2009-09-04 22:25:46 +00:00
|
|
|
GAMEINFOKEY_COLOR(dimcolor, "dimcolor")
|
|
|
|
GAMEINFOKEY_FLOAT(dimamount, "dimamount")
|
2009-09-08 21:01:24 +00:00
|
|
|
GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount")
|
|
|
|
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
|
|
|
|
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
|
|
|
|
GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
|
|
|
|
GAMEINFOKEY_CSTRING(Endoom, "endoom", 8)
|
2009-11-24 06:55:38 +00:00
|
|
|
GAMEINFOKEY_INT(player5start, "player5start")
|
2010-09-14 17:28:18 +00:00
|
|
|
GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0)
|
|
|
|
GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")
|
|
|
|
GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label")
|
|
|
|
GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value")
|
|
|
|
GAMEINFOKEY_STRING(mFontColorMore, "menufontcolor_action")
|
|
|
|
GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header")
|
|
|
|
GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight")
|
|
|
|
GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection")
|
|
|
|
GAMEINFOKEY_CSTRING(mBackButton, "menubackbutton", 8)
|
2010-10-06 10:44:03 +00:00
|
|
|
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
|
|
|
|
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
|
|
|
|
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
|
2010-11-06 09:28:17 +00:00
|
|
|
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
|
|
|
|
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
|
|
|
|
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
|
|
|
|
GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
|
|
|
|
GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
|
2010-09-14 17:28:18 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// ignore unkown keys.
|
|
|
|
sc.UnGet();
|
|
|
|
SkipToNext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
const char *gameinfo_t::GetFinalePage(unsigned int num) const
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-03-22 11:37:56 +00:00
|
|
|
if (finalePages.Size() == 0) return "-NOFLAT-";
|
|
|
|
else if (num < 1 || num > finalePages.Size()) return finalePages[0];
|
|
|
|
else return finalePages[num-1];
|
|
|
|
}
|