Example #1
0
void gl_ParseHardwareShader(FScanner &sc, int deflump)
{
	int type = FTexture::TEX_Any;
	bool disable_fullbright=false;
	bool thiswad = false;
	bool iwad = false;
	int maplump = -1;
	FString maplumpname;
	float speed = 1.f;

	sc.MustGetString();
	if (sc.Compare("texture")) type = FTexture::TEX_Wall;
	else if (sc.Compare("flat")) type = FTexture::TEX_Flat;
	else if (sc.Compare("sprite")) type = FTexture::TEX_Sprite;
	else sc.UnGet();

	sc.MustGetString();
	FTextureID no = TexMan.CheckForTexture(sc.String, type);
	FTexture *tex = TexMan[no];

	sc.MustGetToken('{');
	while (!sc.CheckToken('}'))
	{
		sc.MustGetString();
		if (sc.Compare("shader"))
		{
			sc.MustGetString();
			maplumpname = sc.String;
		}
		else if (sc.Compare("speed"))
		{
			sc.MustGetFloat();
			speed = float(sc.Float);
		}
	}
	if (!tex)
	{
		return;
	}

	if (maplumpname.IsNotEmpty())
	{
		if (tex->bWarped != 0)
		{
			Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->Name.GetChars());
			return;
		}
		tex->gl_info.shaderspeed = speed; 
		for(unsigned i=0;i<usershaders.Size();i++)
		{
			if (!usershaders[i].CompareNoCase(maplumpname))
			{
				tex->gl_info.shaderindex = i + FIRST_USER_SHADER;
				return;
			}
		}
		tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER;
	}	
}
Example #2
0
static void ParseTime (FScanner &sc, DWORD &min, DWORD &max)
{
	sc.MustGetString ();
	if (sc.Compare ("tics"))
	{
		sc.MustGetFloat ();
		min = max = DWORD(sc.Float * 1000 / 35);
	}
	else if (sc.Compare ("rand"))
	{
		sc.MustGetFloat ();
		min = DWORD(sc.Float * 1000 / 35);
		sc.MustGetFloat ();
		max = DWORD(sc.Float * 1000 / 35);
	}
	else
	{
		sc.ScriptError ("Must specify a duration for animation frame");
	}
}
Example #3
0
void FTextureManager::ParseTime (FScanner &sc, uint32_t &min, uint32_t &max)
{
	sc.MustGetString ();
	if (sc.Compare ("tics"))
	{
		sc.MustGetFloat ();
		min = max = uint32_t(sc.Float * 1000 / 35);
	}
	else if (sc.Compare ("rand"))
	{
		sc.MustGetFloat ();
		min = uint32_t(sc.Float * 1000 / 35);
		sc.MustGetFloat ();
		max = uint32_t(sc.Float * 1000 / 35);
	}
	else
	{
		min = max = 1;
		sc.ScriptError ("Must specify a duration for animation frame");
	}
}
Example #4
0
static void ParseDamageDefinition(FScanner &sc)
{
	sc.SetCMode (true); // This may be 100% irrelevant for such a simple syntax, but I don't know

	// Get DamageType

	sc.MustGetString();
	FName damageType = sc.String;

	DamageTypeDefinition dtd;

	sc.MustGetToken('{');
	while (sc.MustGetAnyToken(), sc.TokenType != '}')
	{
		if (sc.Compare("FACTOR"))
		{
			sc.MustGetFloat();
			dtd.DefaultFactor = sc.Float;
			if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true;
		}
		else if (sc.Compare("REPLACEFACTOR"))
		{
			dtd.ReplaceFactor = true;
		}
		else if (sc.Compare("NOARMOR"))
		{
			dtd.NoArmor = true;
		}
		else
		{
			sc.ScriptError("Unexpected data (%s) in damagetype definition.", sc.String);
		}
	}

	dtd.Apply(damageType);

	sc.SetCMode (false); // (set to true earlier in function)
}
Example #5
0
static void ParseOptionValue(FScanner &sc)
{
	FName optname;

	FOptionValues *val = new FOptionValues;
	sc.MustGetString();
	optname = sc.String;
	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		FOptionValues::Pair &pair = val->mValues[val->mValues.Reserve(1)];
		sc.MustGetFloat();
		pair.Value = sc.Float;
		sc.MustGetStringName(",");
		sc.MustGetString();
		pair.Text = strbin1(sc.String);
	}
	FOptionValues **pOld = OptionValues.CheckKey(optname);
	if (pOld != NULL && *pOld != NULL) 
	{
		delete *pOld;
	}
	OptionValues[optname] = val;
}
Example #6
0
static void ParseFriction (FScanner &sc, int keyword, void *fields)
{
	FTerrainDef *def = (FTerrainDef *)fields;
	fixed_t friction, movefactor;

	sc.MustGetFloat ();

	// These calculations should match those in P_SetSectorFriction().
	// A friction of 1.0 is equivalent to ORIG_FRICTION.

	friction = (fixed_t)(0x1EB8*(sc.Float*100))/0x80 + 0xD001;
	friction = clamp<fixed_t> (friction, 0, FRACUNIT);

	if (friction > ORIG_FRICTION)	// ice
		movefactor = ((0x10092 - friction) * 1024) / 4352 + 568;
	else
		movefactor = ((friction - 0xDB34)*(0xA))/0x80;

	if (movefactor < 32)
		movefactor = 32;

	def->Friction = friction;
	def->MoveFactor = movefactor;
}
Example #7
0
bool FIntermissionActionTextscreen::ParseKey(FScanner &sc)
{
	if (sc.Compare("Position"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_IntConst);
		mTextX = sc.Number;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_IntConst);
		mTextY = sc.Number;
		return true;
	}
	else if (sc.Compare("TextLump"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		int lump = Wads.CheckNumForFullName(sc.String, true);
		if (lump > 0)
		{
			mText = Wads.ReadLump(lump).GetString();
		}
		else
		{
			// only print an error if coming from a PWAD
			if (Wads.GetLumpFile(sc.LumpNum) > 1)
				sc.ScriptMessage("Unknown text lump '%s'", sc.String);
			mText.Format("Unknown text lump '%s'", sc.String);
		}
		return true;
	}
	else if (sc.Compare("Text"))
	{
		sc.MustGetToken('=');
		do
		{
			sc.MustGetToken(TK_StringConst);
			mText << sc.String << '\n';
		}
		while (sc.CheckToken(','));
		return true;
	}
	else if (sc.Compare("TextColor"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		mTextColor = V_FindFontColor(sc.String);
		return true;
	}
	else if (sc.Compare("TextDelay"))
	{
		sc.MustGetToken('=');
		if (!sc.CheckToken('-'))
		{
			sc.MustGetFloat();
			mTextDelay = int(sc.Float*TICRATE);
		}
		else
		{
			sc.MustGetToken(TK_IntConst);
			mTextDelay = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("textspeed"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_IntConst);
		mTextSpeed = sc.Number;
		return true;
	}
	else return Super::ParseKey(sc);
}
Example #8
0
void MapLoader::parseEDLinedef(FScanner &sc, TMap<int, EDLinedef> &EDLines)
{
	EDLinedef ld;
	bool argsset = false;

	memset(&ld, 0, sizeof(ld));
	ld.alpha = 1.;

	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("recordnum"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			ld.recordnum = sc.Number;
		}
		else if (sc.Compare("tag"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			ld.tag = sc.Number;
		}
		else if (sc.Compare("id"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			ld.id = sc.Number;
		}
		else if (sc.Compare("special"))
		{
			sc.CheckString("=");
			if (sc.CheckNumber())
			{
				// Oh joy, this is going to be fun...
				// Here we cannot do anything because we need the tag to make this work. 
				// For now just store a negative number and resolve this later.
				ld.special = -sc.Number;
			}
			else
			{
				sc.MustGetString();
				ld.special = P_FindLineSpecial(sc.String);
			}
		}
		else if (sc.Compare("args"))
		{
			sc.CheckString("=");
			sc.MustGetStringName("{");
			int c = 0;
			while (true)
			{
				sc.MustGetNumber();
				ld.args[c++] = sc.Number;
				if (sc.CheckString("}")) break;
				sc.MustGetStringName(",");
			}
			argsset = true;
		}
		else if (sc.Compare("alpha"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			ld.alpha = sc.Float;
		}
		else if (sc.Compare("extflags"))
		{
			// these are needed to build the proper activation mask out of the possible flags which do not match ZDoom 1:1.
			uint32_t actmethod = 0;
			uint32_t acttype = 0;
			do
			{
				sc.CheckString("=");
				sc.MustGetString();
				for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t"))
				{
					if (!stricmp(tok, "USE")) actmethod |= SPAC_Use | SPAC_MUse;
					else if (!stricmp(tok, "CROSS")) actmethod |= SPAC_Cross | SPAC_MCross | SPAC_PCross;
					else if (!stricmp(tok, "IMPACT")) ld.activation |= SPAC_Impact;
					else if (!stricmp(tok, "PUSH")) actmethod |= SPAC_Push;
					else if (!stricmp(tok, "PLAYER")) acttype |= SPAC_Use | SPAC_Cross | SPAC_Push;
					else if (!stricmp(tok, "MONSTER")) acttype |= SPAC_MUse | SPAC_MCross | SPAC_MPush;
					else if (!stricmp(tok, "MISSILE")) acttype |= SPAC_PCross;
					else if (!stricmp(tok, "REPEAT")) ld.flags |= ML_REPEAT_SPECIAL;
					else if (!stricmp(tok, "1SONLY")) ld.flags |= ML_FIRSTSIDEONLY;
					else if (!stricmp(tok, "ADDITIVE")) ld.flags |= ML_ADDTRANS;
					else if (!stricmp(tok, "BLOCKALL")) ld.flags |= ML_BLOCKEVERYTHING;
					else if (!stricmp(tok, "ZONEBOUNDARY")) ld.flags |= ML_ZONEBOUNDARY;
					else if (!stricmp(tok, "CLIPMIDTEX")) ld.flags |= ML_CLIP_MIDTEX;
					else sc.ScriptError("Unknown option '%s'", tok);
				}
			} while (sc.CheckString("|"));	// Unquoted strings with '|' separator - parse as a separate string in the loop.

			// and finally we must mask in the activation method
			ld.activation |= (actmethod & acttype);
		}
		else
		{
			sc.ScriptError("Unknown property '%s'", sc.String);
		}
	}
	if (ld.tag == 0) ld.tag = ld.id;	// urgh...
	if (ld.special < 0)	// translate numeric specials.
	{
		line_t line;
		maplinedef_t mld;
		mld.special = -ld.special;
		mld.tag = ld.tag;
		Level->TranslateLineDef(&line, &mld);
		ld.special = line.special;
		ld.activation = line.activation;
		ld.flags = (ld.flags & ~(ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)) | (line.flags & (ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY));
		if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args));
	}
	 EDLines[ld.recordnum] = ld;
}
Example #9
0
static void parseMapthing(FScanner &sc, TMap<int, EDMapthing> &EDThings)
{
	EDMapthing mt;

	memset(&mt, 0, sizeof(mt));
	mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH;	// Extradata uses inverse logic, like Doom.exe

	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("recordnum"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			mt.recordnum = sc.Number;
		}
		else if (sc.Compare("tid"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			mt.tid = sc.Number;
		}
		else if (sc.Compare("type"))
		{
			sc.CheckString("=");
			if (sc.CheckNumber())
			{
				mt.type = sc.Number;
			}
			else
			{
				// Class name.
				sc.MustGetString();
				// According to the Eternity Wiki a name may be prefixed with 'thing:'.
				const char *pos = strchr(sc.String, ':');	// Eternity never checks if the prefix actually is 'thing'.
				if (pos) pos++;
				else pos = sc.String;
				const PClass *cls = PClass::FindClass(pos);
				if (cls != nullptr)
				{
					FDoomEdMap::Iterator it(DoomEdMap);
					FDoomEdMap::Pair *pair;
					while (it.NextPair(pair))
					{
						if (pair->Value.Type == cls)
						{
							mt.type = pair->Key;
							break;
						}
					}
				}
				else
				{
					// Let's hope this isn't an internal Eternity name.
					// If so, a name mapping needs to be defined...
					sc.ScriptError("Unknown type '%s'", sc.String);
				}

			}
		}
		else if (sc.Compare("args"))
		{
			sc.CheckString("=");
			sc.MustGetStringName("{");
			int c = 0;
			while (!sc.CheckString("}"))
			{
				sc.MustGetNumber();
				mt.args[c++] = sc.Number;

			}
		}
		else if (sc.Compare("height"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();	// no idea if Eternity allows fractional numbers. Better be safe and do it anyway.
			mt.height = sc.Float;
		}
		else if (sc.Compare("options"))
		{
			sc.CheckString("=");
			do
			{
				sc.MustGetString();
				for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t"))
				{
					if (!stricmp(tok, "EASY")) mt.skillfilter |= 3;
					else if (!stricmp(tok, "NORMAL")) mt.skillfilter |= 4;
					else if (!stricmp(tok, "HARD")) mt.skillfilter |= 24;
					else if (!stricmp(tok, "AMBUSH")) mt.flags |= MTF_AMBUSH;
					else if (!stricmp(tok, "NOTSINGLE")) mt.flags &= ~MTF_SINGLE;
					else if (!stricmp(tok, "NOTDM")) mt.flags &= ~MTF_DEATHMATCH;
					else if (!stricmp(tok, "NOTCOOP")) mt.flags &= ~MTF_COOPERATIVE;
					else if (!stricmp(tok, "FRIEND")) mt.flags |= MTF_FRIENDLY;
					else if (!stricmp(tok, "DORMANT")) mt.flags |= MTF_DORMANT;
					else sc.ScriptError("Unknown option '%s'", tok);
				}
			} while (sc.CheckString("|"));	// Unquoted strings with '|' separator - parse as a separate string in the loop.
		}
		else
		{
			sc.ScriptError("Unknown property '%s'", sc.String);
		}
	}
	EDThings[mt.recordnum] = mt;
}
Example #10
0
static void parseSector(FScanner &sc, TMap<int, EDSector> &EDSectors)
{
	EDSector sec;

	memset(&sec, 0, sizeof(sec));
	sec.Overlayalpha[sector_t::floor] = sec.Overlayalpha[sector_t::ceiling] = 1.;
	sec.floorterrain = sec.ceilingterrain = -1;

	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("recordnum"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			sec.recordnum = sc.Number;
		}
		else if (sc.Compare("flags"))
		{
			uint32_t *flagvar = nullptr;
			if (sc.CheckString("."))
			{
				sc.MustGetString();
				if (sc.Compare("add"))
				{
					flagvar = &sec.flagsAdd;
				}
				else if (sc.Compare("remove"))
				{
					flagvar = &sec.flagsRemove;
				}
				else
				{
					sc.ScriptError("Invalid property  'flags.%s'", sc.String);
				}
			}
			else
			{
				sec.flagsSet = true;
				flagvar = &sec.flags;
			}
			sc.CheckString("=");
			do
			{
				sc.MustGetString();
				for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t"))
				{
					if (!stricmp(tok, "SECRET")) *flagvar |= SECF_SECRET | SECF_WASSECRET;
					else if (!stricmp(tok, "FRICTION")) *flagvar |= SECF_FRICTION;
					else if (!stricmp(tok, "PUSH")) *flagvar |= SECF_PUSH;
					else if (!stricmp(tok, "KILLSOUND")) *flagvar |= SECF_SILENT;
					else if (!stricmp(tok, "KILLMOVESOUND")) *flagvar |= SECF_SILENTMOVE;
					else sc.ScriptError("Unknown option '%s'", tok);
				}
			} while (sc.CheckString("|"));	// Unquoted strings with '|' separator - parse as a separate string in the loop.
		}
		else if (sc.Compare("damage"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			sec.damageamount = sc.Number;
		}
		else if (sc.Compare("damagemod"))
		{
			sc.CheckString("=");
			sc.MustGetString();
			sec.damagetype = sc.String;
		}
		else if (sc.Compare("damagemask"))
		{
			sc.CheckString("=");
			sc.MustGetNumber();
			sec.damageinterval = sc.Number;
		}
		else if (sc.Compare("damageflags"))
		{
			uint32_t *flagvar = nullptr;
			uint8_t *leakvar = nullptr;
			if (sc.CheckString("."))
			{
				sc.MustGetString();
				if (sc.Compare("add"))
				{
					flagvar = &sec.damageflagsAdd;
					leakvar = &sec.leakyadd;
				}
				else if (sc.Compare("remove"))
				{
					flagvar = &sec.damageflagsRemove;
					leakvar = &sec.leakyremove;
				}
				else
				{
					sc.ScriptError("Invalid property  'flags.%s'", sc.String);
				}
			}
			else
			{
				sec.damageflagsSet = true;
				flagvar = &sec.damageflags;
				leakvar = &sec.leaky;
			}
			sc.CheckString("=");
			do
			{
				sc.MustGetString();
				for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t"))
				{
					if (!stricmp(tok, "LEAKYSUIT")) *leakvar |= 1;
					else if (!stricmp(tok, "IGNORESUIT")) *leakvar |= 2;	// these 2 bits will be used to set 'leakychance', but this can only be done when the sector gets initialized
					else if (!stricmp(tok, "ENDGODMODE")) *flagvar |= SECF_ENDGODMODE;
					else if (!stricmp(tok, "ENDLEVEL")) *flagvar |= SECF_ENDLEVEL;
					else if (!stricmp(tok, "TERRAINHIT")) *flagvar |= SECF_DMGTERRAINFX;
					else sc.ScriptError("Unknown option '%s'", tok);
				}
			} while (sc.CheckString("|"));	// Unquoted strings with '|' separator - parse as a separate string in the loop.
		}
		else if (sc.Compare("floorterrain"))
		{
			sc.CheckString("=");
			sc.MustGetString();
			sec.floorterrain = P_FindTerrain(sc.String);
		}
		else if (sc.Compare("floorangle"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.angle[sector_t::floor] = sc.Float;
		}
		else if (sc.Compare("flooroffsetx"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.xoffs[sector_t::floor] = sc.Float;
		}
		else if (sc.Compare("flooroffsety"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.yoffs[sector_t::floor] = sc.Float;
		}
		else if (sc.Compare("ceilingterrain"))
		{
			sc.CheckString("=");
			sc.MustGetString();
			sec.ceilingterrain = P_FindTerrain(sc.String);
		}
		else if (sc.Compare("ceilingangle"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.angle[sector_t::ceiling] = sc.Float;
		}
		else if (sc.Compare("ceilingoffsetx"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.xoffs[sector_t::ceiling] = sc.Float;
		}
		else if (sc.Compare("ceilingoffsety"))
		{
			sc.CheckString("=");
			sc.MustGetFloat();
			sec.yoffs[sector_t::ceiling] = sc.Float;
		}
		else if (sc.Compare("colormaptop") || sc.Compare("colormapbottom"))
		{
			sc.CheckString("=");
			sc.MustGetString();
			// these properties are not implemented by ZDoom
		}
		else if (sc.Compare("colormapmid"))
		{
			sc.CheckString("=");
			sc.MustGetString();
			// Eternity is based on SMMU and uses colormaps differently than all other ports.
			// The only solution here is to convert the colormap to an RGB value and set it as the sector's color.
			uint32_t cmap = R_ColormapNumForName(sc.String);
			if (cmap != 0)
			{
				sec.color = R_BlendForColormap(cmap) & 0xff000000;
				sec.colorSet = true;
			}
		}
		else if (sc.Compare("overlayalpha"))
		{
			sc.MustGetStringName(".");
			sc.MustGetString();
			if (sc.Compare("floor"))
			{
				sc.MustGetNumber();
				if (sc.CheckString("%")) sc.Float = sc.Number / 100.f;
				else sc.Float = sc.Number / 255.f;
				sec.Overlayalpha[sector_t::floor] = sc.Float;
			}
			else if (sc.Compare("ceiling"))
			{
				sc.MustGetFloat();
				if (sc.CheckString("%")) sc.Float = sc.Number / 100.f;
				else sc.Float = sc.Number / 255.f;
				sec.Overlayalpha[sector_t::floor] = sc.Float;
			}
		}
		else if (sc.Compare("portalflags"))
		{
			int dest = 0;
			sc.MustGetStringName(".");
			sc.MustGetString();
			if (sc.Compare("floor")) dest = sector_t::floor;
			else if (sc.Compare("ceiling")) dest = sector_t::ceiling;
			else sc.ScriptError("Unknown portal type '%s'", sc.String);

			sc.CheckString("=");
			do
			{
				sc.MustGetString();
				for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t"))
				{
					if (!stricmp(tok, "DISABLED")) sec.portalflags[dest] |= PLANEF_DISABLED;
					else if (!stricmp(tok, "NORENDER")) sec.portalflags[dest] |= PLANEF_NORENDER;
					else if (!stricmp(tok, "NOPASS")) sec.portalflags[dest] |= PLANEF_NOPASS;
					else if (!stricmp(tok, "BLOCKSOUND")) sec.portalflags[dest] |= PLANEF_BLOCKSOUND;
					else if (!stricmp(tok, "OVERLAY")) sec.portalflags[dest] |= 0;	// we do not use this. Alpha is the sole determinant for overlay drawing
					else if (!stricmp(tok, "ADDITIVE")) sec.portalflags[dest] |= PLANEF_ADDITIVE;
					else if (!stricmp(tok, "USEGLOBALTEX")) {}	// not implemented
					else sc.ScriptError("Unknown option '%s'", tok);
				}
			} while (sc.CheckString("|"));	// Unquoted strings with '|' separator - parse as a separate string in the loop.
		}
		else
		{
			sc.ScriptError("Unknown property '%s'", sc.String);
		}
	}
	EDSectors[sec.recordnum] = sec;
}
Example #11
0
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init)
{
	FString patchname;
	int Mirror = 0;
	sc.MustGetString();

	init.TexName = sc.String;
	sc.MustGetStringName(",");
	sc.MustGetNumber();
	part.OriginX = sc.Number;
	sc.MustGetStringName(",");
	sc.MustGetNumber();
	part.OriginY = sc.Number;

	if (sc.CheckString("{"))
	{
		while (!sc.CheckString("}"))
		{
			sc.MustGetString();
			if (sc.Compare("flipx"))
			{
				Mirror |= 1;
			}
			else if (sc.Compare("flipy"))
			{
				Mirror |= 2;
			}
			else if (sc.Compare("rotate"))
			{
				sc.MustGetNumber();
				sc.Number = (((sc.Number + 90)%360)-90);
 				if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90)
 				{
					sc.ScriptError("Rotation must be a multiple of 90 degrees.");
				}
				part.Rotate = (sc.Number / 90) & 3;
			}
			else if (sc.Compare("Translation"))
			{
				int match;

				bComplex = true;
				if (part.Translation != NULL) delete part.Translation;
				part.Translation = NULL;
				part.Blend = 0;
				static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL };
				sc.MustGetString();

				match = sc.MatchString(maps);
				if (match >= 0)
				{
					part.Blend = BLEND_SPECIALCOLORMAP1 + match;
				}
				else if (sc.Compare("ICE"))
				{
					part.Blend = BLEND_ICEMAP;
				}
				else if (sc.Compare("DESATURATE"))
				{
					sc.MustGetStringName(",");
					sc.MustGetNumber();
					part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30);
				}
				else
				{
					sc.UnGet();
					part.Translation = new FRemapTable;
					part.Translation->MakeIdentity();
					do
					{
						sc.MustGetString();
						part.Translation->AddToTranslation(sc.String);
					}
					while (sc.CheckString(","));
				}

			}
			else if (sc.Compare("Colormap"))
			{
				float r1,g1,b1;
				float r2,g2,b2;

				sc.MustGetFloat();
				r1 = (float)sc.Float;
				sc.MustGetStringName(",");
				sc.MustGetFloat();
				g1 = (float)sc.Float;
				sc.MustGetStringName(",");
				sc.MustGetFloat();
				b1 = (float)sc.Float;
				if (!sc.CheckString(","))
				{
					part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1);
				}
				else
				{
					sc.MustGetFloat();
					r2 = (float)sc.Float;
					sc.MustGetStringName(",");
					sc.MustGetFloat();
					g2 = (float)sc.Float;
					sc.MustGetStringName(",");
					sc.MustGetFloat();
					b2 = (float)sc.Float;
					part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2);
				}
			}
			else if (sc.Compare("Blend"))
			{
				bComplex = true;
				if (part.Translation != NULL) delete part.Translation;
				part.Translation = NULL;
				part.Blend = 0;

				if (!sc.CheckNumber())
				{
					sc.MustGetString();
					part.Blend = V_GetColor(NULL, sc);
				}
				else
				{
					int r,g,b;

					r = sc.Number;
					sc.MustGetStringName(",");
					sc.MustGetNumber();
					g = sc.Number;
					sc.MustGetStringName(",");
					sc.MustGetNumber();
					b = sc.Number;
					//sc.MustGetStringName(","); This was never supposed to be here. 
					part.Blend = MAKERGB(r, g, b);
				}
				// Blend.a may never be 0 here.
				if (sc.CheckString(","))
				{
					sc.MustGetFloat();
					if (sc.Float > 0.f)
						part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
					else
						part.Blend = 0;
				}
				else part.Blend.a = 255;
			}
			else if (sc.Compare("alpha"))
			{
				sc.MustGetFloat();
				part.Alpha = clamp<blend_t>(int(sc.Float * BLENDUNIT), 0, BLENDUNIT);
				// bComplex is not set because it is only needed when the style is not OP_COPY.
			}
			else if (sc.Compare("style"))
			{
				static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL };
				sc.MustGetString();
				part.op = sc.MustMatchString(styles);
				bComplex |= (part.op != OP_COPY);
				bTranslucentPatches = bComplex;
			}
			else if (sc.Compare("useoffsets"))
			{
				init.UseOffsets = true;
			}
		}
	}
	if (Mirror & 2)
	{
		part.Rotate = (part.Rotate + 2) & 3;
		Mirror ^= 1;
	}
	if (Mirror & 1)
	{
		part.Rotate |= 4;
	}
}
Example #12
0
static void ReadReverbDef (int lump)
{
	FScanner sc;
	const ReverbContainer *def;
	ReverbContainer *newenv;
	REVERB_PROPERTIES props;
	char *name;
	int id1, id2, i, j;
	bool inited[NUM_REVERB_FIELDS];
	BYTE bools[32];

	sc.OpenLumpNum(lump);
	while (sc.GetString ())
	{
		name = copystring (sc.String);
		sc.MustGetNumber ();
		id1 = sc.Number;
		sc.MustGetNumber ();
		id2 = sc.Number;
		sc.MustGetStringName ("{");
		memset (inited, 0, sizeof(inited));
		props.Instance = 0;
		props.Flags = 0;
		while (sc.MustGetString (), NUM_REVERB_FIELDS > (i = sc.MustMatchString (ReverbFieldNames)))
		{
			if (ReverbFields[i].Float)
			{
				sc.MustGetFloat ();
				props.*ReverbFields[i].Float = (float)clamp (sc.Float,
					double(ReverbFields[i].Min)/1000,
					double(ReverbFields[i].Max)/1000);
			}
			else if (ReverbFields[i].Int)
			{
				sc.MustGetNumber ();
				props.*ReverbFields[i].Int = (j = clamp (sc.Number,
					ReverbFields[i].Min, ReverbFields[i].Max));
				if (i == 0 && j != sc.Number)
				{
					sc.ScriptError ("The Environment field is out of range.");
				}
			}
			else
			{
				sc.MustGetString ();
				bools[ReverbFields[i].Flag] = sc.MustMatchString (BoolNames);
			}
			inited[i] = true;
		}
		if (!inited[0])
		{
			sc.ScriptError ("Sound %s is missing an Environment field.", name);
		}

		// Add the new environment to the list, filling in uninitialized fields
		// with values from the standard environment specified.
		def = DefaultEnvironments[props.Environment];
		for (i = 0; i < NUM_REVERB_FIELDS; ++i)
		{
			if (ReverbFields[i].Float)
			{
				if (!inited[i])
				{
					props.*ReverbFields[i].Float = def->Properties.*ReverbFields[i].Float;
				}
			}
			else if (ReverbFields[i].Int)
			{
				if (!inited[i])
				{
					props.*ReverbFields[i].Int = def->Properties.*ReverbFields[i].Int;
				}
			}
			else
			{
				if (!inited[i])
				{
					int mask = 1 << ReverbFields[i].Flag;
					if (def->Properties.Flags & mask)
					{
						props.Flags |= mask;
					}
				}
				else
				{
					if (bools[ReverbFields[i].Flag])
					{
						props.Flags |= 1 << ReverbFields[i].Flag;
					}
				}
			}
		}

		newenv = new ReverbContainer;
		newenv->Next = NULL;
		newenv->Name = name;
		newenv->ID = (id1 << 8) | id2;
		newenv->Builtin = false;
		newenv->Properties = props;
		newenv->SoftwareWater = false;
		S_AddEnvironment (newenv);
	}
}
Example #13
0
static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
{
	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("ifgame"))
		{
			if (!CheckSkipGameBlock(sc))
			{
				// recursively parse sub-block
				ParseOptionMenuBody(sc, desc);
			}
		}
		else if (sc.Compare("ifoption"))
		{
			if (!CheckSkipOptionBlock(sc))
			{
				// recursively parse sub-block
				ParseOptionMenuBody(sc, desc);
			}
		}
		else if (sc.Compare("Class"))
		{
			sc.MustGetString();
			const PClass *cls = PClass::FindClass(sc.String);
			if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(DOptionMenu)))
			{
				sc.ScriptError("Unknown menu class '%s'", sc.String);
			}
			desc->mClass = cls;
		}
		else if (sc.Compare("Title"))
		{
			sc.MustGetString();
			desc->mTitle = sc.String;
		}
		else if (sc.Compare("Position"))
		{
			sc.MustGetNumber();
			desc->mPosition = sc.Number;
		}
		else if (sc.Compare("DefaultSelection"))
		{
			sc.MustGetNumber();
			desc->mSelectedItem = sc.Number;
		}
		else if (sc.Compare("ScrollTop"))
		{
			sc.MustGetNumber();
			desc->mScrollTop = sc.Number;
		}
		else if (sc.Compare("Indent"))
		{
			sc.MustGetNumber();
			desc->mIndent = sc.Number;
		}
		else if (sc.Compare("Submenu"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuItemSubmenu(label, sc.String);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("Option"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FString cvar = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FString values = sc.String;
			FString check;
			int center = 0;
			if (sc.CheckString(","))
			{
				sc.MustGetString();
				if (*sc.String != 0) check = sc.String;
				if (sc.CheckString(","))
				{
					sc.MustGetNumber();
					center = sc.Number;
				}
			}
			FOptionMenuItem *it = new FOptionMenuItemOption(label, cvar, values, check, center);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("Command"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuItemCommand(label, sc.String);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("SafeCommand"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, sc.String);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("Control") || sc.Compare("MapControl"))
		{
			bool map = sc.Compare("MapControl");
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("ColorPicker"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuItemColorPicker(label, sc.String);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("StaticText"))
		{
			sc.MustGetString();
			FString label = sc.String;
			bool cr = false;
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				cr = !!sc.Number;
			}
			FOptionMenuItem *it = new FOptionMenuItemStaticText(label, cr);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("StaticTextSwitchable"))
		{
			sc.MustGetString();
			FString label = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FString label2 = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FName action = sc.String;
			bool cr = false;
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				cr = !!sc.Number;
			}
			FOptionMenuItem *it = new FOptionMenuItemStaticTextSwitchable(label, label2, action, cr);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("Slider"))
		{
			sc.MustGetString();
			FString text = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetString();
			FString action = sc.String;
			sc.MustGetStringName(",");
			sc.MustGetFloat();
			double min = sc.Float;
			sc.MustGetStringName(",");
			sc.MustGetFloat();
			double max = sc.Float;
			sc.MustGetStringName(",");
			sc.MustGetFloat();
			double step = sc.Float;
			int showvalue = 1;
			if (sc.CheckString(","))
			{
				sc.MustGetNumber();
				showvalue = sc.Number;
			}
			FOptionMenuItem *it = new FOptionMenuSliderCVar(text, action, min, max, step, showvalue);
			desc->mItems.Push(it);
		}
		else if (sc.Compare("screenresolution"))
		{
			sc.MustGetString();
			FOptionMenuItem *it = new FOptionMenuScreenResolutionLine(sc.String);
			desc->mItems.Push(it);
		}
		else
		{
			sc.ScriptError("Unknown keyword '%s'", sc.String);
		}
	}
}
Example #14
0
static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defaults, Baggage &bag)
{
	static TArray<FPropParam> params;
	static TArray<FString> strings;

	params.Clear();
	strings.Clear();
	params.Reserve(1);
	params[0].i = 0;
	if (prop->params[0] != '0')
	{
		const char * p = prop->params;
		bool nocomma;
		bool optcomma;
		while (*p)
		{
			FPropParam conv;
			FPropParam pref;

			nocomma = false;
			conv.s = NULL;
			pref.s = NULL;
			pref.i = -1;
			bag.ScriptPosition = sc;
			switch ((*p) & 223)
			{
			case 'X':	// Expression in parentheses or number.
				{
					FxExpression *x = NULL;

					if (sc.CheckString ("("))
					{
						x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true);
						sc.MustGetStringName(")");
					}
					else
					{
						sc.MustGetNumber();
						if (sc.Number != 0)
						{
							x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false);
						}
					}
					conv.exp = x;
					params.Push(conv);
				}
				break;

			case 'I':
				sc.MustGetNumber();
				conv.i = sc.Number;
				break;

			case 'F':
				sc.MustGetFloat();
				conv.d = sc.Float;
				break;

			case 'Z':	// an optional string. Does not allow any numerical value.
				if (sc.CheckFloat())
				{
					nocomma = true;
					sc.UnGet();
					break;
				}
				// fall through

			case 'S':
				sc.MustGetString();
				conv.s = strings[strings.Reserve(1)] = sc.String;
				break;

			case 'T':
				sc.MustGetString();
				conv.s = strings[strings.Reserve(1)] = strbin1(sc.String);
				break;

			case 'C':
				if (sc.CheckNumber ())
				{
					int R, G, B;
					R = clamp (sc.Number, 0, 255);
					sc.CheckString (",");
					sc.MustGetNumber ();
					G = clamp (sc.Number, 0, 255);
					sc.CheckString (",");
					sc.MustGetNumber ();
					B = clamp (sc.Number, 0, 255);
					conv.i = MAKERGB(R, G, B);
					pref.i = 0;
				}
				else
				{
					sc.MustGetString ();
					conv.s = strings[strings.Reserve(1)] = sc.String;
					pref.i = 1;
				}
				break;

			case 'M':	// special case. An expression-aware parser will not need this.
				conv.i = ParseMorphStyle(sc);
				break;
				
			case 'N':	// special case. An expression-aware parser will not need this.
				conv.i = ParseThingActivation(sc);
				break;

			case 'L':	// Either a number or a list of strings
				if (sc.CheckNumber())
				{
					pref.i = 0;
					conv.i = sc.Number;
				}
				else
				{
					pref.i = 1;
					params.Push(pref);
					params[0].i++;

					do
					{
						sc.MustGetString ();
						conv.s = strings[strings.Reserve(1)] = sc.String;
						params.Push(conv);
						params[0].i++;
					}
					while (sc.CheckString(","));
					goto endofparm;
				}
				break;

			default:
				assert(false);
				break;

			}
			if (pref.i != -1)
			{
				params.Push(pref);
				params[0].i++;
			}
			params.Push(conv);
			params[0].i++;
		endofparm:
			p++;
			// Hack for some properties that have to allow comma less
			// parameter lists for compatibility.
			if ((optcomma = (*p == '_'))) 
				p++;

			if (nocomma) 
			{
				continue;
			}
			else if (*p == 0) 
			{
				break;
			}
			else if (*p >= 'a')
			{
				if (!sc.CheckString(","))
				{
					if (optcomma)
					{
						if (!sc.CheckFloat()) break;
						else sc.UnGet();
					}
					else break;
				}
			}
			else 
			{
				if (!optcomma) sc.MustGetStringName(",");
				else sc.CheckString(",");
			}
		}
	}
	// call the handler
	try
	{
		prop->Handler(defaults, bag.Info, bag, &params[0]);
	}
	catch (CRecoverableError &error)
	{
		sc.ScriptError("%s", error.GetMessage());
	}

	return true;
}
Example #15
0
static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keywords,
	void *fields, const char *type, FName name)
{
	bool notdone = true;
	int keyword;
	int val = 0;
	const PClass *info;

	do
	{
		sc.MustGetString ();
		keyword = sc.MustMatchString (keywords);
		switch (parser[keyword].Type)
		{
		case GEN_End:
			notdone = false;
			break;

		case GEN_Fixed:
			sc.MustGetFloat ();
			SET_FIELD (fixed_t, (fixed_t)(FRACUNIT * sc.Float));
			break;

		case GEN_Sound:
			sc.MustGetString ();
			SET_FIELD (FSoundID, FSoundID(sc.String));
			/* unknown sounds never produce errors anywhere else so they shouldn't here either.
			if (val == 0)
			{
				Printf ("Unknown sound %s in %s %s\n",
					sc.String, type, name.GetChars());
			}
			*/
			break;

		case GEN_Byte:
			sc.MustGetNumber ();
			SET_FIELD (BYTE, sc.Number);
			break;

		case GEN_Class:
			sc.MustGetString ();
			if (sc.Compare ("None"))
			{
				info = NULL;
			}
			else
			{
				info = PClass::FindClass (sc.String);
				if (!info->IsDescendantOf (RUNTIME_CLASS(AActor)))
				{
					Printf ("%s is not an Actor (in %s %s)\n",
						sc.String, type, name.GetChars());
					info = NULL;
				}
				else if (info == NULL)
				{
					Printf ("Unknown actor %s in %s %s\n",
						sc.String, type, name.GetChars());
				}
			}
			SET_FIELD (const PClass *, info);
			break;

		case GEN_Splash:
			sc.MustGetString ();
			val = FindSplash (sc.String);
			SET_FIELD (int, val);
			if (val == -1)
			{
				Printf ("Splash %s is not defined yet (in %s %s)\n",
					sc.String, type, name.GetChars());
			}
			break;

		case GEN_Float:
			sc.MustGetFloat ();
			SET_FIELD (float, float(sc.Float));
			break;

		case GEN_Time:
			sc.MustGetFloat ();
			SET_FIELD (int, (int)(sc.Float * TICRATE));
			break;

		case GEN_Bool:
			SET_FIELD (bool, true);
			break;

		case GEN_Int:
			sc.MustGetNumber ();
			SET_FIELD (int, sc.Number);
			break;

		case GEN_Custom:
			parser[keyword].u.Handler (sc, keyword, fields);
			break;
		}
	} while (notdone);
}
Example #16
0
bool FIntermissionActionScroller::ParseKey(FScanner &sc)
{
	struct ScrollType
	{
		const char *Name;
		EScrollDir Type;
	}
	const ST[] = {
		{ "Left", SCROLL_Left },
		{ "Right", SCROLL_Right },
		{ "Up", SCROLL_Up },
		{ "Down", SCROLL_Down },
		{ NULL, SCROLL_Left }
	};

	if (sc.Compare("ScrollDirection"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_Identifier);
		int v = sc.MatchString(&ST[0].Name, sizeof(ST[0]));
		if (v != -1) mScrollDir = ST[v].Type;
		return true;
	}
	else if (sc.Compare("InitialDelay"))
	{
		sc.MustGetToken('=');
		if (!sc.CheckToken('-'))
		{
			sc.MustGetFloat();
			mScrollDelay = int(sc.Float*TICRATE);
		}
		else
		{
			sc.MustGetToken(TK_IntConst);
			mScrollDelay = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("ScrollTime"))
	{
		sc.MustGetToken('=');
		if (!sc.CheckToken('-'))
		{
			sc.MustGetFloat();
			mScrollTime = int(sc.Float*TICRATE);
		}
		else
		{
			sc.MustGetToken(TK_IntConst);
			mScrollTime = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("Background2"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		mSecondPic = sc.String;
		return true;
	}
	else return Super::ParseKey(sc);
}
Example #17
0
bool FIntermissionAction::ParseKey(FScanner &sc)
{
	if (sc.Compare("music"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		mMusic = sc.String;
		mMusicOrder = 0;
		if (sc.CheckToken(','))
		{
			sc.MustGetToken(TK_IntConst);
			mMusicOrder = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("cdmusic"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_IntConst);
		mCdTrack = sc.Number;
		mCdId = 0;
		if (sc.CheckToken(','))
		{
			sc.MustGetToken(TK_IntConst);
			mCdId = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("Time"))
	{
		sc.MustGetToken('=');
		if (!sc.CheckToken('-'))
		{
			sc.MustGetFloat();
			mDuration = int(sc.Float*TICRATE);
		}
		else
		{
			sc.MustGetToken(TK_IntConst);
			mDuration = sc.Number;
		}
		return true;
	}
	else if (sc.Compare("Background"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		mBackground = sc.String;
		mFlatfill = 0;
		if (sc.CheckToken(','))
		{
			sc.MustGetToken(TK_IntConst);
			mFlatfill = !!sc.Number;
			if (sc.CheckToken(','))
			{
				sc.MustGetToken(TK_StringConst);
				mPalette = sc.String;
			}
		}
		return true;
	}
	else if (sc.Compare("Sound"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		mSound = sc.String;
		return true;
	}
	else if (sc.Compare("Draw"))
	{
		FIntermissionPatch *pat = &mOverlays[mOverlays.Reserve(1)];
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		pat->mName = sc.String;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_IntConst);
		pat->x = sc.Number;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_IntConst);
		pat->y = sc.Number;
		pat->mCondition = NAME_None;
		return true;
	}
	else if (sc.Compare("DrawConditional"))
	{
		FIntermissionPatch *pat = &mOverlays[mOverlays.Reserve(1)];
		sc.MustGetToken('=');
		sc.MustGetToken(TK_StringConst);
		pat->mCondition = sc.String;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_StringConst);
		pat->mName = sc.String;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_IntConst);
		pat->x = sc.Number;
		sc.MustGetToken(',');
		sc.MustGetToken(TK_IntConst);
		pat->y = sc.Number;
		return true;
	}
	else return false;
}
Example #18
0
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, ETextureType usetype)
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
{
	TArray<TexPart> parts;
	TArray<TexInit> inits;
	bool bSilent = false;

	bMultiPatch = true;
	sc.SetCMode(true);
	sc.MustGetString();
	const char* textureName = NULL;
	if (sc.Compare("optional"))
	{
		bSilent = true;
		sc.MustGetString();
		if (sc.Compare(","))
		{
			// this is not right. Apparently a texture named 'optional' is being defined right now...
			sc.UnGet();
			textureName = "optional";
			bSilent = false;
		}
	}
	Name = !textureName ? sc.String : textureName;
	Name.ToUpper();
	sc.MustGetStringName(",");
	sc.MustGetNumber();
	Width = sc.Number;
	sc.MustGetStringName(",");
	sc.MustGetNumber();
	Height = sc.Number;
	UseType = usetype;
	
	bool offset2set = false;
	if (sc.CheckString("{"))
	{
		while (!sc.CheckString("}"))
		{
			sc.MustGetString();
			if (sc.Compare("XScale"))
			{
				sc.MustGetFloat();
				Scale.X = sc.Float;
				if (Scale.X == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name.GetChars());
			}
			else if (sc.Compare("YScale"))
			{
				sc.MustGetFloat();
				Scale.Y = sc.Float;
				if (Scale.Y == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name.GetChars());
			}
			else if (sc.Compare("WorldPanning"))
			{
				bWorldPanning = true;
			}
			else if (sc.Compare("NullTexture"))
			{
				UseType = ETextureType::Null;
			}
			else if (sc.Compare("NoDecals"))
			{
				bNoDecals = true;
			}
			else if (sc.Compare("Patch"))
			{
				TexPart part;
				TexInit init;
				ParsePatch(sc, part, init);
				if (init.TexName.IsNotEmpty())
				{
					parts.Push(part);
					init.UseType = ETextureType::WallPatch;
					init.Silent = bSilent;
					init.HasLine = true;
					init.sc = sc;
					inits.Push(init);
				}
				part.Texture = NULL;
				part.Translation = NULL;
			}
			else if (sc.Compare("Sprite"))
			{
				TexPart part;
				TexInit init;
				ParsePatch(sc, part, init);
				if (init.TexName.IsNotEmpty())
				{
					parts.Push(part);
					init.UseType = ETextureType::Sprite;
					init.Silent = bSilent;
					init.HasLine = true;
					init.sc = sc;
					inits.Push(init);
				}
				part.Texture = NULL;
				part.Translation = NULL;
			}
			else if (sc.Compare("Graphic"))
			{
				TexPart part;
				TexInit init;
				ParsePatch(sc, part, init);
				if (init.TexName.IsNotEmpty())
				{
					parts.Push(part);
					init.UseType = ETextureType::MiscPatch;
					init.Silent = bSilent;
					init.HasLine = true;
					init.sc = sc;
					inits.Push(init);
				}
				part.Texture = NULL;
				part.Translation = NULL;
			}
			else if (sc.Compare("Offset"))
			{
				sc.MustGetNumber();
				_LeftOffset[0] = sc.Number;
				sc.MustGetStringName(",");
				sc.MustGetNumber();
				_TopOffset[0] = sc.Number;
				if (!offset2set)
				{
					_LeftOffset[1] = _LeftOffset[0];
					_TopOffset[1] = _TopOffset[0];
				}
			}
			else if (sc.Compare("Offset2"))
			{
				sc.MustGetNumber();
				_LeftOffset[1] = sc.Number;
				sc.MustGetStringName(",");
				sc.MustGetNumber();
				_TopOffset[1] = sc.Number;
				offset2set = true;
			}
			else
			{
				sc.ScriptError("Unknown texture property '%s'", sc.String);
			}
		}

		NumParts = parts.Size();
		Parts = new TexPart[NumParts];
		memcpy(Parts, &parts[0], NumParts * sizeof(*Parts));
		Inits = new TexInit[NumParts];
		for (int i = 0; i < NumParts; i++)
		{
			Inits[i] = inits[i];
		}
	}
	
	if (Width <= 0 || Height <= 0)
	{
		UseType = ETextureType::Null;
		Printf("Texture %s has invalid dimensions (%d, %d)\n", Name.GetChars(), Width, Height);
		Width = Height = 1;
	}
	CalcBitSize ();

	
	sc.SetCMode(false);
}