Beispiel #1
0
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");
}
Beispiel #2
0
FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font)
{
	if (arc.IsStoring ())
	{
		arc << font->Name;
	}
	else
	{
		char *name = NULL;

		arc << name;
		font = V_GetFont(name);
		if (font == NULL)
		{
			Printf ("Could not load font %s\n", name);
			font = SmallFont;
		}
		delete[] name;
	}
	return arc;
}
FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITFIELD flags)
{
	int i;
	int firstfound = -1;
	int firsttype = FTexture::TEX_Null;

	if (name == NULL || name[0] == '\0')
	{
		return FTextureID(-1);
	}
	// [RH] Doom counted anything beginning with '-' as "no texture".
	// Hopefully nobody made use of that and had textures like "-EMPTY",
	// because -NOFLAT- is a valid graphic for ZDoom.
	if (name[0] == '-' && name[1] == '\0')
	{
		return FTextureID(0);
	}
	i = HashFirst[MakeKey (name) % HASH_SIZE];

	while (i != HASH_END)
	{
		const FTexture *tex = Textures[i].Texture;

		if (stricmp (tex->Name, name) == 0)
		{
			// The name matches, so check the texture type
			if (usetype == FTexture::TEX_Any)
			{
				// All NULL textures should actually return 0
				if (tex->UseType == FTexture::TEX_FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0;
				return FTextureID(tex->UseType==FTexture::TEX_Null? 0 : i);
			}
			else if ((flags & TEXMAN_Overridable) && tex->UseType == FTexture::TEX_Override)
			{
				return FTextureID(i);
			}
			else if (tex->UseType == usetype)
			{
				return FTextureID(i);
			}
			else if (tex->UseType == FTexture::TEX_FirstDefined && usetype == FTexture::TEX_Wall)
			{
				if (!(flags & TEXMAN_ReturnFirst)) return FTextureID(0);
				else return FTextureID(i);
			}
			else if (tex->UseType == FTexture::TEX_Null && usetype == FTexture::TEX_Wall)
			{
				// We found a NULL texture on a wall -> return 0
				return FTextureID(0);
			}
			else
			{
				if (firsttype == FTexture::TEX_Null ||
					(firsttype == FTexture::TEX_MiscPatch &&
					 tex->UseType != firsttype &&
					 tex->UseType != FTexture::TEX_Null)
				   )
				{
					firstfound = i;
					firsttype = tex->UseType;
				}
			}
		}
		i = Textures[i].HashNext;
	}

	size_t namelen = strlen(name);
	if(name[0] == '#' && namelen == 7)
	{
		FTexture *solidTex = SolidTexture_TryCreate(name+1);
		solidTex->UseType = FTexture::TEX_Flat;
		return AddTexture(solidTex);
	}

	// Handle font look ups (FONTNAME:XX)
	if(namelen > 3 && name[namelen-3] == ':')
	{
		FString fontName(name, namelen-3);
		FFont *font = V_GetFont(fontName);
		if(font)
		{
			return font->GetCharID(ParseHex(name+namelen-2));
		}
	}

	if ((flags & TEXMAN_TryAny) && usetype != FTexture::TEX_Any)
	{
		// Never return the index of NULL textures.
		if (firstfound != -1)
		{
			if (firsttype == FTexture::TEX_Null) return FTextureID(0);
			if (firsttype == FTexture::TEX_FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0);
		}
		return FTextureID(firstfound);
	}

	return FTextureID(-1);
}
Beispiel #4
0
void HUD_InitHud()
{
	switch (gameinfo.gametype)
	{
	case GAME_Heretic:
	case GAME_Hexen:
		healthpic = TexMan.FindTexture("ARTIPTN2");
		HudFont=FFont::FindFont("HUDFONT_RAVEN");
		break;

	case GAME_Strife:
		healthpic = TexMan.FindTexture("I_MDKT");
		HudFont=BigFont;	// Strife doesn't have anything nice so use the standard font
		break;

	default:
		healthpic = TexMan.FindTexture("MEDIA0");
		berserkpic = TexMan.FindTexture("PSTRA0");
		HudFont=FFont::FindFont("HUDFONT_DOOM");
		break;
	}

	IndexFont = V_GetFont("INDEXFONT");

	if (HudFont == NULL) HudFont = BigFont;
	if (IndexFont == NULL) IndexFont = ConFont;	// Emergency fallback

	invgems[0] = TexMan.FindTexture("INVGEML1");
	invgems[1] = TexMan.FindTexture("INVGEML2");
	invgems[2] = TexMan.FindTexture("INVGEMR1");
	invgems[3] = TexMan.FindTexture("INVGEMR2");

	fragpic = TexMan.FindTexture("HU_FRAGS");	// Sadly, I don't have anything usable for this. :(

	KeyTypes.Clear();
	UnassignedKeyTypes.Clear();

	statspace = SmallFont->StringWidth("Ac:");



	// Now read custom icon overrides
	int lump, lastlump = 0;

	while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
	{
		FScanner sc(lump);
		while (sc.GetString())
		{
			if (sc.Compare("Health"))
			{
				sc.MustGetString();
				FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				if (tex.isValid()) healthpic = TexMan[tex];
			}
			else if (sc.Compare("Berserk"))
			{
				sc.MustGetString();
				FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				if (tex.isValid()) berserkpic = TexMan[tex];
			}
			else
			{
				PClass *ti = PClass::FindClass(sc.String);
				if (!ti)
				{
					Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String);
				}
				else if (!ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
				{
					Printf("Invalid item class '%s' in ALTHUDCF\n", sc.String);
					ti=NULL;
				}
				sc.MustGetString();
				FTextureID tex;

				if (!sc.Compare("0") && !sc.Compare("NULL") && !sc.Compare(""))
				{
					tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				}
				else tex.SetInvalid();

				if (ti) SetHUDIcon(static_cast<PClassInventory*>(ti), tex);
			}
		}
	}
}
Beispiel #5
0
static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
{
	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("else"))
		{
			SkipSubBlock(sc);
		}
		else if (sc.Compare("ifgame"))
		{
			if (!CheckSkipGameBlock(sc))
			{
				// recursively parse sub-block
				ParseListMenuBody(sc, desc);
			}
		}
		else if (sc.Compare("ifoption"))
		{
			if (!CheckSkipOptionBlock(sc))
			{
				// recursively parse sub-block
				ParseListMenuBody(sc, desc);
			}
		}
		else if (sc.Compare("Class"))
		{
			sc.MustGetString();
			const PClass *cls = PClass::FindClass(sc.String);
			if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(DListMenu)))
			{
				sc.ScriptError("Unknown menu class '%s'", sc.String);
			}
			desc->mClass = cls;
		}
		else if (sc.Compare("Selector"))
		{
			sc.MustGetString();
			desc->mSelector = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			desc->mSelectOfsX = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			desc->mSelectOfsY = sc.Number;
		}
		else if (sc.Compare("Linespacing"))
		{
			sc.MustGetNumber();
			desc->mLinespacing = sc.Number;
		}
		else if (sc.Compare("Position"))
		{
			sc.MustGetNumber();
			desc->mXpos = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			desc->mYpos = sc.Number;
		}
		else if (sc.Compare("Centermenu"))
		{
			desc->mCenter = true;
		}
		else if (sc.Compare("MouseWindow"))
		{
			sc.MustGetNumber();
			desc->mWLeft = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			desc->mWRight = sc.Number;
		}
		else if (sc.Compare("StaticPatch") || sc.Compare("StaticPatchCentered"))
		{
			bool centered = sc.Compare("StaticPatchCentered");
			sc.MustGetNumber();
			int x = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int y = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);

			FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered"))
		{
			bool centered = sc.Compare("StaticTextCentered");
			sc.MustGetNumber();
			int x = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int y = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FListMenuItem *it = new FListMenuItemStaticText(x, y, sc.String, desc->mFont, desc->mFontColor, centered);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("PatchItem"))
		{
			sc.MustGetString();
			FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
			sc.MustGetStringName(",");
			sc.MustGetString();
			int hotkey = sc.String[0];
			sc.MustGetStringName(",");
			sc.MustGetString();
			FName action = sc.String;
			int param = 0;
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				param = sc.Number;
			}

			FListMenuItem *it = new FListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param);
			desc->mItems.Push(it);
			desc->mYpos += desc->mLinespacing;
			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
		}
		else if (sc.Compare("TextItem"))
		{
			sc.MustGetString();
			FString text = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			int hotkey = sc.String[0];
			sc.MustGetStringName(",");
			sc.MustGetString();
			FName action = sc.String;
			int param = 0;
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				param = sc.Number;
			}

			FListMenuItem *it = new FListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param);
			desc->mItems.Push(it);
			desc->mYpos += desc->mLinespacing;
			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;

		}
		else if (sc.Compare("Font"))
		{
			sc.MustGetString();
			FFont *newfont = V_GetFont(sc.String);
			if (newfont != NULL) desc->mFont = newfont;
			if (sc.CheckString(","))
			{
				sc.MustGetString();
				desc->mFontColor2 = desc->mFontColor = V_FindFontColor((FName)sc.String);
				if (sc.CheckString(","))
				{
					sc.MustGetString();
					desc->mFontColor2 = V_FindFontColor((FName)sc.String);
				}
			}
			else
			{
				desc->mFontColor = OptionSettings.mFontColor;
				desc->mFontColor2 = OptionSettings.mFontColorValue;
			}
		}
		else if (sc.Compare("NetgameMessage"))
		{
			sc.MustGetString();
			desc->mNetgameMessage = sc.String;
		}
		else if (sc.Compare("PlayerDisplay"))
		{
			bool noportrait = false;
			FName action = NAME_None;
			sc.MustGetNumber();
			int x = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int y = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetString();
			PalEntry c1 = V_GetColor(NULL, sc.String);
			sc.MustGetStringName(",");
			sc.MustGetString();
			PalEntry c2 = V_GetColor(NULL, sc.String);
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				noportrait = !!sc.Number;
				if (sc.CheckString(","))
				{
					sc.MustGetString();
					action = sc.String;
				}
			}
			FListMenuItemPlayerDisplay *it = new FListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("PlayerNameBox"))
		{
			sc.MustGetString();
			FString text = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int ofs = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FListMenuItem *it = new FPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String);
			desc->mItems.Push(it);
			desc->mYpos += desc->mLinespacing;
			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
		}
		else if (sc.Compare("ValueText"))
		{
			sc.MustGetString();
			FString text = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FName action = sc.String;
			FName values;
			if (sc.CheckString(","))
			{
				sc.MustGetString();
				values = sc.String;
			}
			FListMenuItem *it = new FValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values);
			desc->mItems.Push(it);
			desc->mYpos += desc->mLinespacing;
			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
		}
		else if (sc.Compare("Slider"))
		{
			sc.MustGetString();
			FString text = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FString action = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int min = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int max = sc.Number;
			sc.MustGetStringName(",");
			sc.MustGetNumber();
			int step = sc.Number;
			FListMenuItem *it = new FSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step);
			desc->mItems.Push(it);
			desc->mYpos += desc->mLinespacing;
			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
		}
		else
		{
			sc.ScriptError("Unknown keyword '%s'", sc.String);
		}
	}
}
Beispiel #6
0
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("runeicon"))
						cmd.flags |= DRAWIMAGE_RUNEICON;
					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, block.fullScreenOffsets, cmd.x, cmd.y);
				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 if(sc.Compare("teamscore")) //Takes in a number for team
					{
						cmd.flags |= DRAWNUMBER_TEAMSCORE;
						sc.MustGetToken(TK_StringConst);
						int t = -1;
						for(unsigned int i = 0;i < teams.Size();i++)
						{
							if(teams[i].Name.CompareNoCase(sc.String) == 0)
							{
								t = (int) i;
								break;
							}
						}
						if(t == -1)
							sc.ScriptError("'%s' is not a valid team.", sc.String);
						cmd.value = t;
					}
					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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				cmd.special2 = *(cmd.x + 30);
				cmd.special3 = *(cmd.y + 24);
				cmd.translation = CR_GOLD;
				if(sc.CheckToken(',')) //more font information
				{
					this->getCoordinates(sc, block.fullScreenOffsets, cmd.special2, cmd.special3);
					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, block.fullScreenOffsets, cmd.x, cmd.y);
				cmd.special2 = *(cmd.x + 26);
				cmd.special3 = *(cmd.y + 22);
				cmd.translation = CR_GOLD;
				if(sc.CheckToken(',')) //more font information
				{
					this->getCoordinates(sc, block.fullScreenOffsets, cmd.special2, cmd.special3);
					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 if(sc.Compare("teamscore")) //Takes in a number for team
				{
					cmd.flags |= DRAWNUMBER_TEAMSCORE;
					sc.MustGetToken(TK_StringConst);
					int t = -1;
					for(unsigned int i = 0;i < teams.Size();i++)
					{
						if(teams[i].Name.CompareNoCase(sc.String) == 0)
						{
							t = (int) i;
							break;
						}
					}
					if(t == -1)
						sc.ScriptError("'%s' is not a valid team.", sc.String);
					cmd.value = t;
				}
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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, block.fullScreenOffsets, cmd.x, cmd.y);
				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 if(sc.Compare("ctf"))
						cmd.flags |= GAMETYPE_CTF;
					else if(sc.Compare("oneflagctf"))
						cmd.flags |= GAMETYPE_ONEFLAGCTF;
					else if(sc.Compare("skulltag"))
						cmd.flags |= GAMETYPE_SKULLTAG;
					else if(sc.Compare("invasion"))
						cmd.flags |= GAMETYPE_INVASION;
					else if(sc.Compare("possession"))
						cmd.flags |= GAMETYPE_POSSESSION;
					else if(sc.Compare("teampossession"))
						cmd.flags |= GAMETYPE_TEAMPOSSESSION;
					else if(sc.Compare("lastmanstanding"))
						cmd.flags |= GAMETYPE_LASTMANSTANDING;
					else if(sc.Compare("teamlms"))
						cmd.flags |= GAMETYPE_TEAMLMS;
					else if(sc.Compare("survival"))
						cmd.flags |= GAMETYPE_SURVIVAL;
					else if(sc.Compare("instagib"))
						cmd.flags |= GAMETYPE_INSTAGIB;
					else if(sc.Compare("buckshot"))
						cmd.flags |= GAMETYPE_BUCKSHOT;
					//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:
			case SBARINFO_USESAMMO:
				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('{');
				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:
				cmd.special2 = cmd.special3 = 0;
				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(','))
					{
						sc.MustGetNumber();
						if (i == 0) cmd.special2 = sc.Number;
						else cmd.special3 = sc.Number;
					}

					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('}');
}