so that using the same flag multiple times will not have unexpected results. - sbarinfo update #21 * Added: sigil image type to correctly draw the sigil's icon. * Added: Strife inventory bar style. This is the only style that is radically different from the others. First of all it changes the SELECTBO to be INVCURS and draws it before the icons. Each box is changed to have a width of 35 pixels instead of 31 pixels. And the INVCURS graphic is drawn at (x-6, y-2). * Added: whennnotzero flag to drawnumber which will cause it to draw nothing if the value is 0. * Fixed: New mugshot code would not leave the god state when it was supposed to enter the rampage state. * Fixed: The ouch state was mostly broken. SVN r981 (trunk)
1448 lines
39 KiB
C++
1448 lines
39 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 "sbar.h"
|
|
#include "d_player.h"
|
|
#include "sbarinfo.h"
|
|
#include "templates.h"
|
|
#include "m_random.h"
|
|
#include "gi.h"
|
|
#include "i_system.h"
|
|
|
|
SBarInfo *SBarInfoScript;
|
|
TArray<MugShotState> MugShotStates;
|
|
|
|
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",
|
|
"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
|
|
{
|
|
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);
|
|
MugShotState state(sc.String);
|
|
if(sc.CheckToken(',')) //first loop must be a comma
|
|
{
|
|
do
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("health"))
|
|
state.usesLevels = true;
|
|
else if(sc.Compare("health2"))
|
|
state.usesLevels = state.health2 = true;
|
|
else if(sc.Compare("healthspecial"))
|
|
state.usesLevels = state.healthspecial = true;
|
|
else if(sc.Compare("directional"))
|
|
state.directional = true;
|
|
else
|
|
sc.ScriptError("Unknown MugShot state flag '%s'.", sc.String);
|
|
}
|
|
while(sc.CheckToken(',') || sc.CheckToken('|'));
|
|
}
|
|
ParseMugShotBlock(sc, state);
|
|
int index = 0;
|
|
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("keys"))
|
|
pop = 0;
|
|
else if(sc.Compare("log"))
|
|
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
|
|
{
|
|
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;
|
|
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("translatable"))
|
|
{
|
|
cmd.flags |= DRAWIMAGE_TRANSLATABLE;
|
|
getImage = true;
|
|
}
|
|
else
|
|
{
|
|
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 = ((AInventory *)GetDefaultByType(item))->Icon;
|
|
}
|
|
}
|
|
if(getImage)
|
|
{
|
|
sc.MustGetToken(TK_StringConst);
|
|
cmd.sprite = newImage(sc.String);
|
|
}
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd);
|
|
if(sc.CheckToken(','))
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(sc.Compare("center"))
|
|
cmd.flags |= DRAWIMAGE_OFFSET_CENTER;
|
|
else
|
|
sc.ScriptError("Expected 'center' got '%s' instead.", 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
|
|
{
|
|
cmd.flags = DRAWNUMBER_INVENTORY;
|
|
sc.MustGetToken(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 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
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd);
|
|
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
|
|
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
|
if(!sc.CheckToken('|'))
|
|
sc.MustGetToken(',');
|
|
}
|
|
this->getCoordinates(sc, cmd);
|
|
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
|
|
{
|
|
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(',');
|
|
}
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.x = sc.Number;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.y = sc.Number - (200 - this->height);
|
|
cmd.special2 = cmd.x + 30;
|
|
cmd.special3 = cmd.y + 24;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
if(alternateonempty)
|
|
{
|
|
sc.MustGetToken('{');
|
|
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
|
|
{
|
|
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);
|
|
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.sprite = newImage(sc.String);
|
|
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
|
|
{
|
|
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);
|
|
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.sprite = newImage(sc.String);
|
|
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);
|
|
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);
|
|
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);
|
|
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(',');
|
|
sc.MustGetToken(TK_IntConst);
|
|
cmd.special = sc.Number;
|
|
sc.MustGetToken(',');
|
|
this->getCoordinates(sc, cmd);
|
|
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
|
|
sc.ScriptError("Unknown gamemode: %s", sc.String);
|
|
if(sc.CheckToken('{'))
|
|
break;
|
|
sc.MustGetToken(',');
|
|
}
|
|
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:
|
|
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('{');
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
case SBARINFO_ISSELECTED:
|
|
if(sc.CheckToken(TK_Identifier))
|
|
{
|
|
if(sc.Compare("not"))
|
|
{
|
|
cmd.flags |= SBARINFOEVENT_NOT;
|
|
}
|
|
else
|
|
sc.ScriptError("Expected 'not' got '%s' instead.", sc.String);
|
|
}
|
|
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(','))
|
|
sc.MustGetToken(TK_StringConst);
|
|
else
|
|
break;
|
|
}
|
|
sc.MustGetToken('{');
|
|
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('{');
|
|
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('{');
|
|
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('{');
|
|
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('{');
|
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
|
break;
|
|
}
|
|
block.commands.Push(cmd);
|
|
}
|
|
sc.MustGetToken('}');
|
|
}
|
|
|
|
void SBarInfo::ParseMugShotBlock(FScanner &sc, MugShotState &state)
|
|
{
|
|
sc.MustGetToken('{');
|
|
while(!sc.CheckToken('}'))
|
|
{
|
|
MugShotFrame frame;
|
|
bool multiframe = false;
|
|
if(sc.CheckToken('{'))
|
|
multiframe = true;
|
|
do
|
|
{
|
|
sc.MustGetToken(TK_Identifier);
|
|
if(strlen(sc.String) > 5)
|
|
sc.ScriptError("MugShot frames can not 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 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);
|
|
cmd.y = (negative ? -sc.Number : sc.Number) - (200 - this->height);
|
|
}
|
|
|
|
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, 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;
|
|
sprite = 0;
|
|
translation = CR_UNTRANSLATED;
|
|
translation2 = CR_UNTRANSLATED;
|
|
translation3 = CR_UNTRANSLATED;
|
|
font = V_GetFont("CONFONT");
|
|
}
|
|
|
|
SBarInfoCommand::~SBarInfoCommand()
|
|
{
|
|
}
|
|
|
|
SBarInfoBlock::SBarInfoBlock()
|
|
{
|
|
forceScaled = false;
|
|
alpha = FRACUNIT;
|
|
}
|
|
|
|
const MugShotState *FindMugShotState(FString state)
|
|
{
|
|
state.ToLower();
|
|
for(unsigned int i = 0;i < MugShotStates.Size();i++)
|
|
{
|
|
if(MugShotStates[i].state == state)
|
|
return &MugShotStates[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//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;
|
|
}
|
|
|
|
//Used to allow replacements of states
|
|
int FindMugShotStateIndex(FName state)
|
|
{
|
|
for(unsigned int i = 0;i < MugShotStates.Size();i++)
|
|
{
|
|
if(MugShotStates[i].state == state)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|