2010-10-06 10:44:03 +00:00
|
|
|
/*
|
|
|
|
** intermission_parser.cpp
|
|
|
|
** Parser for intermission definitions in MAPINFO
|
|
|
|
** (both new style and old style 'ENDGAME' blocks)
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2010 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "intermission/intermission.h"
|
|
|
|
#include "g_level.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "gi.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void ReplaceIntermission(FName intname,FIntermissionDescriptor *desc)
|
|
|
|
{
|
|
|
|
FIntermissionDescriptor ** pDesc = IntermissionDescriptors.CheckKey(intname);
|
|
|
|
if (pDesc != NULL && *pDesc != NULL) delete *pDesc;
|
|
|
|
IntermissionDescriptors[intname] = desc;
|
|
|
|
}
|
|
|
|
|
2010-10-17 13:25:21 +00:00
|
|
|
void DeinitIntermissions()
|
|
|
|
{
|
|
|
|
FIntermissionDescriptorList::Iterator it(IntermissionDescriptors);
|
|
|
|
|
|
|
|
FIntermissionDescriptorList::Pair *pair;
|
|
|
|
|
|
|
|
while (it.NextPair(pair))
|
|
|
|
{
|
|
|
|
delete pair->Value;
|
|
|
|
pair->Value = NULL;
|
|
|
|
}
|
2010-12-15 11:45:39 +00:00
|
|
|
IntermissionDescriptors.Clear();
|
2010-10-17 13:25:21 +00:00
|
|
|
}
|
|
|
|
|
2010-10-06 10:44:03 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionAction
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionAction::FIntermissionAction()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionAction);
|
|
|
|
mClass = RUNTIME_CLASS(DIntermissionScreen);
|
|
|
|
mMusicOrder =
|
|
|
|
mCdId =
|
|
|
|
mCdTrack =
|
|
|
|
mDuration = 0;
|
|
|
|
mFlatfill = false;
|
|
|
|
mMusicLooping = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = xs_RoundToInt(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionActionFader
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionActionFader::FIntermissionActionFader()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionActionFader);
|
|
|
|
mClass = RUNTIME_CLASS(DIntermissionScreenFader);
|
|
|
|
mFadeType = FADE_In;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FIntermissionActionFader::ParseKey(FScanner &sc)
|
|
|
|
{
|
|
|
|
struct FadeType
|
|
|
|
{
|
|
|
|
const char *Name;
|
|
|
|
EFadeType Type;
|
|
|
|
}
|
|
|
|
const FT[] = {
|
|
|
|
{ "FadeIn", FADE_In },
|
|
|
|
{ "FadeOut", FADE_Out },
|
|
|
|
{ NULL, FADE_In }
|
|
|
|
};
|
|
|
|
|
|
|
|
if (sc.Compare("FadeType"))
|
|
|
|
{
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_Identifier);
|
|
|
|
int v = sc.MatchString(&FT[0].Name, sizeof(FT[0]));
|
|
|
|
if (v != -1) mFadeType = FT[v].Type;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else return Super::ParseKey(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionActionWiper
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionActionWiper::FIntermissionActionWiper()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionActionWiper);
|
|
|
|
mClass = WIPER_ID;
|
|
|
|
mWipeType = GS_FORCEWIPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FIntermissionActionWiper::ParseKey(FScanner &sc)
|
|
|
|
{
|
|
|
|
struct WipeType
|
|
|
|
{
|
|
|
|
const char *Name;
|
|
|
|
gamestate_t Type;
|
|
|
|
}
|
|
|
|
const FT[] = {
|
|
|
|
{ "Crossfade", GS_FORCEWIPEFADE },
|
|
|
|
{ "Melt", GS_FORCEWIPEMELT },
|
|
|
|
{ "Burn", GS_FORCEWIPEBURN },
|
|
|
|
{ "Default", GS_FORCEWIPE },
|
|
|
|
{ NULL, GS_FORCEWIPE }
|
|
|
|
};
|
|
|
|
|
|
|
|
if (sc.Compare("WipeType"))
|
|
|
|
{
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_Identifier);
|
|
|
|
int v = sc.MatchString(&FT[0].Name, sizeof(FT[0]));
|
|
|
|
if (v != -1) mWipeType = FT[v].Type;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else return Super::ParseKey(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionActionFader
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionActionTextscreen::FIntermissionActionTextscreen()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionActionTextscreen);
|
|
|
|
mClass = RUNTIME_CLASS(DIntermissionScreenText);
|
|
|
|
mTextSpeed = 2;
|
|
|
|
mTextX = -1; // use gameinfo defaults
|
|
|
|
mTextY = -1;
|
|
|
|
mTextColor = CR_UNTRANSLATED;
|
|
|
|
mTextDelay = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = xs_RoundToInt(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);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionAction
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionActionCast::FIntermissionActionCast()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionActionCast);
|
|
|
|
mClass = RUNTIME_CLASS(DIntermissionScreenCast);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FIntermissionActionCast::ParseKey(FScanner &sc)
|
|
|
|
{
|
|
|
|
if (sc.Compare("CastName"))
|
|
|
|
{
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
mName = sc.String;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("CastClass"))
|
|
|
|
{
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
mCastClass = sc.String;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("AttackSound"))
|
|
|
|
{
|
|
|
|
static const char *const seqs[] = {"Missile", "Melee", NULL};
|
|
|
|
FCastSound *cs = &mCastSounds[mCastSounds.Reserve(1)];
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
cs->mSequence = (BYTE)sc.MatchString(seqs);
|
|
|
|
sc.MustGetToken(',');
|
|
|
|
sc.MustGetToken(TK_IntConst);
|
|
|
|
cs->mIndex = (BYTE)sc.Number;
|
|
|
|
sc.MustGetToken(',');
|
|
|
|
sc.MustGetToken(TK_StringConst);
|
|
|
|
cs->mSound = sc.String;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else return Super::ParseKey(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FIntermissionActionScroller
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FIntermissionActionScroller::FIntermissionActionScroller()
|
|
|
|
{
|
|
|
|
mSize = sizeof(FIntermissionActionScroller);
|
|
|
|
mClass = RUNTIME_CLASS(DIntermissionScreenScroller);
|
|
|
|
mScrollDelay = 0;
|
|
|
|
mScrollTime = 640;
|
|
|
|
mScrollDir = SCROLL_Right;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = xs_RoundToInt(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 = xs_RoundToInt(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);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ParseIntermission
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FMapInfoParser::ParseIntermissionAction(FIntermissionDescriptor *desc)
|
|
|
|
{
|
|
|
|
FIntermissionAction *ac = NULL;
|
|
|
|
|
|
|
|
sc.MustGetToken(TK_Identifier);
|
|
|
|
if (sc.Compare("image"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionAction;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("scroller"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionActionScroller;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("cast"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionActionCast;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("Fader"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionActionFader;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("Wiper"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionActionWiper;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("TextScreen"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionActionTextscreen;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("GotoTitle"))
|
|
|
|
{
|
|
|
|
ac = new FIntermissionAction;
|
|
|
|
ac->mClass = TITLE_ID;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("Link"))
|
|
|
|
{
|
|
|
|
sc.MustGetToken('=');
|
|
|
|
sc.MustGetToken(TK_Identifier);
|
|
|
|
desc->mLink = sc.String;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sc.ScriptMessage("Unknown intermission type '%s'", sc.String);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc.MustGetToken('{');
|
|
|
|
while (!sc.CheckToken('}'))
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
if (!sc.CheckToken(TK_Sound))
|
|
|
|
{
|
|
|
|
sc.MustGetToken(TK_Identifier);
|
|
|
|
}
|
|
|
|
if (ac != NULL)
|
|
|
|
{
|
|
|
|
success = ac->ParseKey(sc);
|
|
|
|
if (!success)
|
|
|
|
{
|
|
|
|
sc.ScriptMessage("Unknown key name '%s'\n", sc.String);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!success) SkipToNext();
|
|
|
|
}
|
|
|
|
if (ac != NULL) desc->mActions.Push(ac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ParseIntermission
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FMapInfoParser::ParseIntermission()
|
|
|
|
{
|
|
|
|
sc.MustGetString();
|
|
|
|
FName intname = sc.String;
|
|
|
|
FIntermissionDescriptor *desc = new FIntermissionDescriptor();
|
|
|
|
|
|
|
|
ReplaceIntermission(intname, desc);
|
|
|
|
sc.MustGetToken('{');
|
|
|
|
while (!sc.CheckToken('}'))
|
|
|
|
{
|
|
|
|
ParseIntermissionAction(desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Parse old style endsequence
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
struct EndSequence
|
|
|
|
{
|
|
|
|
SBYTE EndType;
|
|
|
|
bool MusicLooping;
|
|
|
|
bool PlayTheEnd;
|
|
|
|
FString PicName;
|
|
|
|
FString PicName2;
|
|
|
|
FString Music;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum EndTypes
|
|
|
|
{
|
|
|
|
END_Pic,
|
|
|
|
END_Bunny,
|
|
|
|
END_Cast,
|
|
|
|
END_Demon
|
|
|
|
};
|
|
|
|
|
|
|
|
FName FMapInfoParser::ParseEndGame()
|
|
|
|
{
|
|
|
|
EndSequence newSeq;
|
|
|
|
static int generated = 0;
|
|
|
|
|
|
|
|
newSeq.EndType = -1;
|
|
|
|
newSeq.PlayTheEnd = false;
|
|
|
|
newSeq.MusicLooping = true;
|
|
|
|
while (!sc.CheckString("}"))
|
|
|
|
{
|
|
|
|
sc.MustGetString();
|
|
|
|
if (sc.Compare("pic"))
|
|
|
|
{
|
|
|
|
ParseAssign();
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.EndType = END_Pic;
|
|
|
|
newSeq.PicName = sc.String;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("hscroll"))
|
|
|
|
{
|
|
|
|
ParseAssign();
|
|
|
|
newSeq.EndType = END_Bunny;
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.PicName = sc.String;
|
|
|
|
ParseComma();
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.PicName2 = sc.String;
|
|
|
|
if (CheckNumber())
|
|
|
|
newSeq.PlayTheEnd = !!sc.Number;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("vscroll"))
|
|
|
|
{
|
|
|
|
ParseAssign();
|
|
|
|
newSeq.EndType = END_Demon;
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.PicName = sc.String;
|
|
|
|
ParseComma();
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.PicName2 = sc.String;
|
|
|
|
}
|
|
|
|
else if (sc.Compare("cast"))
|
|
|
|
{
|
|
|
|
newSeq.EndType = END_Cast;
|
2010-10-07 22:57:09 +00:00
|
|
|
if (newSeq.PicName.IsEmpty()) newSeq.PicName = "$bgcastcall";
|
2010-10-06 10:44:03 +00:00
|
|
|
}
|
|
|
|
else if (sc.Compare("music"))
|
|
|
|
{
|
|
|
|
ParseAssign();
|
|
|
|
sc.MustGetString();
|
|
|
|
newSeq.Music = sc.String;
|
|
|
|
if (CheckNumber())
|
|
|
|
{
|
|
|
|
newSeq.MusicLooping = !!sc.Number;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (format_type == FMT_New)
|
|
|
|
{
|
|
|
|
// Unknown
|
|
|
|
sc.ScriptMessage("Unknown property '%s' found in endgame definition\n", sc.String);
|
|
|
|
SkipToNext();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sc.ScriptError("Unknown property '%s' found in endgame definition\n", sc.String);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FIntermissionDescriptor *desc = new FIntermissionDescriptor;
|
|
|
|
FIntermissionAction *action;
|
|
|
|
|
|
|
|
switch (newSeq.EndType)
|
|
|
|
{
|
|
|
|
case END_Pic:
|
|
|
|
action = new FIntermissionAction;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case END_Bunny:
|
|
|
|
{
|
|
|
|
FIntermissionActionScroller *bunny = new FIntermissionActionScroller;
|
|
|
|
bunny->mSecondPic = newSeq.PicName2;
|
|
|
|
bunny->mScrollDir = SCROLL_Left;
|
|
|
|
bunny->mScrollDelay = 230;
|
|
|
|
bunny->mScrollTime = 640;
|
|
|
|
bunny->mDuration = 1130;
|
|
|
|
action = bunny;
|
|
|
|
if (newSeq.PlayTheEnd) desc->mLink = "TheEnd";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case END_Demon:
|
|
|
|
{
|
|
|
|
FIntermissionActionScroller *demon = new FIntermissionActionScroller;
|
|
|
|
demon->mSecondPic = newSeq.PicName2;
|
|
|
|
demon->mScrollDir = SCROLL_Up;
|
|
|
|
demon->mScrollDelay = 70;
|
|
|
|
demon->mScrollTime = 600;
|
|
|
|
action = demon;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case END_Cast:
|
|
|
|
action = new FIntermissionAction;
|
|
|
|
action->mDuration = 1;
|
|
|
|
desc->mLink = "Doom2Cast";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
action->mBackground = newSeq.PicName;
|
|
|
|
action->mMusic = newSeq.Music;
|
|
|
|
action->mMusicLooping = newSeq.MusicLooping;
|
2010-10-07 22:57:09 +00:00
|
|
|
desc->mActions.Push(action);
|
2010-10-06 10:44:03 +00:00
|
|
|
|
|
|
|
FString seq;
|
|
|
|
seq.Format("@EndSequence_%d_", generated++);
|
|
|
|
ReplaceIntermission(seq, desc);
|
|
|
|
return FName(seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Checks map name for end sequence
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FName FMapInfoParser::CheckEndSequence()
|
|
|
|
{
|
|
|
|
const char *seqname = NULL;
|
|
|
|
|
|
|
|
if (sc.Compare("endgame"))
|
|
|
|
{
|
|
|
|
if (!sc.CheckString("{"))
|
|
|
|
{
|
|
|
|
// Make Demon Eclipse work again
|
|
|
|
sc.UnGet();
|
|
|
|
goto standard_endgame;
|
|
|
|
}
|
|
|
|
return ParseEndGame();
|
|
|
|
}
|
|
|
|
else if (strnicmp (sc.String, "EndGame", 7) == 0)
|
|
|
|
{
|
|
|
|
switch (sc.String[7])
|
|
|
|
{
|
|
|
|
case '1': seqname = "Inter_Pic1"; break;
|
|
|
|
case '2': seqname = "Inter_Pic2"; break;
|
|
|
|
case '3': seqname = "Inter_Bunny"; break;
|
|
|
|
case 'C': seqname = "Inter_Cast"; break;
|
|
|
|
case 'W': seqname = "Inter_Underwater"; break;
|
|
|
|
case 'S': seqname = "Inter_Strife"; break;
|
|
|
|
standard_endgame:
|
|
|
|
default: seqname = "Inter_Pic3"; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endpic"))
|
|
|
|
{
|
|
|
|
ParseComma();
|
|
|
|
sc.MustGetString ();
|
|
|
|
FString seqname;
|
|
|
|
seqname << "@EndPic_" << sc.String;
|
|
|
|
FIntermissionDescriptor *desc = new FIntermissionDescriptor;
|
|
|
|
FIntermissionAction *action = new FIntermissionAction;
|
|
|
|
action->mBackground = sc.String;
|
|
|
|
desc->mActions.Push(action);
|
|
|
|
ReplaceIntermission(seqname, desc);
|
|
|
|
return FName(seqname);
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endbunny"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Bunny";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endcast"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Cast";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("enddemon"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Demonscroll";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endchess"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Chess";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endunderwater"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Underwater";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endbuystrife"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_BuyStrife";
|
|
|
|
}
|
|
|
|
else if (sc.Compare("endtitle"))
|
|
|
|
{
|
|
|
|
seqname = "Inter_Titlescreen";
|
|
|
|
}
|
2010-10-10 06:21:23 +00:00
|
|
|
else if (sc.Compare("endsequence"))
|
|
|
|
{
|
|
|
|
ParseComma();
|
|
|
|
sc.MustGetString();
|
|
|
|
seqname = sc.String;
|
|
|
|
}
|
2010-10-06 10:44:03 +00:00
|
|
|
|
|
|
|
if (seqname != NULL)
|
|
|
|
{
|
|
|
|
return FName(seqname);
|
|
|
|
}
|
|
|
|
return NAME_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Creates an intermission from the cluster's finale info
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat,
|
|
|
|
const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText,
|
|
|
|
bool ending, FName endsequence)
|
|
|
|
{
|
2011-01-05 22:45:25 +00:00
|
|
|
// Hexen's chess ending doesn't have a text screen, even if the cluster has a message defined.
|
|
|
|
if (text != NULL && *text != 0 && endsequence != NAME_Inter_Chess)
|
2010-10-06 10:44:03 +00:00
|
|
|
{
|
|
|
|
FIntermissionActionTextscreen *textscreen = new FIntermissionActionTextscreen;
|
|
|
|
if (textInLump)
|
|
|
|
{
|
|
|
|
int lump = Wads.CheckNumForFullName(text, true);
|
|
|
|
if (lump > 0)
|
|
|
|
{
|
|
|
|
textscreen->mText = Wads.ReadLump(lump).GetString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textscreen->mText.Format("Unknown text lump '%s'", text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!lookupText)
|
|
|
|
{
|
|
|
|
textscreen->mText = text;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textscreen->mText << '$' << text;
|
|
|
|
}
|
|
|
|
textscreen->mTextDelay = 10;
|
2010-12-15 08:00:38 +00:00
|
|
|
if (flat != NULL && *flat != 0)
|
|
|
|
{
|
|
|
|
textscreen->mBackground = flat;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// force a black screen if no texture is set.
|
|
|
|
textscreen->mBackground = "-";
|
|
|
|
}
|
2010-10-06 10:44:03 +00:00
|
|
|
textscreen->mFlatfill = !finalePic;
|
|
|
|
|
|
|
|
if (music != NULL && *music != 0)
|
|
|
|
{
|
|
|
|
textscreen->mMusic = music;
|
|
|
|
textscreen->mMusicOrder = musicorder;
|
|
|
|
}
|
|
|
|
if (cdtrack > 0)
|
|
|
|
{
|
|
|
|
textscreen->mCdTrack = cdtrack;
|
|
|
|
textscreen->mCdId = cdid;
|
|
|
|
}
|
|
|
|
FIntermissionDescriptor *desc = new FIntermissionDescriptor;
|
|
|
|
desc->mActions.Push(textscreen);
|
|
|
|
|
|
|
|
if (ending)
|
|
|
|
{
|
|
|
|
desc->mLink = endsequence;
|
|
|
|
FIntermissionActionWiper *wiper = new FIntermissionActionWiper;
|
|
|
|
desc->mActions.Push(wiper);
|
|
|
|
}
|
|
|
|
|
|
|
|
F_StartIntermission(desc, true, ending? FSTATE_EndingGame : FSTATE_ChangingLevel);
|
|
|
|
}
|
|
|
|
else if (ending)
|
|
|
|
{
|
|
|
|
FIntermissionDescriptor **pdesc = IntermissionDescriptors.CheckKey(endsequence);
|
|
|
|
if (pdesc != NULL)
|
|
|
|
{
|
|
|
|
F_StartIntermission(*pdesc, false, ending? FSTATE_EndingGame : FSTATE_ChangingLevel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|