- merged finale branch back into trunk.
SVN r2911 (trunk)
This commit is contained in:
parent
0490c35347
commit
d9970ab9b6
30 changed files with 6132 additions and 5157 deletions
875
src/intermission/intermission.cpp
Normal file
875
src/intermission/intermission.cpp
Normal file
|
|
@ -0,0 +1,875 @@
|
|||
/*
|
||||
** intermission.cpp
|
||||
** Framework for intermissions (text screens, slideshows, etc)
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 "doomtype.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h"
|
||||
#include "gi.h"
|
||||
#include "v_video.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_main.h"
|
||||
#include "gstrings.h"
|
||||
#include "intermission/intermission.h"
|
||||
#include "actor.h"
|
||||
#include "d_player.h"
|
||||
#include "r_state.h"
|
||||
#include "r_translate.h"
|
||||
#include "c_bind.h"
|
||||
#include "g_level.h"
|
||||
#include "p_conversation.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
FIntermissionDescriptorList IntermissionDescriptors;
|
||||
|
||||
IMPLEMENT_CLASS(DIntermissionScreen)
|
||||
IMPLEMENT_CLASS(DIntermissionScreenFader)
|
||||
IMPLEMENT_CLASS(DIntermissionScreenText)
|
||||
IMPLEMENT_CLASS(DIntermissionScreenCast)
|
||||
IMPLEMENT_CLASS(DIntermissionScreenScroller)
|
||||
IMPLEMENT_POINTY_CLASS(DIntermissionController)
|
||||
DECLARE_POINTER(mScreen)
|
||||
END_POINTERS
|
||||
|
||||
extern int NoWipe;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
|
||||
{
|
||||
int lumpnum;
|
||||
|
||||
if (desc->mCdTrack == 0 || !S_ChangeCDMusic (desc->mCdTrack, desc->mCdId))
|
||||
{
|
||||
if (desc->mMusic.IsEmpty())
|
||||
{
|
||||
// only start the default music if this is the first action in an intermission
|
||||
if (first) S_ChangeMusic (gameinfo.finaleMusic, 0, desc->mMusicLooping);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping);
|
||||
}
|
||||
}
|
||||
mDuration = desc->mDuration;
|
||||
|
||||
const char *texname = desc->mBackground;
|
||||
if (*texname == '@')
|
||||
{
|
||||
char *pp;
|
||||
unsigned int v = strtoul(texname+1, &pp, 10) - 1;
|
||||
if (*pp == 0 && v < gameinfo.finalePages.Size())
|
||||
{
|
||||
texname = gameinfo.finalePages[v].GetChars();
|
||||
}
|
||||
else if (gameinfo.finalePages.Size() > 0)
|
||||
{
|
||||
texname = gameinfo.finalePages[0].GetChars();
|
||||
}
|
||||
else
|
||||
{
|
||||
texname = gameinfo.titlePage;
|
||||
}
|
||||
}
|
||||
else if (*texname == '$')
|
||||
{
|
||||
texname = GStrings[texname+1];
|
||||
}
|
||||
FTextureID tex = TexMan.CheckForTexture(texname, FTexture::TEX_MiscPatch);
|
||||
if (tex.isValid())
|
||||
{
|
||||
mBackground = tex;
|
||||
mFlatfill = desc->mFlatfill;
|
||||
}
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, desc->mSound, 1.0f, ATTN_NONE);
|
||||
if (desc->mPalette.IsNotEmpty() && (lumpnum = Wads.CheckNumForFullName(desc->mPalette, true)) > 0)
|
||||
{
|
||||
PalEntry *palette;
|
||||
const BYTE *orgpal;
|
||||
FMemLump lump;
|
||||
int i;
|
||||
|
||||
lump = Wads.ReadLump (lumpnum);
|
||||
orgpal = (BYTE *)lump.GetMem();
|
||||
palette = screen->GetPalette ();
|
||||
for (i = 256; i > 0; i--, orgpal += 3)
|
||||
{
|
||||
*palette++ = PalEntry (orgpal[0], orgpal[1], orgpal[2]);
|
||||
}
|
||||
screen->UpdatePalette ();
|
||||
mPaletteChanged = true;
|
||||
NoWipe = 1;
|
||||
M_EnableMenu(false);
|
||||
}
|
||||
mOverlays.Resize(desc->mOverlays.Size());
|
||||
for (unsigned i=0; i < mOverlays.Size(); i++)
|
||||
{
|
||||
mOverlays[i].x = desc->mOverlays[i].x;
|
||||
mOverlays[i].y = desc->mOverlays[i].y;
|
||||
mOverlays[i].mCondition = desc->mOverlays[i].mCondition;
|
||||
mOverlays[i].mPic = TexMan.CheckForTexture(desc->mOverlays[i].mName, FTexture::TEX_MiscPatch);
|
||||
}
|
||||
mTicker = 0;
|
||||
}
|
||||
|
||||
|
||||
int DIntermissionScreen::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DIntermissionScreen::Ticker ()
|
||||
{
|
||||
if (++mTicker >= mDuration && mDuration > 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DIntermissionScreen::CheckOverlay(int i)
|
||||
{
|
||||
if (mOverlays[i].mCondition == NAME_Multiplayer && !multiplayer) return false;
|
||||
else if (mOverlays[i].mCondition != NAME_None)
|
||||
{
|
||||
if (multiplayer || players[0].mo == NULL) return false;
|
||||
const PClass *cls = PClass::FindClass(mOverlays[i].mCondition);
|
||||
if (cls == NULL) return false;
|
||||
if (!players[0].mo->IsKindOf(cls)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DIntermissionScreen::Drawer ()
|
||||
{
|
||||
if (mBackground.isValid())
|
||||
{
|
||||
if (!mFlatfill)
|
||||
{
|
||||
screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->FlatFill (0,0, SCREENWIDTH, SCREENHEIGHT, TexMan[mBackground]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->Clear (0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0);
|
||||
}
|
||||
for (unsigned i=0; i < mOverlays.Size(); i++)
|
||||
{
|
||||
if (CheckOverlay(i))
|
||||
screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
if (!mFlatfill) screen->FillBorder (NULL);
|
||||
}
|
||||
|
||||
void DIntermissionScreen::Destroy()
|
||||
{
|
||||
if (mPaletteChanged)
|
||||
{
|
||||
PalEntry *palette;
|
||||
int i;
|
||||
|
||||
palette = screen->GetPalette ();
|
||||
for (i = 0; i < 256; ++i)
|
||||
{
|
||||
palette[i] = GPalette.BaseColors[i];
|
||||
}
|
||||
screen->UpdatePalette ();
|
||||
NoWipe = 5;
|
||||
mPaletteChanged = false;
|
||||
M_EnableMenu(true);
|
||||
}
|
||||
S_StopSound(CHAN_VOICE);
|
||||
Super::Destroy();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DIntermissionScreenFader::Init(FIntermissionAction *desc, bool first)
|
||||
{
|
||||
Super::Init(desc, first);
|
||||
mType = static_cast<FIntermissionActionFader*>(desc)->mFadeType;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FadePic
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int DIntermissionScreenFader::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{
|
||||
V_SetBlend(0,0,0,0);
|
||||
return -1;
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
int DIntermissionScreenFader::Ticker ()
|
||||
{
|
||||
if (mFlatfill || !mBackground.isValid()) return -1;
|
||||
return Super::Ticker();
|
||||
}
|
||||
|
||||
void DIntermissionScreenFader::Drawer ()
|
||||
{
|
||||
if (!mFlatfill && mBackground.isValid())
|
||||
{
|
||||
double factor = clamp(double(mTicker) / mDuration, 0., 1.);
|
||||
if (mType == FADE_In) factor = 1.0 - factor;
|
||||
int color = MAKEARGB(xs_RoundToInt(factor*255), 0,0,0);
|
||||
|
||||
if (screen->Begin2D(false))
|
||||
{
|
||||
screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE);
|
||||
for (unsigned i=0; i < mOverlays.Size(); i++)
|
||||
{
|
||||
if (CheckOverlay(i))
|
||||
screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
|
||||
}
|
||||
screen->FillBorder (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_SetBlend (0,0,0,int(256*factor));
|
||||
Super::Drawer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DIntermissionScreenText::Init(FIntermissionAction *desc, bool first)
|
||||
{
|
||||
Super::Init(desc, first);
|
||||
mText = static_cast<FIntermissionActionTextscreen*>(desc)->mText;
|
||||
if (mText[0] == '$') mText = GStrings[&mText[1]];
|
||||
mTextSpeed = static_cast<FIntermissionActionTextscreen*>(desc)->mTextSpeed;
|
||||
mTextX = static_cast<FIntermissionActionTextscreen*>(desc)->mTextX;
|
||||
if (mTextX < 0) mTextX =gameinfo.TextScreenX;
|
||||
mTextY = static_cast<FIntermissionActionTextscreen*>(desc)->mTextY;
|
||||
if (mTextY < 0) mTextY =gameinfo.TextScreenY;
|
||||
mTextLen = (int)strlen(mText);
|
||||
mTextDelay = static_cast<FIntermissionActionTextscreen*>(desc)->mTextDelay;
|
||||
mTextColor = static_cast<FIntermissionActionTextscreen*>(desc)->mTextColor;
|
||||
// For text screens, the duration only counts when the text is complete.
|
||||
if (mDuration > 0) mDuration += mTextDelay + mTextSpeed * mTextLen;
|
||||
}
|
||||
|
||||
int DIntermissionScreenText::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{
|
||||
if (mTicker < mTextDelay + (mTextLen * mTextSpeed))
|
||||
{
|
||||
mTicker = mTextDelay + (mTextLen * mTextSpeed);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
void DIntermissionScreenText::Drawer ()
|
||||
{
|
||||
Super::Drawer();
|
||||
if (mTicker >= mTextDelay)
|
||||
{
|
||||
FTexture *pic;
|
||||
int w;
|
||||
size_t count;
|
||||
int c;
|
||||
const FRemapTable *range;
|
||||
|
||||
// draw some of the text onto the screen
|
||||
int rowheight = SmallFont->GetHeight () + (gameinfo.gametype & (GAME_DoomStrifeChex) ? 3 : -1);
|
||||
bool scale = (CleanXfac != 1 || CleanYfac != 1);
|
||||
|
||||
int cx = mTextX;
|
||||
int cy = mTextY;
|
||||
const char *ch = mText;
|
||||
|
||||
count = (mTicker - mTextDelay) / mTextSpeed;
|
||||
range = SmallFont->GetColorTranslation (mTextColor);
|
||||
|
||||
for ( ; count > 0 ; count-- )
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
if (c == '\n')
|
||||
{
|
||||
cx = mTextX;
|
||||
cy += rowheight;
|
||||
continue;
|
||||
}
|
||||
|
||||
pic = SmallFont->GetChar (c, &w);
|
||||
if (cx+w > SCREENWIDTH)
|
||||
continue;
|
||||
if (pic != NULL)
|
||||
{
|
||||
if (scale)
|
||||
{
|
||||
screen->DrawTexture (pic,
|
||||
cx,// + 320 / 2,
|
||||
cy,// + 200 / 2,
|
||||
DTA_Translation, range,
|
||||
DTA_Clean, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture (pic,
|
||||
cx,// + 320 / 2,
|
||||
cy,// + 200 / 2,
|
||||
DTA_Translation, range,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
cx += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first)
|
||||
{
|
||||
Super::Init(desc, first);
|
||||
mName = static_cast<FIntermissionActionCast*>(desc)->mName;
|
||||
mClass = PClass::FindClass(static_cast<FIntermissionActionCast*>(desc)->mCastClass);
|
||||
if (mClass != NULL) mDefaults = GetDefaultByType(mClass);
|
||||
else mDefaults = NULL;
|
||||
|
||||
mCastSounds.Resize(static_cast<FIntermissionActionCast*>(desc)->mCastSounds.Size());
|
||||
for (unsigned i=0; i < mCastSounds.Size(); i++)
|
||||
{
|
||||
mCastSounds[i].mSequence = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mSequence;
|
||||
mCastSounds[i].mIndex = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mIndex;
|
||||
mCastSounds[i].mSound = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mSound;
|
||||
}
|
||||
caststate = mDefaults->SeeState;
|
||||
if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
advplayerstate = mDefaults->MissileState;
|
||||
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
|
||||
casttranslation = translationtables[TRANSLATION_Players][consoleplayer];
|
||||
}
|
||||
else
|
||||
{
|
||||
advplayerstate = NULL;
|
||||
if (caststate != NULL) castsprite = caststate->sprite;
|
||||
else castsprite = -1;
|
||||
casttranslation = NULL;
|
||||
}
|
||||
castdeath = false;
|
||||
castframes = 0;
|
||||
castonmelee = 0;
|
||||
castattacking = false;
|
||||
if (mDefaults->SeeSound)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, mDefaults->SeeSound, 1, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
int DIntermissionScreenCast::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type != EV_KeyDown) return 0;
|
||||
|
||||
if (castdeath)
|
||||
return 1; // already in dying frames
|
||||
|
||||
castdeath = true;
|
||||
caststate = mClass->ActorInfo->FindState(NAME_Death);
|
||||
if (caststate == NULL) return -1;
|
||||
|
||||
casttics = caststate->GetTics();
|
||||
castframes = 0;
|
||||
castattacking = false;
|
||||
|
||||
if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
int snd = S_FindSkinnedSound(players[consoleplayer].mo, "*death");
|
||||
if (snd != 0) S_Sound (CHAN_VOICE | CHAN_UI, snd, 1, ATTN_NONE);
|
||||
}
|
||||
else if (mDefaults->DeathSound)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, mDefaults->DeathSound, 1, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int DIntermissionScreenCast::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
|
||||
if (--casttics > 0 && caststate != NULL)
|
||||
return 0; // not time to change state yet
|
||||
|
||||
if (caststate == NULL || caststate->GetTics() == -1 || caststate->GetNextState() == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sound hacks....
|
||||
if (caststate != NULL && castattacking)
|
||||
{
|
||||
for (unsigned i = 0; i < mCastSounds.Size(); i++)
|
||||
{
|
||||
if ((!!mCastSounds[i].mSequence) == (basestate != mDefaults->MissileState) &&
|
||||
(caststate == basestate + mCastSounds[i].mIndex - 1))
|
||||
{
|
||||
S_StopAllChannels ();
|
||||
S_Sound (CHAN_WEAPON | CHAN_UI, mCastSounds[i].mSound, 1, ATTN_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just advance to next state in animation
|
||||
if (caststate == advplayerstate)
|
||||
goto stopattack; // Oh, gross hack!
|
||||
|
||||
caststate = caststate->GetNextState();
|
||||
castframes++;
|
||||
}
|
||||
|
||||
if (castframes == 12)
|
||||
{
|
||||
// go into attack frame
|
||||
castattacking = true;
|
||||
if (castonmelee)
|
||||
basestate = caststate = mDefaults->MeleeState;
|
||||
else
|
||||
basestate = caststate = mDefaults->MissileState;
|
||||
castonmelee ^= 1;
|
||||
if (caststate == NULL)
|
||||
{
|
||||
if (castonmelee)
|
||||
basestate = caststate = mDefaults->MeleeState;
|
||||
else
|
||||
basestate = caststate = mDefaults->MissileState;
|
||||
}
|
||||
}
|
||||
|
||||
if (castattacking)
|
||||
{
|
||||
if (castframes == 24 || caststate == mDefaults->SeeState )
|
||||
{
|
||||
stopattack:
|
||||
castattacking = false;
|
||||
castframes = 0;
|
||||
caststate = mDefaults->SeeState;
|
||||
}
|
||||
}
|
||||
|
||||
casttics = caststate->GetTics();
|
||||
if (casttics == -1)
|
||||
casttics = 15;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DIntermissionScreenCast::Drawer ()
|
||||
{
|
||||
spriteframe_t* sprframe;
|
||||
FTexture* pic;
|
||||
|
||||
Super::Drawer();
|
||||
|
||||
const char *name = mName;
|
||||
if (name != NULL)
|
||||
{
|
||||
if (*name == '$') name = GStrings(name+1);
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED,
|
||||
(SCREENWIDTH - SmallFont->StringWidth (name) * CleanXfac)/2,
|
||||
(SCREENHEIGHT * 180) / 200,
|
||||
name,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
|
||||
// draw the current frame in the middle of the screen
|
||||
if (caststate != NULL)
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[castsprite].spriteframes + caststate->GetFrame()];
|
||||
pic = TexMan(sprframe->Texture[0]);
|
||||
|
||||
screen->DrawTexture (pic, 160, 170,
|
||||
DTA_320x200, true,
|
||||
DTA_FlipX, sprframe->Flip & 1,
|
||||
DTA_Translation, casttranslation,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DIntermissionScreenScroller::Init(FIntermissionAction *desc, bool first)
|
||||
{
|
||||
Super::Init(desc, first);
|
||||
mFirstPic = mBackground;
|
||||
mSecondPic = TexMan.CheckForTexture(static_cast<FIntermissionActionScroller*>(desc)->mSecondPic, FTexture::TEX_MiscPatch);
|
||||
mScrollDelay = static_cast<FIntermissionActionScroller*>(desc)->mScrollDelay;
|
||||
mScrollTime = static_cast<FIntermissionActionScroller*>(desc)->mScrollTime;
|
||||
mScrollDir = static_cast<FIntermissionActionScroller*>(desc)->mScrollDir;
|
||||
}
|
||||
|
||||
void DIntermissionScreenScroller::Drawer ()
|
||||
{
|
||||
FTexture *tex = TexMan[mFirstPic];
|
||||
FTexture *tex2 = TexMan[mSecondPic];
|
||||
if (mTicker >= mScrollDelay && mTicker < mScrollDelay + mScrollTime && tex != NULL && tex2 != NULL)
|
||||
{
|
||||
|
||||
int fwidth = tex->GetScaledWidth();
|
||||
int fheight = tex->GetScaledHeight();
|
||||
|
||||
double xpos1 = 0, ypos1 = 0, xpos2 = 0, ypos2 = 0;
|
||||
|
||||
switch (mScrollDir)
|
||||
{
|
||||
case SCROLL_Up:
|
||||
ypos1 = double(mTicker - mScrollDelay) * fheight / mScrollTime;
|
||||
ypos2 = ypos1 - fheight;
|
||||
break;
|
||||
|
||||
case SCROLL_Down:
|
||||
ypos1 = -double(mTicker - mScrollDelay) * fheight / mScrollTime;
|
||||
ypos2 = ypos1 + fheight;
|
||||
break;
|
||||
|
||||
case SCROLL_Left:
|
||||
default:
|
||||
xpos1 = double(mTicker - mScrollDelay) * fwidth / mScrollTime;
|
||||
xpos2 = xpos1 - fwidth;
|
||||
break;
|
||||
|
||||
case SCROLL_Right:
|
||||
xpos1 = -double(mTicker - mScrollDelay) * fwidth / mScrollTime;
|
||||
xpos2 = xpos1 + fwidth;
|
||||
break;
|
||||
}
|
||||
|
||||
screen->DrawTexture (tex, xpos1, ypos1,
|
||||
DTA_VirtualWidth, fwidth,
|
||||
DTA_VirtualHeight, fheight,
|
||||
DTA_Masked, false,
|
||||
TAG_DONE);
|
||||
screen->DrawTexture (tex2, xpos2, ypos2,
|
||||
DTA_VirtualWidth, fwidth,
|
||||
DTA_VirtualHeight, fheight,
|
||||
DTA_Masked, false,
|
||||
TAG_DONE);
|
||||
|
||||
screen->FillBorder (NULL);
|
||||
mBackground = mSecondPic;
|
||||
}
|
||||
else
|
||||
{
|
||||
Super::Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DIntermissionController *DIntermissionController::CurrentIntermission;
|
||||
|
||||
DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, bool DeleteDesc, BYTE state)
|
||||
{
|
||||
mDesc = Desc;
|
||||
mDeleteDesc = DeleteDesc;
|
||||
mIndex = 0;
|
||||
mAdvance = false;
|
||||
mScreen = NULL;
|
||||
mFirst = true;
|
||||
mGameState = state;
|
||||
NextPage();
|
||||
}
|
||||
|
||||
bool DIntermissionController::NextPage ()
|
||||
{
|
||||
FTextureID bg;
|
||||
bool fill = false;
|
||||
|
||||
if (mIndex == (int)mDesc->mActions.Size() && mDesc->mLink == NAME_None)
|
||||
{
|
||||
// last page
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mScreen != NULL)
|
||||
{
|
||||
bg = mScreen->GetBackground(&fill);
|
||||
mScreen->Destroy();
|
||||
}
|
||||
again:
|
||||
while ((unsigned)mIndex < mDesc->mActions.Size())
|
||||
{
|
||||
FIntermissionAction *action = mDesc->mActions[mIndex++];
|
||||
if (action->mClass == WIPER_ID)
|
||||
{
|
||||
wipegamestate = static_cast<FIntermissionActionWiper*>(action)->mWipeType;
|
||||
}
|
||||
else if (action->mClass == TITLE_ID)
|
||||
{
|
||||
Destroy();
|
||||
D_StartTitle ();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create page here
|
||||
mScreen = (DIntermissionScreen*)action->mClass->CreateNew();
|
||||
mScreen->SetBackground(bg, fill); // copy last screen's background before initializing
|
||||
mScreen->Init(action, mFirst);
|
||||
mFirst = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mDesc->mLink != NAME_None)
|
||||
{
|
||||
FIntermissionDescriptor **pDesc = IntermissionDescriptors.CheckKey(mDesc->mLink);
|
||||
if (pDesc != NULL)
|
||||
{
|
||||
if (mDeleteDesc) delete mDesc;
|
||||
mDeleteDesc = false;
|
||||
mIndex = 0;
|
||||
mDesc = *pDesc;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DIntermissionController::Responder (event_t *ev)
|
||||
{
|
||||
if (mScreen != NULL)
|
||||
{
|
||||
if (!mScreen->mPaletteChanged && ev->type == EV_KeyDown)
|
||||
{
|
||||
const char *cmd = Bindings.GetBind (ev->data1);
|
||||
|
||||
if (cmd != NULL && !stricmp (cmd, "toggleconsole"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mScreen->mTicker < 2) return false; // prevent some leftover events from auto-advancing
|
||||
int res = mScreen->Responder(ev);
|
||||
mAdvance = (res == -1);
|
||||
return !!res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DIntermissionController::Ticker ()
|
||||
{
|
||||
if (mScreen != NULL)
|
||||
{
|
||||
mAdvance |= (mScreen->Ticker() == -1);
|
||||
}
|
||||
if (mAdvance)
|
||||
{
|
||||
mAdvance = false;
|
||||
if (!NextPage())
|
||||
{
|
||||
switch (mGameState)
|
||||
{
|
||||
case FSTATE_InLevel:
|
||||
if (level.cdtrack == 0 || !S_ChangeCDMusic (level.cdtrack, level.cdid))
|
||||
S_ChangeMusic (level.Music, level.musicorder);
|
||||
gamestate = GS_LEVEL;
|
||||
wipegamestate = GS_LEVEL;
|
||||
P_ResumeConversation ();
|
||||
viewactive = true;
|
||||
Destroy();
|
||||
break;
|
||||
|
||||
case FSTATE_ChangingLevel:
|
||||
gameaction = ga_worlddone;
|
||||
Destroy();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DIntermissionController::Drawer ()
|
||||
{
|
||||
if (mScreen != NULL)
|
||||
{
|
||||
mScreen->Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
void DIntermissionController::Destroy ()
|
||||
{
|
||||
Super::Destroy();
|
||||
if (mScreen != NULL) mScreen->Destroy();
|
||||
if (mDeleteDesc) delete mDesc;
|
||||
mDesc = NULL;
|
||||
if (CurrentIntermission == this) CurrentIntermission = NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// starts a new intermission
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, BYTE state)
|
||||
{
|
||||
if (DIntermissionController::CurrentIntermission != NULL)
|
||||
{
|
||||
DIntermissionController::CurrentIntermission->Destroy();
|
||||
}
|
||||
V_SetBlend (0,0,0,0);
|
||||
S_StopAllChannels ();
|
||||
gameaction = ga_nothing;
|
||||
gamestate = GS_FINALE;
|
||||
if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level.
|
||||
viewactive = false;
|
||||
automapactive = false;
|
||||
DIntermissionController::CurrentIntermission = new DIntermissionController(desc, deleteme, state);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// starts a new intermission
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void F_StartIntermission(FName seq, BYTE state)
|
||||
{
|
||||
FIntermissionDescriptor **pdesc = IntermissionDescriptors.CheckKey(seq);
|
||||
if (pdesc != NULL)
|
||||
{
|
||||
F_StartIntermission(*pdesc, false, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Called by main loop.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool F_Responder (event_t* ev)
|
||||
{
|
||||
if (DIntermissionController::CurrentIntermission != NULL)
|
||||
{
|
||||
return DIntermissionController::CurrentIntermission->Responder(ev);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Called by main loop.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void F_Ticker ()
|
||||
{
|
||||
if (DIntermissionController::CurrentIntermission != NULL)
|
||||
{
|
||||
DIntermissionController::CurrentIntermission->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Called by main loop.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void F_Drawer ()
|
||||
{
|
||||
if (DIntermissionController::CurrentIntermission != NULL)
|
||||
{
|
||||
DIntermissionController::CurrentIntermission->Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Called by main loop.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void F_EndFinale ()
|
||||
{
|
||||
if (DIntermissionController::CurrentIntermission != NULL)
|
||||
{
|
||||
DIntermissionController::CurrentIntermission->Destroy();
|
||||
DIntermissionController::CurrentIntermission = NULL;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue