mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-08 14:01:32 +00:00
6b9129105a
- Added the following flags to drawselectedinventory center, centerbottom, and drawshadow. - Fixed: The translucent flag for drawinventorybar should only have affected the artibox image. - Fixed: compatf_limitpain must check for 21 Lost Souls, not 20. SVN r1297 (trunk)
1574 lines
44 KiB
C++
1574 lines
44 KiB
C++
/*
|
|
** sbarinfo_parser.cpp
|
|
**
|
|
** Reads custom status bar definitions.
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2008 Braden Obrzut
|
|
** 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 "doomtype.h"
|
|
#include "doomstat.h"
|
|
#include "sc_man.h"
|
|
#include "v_font.h"
|
|
#include "w_wad.h"
|
|
#include "d_player.h"
|
|
#include "sbar.h"
|
|
#include "sbarinfo.h"
|
|
#include "templates.h"
|
|
#include "m_random.h"
|
|
#include "gi.h"
|
|
#include "i_system.h"
|
|
#include "g_level.h"
|
|
|
|
SBarInfo *SBarInfoScript;
|
|
|
|
static const char *SBarInfoTopLevel[] =
|
|
{
|
|
"base",
|
|
"height",
|
|
"interpolatehealth",
|
|
"interpolatearmor",
|
|
"completeborder",
|
|
"monospacefonts",
|
|
"lowerhealthcap",
|
|
"statusbar",
|
|
"mugshot",
|
|
"createpopup",
|
|
NULL
|
|
};
|
|
|
|
static const char *StatusBars[] =
|
|
{
|
|
"none",
|
|
"fullscreen",
|
|
"normal",
|
|
"automap",
|
|
"inventory",
|
|
"inventoryfullscreen",
|
|
"popuplog",
|
|
"popupkeys",
|
|
"popupstatus",
|
|
NULL
|
|
};
|
|
|
|
static const char *SBarInfoRoutineLevel[] =
|
|
{
|
|
"drawimage",
|
|
"drawnumber",
|
|
"drawswitchableimage",
|
|
"drawmugshot",
|
|
"drawselectedinventory",
|
|
"drawinventorybar",
|
|
"drawbar",
|
|
"drawgem",
|
|
"drawshader",
|
|
"drawstring",
|
|
"drawkeybar",
|
|
"gamemode",
|
|
"playerclass",
|
|
"aspectratio",
|
|
"isselected",
|
|
"usessecondaryammo",
|
|
"hasweaponpiece",
|
|
"inventorybarnotvisible",
|
|
"weaponammo", //event
|
|
"ininventory",
|
|
NULL
|
|
};
|
|
|
|
static void FreeSBarInfoScript()
|
|
{
|
|
if (SBarInfoScript != NULL)
|
|
{
|
|
delete SBarInfoScript;
|
|
SBarInfoScript = NULL;
|
|
}
|
|
}
|
|
|
|
void SBarInfo::Load()
|
|
{
|
|
if(Wads.CheckNumForName("SBARINFO") != -1)
|
|
{
|
|
Printf ("ParseSBarInfo: Loading custom status bar definition.\n");
|
|
int lastlump, lump;
|
|
lastlump = 0;
|
|
while((lump = Wads.FindLump("SBARINFO", &lastlump)) != -1)
|
|
{
|
|
if(SBarInfoScript == NULL)
|
|
SBarInfoScript = new SBarInfo(lump);
|
|
else //We now have to load multiple SBarInfo Lumps so the 2nd time we need to use this method instead.
|
|
SBarInfoScript->ParseSBarInfo(lump);
|
|
}
|
|
atterm(FreeSBarInfoScript);
|
|
}
|
|
}
|
|
|
|
//SBarInfo Script Reader
|
|
void SBarInfo::ParseSBarInfo(int lump)
|
|
{
|
|
gameType = gameinfo.gametype;
|
|
bool baseSet = false;
|
|
FScanner sc(lump);
|
|
sc.SetCMode(true);
|
|
while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include))
|
|
{
|
|
if(sc.TokenType == TK_Include)
|
|
{
|
|
sc.MustGetToken(TK_StringConst);
|
|
int lump = Wads.CheckNumForFullName(sc.String, true);
|
|
if (lump == -1)
|
|
sc.ScriptError("Lump '%s' not found", sc.String);
|
|
ParseSBarInfo(lump);
|
|
continue;
|
|
}
|
|
switch(sc.MustMatchString(SBarInfoTopLevel))
|
|
{
|
|
case SBARINFO_BASE:
|
|
baseSet = true;
|
|
if(!sc.CheckToken(TK_None))
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("Doom"))
|
|
gameType = GAME_Doom;
|
|
else if(sc.Compare("Heretic"))
|
|
gameType = GAME_Heretic;
|
|
else if(sc.Compare("Hexen"))
|
|
gameType = GAME_Hexen;
|
|
else if(sc.Compare("Strife"))
|
|
gameType = GAME_Strife;
|
|
else if(sc.Compare("None"))
|
|
gameType = GAME_Any;
|
|
else
|
|
sc.ScriptError("Bad game name: %s", sc.String);
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_HEIGHT:
|
|
sc.MustGetToken(TK_IntConst);
|
|
this->height = sc.Number;
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_INTERPOLATEHEALTH: //mimics heretics interpolated health values.
|
|
if(sc.CheckToken(TK_True))
|
|
{
|
|
interpolateHealth = true;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_False);
|
|
interpolateHealth = false;
|
|
}
|
|
if(sc.CheckToken(',')) //speed param
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
this->interpolationSpeed = sc.Number;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_INTERPOLATEARMOR: //Since interpolatehealth is such a popular command
|
|
if(sc.CheckToken(TK_True))
|
|
{
|
|
interpolateArmor = true;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_False);
|
|
interpolateArmor = false;
|
|
}
|
|
if(sc.CheckToken(',')) //speed
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
this->armorInterpolationSpeed = sc.Number;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_COMPLETEBORDER: //draws the border instead of an HOM
|
|
if(sc.CheckToken(TK_True))
|
|
{
|
|
completeBorder = true;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_False);
|
|
completeBorder = false;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_MONOSPACEFONTS:
|
|
if(sc.CheckToken(TK_True))
|
|
{
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
spacingCharacter = sc.String[0];
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_False);
|
|
spacingCharacter = '\0';
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst); //Don't tell anyone we're just ignoring this ;)
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_LOWERHEALTHCAP:
|
|
if(sc.CheckToken(TK_False))
|
|
{
|
|
lowerHealthCap = false;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_True);
|
|
lowerHealthCap = true;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_STATUSBAR:
|
|
{
|
|
if(!baseSet) //If the user didn't explicitly define a base, do so now.
|
|
gameType = GAME_Any;
|
|
int barNum = 0;
|
|
if(!sc.CheckToken(TK_None))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
barNum = sc.MustMatchString(StatusBars);
|
|
}
|
|
this->huds[barNum] = SBarInfoBlock();
|
|
if(sc.CheckToken(','))
|
|
{
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("forcescaled"))
|
|
{
|
|
this->huds[barNum].forceScaled = true;
|
|
}
|
|
else if(sc.Compare("fullscreenoffsets"))
|
|
{
|
|
this->huds[barNum].fullScreenOffsets = true;
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Unkown flag '%s'.", sc.String);
|
|
}
|
|
if(!sc.CheckToken('|') && !sc.CheckToken(','))
|
|
goto FinishStatusBar; //No more args so we must skip over anything else and go to the end.
|
|
}
|
|
sc.MustGetToken(TK_FloatConst);
|
|
this->huds[barNum].alpha = fixed_t(FRACUNIT * sc.Float);
|
|
}
|
|
FinishStatusBar:
|
|
sc.MustGetToken('{');
|
|
if(barNum == STBAR_AUTOMAP)
|
|
{
|
|
automapbar = true;
|
|
}
|
|
ParseSBarInfoBlock(sc, this->huds[barNum]);
|
|
break;
|
|
}
|
|
case SBARINFO_MUGSHOT:
|
|
{
|
|
sc.MustGetToken(TK_StringConst);
|
|
FMugShotState state(sc.String);
|
|
if(sc.CheckToken(',')) //first loop must be a comma
|
|
{
|
|
do
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("health"))
|
|
state.bUsesLevels = true;
|
|
else if(sc.Compare("health2"))
|
|
state.bUsesLevels = state.bHealth2 = true;
|
|
else if(sc.Compare("healthspecial"))
|
|
state.bUsesLevels = state.bHealthSpecial = true;
|
|
else if(sc.Compare("directional"))
|
|
state.bDirectional = true;
|
|
else
|
|
sc.ScriptError("Unknown MugShot state flag '%s'.", sc.String);
|
|
}
|
|
while(sc.CheckToken(',') || sc.CheckToken('|'));
|
|
}
|
|
ParseMugShotBlock(sc, state);
|
|
int index;
|
|
if((index = FindMugShotStateIndex(state.State)) != -1) //We already had this state, remove the old one.
|
|
{
|
|
MugShotStates.Delete(index);
|
|
}
|
|
MugShotStates.Push(state);
|
|
break;
|
|
}
|
|
case SBARINFO_CREATEPOPUP:
|
|
{
|
|
int pop = 0;
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("log"))
|
|
pop = 0;
|
|
else if(sc.Compare("keys"))
|
|
pop = 1;
|
|
else if(sc.Compare("status"))
|
|
pop = 2;
|
|
else
|
|
sc.ScriptError("Unkown popup: '%s'", sc.String);
|
|
Popup &popup = popups[pop];
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
popup.width = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
popup.height = sc.Number;
|
|
sc.MustGetToken(',');
|
|
if(!sc.CheckToken(TK_None))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("slideinbottom"))
|
|
{
|
|
popup.transition = TRANSITION_SLIDEINBOTTOM;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
popup.speed = sc.Number;
|
|
}
|
|
else if(sc.Compare("fade"))
|
|
{
|
|
popup.transition = TRANSITION_FADE;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_FloatConst);
|
|
popup.speed = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float)));
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_FloatConst);
|
|
popup.speed2 = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float)));
|
|
}
|
|
else
|
|
sc.ScriptError("Unkown transition type: '%s'", sc.String);
|
|
}
|
|
popup.init();
|
|
sc.MustGetToken(';');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|
{
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
SBarInfoCommand cmd;
|
|
|
|
switch(cmd.type = sc.MustMatchString(SBarInfoRoutineLevel))
|
|
{
|
|
case SBARINFO_DRAWSWITCHABLEIMAGE:
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("weaponslot"))
|
|
{
|
|
cmd.flags = DRAWIMAGE_WEAPONSLOT;
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.value = sc.Number;
|
|
}
|
|
else if(sc.Compare("invulnerable"))
|
|
{
|
|
cmd.flags = DRAWIMAGE_INVULNERABILITY;
|
|
}
|
|
else if(sc.Compare("keyslot"))
|
|
{
|
|
cmd.flags = DRAWIMAGE_KEYSLOT;
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.value = sc.Number;
|
|
}
|
|
else
|
|
{
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
if(sc.CheckToken(TK_AndAnd))
|
|
{
|
|
cmd.flags |= DRAWIMAGE_SWITCHABLE_AND;
|
|
if(cmd.flags & DRAWIMAGE_KEYSLOT)
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special4 = sc.Number;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 1);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.special = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.special2 = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.special3 = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.special = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
}
|
|
case SBARINFO_DRAWIMAGE:
|
|
{
|
|
bool getImage = true;
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
getImage = false;
|
|
if(sc.Compare("playericon"))
|
|
cmd.flags |= DRAWIMAGE_PLAYERICON;
|
|
else if(sc.Compare("ammoicon1"))
|
|
cmd.flags |= DRAWIMAGE_AMMO1;
|
|
else if(sc.Compare("ammoicon2"))
|
|
cmd.flags |= DRAWIMAGE_AMMO2;
|
|
else if(sc.Compare("armoricon"))
|
|
cmd.flags |= DRAWIMAGE_ARMOR;
|
|
else if(sc.Compare("weaponicon"))
|
|
cmd.flags |= DRAWIMAGE_WEAPONICON;
|
|
else if(sc.Compare("sigil"))
|
|
cmd.flags |= DRAWIMAGE_SIGIL;
|
|
else if(sc.Compare("hexenarmor"))
|
|
{
|
|
cmd.flags = DRAWIMAGE_HEXENARMOR;
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("armor"))
|
|
cmd.value = 0;
|
|
else if(sc.Compare("shield"))
|
|
cmd.value = 1;
|
|
else if(sc.Compare("helm"))
|
|
cmd.value = 2;
|
|
else if(sc.Compare("amulet"))
|
|
cmd.value = 3;
|
|
else
|
|
sc.ScriptError("Unkown armor type: '%s'", sc.String);
|
|
sc.MustGetToken(',');
|
|
getImage = true;
|
|
}
|
|
else if(sc.Compare("translatable"))
|
|
{
|
|
cmd.flags |= DRAWIMAGE_TRANSLATABLE;
|
|
getImage = true;
|
|
}
|
|
else
|
|
{
|
|
//sc.CheckToken(TK_Identifier);
|
|
cmd.flags |= DRAWIMAGE_INVENTORYICON;
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
cmd.sprite_index = ((AInventory *)GetDefaultByType(item))->Icon;
|
|
cmd.image_index = -1;
|
|
}
|
|
}
|
|
if(getImage)
|
|
{
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.image_index = newImage(sc.String);
|
|
cmd.sprite_index.SetInvalid();
|
|
}
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("center"))
|
|
cmd.flags |= DRAWIMAGE_OFFSET_CENTER;
|
|
else if(sc.Compare("centerbottom"))
|
|
cmd.flags |= DRAWIMAGE_OFFSET_CENTERBOTTOM;
|
|
else
|
|
sc.ScriptError("'%s' is not a valid alignment.", sc.String);
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
}
|
|
case SBARINFO_DRAWNUMBER:
|
|
cmd.special4 = cmd.special3 = -1;
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.font = V_GetFont(sc.String);
|
|
if(cmd.font == NULL)
|
|
sc.ScriptError("Unknown font '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation = this->GetTranslation(sc, sc.String);
|
|
sc.MustGetToken(',');
|
|
if(sc.CheckToken(TK_IntConst))
|
|
{
|
|
cmd.value = sc.Number;
|
|
sc.MustGetToken(',');
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("health"))
|
|
cmd.flags = DRAWNUMBER_HEALTH;
|
|
else if(sc.Compare("armor"))
|
|
cmd.flags = DRAWNUMBER_ARMOR;
|
|
else if(sc.Compare("ammo1"))
|
|
cmd.flags = DRAWNUMBER_AMMO1;
|
|
else if(sc.Compare("ammo2"))
|
|
cmd.flags = DRAWNUMBER_AMMO2;
|
|
else if(sc.Compare("ammo")) //request the next string to be an ammo type
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 0);
|
|
cmd.flags = DRAWNUMBER_AMMO;
|
|
const PClass* ammo = PClass::FindClass(sc.String);
|
|
if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo
|
|
{
|
|
sc.ScriptError("'%s' is not a type of ammo.", sc.String);
|
|
}
|
|
}
|
|
else if(sc.Compare("ammocapacity"))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 0);
|
|
cmd.flags = DRAWNUMBER_AMMOCAPACITY;
|
|
const PClass* ammo = PClass::FindClass(sc.String);
|
|
if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo
|
|
{
|
|
sc.ScriptError("'%s' is not a type of ammo.", sc.String);
|
|
}
|
|
}
|
|
else if(sc.Compare("frags"))
|
|
cmd.flags = DRAWNUMBER_FRAGS;
|
|
else if(sc.Compare("kills"))
|
|
cmd.flags |= DRAWNUMBER_KILLS;
|
|
else if(sc.Compare("monsters"))
|
|
cmd.flags |= DRAWNUMBER_MONSTERS;
|
|
else if(sc.Compare("items"))
|
|
cmd.flags |= DRAWNUMBER_ITEMS;
|
|
else if(sc.Compare("totalitems"))
|
|
cmd.flags |= DRAWNUMBER_TOTALITEMS;
|
|
else if(sc.Compare("secrets"))
|
|
cmd.flags |= DRAWNUMBER_SECRETS;
|
|
else if(sc.Compare("totalsecrets"))
|
|
cmd.flags |= DRAWNUMBER_TOTALSECRETS;
|
|
else if(sc.Compare("armorclass"))
|
|
cmd.flags |= DRAWNUMBER_ARMORCLASS;
|
|
else if(sc.Compare("globalvar"))
|
|
{
|
|
cmd.flags |= DRAWNUMBER_GLOBALVAR;
|
|
sc.MustGetToken(TK_IntConst);
|
|
if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS)
|
|
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
|
cmd.value = sc.Number;
|
|
}
|
|
else if(sc.Compare("globalarray")) //acts like variable[playernumber()]
|
|
{
|
|
cmd.flags |= DRAWNUMBER_GLOBALARRAY;
|
|
sc.MustGetToken(TK_IntConst);
|
|
if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS)
|
|
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
|
cmd.value = sc.Number;
|
|
}
|
|
else if(sc.Compare("poweruptime"))
|
|
{
|
|
cmd.flags |= DRAWNUMBER_POWERUPTIME;
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(item))
|
|
{
|
|
sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cmd.flags = DRAWNUMBER_INVENTORY;
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of ammo
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
sc.MustGetToken(',');
|
|
}
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("fillzeros"))
|
|
cmd.flags |= DRAWNUMBER_FILLZEROS;
|
|
else if(sc.Compare("whennotzero"))
|
|
cmd.flags |= DRAWNUMBER_WHENNOTZERO;
|
|
else if(sc.Compare("drawshadow"))
|
|
cmd.flags |= DRAWNUMBER_DRAWSHADOW;
|
|
else
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
bool needsComma = false;
|
|
if(sc.CheckToken(TK_IntConst)) //font spacing
|
|
{
|
|
cmd.special2 = sc.Number;
|
|
needsComma = true;
|
|
}
|
|
if(!needsComma || sc.CheckToken(',')) //2nd coloring for "low-on" value
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation2 = this->GetTranslation(sc, sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special3 = sc.Number;
|
|
if(sc.CheckToken(',')) //3rd coloring for "high-on" value
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation3 = this->GetTranslation(sc, sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special4 = sc.Number;
|
|
}
|
|
}
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWMUGSHOT:
|
|
if(sc.CheckToken(TK_StringConst))
|
|
{
|
|
cmd.setString(sc, sc.String, 0, 3, true);
|
|
sc.MustGetToken(',');
|
|
}
|
|
sc.MustGetToken(TK_IntConst); //accuracy
|
|
if(sc.Number < 1 || sc.Number > 9)
|
|
sc.ScriptError("Expected a number between 1 and 9, got %d instead.", sc.Number);
|
|
cmd.special = sc.Number;
|
|
sc.MustGetToken(',');
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("xdeathface"))
|
|
cmd.flags |= DRAWMUGSHOT_XDEATHFACE;
|
|
else if(sc.Compare("animatedgodmode"))
|
|
cmd.flags |= DRAWMUGSHOT_ANIMATEDGODMODE;
|
|
else if(sc.Compare("disablegrin"))
|
|
cmd.flags |= DRAWMUGSHOT_DISABLEGRIN;
|
|
else if(sc.Compare("disableouch"))
|
|
cmd.flags |= DRAWMUGSHOT_DISABLEOUCH;
|
|
else if(sc.Compare("disablepain"))
|
|
cmd.flags |= DRAWMUGSHOT_DISABLEPAIN;
|
|
else if(sc.Compare("disablerampage"))
|
|
cmd.flags |= DRAWMUGSHOT_DISABLERAMPAGE;
|
|
else
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWSELECTEDINVENTORY:
|
|
{
|
|
bool alternateonempty = false;
|
|
while(true) //go until we get a font (non-flag)
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("alternateonempty"))
|
|
{
|
|
alternateonempty = true;
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY;
|
|
}
|
|
else if(sc.Compare("artiflash"))
|
|
{
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_ARTIFLASH;
|
|
}
|
|
else if(sc.Compare("alwaysshowcounter"))
|
|
{
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_ALWAYSSHOWCOUNTER;
|
|
}
|
|
else if(sc.Compare("center"))
|
|
{
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_CENTER;
|
|
}
|
|
else if(sc.Compare("centerbottom"))
|
|
{
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_CENTERBOTTOM;
|
|
}
|
|
else if(sc.Compare("drawshadow"))
|
|
{
|
|
cmd.flags |= DRAWSELECTEDINVENTORY_DRAWSHADOW;
|
|
}
|
|
else
|
|
{
|
|
cmd.font = V_GetFont(sc.String);
|
|
if(cmd.font == NULL)
|
|
sc.ScriptError("Unknown font '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
break;
|
|
}
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
cmd.special2 = cmd.x + 30;
|
|
cmd.special3 = cmd.y + 24;
|
|
cmd.translation = CR_GOLD;
|
|
if(sc.CheckToken(',')) //more font information
|
|
{
|
|
int x = cmd.x;
|
|
int y = cmd.y;
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
cmd.special2 = cmd.x;
|
|
cmd.special3 = cmd.y;
|
|
cmd.x = x;
|
|
cmd.y = y;
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation = this->GetTranslation(sc, sc.String);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special4 = sc.Number;
|
|
}
|
|
}
|
|
}
|
|
if(alternateonempty)
|
|
{
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(';');
|
|
}
|
|
break;
|
|
}
|
|
case SBARINFO_DRAWINVENTORYBAR:
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("Doom"))
|
|
cmd.special = GAME_Doom;
|
|
else if(sc.Compare("Heretic"))
|
|
cmd.special = GAME_Heretic;
|
|
else if(sc.Compare("Hexen"))
|
|
cmd.special = GAME_Hexen;
|
|
else if(sc.Compare("Strife"))
|
|
cmd.special = GAME_Strife;
|
|
else
|
|
sc.ScriptError("Unkown style '%s'.", sc.String);
|
|
|
|
sc.MustGetToken(',');
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("alwaysshow"))
|
|
{
|
|
cmd.flags |= DRAWINVENTORYBAR_ALWAYSSHOW;
|
|
}
|
|
else if(sc.Compare("noartibox"))
|
|
{
|
|
cmd.flags |= DRAWINVENTORYBAR_NOARTIBOX;
|
|
}
|
|
else if(sc.Compare("noarrows"))
|
|
{
|
|
cmd.flags |= DRAWINVENTORYBAR_NOARROWS;
|
|
}
|
|
else if(sc.Compare("alwaysshowcounter"))
|
|
{
|
|
cmd.flags |= DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER;
|
|
}
|
|
else if(sc.Compare("translucent"))
|
|
{
|
|
cmd.flags |= DRAWINVENTORYBAR_TRANSLUCENT;
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
}
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.value = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.font = V_GetFont(sc.String);
|
|
if(cmd.font == NULL)
|
|
sc.ScriptError("Unknown font '%s'.", sc.String);
|
|
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
cmd.special2 = cmd.x + 26;
|
|
cmd.special3 = cmd.y + 22;
|
|
cmd.translation = CR_GOLD;
|
|
if(sc.CheckToken(',')) //more font information
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special2 = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special3 = sc.Number - (200 - this->height);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation = this->GetTranslation(sc, sc.String);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special4 = sc.Number;
|
|
}
|
|
}
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWBAR:
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.image_index = newImage(sc.String);
|
|
cmd.sprite_index.SetInvalid();
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.special = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier); //yeah, this is the same as drawnumber, there might be a better way to copy it...
|
|
if(sc.Compare("health"))
|
|
{
|
|
cmd.flags = DRAWNUMBER_HEALTH;
|
|
if(sc.CheckToken(TK_Identifier)) //comparing reference
|
|
{
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of inventory
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
else
|
|
cmd.special2 = DRAWBAR_COMPAREDEFAULTS;
|
|
}
|
|
else if(sc.Compare("armor"))
|
|
{
|
|
cmd.flags = DRAWNUMBER_ARMOR;
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of inventory
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
else
|
|
cmd.special2 = DRAWBAR_COMPAREDEFAULTS;
|
|
}
|
|
else if(sc.Compare("ammo1"))
|
|
cmd.flags = DRAWNUMBER_AMMO1;
|
|
else if(sc.Compare("ammo2"))
|
|
cmd.flags = DRAWNUMBER_AMMO2;
|
|
else if(sc.Compare("ammo")) //request the next string to be an ammo type
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 0);
|
|
cmd.flags = DRAWNUMBER_AMMO;
|
|
const PClass* ammo = PClass::FindClass(sc.String);
|
|
if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo
|
|
{
|
|
sc.ScriptError("'%s' is not a type of ammo.", sc.String);
|
|
}
|
|
}
|
|
else if(sc.Compare("frags"))
|
|
cmd.flags = DRAWNUMBER_FRAGS;
|
|
else if(sc.Compare("kills"))
|
|
cmd.flags = DRAWNUMBER_KILLS;
|
|
else if(sc.Compare("items"))
|
|
cmd.flags = DRAWNUMBER_ITEMS;
|
|
else if(sc.Compare("secrets"))
|
|
cmd.flags = DRAWNUMBER_SECRETS;
|
|
else if(sc.Compare("poweruptime"))
|
|
{
|
|
cmd.flags |= DRAWNUMBER_POWERUPTIME;
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(item))
|
|
{
|
|
sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cmd.flags = DRAWNUMBER_INVENTORY;
|
|
cmd.setString(sc, sc.String, 0);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(item))
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
}
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("horizontal"))
|
|
cmd.special2 += DRAWBAR_HORIZONTAL;
|
|
else if(!sc.Compare("vertical"))
|
|
sc.ScriptError("Unknown direction '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("reverse"))
|
|
cmd.special2 += DRAWBAR_REVERSE;
|
|
else
|
|
sc.ScriptError("Unkown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
if(sc.CheckToken(',')) //border
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special3 = sc.Number;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWGEM:
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("wiggle"))
|
|
cmd.flags |= DRAWGEM_WIGGLE;
|
|
else if(sc.Compare("translatable"))
|
|
cmd.flags |= DRAWGEM_TRANSLATABLE;
|
|
else if(sc.Compare("armor"))
|
|
cmd.flags |= DRAWGEM_ARMOR;
|
|
else if(sc.Compare("reverse"))
|
|
cmd.flags |= DRAWGEM_REVERSE;
|
|
else
|
|
sc.ScriptError("Unknown drawgem flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
sc.MustGetToken(TK_StringConst); //chain
|
|
cmd.special = newImage(sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst); //gem
|
|
cmd.image_index = newImage(sc.String);
|
|
cmd.sprite_index.SetInvalid();
|
|
sc.MustGetToken(',');
|
|
cmd.special2 = this->getSignedInteger(sc);
|
|
sc.MustGetToken(',');
|
|
cmd.special3 = this->getSignedInteger(sc);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
if(sc.Number < 0)
|
|
sc.ScriptError("Chain size must be a positive number.");
|
|
cmd.special4 = sc.Number;
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWSHADER:
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special = sc.Number;
|
|
if(sc.Number < 1)
|
|
sc.ScriptError("Width must be greater than 1.");
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special2 = sc.Number;
|
|
if(sc.Number < 1)
|
|
sc.ScriptError("Height must be greater than 1.");
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("vertical"))
|
|
cmd.flags |= DRAWSHADER_VERTICAL;
|
|
else if(!sc.Compare("horizontal"))
|
|
sc.ScriptError("Unknown direction '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(!sc.Compare("reverse"))
|
|
{
|
|
sc.ScriptError("Exspected 'reverse', got '%s' instead.", sc.String);
|
|
}
|
|
cmd.flags |= DRAWSHADER_REVERSE;
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWSTRING:
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.font = V_GetFont(sc.String);
|
|
if(cmd.font == NULL)
|
|
sc.ScriptError("Unknown font '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
cmd.translation = this->GetTranslation(sc, sc.String);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.setString(sc, sc.String, 0, -1, false);
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
if(sc.CheckToken(',')) //spacing
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special = sc.Number;
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_DRAWKEYBAR:
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.value = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("vertical"))
|
|
cmd.flags |= DRAWKEYBAR_VERTICAL;
|
|
else if(!sc.Compare("horizontal"))
|
|
sc.ScriptError("Unknown direction '%s'.", sc.String);
|
|
sc.MustGetToken(',');
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("reverserows"))
|
|
cmd.flags |= DRAWKEYBAR_REVERSEROWS;
|
|
else
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
if(sc.CheckToken(TK_Auto))
|
|
cmd.special = -1;
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special = sc.Number;
|
|
}
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd, block.fullScreenOffsets);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
//key offset
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special2 = sc.Number;
|
|
if(sc.CheckToken(','))
|
|
{
|
|
//max per row/column
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special3 = sc.Number;
|
|
sc.MustGetToken(',');
|
|
//row/column spacing (opposite of previous)
|
|
if(sc.CheckToken(TK_Auto))
|
|
cmd.special4 = -1;
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special4 = sc.Number;
|
|
}
|
|
}
|
|
}
|
|
sc.MustGetToken(';');
|
|
break;
|
|
case SBARINFO_GAMEMODE:
|
|
while(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("singleplayer"))
|
|
cmd.flags |= GAMETYPE_SINGLEPLAYER;
|
|
else if(sc.Compare("cooperative"))
|
|
cmd.flags |= GAMETYPE_COOPERATIVE;
|
|
else if(sc.Compare("deathmatch"))
|
|
cmd.flags |= GAMETYPE_DEATHMATCH;
|
|
else if(sc.Compare("teamgame"))
|
|
cmd.flags |= GAMETYPE_TEAMGAME;
|
|
//else I'm removing this error to allow cross port compatiblity. If it doesn't know what a gamemode is lets just ignore it.
|
|
// sc.ScriptError("Unknown gamemode: %s", sc.String);
|
|
if(sc.CheckToken('{'))
|
|
break;
|
|
sc.MustGetToken(',');
|
|
}
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_PLAYERCLASS:
|
|
cmd.special = cmd.special2 = cmd.special3 = -1;
|
|
for(int i = 0;i < 3 && sc.CheckToken(TK_Identifier);i++) //up to 3 classes
|
|
{
|
|
bool foundClass = false;
|
|
for(unsigned int c = 0;c < PlayerClasses.Size();c++)
|
|
{
|
|
if(stricmp(sc.String, PlayerClasses[c].Type->Meta.GetMetaString(APMETA_DisplayName)) == 0)
|
|
{
|
|
foundClass = true;
|
|
if(i == 0)
|
|
cmd.special = PlayerClasses[c].Type->ClassIndex;
|
|
else if(i == 1)
|
|
cmd.special2 = PlayerClasses[c].Type->ClassIndex;
|
|
else //should be 2
|
|
cmd.special3 = PlayerClasses[c].Type->ClassIndex;
|
|
break;
|
|
}
|
|
}
|
|
if(!foundClass)
|
|
sc.ScriptError("Unkown PlayerClass '%s'.", sc.String);
|
|
if(sc.CheckToken('{') || i == 2)
|
|
goto FinishPlayerClass;
|
|
sc.MustGetToken(',');
|
|
}
|
|
FinishPlayerClass:
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_ASPECTRATIO:
|
|
sc.MustGetToken(TK_StringConst);
|
|
if(sc.Compare("4:3"))
|
|
cmd.value = ASPECTRATIO_4_3;
|
|
else if(sc.Compare("16:9"))
|
|
cmd.value = ASPECTRATIO_16_9;
|
|
else if(sc.Compare("16:10"))
|
|
cmd.value = ASPECTRATIO_16_10;
|
|
else if(sc.Compare("5:4"))
|
|
cmd.value = ASPECTRATIO_5_4;
|
|
else
|
|
sc.ScriptError("Unkown aspect ratio: %s", sc.String);
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_ISSELECTED:
|
|
//Using StringConst instead of Identifieres is deperecated!
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("not"))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_NOT;
|
|
if(!sc.CheckToken(TK_StringConst))
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
}
|
|
else
|
|
sc.MustGetToken(TK_StringConst);
|
|
for(int i = 0;i < 2;i++)
|
|
{
|
|
cmd.setString(sc, sc.String, i);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(item))
|
|
{
|
|
sc.ScriptError("'%s' is not a type of weapon.", sc.String);
|
|
}
|
|
if(sc.CheckToken(','))
|
|
{
|
|
if(!sc.CheckToken(TK_StringConst))
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_USESSECONDARYAMMO:
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("not"))
|
|
cmd.flags |= SBARINFOEVENT_NOT;
|
|
else
|
|
sc.ScriptError("Exspected 'not' got '%s' instead.", sc.String);
|
|
}
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_HASWEAPONPIECE:
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
const PClass* weapon = PClass::FindClass(sc.String);
|
|
if(weapon == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(weapon)) //must be a weapon
|
|
sc.ScriptError("%s is not a kind of weapon.", sc.String);
|
|
cmd.setString(sc, sc.String, 0);
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
if(sc.Number < 1)
|
|
sc.ScriptError("Weapon piece number can not be less than 1.");
|
|
cmd.value = sc.Number;
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
}
|
|
case SBARINFO_INVENTORYBARNOTVISIBLE:
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_WEAPONAMMO:
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("not"))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_NOT;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
for(int i = 0;i < 2;i++)
|
|
{
|
|
cmd.setString(sc, sc.String, i);
|
|
const PClass* ammo = PClass::FindClass(sc.String);
|
|
if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo
|
|
{
|
|
sc.ScriptError("'%s' is not a type of ammo.", sc.String);
|
|
}
|
|
if(sc.CheckToken(TK_OrOr))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_OR;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
else if(sc.CheckToken(TK_AndAnd))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_AND;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_ININVENTORY:
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("not"))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_NOT;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
for(int i = 0;i < 2;i++)
|
|
{
|
|
cmd.setString(sc, sc.String, i);
|
|
const PClass* item = PClass::FindClass(sc.String);
|
|
if(item == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(item))
|
|
{
|
|
sc.ScriptError("'%s' is not a type of inventory item.", sc.String);
|
|
}
|
|
if(sc.CheckToken(TK_OrOr))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_OR;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
else if(sc.CheckToken(TK_AndAnd))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_AND;
|
|
sc.MustGetToken(TK_Identifier);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
sc.MustGetToken('{');
|
|
cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets;
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
}
|
|
block.commands.Push(cmd);
|
|
}
|
|
sc.MustGetToken('}');
|
|
}
|
|
|
|
void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state)
|
|
{
|
|
sc.MustGetToken('{');
|
|
while(!sc.CheckToken('}'))
|
|
{
|
|
FMugShotFrame frame;
|
|
bool multiframe = false;
|
|
if(sc.CheckToken('{'))
|
|
multiframe = true;
|
|
do
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(strlen(sc.String) > 5)
|
|
sc.ScriptError("MugShot frames cannot exceed 5 characters.");
|
|
frame.Graphic.Push(sc.String);
|
|
}
|
|
while(multiframe && sc.CheckToken(','));
|
|
if(multiframe)
|
|
sc.MustGetToken('}');
|
|
frame.Delay = getSignedInteger(sc);
|
|
sc.MustGetToken(';');
|
|
state.Frames.Push(frame);
|
|
}
|
|
}
|
|
|
|
void SBarInfo::getCoordinates(FScanner &sc, SBarInfoCommand &cmd, bool fullScreenOffsets)
|
|
{
|
|
bool negative = false;
|
|
negative = sc.CheckToken('-');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.x = negative ? -sc.Number : sc.Number;
|
|
sc.MustGetToken(',');
|
|
negative = sc.CheckToken('-');
|
|
sc.MustGetToken(TK_IntConst);
|
|
if(!fullScreenOffsets)
|
|
cmd.y = (negative ? -sc.Number : sc.Number) - (200 - this->height);
|
|
else
|
|
cmd.y = negative ? -sc.Number : sc.Number;
|
|
}
|
|
|
|
int SBarInfo::getSignedInteger(FScanner &sc)
|
|
{
|
|
if(sc.CheckToken('-'))
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
return -sc.Number;
|
|
}
|
|
else
|
|
{
|
|
sc.MustGetToken(TK_IntConst);
|
|
return sc.Number;
|
|
}
|
|
}
|
|
|
|
int SBarInfo::newImage(const char *patchname)
|
|
{
|
|
if(patchname[0] == '\0' || stricmp(patchname, "nullimage") == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
for(unsigned int i = 0;i < this->Images.Size();i++) //did we already load it?
|
|
{
|
|
if(stricmp(this->Images[i], patchname) == 0)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return this->Images.Push(patchname);
|
|
}
|
|
|
|
//converts a string into a tranlation.
|
|
EColorRange SBarInfo::GetTranslation(FScanner &sc, const char* translation)
|
|
{
|
|
EColorRange returnVal = CR_UNTRANSLATED;
|
|
FString namedTranslation; //we must send in "[translation]"
|
|
const BYTE *trans_ptr;
|
|
namedTranslation.Format("[%s]", translation);
|
|
trans_ptr = (const BYTE *)(&namedTranslation[0]);
|
|
if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED)
|
|
{
|
|
sc.ScriptError("Missing definition for color %s.", translation);
|
|
}
|
|
return returnVal;
|
|
}
|
|
|
|
SBarInfo::SBarInfo() //make results more predicable
|
|
{
|
|
Init();
|
|
}
|
|
|
|
SBarInfo::SBarInfo(int lumpnum)
|
|
{
|
|
Init();
|
|
ParseSBarInfo(lumpnum);
|
|
}
|
|
|
|
void SBarInfo::Init()
|
|
{
|
|
automapbar = false;
|
|
interpolateHealth = false;
|
|
interpolateArmor = false;
|
|
completeBorder = false;
|
|
lowerHealthCap = true;
|
|
interpolationSpeed = 8;
|
|
armorInterpolationSpeed = 8;
|
|
height = 0;
|
|
spacingCharacter = '\0';
|
|
}
|
|
|
|
SBarInfo::~SBarInfo()
|
|
{
|
|
for (size_t i = 0; i < NUMHUDS; ++i)
|
|
{
|
|
huds[i].commands.Clear();
|
|
}
|
|
}
|
|
|
|
void SBarInfoCommand::setString(FScanner &sc, const char* source, int strnum, int maxlength, bool exact)
|
|
{
|
|
if(!exact)
|
|
{
|
|
if(maxlength != -1 && strlen(source) > (unsigned int) maxlength)
|
|
{
|
|
sc.ScriptError("%s is greater than %d characters.", source, maxlength);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(maxlength != -1 && strlen(source) != (unsigned int) maxlength)
|
|
{
|
|
sc.ScriptError("%s must be %d characters.", source, maxlength);
|
|
return;
|
|
}
|
|
}
|
|
string[strnum] = source;
|
|
}
|
|
|
|
SBarInfoCommand::SBarInfoCommand() //sets the default values for more predicable behavior
|
|
{
|
|
type = 0;
|
|
special = 0;
|
|
special2 = 0;
|
|
special3 = 0;
|
|
special4 = 0;
|
|
flags = 0;
|
|
x = 0;
|
|
y = 0;
|
|
value = 0;
|
|
image_index = 0;
|
|
sprite_index.SetInvalid();
|
|
translation = CR_UNTRANSLATED;
|
|
translation2 = CR_UNTRANSLATED;
|
|
translation3 = CR_UNTRANSLATED;
|
|
font = V_GetFont("CONFONT");
|
|
}
|
|
|
|
SBarInfoCommand::~SBarInfoCommand()
|
|
{
|
|
}
|
|
|
|
SBarInfoBlock::SBarInfoBlock()
|
|
{
|
|
forceScaled = false;
|
|
fullScreenOffsets = false;
|
|
alpha = FRACUNIT;
|
|
}
|
|
|
|
//Popup
|
|
Popup::Popup()
|
|
{
|
|
transition = TRANSITION_NONE;
|
|
height = 320;
|
|
width = 200;
|
|
speed = 0;
|
|
x = 320;
|
|
y = 200;
|
|
alpha = FRACUNIT;
|
|
opened = false;
|
|
moving = false;
|
|
}
|
|
|
|
void Popup::init()
|
|
{
|
|
x = width;
|
|
y = height;
|
|
if(transition == TRANSITION_SLIDEINBOTTOM)
|
|
{
|
|
x = 0;
|
|
}
|
|
else if(transition == TRANSITION_FADE)
|
|
{
|
|
alpha = 0;
|
|
x = 0;
|
|
y = 0;
|
|
}
|
|
}
|
|
|
|
void Popup::tick()
|
|
{
|
|
if(transition == TRANSITION_SLIDEINBOTTOM)
|
|
{
|
|
if(moving)
|
|
{
|
|
if(opened)
|
|
y -= clamp(height + (y - height), 1, speed);
|
|
else
|
|
y += clamp(height - y, 1, speed);
|
|
}
|
|
if(y != 0 && y != height)
|
|
moving = true;
|
|
else
|
|
moving = false;
|
|
}
|
|
else if(transition == TRANSITION_FADE)
|
|
{
|
|
if(moving)
|
|
{
|
|
if(opened)
|
|
alpha = clamp(alpha + speed, 0, FRACUNIT);
|
|
else
|
|
alpha = clamp(alpha - speed2, 0, FRACUNIT);
|
|
}
|
|
if(alpha == 0 || alpha == FRACUNIT)
|
|
moving = false;
|
|
else
|
|
moving = true;
|
|
}
|
|
else
|
|
{
|
|
if(opened)
|
|
{
|
|
y = 0;
|
|
x = 0;
|
|
}
|
|
else
|
|
{
|
|
y = height;
|
|
x = width;
|
|
}
|
|
moving = false;
|
|
}
|
|
}
|
|
|
|
bool Popup::isDoneMoving()
|
|
{
|
|
return !moving;
|
|
}
|
|
|
|
int Popup::getXOffset()
|
|
{
|
|
return x;
|
|
}
|
|
|
|
int Popup::getYOffset()
|
|
{
|
|
return y;
|
|
}
|
|
|
|
int Popup::getAlpha(int maxAlpha)
|
|
{
|
|
double a = (double) alpha / (double) FRACUNIT;
|
|
double b = (double) maxAlpha / (double) FRACUNIT;
|
|
return fixed_t((a * b) * FRACUNIT);
|
|
}
|
|
|
|
void Popup::open()
|
|
{
|
|
opened = true;
|
|
moving = true;
|
|
}
|
|
|
|
void Popup::close()
|
|
{
|
|
opened = false;
|
|
moving = true;
|
|
}
|