Exemplo n.º 1
0
bool VCvar::Command(const TArray<VStr>& Args)
{
	guard(VCvar::Command);
	VCvar* cvar = FindVariable(*Args[0]);
	if (!cvar)
	{
		return false;
	}

	// perform a variable print or set
	if (Args.Num() == 1)
	{
		GCon->Log(VStr(cvar->Name) + " is \"" + cvar->StringValue + "\"");
		if (cvar->Flags & CVAR_Latch && cvar->LatchedString.IsNotEmpty())
			GCon->Log(VStr("Latched \"") + cvar->LatchedString + "\"");
	}
	else
	{
		if (cvar->Flags & CVAR_Rom)
		{
			GCon->Logf("%s is read-only", cvar->Name);
		}
		else if (cvar->Flags & CVAR_Init && host_initialised)
		{
			GCon->Logf("%s can be set only from command-line", cvar->Name);
		}
		else
		{
			cvar->Set(Args[1]);
		}
	}
	return true;
	unguard;
}
Exemplo n.º 2
0
void Info_RemoveKey(VStr& s, const VStr& key)
{
    guard(Info_RemoveKey);
    if (s.IsEmpty())
    {
        return;
    }
    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_RemoveKey: oversize infostring");
    }

    if (strchr(*key, '\\'))
    {
        GCon->Log("Can't use a key with a \\");
        return;
    }

    int i = 0;
    while (1)
    {
        int start = i;
        if (s[i] == '\\')
            i++;
        int KeyStart = i;
        while (s[i] != '\\')
        {
            if (!s[i])
                return;
            i++;
        }
        VStr pkey(s, KeyStart, i - KeyStart);
        i++;

        int ValStart = i;
        while (s[i] != '\\' && s[i])
        {
            i++;
        }
        VStr value(s, ValStart, i - ValStart);

        if (!key.Cmp(pkey))
        {
            s = VStr(s, 0, start) + VStr(s, i, s.Length() - i);	// remove this part
            return;
        }

        if (!s[i])
            return;
    }
    unguard;
}
Exemplo n.º 3
0
void VLevelInfo::Completed(int InMap, int InPosition, int SaveAngle)
{
	guard(VLevelInfo::Completed);
	int Map = InMap;
	int Position = InPosition;
	if (Map == -1 && Position == -1)
	{
		if (!deathmatch)
		{
			for (int i = 0; i < svs.max_clients; i++)
			{
				if (Game->Players[i])
				{
					Game->Players[i]->eventClientFinale(
						VStr(NextMap).StartsWith("EndGame") ? *NextMap : "");
				}
			}
			sv.intermission = 2;
			return;
		}
		Map = 1;
		Position = 0;
	}
	NextMap = P_GetMapNameByLevelNum(Map);

	LeavePosition = Position;
	completed = true;
	unguard;
}
Exemplo n.º 4
0
static VStr FindMainWad(VStr MainWad)
{
	//	First check in IWAD directories.
	for (int i = 0; i < IWadDirs.Num(); i++)
	{
		if (Sys_FileExists(IWadDirs[i] + "/" + MainWad))
		{
			return IWadDirs[i] + "/" + MainWad;
		}
	}

	//	Then look in the save directory.
	if (fl_savedir.IsNotEmpty() && Sys_FileExists(fl_savedir + "/" + MainWad))
	{
		return fl_savedir + "/" + MainWad;
	}

	//	Finally in base directory.
	if (Sys_FileExists(fl_basedir + "/" + MainWad))
	{
		return fl_basedir + "/" + MainWad;
	}

	return VStr();
}
Exemplo n.º 5
0
void VBasePlayer::DoClientCentrePrint(VStr Str)
{
    guard(VBasePlayer::DoClientCentrePrint);
    VStr Msg(Str);

    if (Msg.IsEmpty())
    {
        return;
    }

    if (Msg[0] == '$')
    {
        Msg = GLanguage[*VStr(Msg.ToLower(), 1, Msg.Length() - 1)];
    }

    if (msg_echo)
    {
        GCon->Log("<-------------------------------->");
        GCon->Log(Msg);
        GCon->Log("<-------------------------------->");
    }

    ClGame->eventAddCentreMessage(Msg);
    unguard;
}
Exemplo n.º 6
0
VStr VMemberBase::GetFullName() const
{
    guardSlow(VMemberBase::GetFullName);
    if (Outer)
        return Outer->GetFullName() + "." + Name;
    return VStr(Name);
    unguardSlow;
}
Exemplo n.º 7
0
VStr Sys_ReadDir()
{
    struct dirent *de = readdir(current_dir);
    if (de)
    {
        return de->d_name;
    }
    return VStr();
}
Exemplo n.º 8
0
void FConsoleDevice::Serialise(const char* V, EName Event)
{
	dprintf("%s: %s\n", VName::SafeString(Event), *VStr(V).RemoveColours());
	if (Event == NAME_Dev && !developer)
	{
		return;
	}
	DoPrint(V);
	DoPrint("\n");
}
Exemplo n.º 9
0
VStr Info_ValueForKey(const VStr& s, const VStr& key)
{
    guard(Info_ValueForKey);
    if (s.IsEmpty() || key.IsEmpty())
    {
        return VStr();
    }

    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_ValueForKey: oversize infostring");
    }

    int i = 0;
    if (s[i] == '\\')
        i++;
    while (1)
    {
        int Start = i;
        while (s[i] != '\\')
        {
            if (!s[i])
                return VStr();
            i++;
        }
        VStr pkey(s, Start, i - Start);
        i++;

        Start = i;
        while (s[i] != '\\' && s[i])
        {
            i++;
        }

        if (!key.ICmp(pkey))
            return VStr(s, Start, i - Start);

        if (!s[i])
            return VStr();
        i++;
    }
    unguard;
}
Exemplo n.º 10
0
VStr VCvar::GetString(const char* var_name)
{
	guard(VCvar::GetString);
	VCvar* var = FindVariable(var_name);
	if (!var)
	{
		return VStr();
	}
	return var->StringValue;
	unguard;
}
Exemplo n.º 11
0
void P_ReplaceMusicLumpNames(TArray<FReplacedString>& List)
{
	guard(P_ReplaceMusicLumpNames);
	for (int i = 0; i < List.Num(); i++)
	{
		if (List[i].Replaced)
		{
			MapInfo[List[i].Index].SongLump = VName(*(VStr("d_") +
				List[i].New), VName::AddLower8);
		}
	}
	unguard;
}
Exemplo n.º 12
0
void VCvar::DoSet(const VStr& AValue)
{
	guard(VCvar::DoSet);
	StringValue = AValue;
	IntValue = superatoi(*StringValue);
	FloatValue = atof(*StringValue);

#ifdef CLIENT
	if (Flags & CVAR_UserInfo)
	{
		Info_SetValueForKey(cls.userinfo, Name, *StringValue);
		if (cl)
		{
			if (GGameInfo->NetMode == NM_TitleMap ||
				GGameInfo->NetMode == NM_Standalone ||
				GGameInfo->NetMode == NM_ListenServer)
			{
				VCommand::ExecuteString(VStr("setinfo \"") + Name + "\" \"" +
					StringValue + "\"\n", VCommand::SRC_Client, cl);
			}
            else if (false)//cl->Net)
			{
                //cl->Net->SendCommand(VStr("setinfo \"") + Name + "\" \"" +
                //	StringValue + "\"\n");
			}
		}
	}
#endif

#ifdef SERVER
	if (Flags & CVAR_ServerInfo)
	{
		Info_SetValueForKey(svs.serverinfo, Name, *StringValue);
		if (GGameInfo && GGameInfo->NetMode != NM_None &&
			GGameInfo->NetMode != NM_Client)
		{
			for (int i = 0; i < MAXPLAYERS; i++)
			{
				if (GGameInfo->Players[i])
				{
					GGameInfo->Players[i]->eventClientSetServerInfo(
						Name, StringValue);
				}
			}
		}
	}
#endif
	unguard;
}
Exemplo n.º 13
0
void Info_SetValueForKey(VStr& s, const VStr& key, const VStr& value)
{
    guard(Info_SetValueForKey);
    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_SetValueForKey: oversize infostring");
    }

    if (strchr(*key, '\\') || strchr(*value, '\\'))
    {
        GCon->Log("Can't use keys or values with a \\");
        return;
    }

    if (strchr(*key, '\"') || strchr(*value, '\"'))
    {
        GCon->Log("Can't use keys or values with a \"");
        return;
    }

    // this next line is kinda trippy
    VStr v = Info_ValueForKey(s, key);
    if (v.IsNotEmpty())
    {
        //	Key exists, make sure we have enough room for new value, if we
        // don't, don't change it!
        if (value.Length() - v.Length() + s.Length() > MAX_INFO_STRING)
        {
            GCon->Log("Info string length exceeded");
            return;
        }
    }

    Info_RemoveKey(s, key);
    if (value.IsEmpty())
        return;

    VStr newi = VStr("\\") + key + "\\" +  value;

    if (newi.Length() + s.Length() > MAX_INFO_STRING)
    {
        GCon->Log("Info string length exceeded");
        return;
    }

    s = s + newi;
    unguard;
}
Exemplo n.º 14
0
static void SetMapDefaults(mapInfo_t& Info)
{
	guard(SetMapDefaults);
	Info.LumpName = NAME_None;
	Info.Name = VStr();
	Info.LevelNum = 0;
	Info.Cluster = 0;
	Info.WarpTrans = 0;
	Info.NextMap = NAME_None;
	Info.SecretMap = NAME_None;
	Info.SongLump = NAME_None;
	Info.CDTrack = 0;
	Info.Sky1Texture = GTextureManager.DefaultTexture;
	Info.Sky2Texture = GTextureManager.DefaultTexture;
	Info.Sky1ScrollDelta = 0;
	Info.Sky2ScrollDelta = 0;
	Info.SkyBox = NAME_None;
	Info.FadeTable = NAME_colormap;
	Info.Fade = 0;
	Info.OutsideFog = 0;
	Info.Gravity = 0;
	Info.AirControl = 0;
	Info.Flags = 0;
	Info.Flags2 = 0;
	Info.TitlePatch = NAME_None;
	Info.ParTime = 0;
	Info.SuckTime = 0;
	Info.HorizWallShade = -8;
	Info.VertWallShade = 8;
	Info.Infighting = 0;
	Info.SpecialActions.Clear();
	Info.RedirectType = NAME_None;
	Info.RedirectMap = NAME_None;
	Info.ExitPic = NAME_None;
	Info.EnterPic = NAME_None;
	Info.InterMusic = NAME_None;

	if (GGameInfo->Flags & VGameInfo::GIF_DefaultLaxMonsterActivation)
	{
		Info.Flags2 |= MAPINFOF2_LaxMonsterActivation;
	}
	unguard;
}
Exemplo n.º 15
0
void VCvar::Set(const VStr& AValue)
{
	guard(VCvar::Set);
	if (Flags & CVAR_Latch)
	{
		LatchedString = AValue;
		return;
	}

	if (Flags & CVAR_Cheat && !Cheating)
	{
		GCon->Log(VStr(Name) + " cannot be changed while cheating is disabled");
		return;
	}

	DoSet(AValue);

	Flags |= CVAR_Modified;
	unguard;
}
Exemplo n.º 16
0
void VBasePlayer::DoClientPrint(VStr AStr)
{
    guard(VBasePlayer::DoClientPrint);
    VStr Str(AStr);

    if (Str.IsEmpty())
    {
        return;
    }

    if (Str[0] == '$')
    {
        Str = GLanguage[*VStr(Str.ToLower(), 1, Str.Length() - 1)];
    }

    if (msg_echo)
    {
        GCon->Log(Str);
    }

    ClGame->eventAddNotifyMessage(Str);
    unguard;
}
Exemplo n.º 17
0
static void ParseClusterDef(VScriptParser* sc)
{
	guard(ParseClusterDef);
	VClusterDef* CDef = NULL;
	sc->ExpectNumber();

	//	Check for replaced cluster def.
	for (int i = 0; i < ClusterDefs.Num(); i++)
	{
		if (sc->Number == ClusterDefs[i].Cluster)
		{
			CDef = &ClusterDefs[i];
			break;
		}
	}
	if (!CDef)
	{
		CDef = &ClusterDefs.Alloc();
	}

	//	Set defaults.
	CDef->Cluster = sc->Number;
	CDef->Flags = 0;
	CDef->EnterText = VStr();
	CDef->ExitText = VStr();
	CDef->Flat = NAME_None;
	CDef->Music = NAME_None;
	CDef->CDTrack = 0;
	CDef->CDId = 0;

	while (1)
	{
		if (sc->Check("hub"))
		{
			CDef->Flags |= CLUSTERF_Hub;
		}
		else if (sc->Check("entertext"))
		{
			if (sc->Check("lookup"))
			{
				CDef->Flags |= CLUSTERF_LookupEnterText;
				sc->ExpectString();
				CDef->EnterText = sc->String.ToLower();
			}
			else
			{
				CDef->Flags &= ~CLUSTERF_LookupEnterText;
				sc->ExpectString();
				CDef->EnterText = sc->String;
			}
		}
		else if (sc->Check("entertextislump"))
		{
			CDef->Flags |= CLUSTERF_EnterTextIsLump;
		}
		else if (sc->Check("exittext"))
		{
			if (sc->Check("lookup"))
			{
				CDef->Flags |= CLUSTERF_LookupExitText;
				sc->ExpectString();
				CDef->ExitText = sc->String.ToLower();
			}
			else
			{
				CDef->Flags &= ~CLUSTERF_LookupExitText;
				sc->ExpectString();
				CDef->ExitText = sc->String;
			}
		}
		else if (sc->Check("exittextislump"))
		{
			CDef->Flags |= CLUSTERF_ExitTextIsLump;
		}
		else if (sc->Check("flat"))
		{
			sc->ExpectName8();
			CDef->Flat = sc->Name8;
			CDef->Flags &= ~CLUSTERF_FinalePic;
		}
		else if (sc->Check("pic"))
		{
			sc->ExpectName8();
			CDef->Flat = sc->Name8;
			CDef->Flags |= CLUSTERF_FinalePic;
		}
		else if (sc->Check("music"))
		{
			sc->ExpectName8();
			CDef->Music = sc->Name8;
		}
		else if (sc->Check("cdtrack"))
		{
			sc->ExpectNumber();
			CDef->CDTrack = sc->Number;
		}
		else if (sc->Check("cdid"))
		{
			sc->ExpectNumber();
			CDef->CDId = sc->Number;
		}
		else if (sc->Check("name"))
		{
			sc->Check("lookup");
			sc->ExpectString();
			GCon->Logf("Unimplemented MAPINFO cluster comand name");
		}
		else
		{
			break;
		}
	}

	//	Make sure text lump names are in lower case.
	if (CDef->Flags & CLUSTERF_EnterTextIsLump)
	{
		CDef->EnterText = CDef->EnterText.ToLower();
	}
	if (CDef->Flags & CLUSTERF_ExitTextIsLump)
	{
		CDef->ExitText = CDef->ExitText.ToLower();
	}
	unguard;
}
Exemplo n.º 18
0
bool VBasePlayer::ExecuteNetMethod(VMethod* Func)
{
    guard(VBasePlayer::ExecuteNetMethod);

#ifdef CLIENT
    if (GGameInfo->NetMode == NM_TitleMap ||
            GGameInfo->NetMode == NM_Standalone ||
            (GGameInfo->NetMode == NM_ListenServer && this == cl))
    {
        return false;
    }
#endif

    //	Find initial version of the method.
    VMethod* Base = Func;
    while (Base->SuperMethod)
    {
        Base = Base->SuperMethod;
    }
    //	Execute it's replication condition method.
    check(Base->ReplCond);
    P_PASS_REF(this);
    if (!VObject::ExecuteFunction(Base->ReplCond).i)
    {
        return false;
    }

    //	Clean up parameters
    guard(VBasePlayer::ExecuteNetMethod::CleanUp);
    VStack* Param = pr_stackPtr - Func->ParamsSize + 1;	//	Skip self
    for (int i = 0; i < Func->NumParams; i++)
    {
        switch (Func->ParamTypes[i].Type)
        {
        case TYPE_Int:
        case TYPE_Byte:
        case TYPE_Bool:
        case TYPE_Float:
        case TYPE_Name:
        case TYPE_Pointer:
        case TYPE_Reference:
        case TYPE_Class:
        case TYPE_State:
            Param++;
            break;
        case TYPE_String:
            ((VStr*)&Param->p)->Clean();
            Param++;
            break;
        case TYPE_Vector:
            Param += 3;
            break;
        default:
            Sys_Error("Bad method argument type %d", Func->ParamTypes[i].Type);
        }
        if (Func->ParamFlags[i] & FPARM_Optional)
        {
            Param++;
        }
    }
    pr_stackPtr -= Func->ParamsSize;
    unguard;

    //	Push null return value
    guard(VBasePlayer::ExecuteNetMethod::RetVal);
    switch (Func->ReturnType.Type)
    {
    case TYPE_Void:
        break;
    case TYPE_Int:
    case TYPE_Byte:
    case TYPE_Bool:
    case TYPE_Name:
        PR_Push(0);
        break;
    case TYPE_Float:
        PR_Pushf(0);
        break;
    case TYPE_String:
        PR_PushStr(VStr());
        break;
    case TYPE_Pointer:
    case TYPE_Reference:
    case TYPE_Class:
    case TYPE_State:
        PR_PushPtr(NULL);
        break;
    case TYPE_Vector:
        PR_Pushf(0);
        PR_Pushf(0);
        PR_Pushf(0);
        break;
    default:
        Sys_Error("Bad return value type");
    }
    unguard;

    //	It's been handled here.
    return true;
    unguard;
}
Exemplo n.º 19
0
int main(int argc, char** argv)
{
	
	MGraph G;
	GraphAdjList GL;
	int i,j,s;
	int VertexNum;
	int Edge_num;
	int flag;
	int num_CNFSAT;
	int num_APPROX1;
	int num_APPROX2;
	float ratio1,ratio2;

	pthread_t thread_CNFSAT;
	pthread_t thread_APPROX1;
	pthread_t thread_APPROX2;

	clockid_t cid_CNFSAT;
	clockid_t cid_APPROX1;
	clockid_t cid_APPROX2;

	char str[10000];

    while (fgets(str,10000,stdin))
    {
	/*if (str[0] != 's')
        	printf("%s",str);
		fflush(stdout);*/
        if (str[0]=='V')
        {
           VertexNum = VStr(str);
	   //printf("%d \n",VertexNum);
        }
        else if (str[0]=='E')
        {
            Edge_num = ENum(str);
            flag = CreateMGraph(&G, Edge_num, VertexNum, str);
            CreateALGraph(G,&GL);	    
	    if (Edge_num > 0 && flag == 1)
	    {
		s = pthread_create (&thread_CNFSAT,NULL,&VerCover_CNFSAT,&G);
		if (s != 0)
               		handle_error_en(s, "pthread_create");
		/*s = pthread_getcpuclockid(thread_CNFSAT, &cid_CNFSAT);
		if (s != 0)
               		handle_error_en(s, "pthread_getcpuclockid");*/
		pthread_join(thread_CNFSAT,NULL);
		/*char ms1[] = "CNF-SAT-VC's CPU time:  ";
		pclock(ms1, cid_CNFSAT);
		sleep(1);*/
		
		s = pthread_create (&thread_APPROX1,NULL,&VerCover_APPROX1,&G);
		if (s != 0)
               		handle_error_en(s, "pthread_create");
		/*s = pthread_getcpuclockid(thread_APPROX1, &cid_APPROX1);
		if (s != 0)
               		handle_error_en(s, "pthread_getcpuclockid"); */
		pthread_join(thread_APPROX1,NULL);
		/*char ms2[] = "APPROX-VC-1's CPU time:  ";
		pclock(ms2, cid_APPROX1);
		sleep(1);*/
		
		s = pthread_create (&thread_APPROX2,NULL,&VerCover_APPROX2,&G);
		if (s != 0)
               		handle_error_en(s, "pthread_create");
		/*s = pthread_getcpuclockid(thread_APPROX2, &cid_APPROX2);
		if (s != 0)
               		handle_error_en(s, "pthread_getcpuclockid"); 
		char ms3[] = "APPROX-VC-2's CPU time:  ";*/		
		pthread_join(thread_APPROX2,NULL);	
		/*pclock(ms3, cid_APPROX2); 
		sleep(1);*/

		
		/*calculate the approximate ratio*/
		/*float x1, x2, x3;
		x1 = (float) g[0].vNum;
		x2 = (float) g[1].vNum;
		x3 = (float) g[2].vNum;

		char msg1[] = "Approximation ratio of APPROX1: ";
		char msg2[] = "Approximation ratio of APPROX2: ";

		ratio1 = x2/x1;
		pratio(msg1, ratio1);
		ratio2 = x3/x1;
		pratio(msg2, ratio2);*/

		//free(g);
		//g = NULL;
		
	    }
		//free(g);
		//g = NULL;
        }
        else if (str[0]=='s')
        {
            int str_size1;
            int str_size;
            int s_flag;
	    
            for (str_size = 0;str[str_size]!='\0';str_size++)
                {
                    str_size1 = str_size;
                }

            s_flag = 0;

            int flag1 = 1;

            while(str[s_flag]!= ' ')
            {
                s_flag++;
            }

            while(str[s_flag+flag1]!=' ')
            {
                flag1++;
            }

            int s1,s2;
            int firstNode = 0;
            int lastNode = 0;
            for (s1 = s_flag+1; s1 < s_flag + flag1; s1++)
            {
                firstNode = (int)(firstNode + (str[s1]-'0') * pow(10,s_flag + flag1-1-s1));
            }

            for (s2 = s_flag + flag1 + 1; s2 < str_size1;s2++)
            {
                lastNode = (int)(lastNode + (str[s2]-'0') * pow(10,str_size1-1-s2));
//                printf("%d %d %d\n",s2,str[s2]-'0',str_size1-1-s2);
            }
//            printf("%d %d\n",firstNode,lastNode);

            if(firstNode>=VertexNum || lastNode>=VertexNum)
            {
                printf("Error: one or more vertexes do not exist\n");
                continue;
            }

            if(firstNode == lastNode)
            {
                printf("%d-%d\n",firstNode,lastNode);		
                continue;
            }


            CreateALGraph(G,&GL);
            BFSTraverse(GL,firstNode,lastNode);
//	    VerCover(G, VertexNum); 
        }
    }
	return 0;
}
Exemplo n.º 20
0
void FL_Init()
{
	guard(FL_Init);
	const char* p;

	//	Set up base directory (main data files).
	fl_basedir = ".";
	p = GArgs.CheckValue("-basedir");
	if (p)
	{
		fl_basedir = p;
	}

	//	Set up save directory (files written by engine).
	p = GArgs.CheckValue("-savedir");
	if (p)
	{
		fl_savedir = p;
	}
#if !defined(_WIN32)
	else
	{
		const char* HomeDir = getenv("HOME");
		if (HomeDir)
		{
			fl_savedir = VStr(HomeDir) + "/.vavoom";
		}
	}
#endif

	//	Set up additional directories where to look for IWAD files.
	int iwp = GArgs.CheckParm("-iwaddir");
	if (iwp)
	{
		while (++iwp != GArgs.Count() && GArgs[iwp][0] != '-' && GArgs[iwp][0] != '+')
		{
			IWadDirs.Append(GArgs[iwp]);
		}
	}

	AddGameDir("basev/common");

	p = GArgs.CheckValue("-iwad");
	if (p)
	{
		fl_mainwad = p;
	}

	p = GArgs.CheckValue("-devgame");
	if (p)
	{
		fl_devmode = true;
	}
	else
	{
		p = GArgs.CheckValue("-game");
	}

	if (p)
	{
		SetupGameDir(p);
	}
	else
	{
		ParseBase("basev/games.txt");
#ifdef DEVELOPER
		//  I need progs to be loaded from files
		fl_devmode = true;
#endif
	}

	int fp = GArgs.CheckParm("-file");
	if (fp)
	{
		while (++fp != GArgs.Count() && GArgs[fp][0] != '-' && GArgs[fp][0] != '+')
		{
			VStr Ext = VStr(GArgs[fp]).ExtractFileExtension().ToLower();
			if (Ext == "pk3" || Ext == "zip")
				AddZipFile(GArgs[fp]);
			else
				W_AddFile(GArgs[fp], VStr(), false);
		}
	}

	RenameSprites();
	unguard;
}
Exemplo n.º 21
0
static void ParseMapCommon(VScriptParser* sc, mapInfo_t* info, bool& HexenMode)
{
	guard(ParseMapCommon);
	// Process optional tokens
	while (1)
	{
		if (sc->Check("levelnum"))
		{
			sc->ExpectNumber();
			info->LevelNum = sc->Number;
		}
		else if (sc->Check("cluster"))
		{
			sc->ExpectNumber();
			info->Cluster = sc->Number;
			if (P_GetClusterDef(info->Cluster) == &DefaultClusterDef)
			{
				//	Add empty cluster def if it doesn't exist yet.
				VClusterDef& C = ClusterDefs.Alloc();
				C.Cluster = info->Cluster;
				C.Flags = 0;
				C.EnterText = VStr();
				C.ExitText = VStr();
				C.Flat = NAME_None;
				C.Music = NAME_None;
				C.CDTrack = 0;
				C.CDId = 0;
				if (HexenMode)
				{
					C.Flags |= CLUSTERF_Hub;
				}
			}
		}
		else if (sc->Check("warptrans"))
		{
			sc->ExpectNumber();
			info->WarpTrans = sc->Number;
		}
		else if (sc->Check("next"))
		{
			info->NextMap = ParseNextMapName(sc, HexenMode);
		}
		else if (sc->Check("secret") || sc->Check("secretnext"))
		{
			info->SecretMap = ParseNextMapName(sc, HexenMode);
		}
		else if (sc->Check("sky1"))
		{
			sc->ExpectName8();
			info->Sky1Texture = GTextureManager.NumForName(
				sc->Name8, TEXTYPE_Wall, true, false);
			sc->ExpectFloat();
			if (HexenMode)
			{
				sc->Float /= 256.0;
			}
			info->Sky1ScrollDelta = sc->Float * 35.0;
		}
		else if (sc->Check("sky2"))
		{
			sc->ExpectName8();
			info->Sky2Texture = GTextureManager.NumForName(
				sc->Name8, TEXTYPE_Wall, true, false);
			sc->ExpectFloat();
			if (HexenMode)
			{
				sc->Float /= 256.0;
			}
			info->Sky2ScrollDelta = sc->Float * 35.0;
		}
		else if (sc->Check("skybox"))
		{
			sc->ExpectString();
			info->SkyBox = *sc->String;
		}
		else if (sc->Check("doublesky"))
		{
			info->Flags |= MAPINFOF_DoubleSky;
		}
		else if (sc->Check("lightning"))
		{
			info->Flags |= MAPINFOF_Lightning;
		}
		else if (sc->Check("forcenoskystretch"))
		{
			info->Flags |= MAPINFOF_ForceNoSkyStretch;
		}
		else if (sc->Check("fadetable"))
		{
			sc->ExpectName8();
			info->FadeTable = sc->Name8;
		}
		else if (sc->Check("fade"))
		{
			sc->ExpectString();
			info->Fade = M_ParseColour(sc->String);
		}
		else if (sc->Check("outsidefog"))
		{
			sc->ExpectString();
			info->OutsideFog = M_ParseColour(sc->String);
		}
		else if (sc->Check("music"))
		{
			sc->ExpectName8();
			info->SongLump = sc->Name8;
		}
		else if (sc->Check("cdtrack"))
		{
			sc->ExpectNumber();
			info->CDTrack = sc->Number;
		}
		else if (sc->Check("gravity"))
		{
			sc->ExpectNumber();
			info->Gravity = (float)sc->Number;
		}
		else if (sc->Check("aircontrol"))
		{
			sc->ExpectFloat();
			info->AirControl = sc->Float;
		}
		else if (sc->Check("map07special"))
		{
			info->Flags |= MAPINFOF_Map07Special;
		}
		else if (sc->Check("baronspecial"))
		{
			info->Flags |= MAPINFOF_BaronSpecial;
		}
		else if (sc->Check("cyberdemonspecial"))
		{
			info->Flags |= MAPINFOF_CyberDemonSpecial;
		}
		else if (sc->Check("spidermastermindspecial"))
		{
			info->Flags |= MAPINFOF_SpiderMastermindSpecial;
		}
		else if (sc->Check("minotaurspecial"))
		{
			info->Flags |= MAPINFOF_MinotaurSpecial;
		}
		else if (sc->Check("dsparilspecial"))
		{
			info->Flags |= MAPINFOF_DSparilSpecial;
		}
		else if (sc->Check("ironlichspecial"))
		{
			info->Flags |= MAPINFOF_IronLichSpecial;
		}
		else if (sc->Check("specialaction_exitlevel"))
		{
			info->Flags &= ~(MAPINFOF_SpecialActionOpenDoor |
				MAPINFOF_SpecialActionLowerFloor);
		}
		else if (sc->Check("specialaction_opendoor"))
		{
			info->Flags &= ~MAPINFOF_SpecialActionLowerFloor;
			info->Flags |= MAPINFOF_SpecialActionOpenDoor;
		}
		else if (sc->Check("specialaction_lowerfloor"))
		{
			info->Flags |= MAPINFOF_SpecialActionLowerFloor;
			info->Flags &= ~MAPINFOF_SpecialActionOpenDoor;
		}
		else if (sc->Check("specialaction_killmonsters"))
		{
			info->Flags |= MAPINFOF_SpecialActionKillMonsters;
		}
		else if (sc->Check("intermission"))
		{
			info->Flags &= ~MAPINFOF_NoIntermission;
		}
		else if (sc->Check("nointermission"))
		{
			info->Flags |= MAPINFOF_NoIntermission;
		}
		else if (sc->Check("titlepatch"))
		{
			sc->ExpectName8();
			info->TitlePatch = sc->Name8;
		}
		else if (sc->Check("par"))
		{
			sc->ExpectNumber();
			info->ParTime = sc->Number;
		}
		else if (sc->Check("sucktime"))
		{
			sc->ExpectNumber();
			info->SuckTime = sc->Number;
		}
		else if (sc->Check("nosoundclipping"))
		{
			//	Ignored
		}
		else if (sc->Check("allowmonstertelefrags"))
		{
			info->Flags |= MAPINFOF_AllowMonsterTelefrags;
		}
		else if (sc->Check("noallies"))
		{
			info->Flags |= MAPINFOF_NoAllies;
		}
		else if (sc->Check("fallingdamage"))
		{
			info->Flags &= ~(MAPINFOF_OldFallingDamage |
				MAPINFOF_StrifeFallingDamage);
			info->Flags |= MAPINFOF_FallingDamage;
		}
		else if (sc->Check("oldfallingdamage") ||
			sc->Check("forcefallingdamage"))
		{
			info->Flags &= ~(MAPINFOF_FallingDamage |
				MAPINFOF_StrifeFallingDamage);
			info->Flags |= MAPINFOF_OldFallingDamage;
		}
		else if (sc->Check("strifefallingdamage"))
		{
			info->Flags &= ~(MAPINFOF_OldFallingDamage |
				MAPINFOF_FallingDamage);
			info->Flags |= MAPINFOF_StrifeFallingDamage;
		}
		else if (sc->Check("nofallingdamage"))
		{
			info->Flags &= ~(MAPINFOF_OldFallingDamage |
				MAPINFOF_StrifeFallingDamage | MAPINFOF_FallingDamage);
		}
		else if (sc->Check("monsterfallingdamage"))
		{
			info->Flags |= MAPINFOF_MonsterFallingDamage;
		}
		else if (sc->Check("nomonsterfallingdamage"))
		{
			info->Flags &= ~MAPINFOF_MonsterFallingDamage;
		}
		else if (sc->Check("deathslideshow"))
		{
			info->Flags |= MAPINFOF_DeathSlideShow;
		}
		else if (sc->Check("allowfreelook"))
		{
			info->Flags &= ~MAPINFOF_NoFreelook;
		}
		else if (sc->Check("nofreelook"))
		{
			info->Flags |= MAPINFOF_NoFreelook;
		}
		else if (sc->Check("allowjump"))
		{
			info->Flags &= ~MAPINFOF_NoJump;
		}
		else if (sc->Check("nojump"))
		{
			info->Flags |= MAPINFOF_NoJump;
		}
		else if (sc->Check("noautosequences"))
		{
			info->Flags |= MAPINFOF_NoAutoSndSeq;
		}
		else if (sc->Check("activateowndeathspecials"))
		{
			info->Flags |= MAPINFOF_ActivateOwnSpecial;
		}
		else if (sc->Check("killeractivatesdeathspecials"))
		{
			info->Flags &= ~MAPINFOF_ActivateOwnSpecial;
		}
		else if (sc->Check("missilesactivateimpactlines"))
		{
			info->Flags |= MAPINFOF_MissilesActivateImpact;
		}
		else if (sc->Check("missileshootersactivetimpactlines"))
		{
			info->Flags &= ~MAPINFOF_MissilesActivateImpact;
		}
		else if (sc->Check("filterstarts"))
		{
			info->Flags |= MAPINFOF_FilterStarts;
		}
		else if (sc->Check("infiniteflightpowerup"))
		{
			info->Flags |= MAPINFOF_InfiniteFlightPowerup;
		}
		else if (sc->Check("noinfiniteflightpowerup"))
		{
			info->Flags &= ~MAPINFOF_InfiniteFlightPowerup;
		}
		else if (sc->Check("clipmidtextures"))
		{
			info->Flags |= MAPINFOF_ClipMidTex;
		}
		else if (sc->Check("wrapmidtextures"))
		{
			info->Flags |= MAPINFOF_WrapMidTex;
		}
		else if (sc->Check("keepfullinventory"))
		{
			info->Flags |= MAPINFOF_KeepFullInventory;
		}
		else if (sc->Check("compat_shorttex"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatShortTex);
		}
		else if (sc->Check("compat_stairs"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatStairs);
		}
		else if (sc->Check("compat_limitpain"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatLimitPain);
		}
		else if (sc->Check("compat_nopassover"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatNoPassOver);
		}
		else if (sc->Check("compat_notossdrops"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatNoTossDrops);
		}
		else if (sc->Check("compat_useblocking"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatUseBlocking);
		}
		else if (sc->Check("compat_nodoorlight"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatNoDoorLight);
		}
		else if (sc->Check("compat_ravenscroll"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatRavenScroll);
		}
		else if (sc->Check("compat_soundtarget"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatSoundTarget);
		}
		else if (sc->Check("compat_dehhealth"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatDehHealth);
		}
		else if (sc->Check("compat_trace"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatTrace);
		}
		else if (sc->Check("compat_dropoff"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatDropOff);
		}
		else if (sc->Check("compat_boomscroll") ||
			sc->Check("additive_scrollers"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatBoomScroll);
		}
		else if (sc->Check("compat_invisibility"))
		{
			DoCompatFlag(sc, info, MAPINFOF2_CompatInvisibility);
		}
		else if (sc->Check("evenlighting"))
		{
			info->HorizWallShade = 0;
			info->VertWallShade = 0;
		}
		else if (sc->Check("vertwallshade"))
		{
			sc->ExpectNumber();
			info->VertWallShade = MID(-128, sc->Number, 127);
		}
		else if (sc->Check("horizwallshade"))
		{
			sc->ExpectNumber();
			info->HorizWallShade = MID(-128, sc->Number, 127);
		}
		else if (sc->Check("noinfighting"))
		{
			info->Infighting = -1;
		}
		else if (sc->Check("normalinfighting"))
		{
			info->Infighting = 0;
		}
		else if (sc->Check("totalinfighting"))
		{
			info->Infighting = 1;
		}
		else if (sc->Check("specialaction"))
		{
			VMapSpecialAction& A = info->SpecialActions.Alloc();
			sc->SetCMode(true);
			sc->ExpectString();
			A.TypeName = *sc->String.ToLower();
			sc->Expect(",");
			sc->ExpectString();
			A.Special = 0;
			for (int i = 0; i < LineSpecialInfos.Num(); i++)
			{
				if (!LineSpecialInfos[i].Name.ICmp(sc->String))
				{
					A.Special = LineSpecialInfos[i].Number;
					break;
				}
			}
			if (!A.Special)
			{
				GCon->Logf("Unknown action special %s", *sc->String);
			}
			memset(A.Args, 0, sizeof(A.Args));
			for (int i = 0; i < 5 && sc->Check(","); i++)
			{
				sc->ExpectNumber();
				A.Args[i] = sc->Number;
			}
			sc->SetCMode(false);
		}
		else if (sc->Check("redirect"))
		{
			sc->ExpectString();
			info->RedirectType = *sc->String.ToLower();
			info->RedirectMap = ParseNextMapName(sc, HexenMode);
		}
		else if (sc->Check("strictmonsteractivation"))
		{
			info->Flags2 &= ~MAPINFOF2_LaxMonsterActivation;
			info->Flags2 |= MAPINFOF2_HaveMonsterActivation;
		}
		else if (sc->Check("laxmonsteractivation"))
		{
			info->Flags2 |= MAPINFOF2_LaxMonsterActivation;
			info->Flags2 |= MAPINFOF2_HaveMonsterActivation;
		}
		else if (sc->Check("interpic") || sc->Check("exitpic"))
		{
			sc->ExpectName8();
			info->ExitPic = *sc->String.ToLower();
		}
		else if (sc->Check("enterpic"))
		{
			sc->ExpectName8();
			info->EnterPic = *sc->String.ToLower();
		}
		else if (sc->Check("intermusic"))
		{
			sc->ExpectString();
			info->InterMusic = *sc->String.ToLower();
		}
		else if (sc->Check("cd_start_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_STARTTRACK] = sc->Number;
		}
		else if (sc->Check("cd_end1_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_END1TRACK] = sc->Number;
		}
		else if (sc->Check("cd_end2_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_END2TRACK] = sc->Number;
		}
		else if (sc->Check("cd_end3_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_END3TRACK] = sc->Number;
		}
		else if (sc->Check("cd_intermission_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_INTERTRACK] = sc->Number;
		}
		else if (sc->Check("cd_title_track"))
		{
			sc->ExpectNumber();
			cd_NonLevelTracks[CD_TITLETRACK] = sc->Number;
		}
		//	These are stubs for now.
		else if (sc->Check("cdid"))
		{
			GCon->Logf("Unimplemented MAPINFO comand cdid");
			sc->ExpectString();
		}
		else if (sc->Check("noinventorybar"))
		{
			GCon->Logf("Unimplemented MAPINFO comand noinventorybar");
		}
		else if (sc->Check("airsupply"))
		{
			GCon->Logf("Unimplemented MAPINFO comand airsupply");
			sc->ExpectNumber();
		}
		else if (sc->Check("sndseq"))
		{
			GCon->Logf("Unimplemented MAPINFO comand sndseq");
			sc->ExpectName8();
		}
		else if (sc->Check("sndinfo"))
		{
			GCon->Logf("Unimplemented MAPINFO comand sndinfo");
			sc->ExpectName8();
		}
		else if (sc->Check("soundinfo"))
		{
			GCon->Logf("Unimplemented MAPINFO comand soundinfo");
			sc->ExpectName8();
		}
		else if (sc->Check("allowcrouch"))
		{
			GCon->Logf("Unimplemented MAPINFO comand allowcrouch");
		}
		else if (sc->Check("nocrouch"))
		{
			GCon->Logf("Unimplemented MAPINFO comand nocrouch");
		}
		else if (sc->Check("pausemusicinmenus"))
		{
			GCon->Logf("Unimplemented MAPINFO comand pausemusicinmenus");
		}
		else if (sc->Check("bordertexture"))
		{
			GCon->Logf("Unimplemented MAPINFO comand bordertexture");
			sc->ExpectName8();
		}
		else if (sc->Check("f1"))
		{
			GCon->Logf("Unimplemented MAPINFO comand f1");
			sc->ExpectString();
		}
		else if (sc->Check("allowrespawn"))
		{
			GCon->Logf("Unimplemented MAPINFO comand allowrespawn");
		}
		else if (sc->Check("teamdamage"))
		{
			GCon->Logf("Unimplemented MAPINFO comand teamdamage");
			sc->ExpectFloat();
		}
		else if (sc->Check("fogdensity"))
		{
			GCon->Logf("Unimplemented MAPINFO comand fogdensity");
			sc->ExpectNumber();
		}
		else if (sc->Check("outsidefogdensity"))
		{
			GCon->Logf("Unimplemented MAPINFO comand outsidefogdensity");
			sc->ExpectNumber();
		}
		else if (sc->Check("skyfog"))
		{
			GCon->Logf("Unimplemented MAPINFO comand skyfog");
			sc->ExpectNumber();
		}
		else if (sc->Check("teamplayon"))
		{
			GCon->Logf("Unimplemented MAPINFO comand teamplayon");
		}
		else if (sc->Check("teamplayoff"))
		{
			GCon->Logf("Unimplemented MAPINFO comand teamplayoff");
		}
		else if (sc->Check("checkswitchrange"))
		{
			GCon->Logf("Unimplemented MAPINFO comand checkswitchrange");
		}
		else if (sc->Check("nocheckswitchrange"))
		{
			GCon->Logf("Unimplemented MAPINFO comand nocheckswitchrange");
		}
		else if (sc->Check("translator"))
		{
			GCon->Logf("Unimplemented MAPINFO comand translator");
			sc->ExpectString();
		}
		else if (sc->Check("unfreezesingleplayerconversations"))
		{
			GCon->Logf("Unimplemented MAPINFO comand unfreezesingleplayerconversations");
		}
		else
		{
			break;
		}
	}

	//	Second sky defaults to first sky
	if (info->Sky2Texture == GTextureManager.DefaultTexture)
	{
		info->Sky2Texture = info->Sky1Texture;
	}

	if (info->Flags & MAPINFOF_DoubleSky)
	{
		GTextureManager.SetFrontSkyLayer(info->Sky1Texture);
	}
	unguard;
}
Exemplo n.º 22
0
VZipFile::VZipFile(const VStr& zipfile)
: ZipFileName(zipfile)
, Files(NULL)
, NumFiles(0)
{
	guard(VZipFile::VZipFile);
	GCon->Logf(NAME_Init, "Adding %s", *ZipFileName);

	FileStream = FL_OpenSysFileRead(ZipFileName);
	check(FileStream);

	vuint32 central_pos = SearchCentralDir();
	check(central_pos);

	FileStream->Seek(central_pos);

	vuint32 Signature;
	vuint16 number_disk;		//	Number of the current dist, used for
								// spaning ZIP, unsupported, always 0
	vuint16 number_disk_with_CD;//	Number the the disk with central dir, used
								// for spaning ZIP, unsupported, always 0
	vuint16 number_entry_CD;	//	Total number of entries in
								// the central dir
								// (same than number_entry on nospan)
	vuint16 size_comment;		//	Size of the global comment of the zipfile

	*FileStream
		//	The signature, already checked
		<< Signature
		//	Number of this disk
		<< number_disk
		//	Number of the disk with the start of the central directory
		<< number_disk_with_CD
		//	Total number of entries in the central dir on this disk
		<< NumFiles
		//	Total number of entries in the central dir
		<< number_entry_CD;

	check(number_entry_CD == NumFiles);
	check(number_disk_with_CD == 0);
	check(number_disk == 0);

	vuint32		size_central_dir;	//	Size of the central directory
	vuint32		offset_central_dir;	//	Offset of start of central directory with
									// respect to the starting disk number

	*FileStream
		<< size_central_dir
		<< offset_central_dir
		<< size_comment;

	check(central_pos >= offset_central_dir + size_central_dir);

	BytesBeforeZipFile = central_pos - (offset_central_dir + size_central_dir);

	Files = new VZipFileInfo[NumFiles];

	//	Set the current file of the zipfile to the first file.
	vuint32 pos_in_central_dir = offset_central_dir;
	for (int i = 0; i < NumFiles; i++)
	{
		VZipFileInfo& file_info = Files[i];

		FileStream->Seek(pos_in_central_dir + BytesBeforeZipFile);

		vuint32 Magic;
		vuint16 version;		//	Version made by
		vuint16 version_needed;	//	Version needed to extract
		vuint32 dosDate;		//	Last mod file date in Dos fmt
		vuint16 size_file_extra;//	Extra field length
		vuint16 size_file_comment;	//	File comment length
		vuint16 disk_num_start;	//	Disk number start
		vuint16 internal_fa;	//	Internal file attributes
		vuint32 external_fa;	//	External file attributes

		/* we check the magic */
		*FileStream
			<< Magic
			<< version
			<< version_needed
			<< file_info.flag
			<< file_info.compression_method
			<< dosDate
			<< file_info.crc
			<< file_info.compressed_size
			<< file_info.uncompressed_size
			<< file_info.size_filename
			<< size_file_extra
			<< size_file_comment
			<< disk_num_start
			<< internal_fa
			<< external_fa
			<< file_info.offset_curfile;

		check(Magic == 0x02014b50);

		char* filename_inzip = new char[file_info.size_filename + 1];
		filename_inzip[file_info.size_filename] = '\0';
		FileStream->Serialise(filename_inzip, file_info.size_filename);
		Files[i].Name = VStr(filename_inzip).ToLower().FixFileSlashes();
		delete[] filename_inzip;
		filename_inzip = NULL;

		//	Set up lump name for WAD-like access.
		VStr LumpName = Files[i].Name.ExtractFileName().StripExtension();

		//	Map some directories to WAD namespaces.
		Files[i].LumpNamespace =
			Files[i].Name.StartsWith("sprites/") ? WADNS_Sprites :
			Files[i].Name.StartsWith("flats/") ? WADNS_Flats :
			Files[i].Name.StartsWith("colormaps/") ? WADNS_ColourMaps :
			Files[i].Name.StartsWith("acs/") ? WADNS_ACSLibrary :
			Files[i].Name.StartsWith("textures/") ? WADNS_NewTextures :
			Files[i].Name.StartsWith("voices/") ? WADNS_Voices :
			Files[i].Name.StartsWith("hires/") ? WADNS_HiResTextures :
			Files[i].Name.StartsWith("patches/") ? WADNS_Patches :
			Files[i].Name.StartsWith("graphics/") ? WADNS_Graphics :
			Files[i].Name.StartsWith("sounds/") ? WADNS_Sounds :
			Files[i].Name.StartsWith("music/") ? WADNS_Music :
			Files[i].Name.IndexOf('/') == -1 ? WADNS_Global : -1;

		//	Anything from other directories won't be accessed as lump.
		if (Files[i].LumpNamespace == -1)
			LumpName = VStr();

		//	For sprites \ is a valid frame character but is not allowed to
		// be in a file name, so we do a little mapping here.
		if (Files[i].LumpNamespace == WADNS_Sprites)
		{
			for (size_t ni = 0; ni < LumpName.Length(); ni++)
			{
				if (LumpName[ni] == '^')
				{
					LumpName[ni] = '\\';
				}
			}
		}

		//	Final lump name;
		Files[i].LumpName = VName(*LumpName, VName::AddLower8);

		//	Set the current file of the zipfile to the next file.
		pos_in_central_dir += SIZECENTRALDIRITEM + file_info.size_filename +
			size_file_extra + size_file_comment;
	}

	//	Sort files alphabetically.
	qsort(Files, NumFiles, sizeof(VZipFileInfo), FileCmpFunc);
	unguard;
}
Exemplo n.º 23
0
void VCvar::Set(float value)
{
	guard(VCvar::Set);
	Set(VStr(value));
	unguard;
}
Exemplo n.º 24
0
static void ParseEpisodeDef(VScriptParser* sc)
{
	guard(ParseEpisodeDef);
	VEpisodeDef* EDef = NULL;
	int EIdx = 0;
	sc->ExpectName8();

	//	Check for replaced episode.
	for (int i = 0; i < EpisodeDefs.Num(); i++)
	{
		if (sc->Name8 == EpisodeDefs[i].Name)
		{
			EDef = &EpisodeDefs[i];
			EIdx = i;
			break;
		}
	}
	if (!EDef)
	{
		EDef = &EpisodeDefs.Alloc();
		EIdx = EpisodeDefs.Num() - 1;
	}

	//	Check for removal of an episode.
	if (sc->Check("remove"))
	{
		EpisodeDefs.RemoveIndex(EIdx);
		return;
	}

	//	Set defaults.
	EDef->Name = sc->Name8;
	EDef->TeaserName = NAME_None;
	EDef->Text = VStr();
	EDef->PicName = NAME_None;
	EDef->Flags = 0;
	EDef->Key = VStr();

	if (sc->Check("teaser"))
	{
		sc->ExpectName8();
		EDef->TeaserName = sc->Name8;
	}

	while (1)
	{
		if (sc->Check("name"))
		{
			if (sc->Check("lookup"))
			{
				EDef->Flags |= EPISODEF_LookupText;
				sc->ExpectString();
				EDef->Text = sc->String.ToLower();
			}
			else
			{
				EDef->Flags &= ~EPISODEF_LookupText;
				sc->ExpectString();
				EDef->Text = sc->String;
			}
		}
		else if (sc->Check("picname"))
		{
			sc->ExpectName8();
			EDef->PicName = sc->Name8;
		}
		else if (sc->Check("key"))
		{
			sc->ExpectString();
			EDef->Key = sc->String.ToLower();
		}
		else if (sc->Check("noskillmenu"))
		{
			EDef->Flags |= EPISODEF_NoSkillMenu;
		}
		else if (sc->Check("optional"))
		{
			EDef->Flags |= EPISODEF_Optional;
		}
		else
		{
			break;
		}
	}
	unguard;
}