LOL: moved TIM animation code into a separate class

svn-id: r46351
This commit is contained in:
Florian Kagerer 2009-12-12 20:06:42 +00:00
parent 0e7c2265b5
commit f4c54fb636
7 changed files with 343 additions and 264 deletions

View File

@ -0,0 +1,228 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/system.h"
#include "kyra/script_tim.h"
#include "kyra/wsamovie.h"
#include "kyra/screen_lol.h"
#ifdef ENABLE_LOL
#include "kyra/lol.h"
#endif ENABLE_LOL
namespace Kyra {
TimAnimator::TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts) : _vm(engine), _screen(screen_v2), _system(system), _useParts(useParts) {
_animations = new Animation[TIM::kWSASlots];
memset(_animations, 0, TIM::kWSASlots * sizeof(Animation));
if (_useParts) {
for (int i = 0; i < TIM::kWSASlots; i++) {
_animations[i].parts = new AnimPart[TIM::kAnimParts];
memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart));
}
}
}
TimAnimator::~TimAnimator() {
for (int i = 0; i < TIM::kWSASlots; i++) {
delete _animations[i].wsa;
if (_useParts)
delete[] _animations[i].parts;
}
delete[] _animations;
}
void TimAnimator::init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay) {
TimAnimator::Animation *anim = &_animations[animIndex];
anim->wsa = wsa;
anim->x = x;
anim->y = y;
anim->wsaCopyParams = wsaCopyParams;
anim->frameDelay = frameDelay;
anim->enable = 0;
anim->lastPart = -1;
}
void TimAnimator::reset(int animIndex, bool clearStruct) {
TimAnimator::Animation *anim = &_animations[animIndex];
if (!anim)
return;
anim->field_D = 0;
anim->enable = 0;
delete anim->wsa;
anim->wsa = 0;
if (clearStruct) {
if (_useParts)
delete[] anim->parts;
memset(anim, 0, sizeof(Animation));
if (_useParts) {
anim->parts = new AnimPart[TIM::kAnimParts];
memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart));
}
}
}
void TimAnimator::displayFrame(int animIndex, int page, int frame) {
TimAnimator::Animation *anim = &_animations[animIndex];
if ((anim->wsaCopyParams & 0x4000) != 0)
page = 2;
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
if (anim->wsa)
anim->wsa->displayFrame(frame, page, anim->x, anim->y, anim->wsaCopyParams & 0xF0FF, 0, 0);
if (!page)
_screen->updateScreen();
}
void TimAnimator::setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {
AnimPart *a = &_animations[animIndex].parts[part];
a->firstFrame = firstFrame;
a->lastFrame = lastFrame;
a->cycles = cycles;
a->nextPart = nextPart;
a->partDelay = partDelay;
a->field_A = f;
a->sfxIndex = sfxIndex;
a->sfxFrame = sfxFrame;
}
void TimAnimator::start(int animIndex, int part) {
if (!_vm || !_system || !_screen)
return;
Animation *anim = &_animations[animIndex];
anim->curPart = part;
AnimPart *p = &anim->parts[part];
anim->enable = 1;
anim->nextFrame = _system->getMillis() + anim->frameDelay * _vm->_tickLength;
anim->curFrame = p->firstFrame;
anim->cyclesCompleted = 0;
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
if (anim->wsa)
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
}
void TimAnimator::stop(int animIndex) {
Animation *anim = &_animations[animIndex];
anim->enable = 0;
anim->field_D = 0;
if (animIndex == 5) {
delete anim->wsa;
anim->wsa = 0;
}
}
void TimAnimator::update(int animIndex) {
if (!_vm || !_system || !_screen)
return;
Animation *anim = &_animations[animIndex];
if (!anim->enable || anim->nextFrame >= _system->getMillis())
return;
AnimPart *p = &anim->parts[anim->curPart];
anim->nextFrame = 0;
int step = 0;
if (p->lastFrame >= p->firstFrame) {
step = 1;
anim->curFrame++;
} else {
step = -1;
anim->curFrame--;
}
if (anim->curFrame == (p->lastFrame + step)) {
anim->cyclesCompleted++;
if ((anim->cyclesCompleted > p->cycles) || anim->field_D) {
anim->lastPart = anim->curPart;
if ((p->nextPart == -1) || (anim->field_D && p->field_A)) {
anim->enable = 0;
anim->field_D = 0;
return;
}
anim->nextFrame += (p->partDelay * _vm->_tickLength);
anim->curPart = p->nextPart;
p = &anim->parts[anim->curPart];
anim->curFrame = p->firstFrame;
anim->cyclesCompleted = 0;
} else {
anim->curFrame = p->firstFrame;
}
}
if (p->sfxIndex != -1 && p->sfxFrame == anim->curFrame)
_vm->snd_playSoundEffect(p->sfxIndex, -1);
anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
anim->nextFrame += _system->getMillis();
}
void TimAnimator::playPart(int animIndex, int firstFrame, int lastFrame, int delay) {
if (!_vm || !_system || !_screen)
return;
Animation *anim = &_animations[animIndex];
int step = (lastFrame >= firstFrame) ? 1 : -1;
for (int i = firstFrame; i != (lastFrame + step) ; i += step) {
uint32 next = _system->getMillis() + delay * _vm->_tickLength;
if (anim->wsaCopyParams & 0x4000) {
_screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2);
anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_transparencyTable1, _vm->_transparencyTable2);
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
_screen->updateScreen();
} else {
anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0);
_screen->updateScreen();
}
int32 del = (int32)(next - _system->getMillis());
if (del > 0)
_vm->delay(del, true);
}
}
int TimAnimator::resetLastPart(int animIndex) {
Animation *anim = &_animations[animIndex];
int8 res = -1;
SWAP(res, anim->lastPart);
return res;
}
} // End of namespace Kyra

View File

@ -47,6 +47,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_gui = 0;
_txt = 0;
_tim = 0;
_animator = 0;
switch (_flags.lang) {
case Common::EN_ANY:
@ -579,6 +580,7 @@ Common::Error LoLEngine::go() {
_tim = new TIMInterpreter_LoL(this, _screen, _system);
assert(_tim);
_animator = _tim->animator();
if (shouldQuit())
return Common::kNoError;
@ -1796,7 +1798,7 @@ void LoLEngine::updateSequenceBackgroundAnimations() {
return;
for (int i = 0; i < 6; i++)
_tim->updateBackgroundAnimation(i);
_animator->update(i);
}
void LoLEngine::loadTalkFile(int index) {

View File

@ -300,6 +300,7 @@ class LoLEngine : public KyraEngine_v1 {
friend class GUI_LoL;
friend class TextDisplayer_LoL;
friend class TIMInterpreter_LoL;
friend class TimAnimator;
friend class Debugger_LoL;
friend class HistoryPlayer;
public:
@ -314,6 +315,7 @@ private:
GUI_LoL *_gui;
TIMInterpreter *_tim;
TimAnimator *_animator;
Common::Error init();
Common::Error go();

View File

@ -5,6 +5,7 @@ MODULE_OBJS := \
animator_v2.o \
animator_hof.o \
animator_mr.o \
animator_tim.o \
debugger.o \
detection.o \
gui.o \

View File

@ -520,7 +520,7 @@ int LoLEngine::olol_initAnimStruct(EMCState *script) {
int LoLEngine::olol_playAnimationPart(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimationPart(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_tim->playAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_animator->playPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
return 1;
}
@ -589,13 +589,13 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) {
int LoLEngine::olol_setupBackgroundAnimationPart(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setupBackgroundAnimationPart(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
_tim->setupBackgroundAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
_animator->setupPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
return 0;
}
int LoLEngine::olol_startBackgroundAnimation(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_startBackgroundAnimation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_tim->startBackgroundAnimation(stackPos(0), stackPos(1));
_animator->start(stackPos(0), stackPos(1));
return 1;
}
@ -625,7 +625,7 @@ int LoLEngine::olol_loadBitmap(EMCState *script) {
int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopBackgroundAnimation(%p) (%d)", (const void *)script, stackPos(0));
_tim->stopBackgroundAnimation(stackPos(0));
_animator->stop(stackPos(0));
return 1;
}
@ -1978,7 +1978,7 @@ int LoLEngine::olol_removeInventoryItem(EMCState *script) {
int LoLEngine::olol_getAnimationLastPart(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getAnimationLastPart(%p) (%d)", (const void *)script, stackPos(0));
return _tim->resetAnimationLastPart(stackPos(0));
return _animator->resetLastPart(stackPos(0));
}
int LoLEngine::olol_assignSpecialGuiShape(EMCState *script) {
@ -2393,7 +2393,7 @@ int LoLEngine::tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_processWsaFrame(%p, %p) (%d, %d, %d, %d, %d)",
(const void *)tim, (const void *)param, param[0], param[1], param[2], param[3], param[4]);
TIMInterpreter::Animation *anim = (TIMInterpreter::Animation *)tim->wsa[param[0]].anim;
TimAnimator::Animation *anim = (TimAnimator::Animation *) tim->wsa[param[0]].anim;
const int frame = param[1];
const int x2 = param[2];
const int y2 = param[3];
@ -2576,13 +2576,13 @@ int LoLEngine::tlol_playSoundEffect(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_startBackgroundAnimation(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_startBackgroundAnimation(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]);
_tim->startBackgroundAnimation(param[0], param[1]);
_animator->start(param[0], param[1]);
return 1;
}
int LoLEngine::tlol_stopBackgroundAnimation(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_stopBackgroundAnimation(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]);
_tim->stopBackgroundAnimation(param[0]);
_animator->stop(param[0]);
return 1;
}
@ -2665,7 +2665,7 @@ int LoLEngine::tlol_fadeOutSound(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_displayAnimFrame(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]);
TIMInterpreter::Animation *anim = (TIMInterpreter::Animation *)tim->wsa[param[0]].anim;
TimAnimator::Animation *anim = (TimAnimator::Animation *)tim->wsa[param[0]].anim;
if (param[1] == 0xFFFF) {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK);
} else {

View File

@ -91,9 +91,6 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys
_commands = commandProcs;
_commandsSize = ARRAYSIZE(commandProcs);
_animations = new Animation[TIM::kWSASlots];
memset(_animations, 0, TIM::kWSASlots * sizeof(Animation));
_langData = 0;
_textDisplayed = false;
_textAreaBuffer = new uint8[320*40];
@ -103,6 +100,8 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys
else
_drawPage2 = 8;
_animator = new TimAnimator(0, 0, 0, false);
_palDelayInc = _palDiff = _palDelayAcc = 0;
_abortFlag = 0;
_tim = 0;
@ -111,13 +110,7 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys
TIMInterpreter::~TIMInterpreter() {
delete[] _langData;
delete[] _textAreaBuffer;
for (int i = 0; i < TIM::kWSASlots; i++) {
delete _animations[i].wsa;
delete[] _animations[i].parts;
}
delete[] _animations;
delete _animator;
}
bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
@ -472,11 +465,9 @@ void TIMInterpreter::setupTextPalette(uint index, int fadePalette) {
}
}
TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags) {
Animation *anim = &_animations[index];
anim->x = x;
anim->y = y;
anim->wsaCopyParams = wsaFlags;
TimAnimator::Animation *TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags) {
Movie *wsa = 0;
const bool isLoLDemo = _vm->gameFlags().isDemo && _vm->gameFlags().gameID == GI_LOL;
if (isLoLDemo || _vm->gameFlags().platform == Common::kPlatformPC98 || _currentTim->isLoLOutro)
@ -502,34 +493,34 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
if (_vm->resource()->exists(file)) {
if (isLoLDemo)
anim->wsa = new WSAMovie_v1(_vm);
wsa = new WSAMovie_v1(_vm);
else
anim->wsa = new WSAMovie_v2(_vm);
assert(anim->wsa);
wsa = new WSAMovie_v2(_vm);
assert(wsa);
anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0);
wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0);
}
if (anim->wsa && anim->wsa->opened()) {
if (wsa && wsa->opened()) {
if (isLoLDemo) {
if (x == -1) {
int16 t = int8(320 - anim->wsa->width());
int16 t = int8(320 - wsa->width());
uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8);
v >>= 1;
anim->x = x = v;
x = v;
}
if (y == -1) {
int16 t = int8(200 - anim->wsa->height());
int16 t = int8(200 - wsa->height());
uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8);
v >>= 1;
anim->y = y = v;
y = v;
}
} else {
if (x == -1)
anim->x = x = 0;
x = 0;
if (y == -1)
anim->y = y = 0;
y = 0;
}
if (wsaFlags & 2) {
@ -551,7 +542,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
_screen->updateScreen();
}
anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
wsa->displayFrame(0, 0, x, y, 0, 0, 0);
}
if (wsaFlags & 2)
@ -579,16 +570,13 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
_screen->fadePalette(_screen->getPalette(0), 30, 0);
}
return anim;
_animator->init(index, wsa, x, y, wsaFlags, 0);
return _animator->getAnimPtr(index);
}
int TIMInterpreter::freeAnimStruct(int index) {
Animation *anim = &_animations[index];
if (!anim)
return 0;
delete anim->wsa;
memset(anim, 0, sizeof(Animation));
_animator->reset(index, true);
return 1;
}
@ -666,26 +654,13 @@ int TIMInterpreter::cmd_uninitWSA(const uint16 *param) {
if (!slot.anim)
return 0;
Animation &anim = _animations[index];
if (slot.offscreen) {
delete anim.wsa;
anim.wsa = 0;
_animator->reset(index, false);
slot.anim = 0;
} else {
//XXX
delete anim.wsa;
bool hasParts = anim.parts ? true : false;
delete[] anim.parts;
memset(&anim, 0, sizeof(Animation));
_animator->reset(index, true);
memset(&slot, 0, sizeof(TIM::WSASlot));
if (hasParts) {
anim.parts = new AnimPart[TIM::kAnimParts];
memset(anim.parts, 0, TIM::kAnimParts * sizeof(AnimPart));
}
}
return 1;
@ -709,14 +684,7 @@ int TIMInterpreter::cmd_stopFunc(const uint16 *param) {
}
int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) {
Animation &anim = _animations[param[0]];
const int frame = param[1];
int page = (anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2;
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
if (anim.wsa)
anim.wsa->displayFrame(frame, page, anim.x, anim.y, anim.wsaCopyParams & 0xF0FF, 0, 0);
if (!page)
_screen->updateScreen();
_animator->displayFrame(param[0], _drawPage2, param[1]);
return 1;
}
@ -944,10 +912,7 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2,
_screen = engine->_screen;
for (int i = 0; i < TIM::kWSASlots; i++) {
_animations[i].parts = new AnimPart[TIM::kAnimParts];
memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart));
}
_animator = new TimAnimator(engine, screen_v2, system, true);
_drawPage2 = 0;
@ -955,15 +920,8 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2,
_dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0;
}
TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) {
Animation *anim = &_animations[index];
anim->x = x;
anim->y = y;
anim->frameDelay = frameDelay;
anim->wsaCopyParams = wsaFlags;
anim->enable = 0;
anim->lastPart = -1;
TimAnimator::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) {
Movie *wsa = 0;
uint16 wsaOpenFlags = 0;
if (wsaFlags & 0x10)
wsaOpenFlags |= 2;
@ -974,9 +932,9 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
snprintf(file, 32, "%s.WSA", filename);
if (_vm->resource()->exists(file)) {
anim->wsa = new WSAMovie_v2(_vm);
assert(anim->wsa);
anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3));
wsa = new WSAMovie_v2(_vm);
assert(wsa);
wsa->open(file, wsaOpenFlags, &_screen->getPalette(3));
}
if (!_vm->_flags.use16ColorMode) {
@ -990,7 +948,7 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
}
if (wsaFlags & 7)
anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
wsa->displayFrame(0, 0, x, y, 0, 0, 0);
if (wsaFlags & 3) {
if (_vm->_flags.use16ColorMode) {
@ -1002,21 +960,13 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
_screen->_fadeFlag = 0;
}
return anim;
_animator->init(index, wsa, x, y, wsaFlags, frameDelay);
return _animator->getAnimPtr(index);
}
int TIMInterpreter_LoL::freeAnimStruct(int index) {
Animation *anim = &_animations[index];
if (!anim)
return 0;
delete anim->wsa;
delete[] anim->parts;
memset(anim, 0, sizeof(Animation));
anim->parts = new AnimPart[TIM::kAnimParts];
memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart));
_animator->reset(index, true);
return 1;
}
@ -1067,120 +1017,6 @@ void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char
_vm->removeInputTop();
}
void TIMInterpreter_LoL::setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {
AnimPart *a = &_animations[animIndex].parts[part];
a->firstFrame = firstFrame;
a->lastFrame = lastFrame;
a->cycles = cycles;
a->nextPart = nextPart;
a->partDelay = partDelay;
a->field_A = f;
a->sfxIndex = sfxIndex;
a->sfxFrame = sfxFrame;
}
void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) {
Animation *anim = &_animations[animIndex];
anim->curPart = part;
AnimPart *p = &anim->parts[part];
anim->enable = 1;
anim->nextFrame = _system->getMillis() + anim->frameDelay * _vm->_tickLength;
anim->curFrame = p->firstFrame;
anim->cyclesCompleted = 0;
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
if (anim->wsa)
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
}
void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) {
Animation *anim = &_animations[animIndex];
anim->enable = 0;
anim->field_D = 0;
if (animIndex == 5) {
delete anim->wsa;
anim->wsa = 0;
}
}
void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) {
Animation *anim = &_animations[animIndex];
if (!anim->enable || anim->nextFrame >= _system->getMillis())
return;
AnimPart *p = &anim->parts[anim->curPart];
anim->nextFrame = 0;
int step = 0;
if (p->lastFrame >= p->firstFrame) {
step = 1;
anim->curFrame++;
} else {
step = -1;
anim->curFrame--;
}
if (anim->curFrame == (p->lastFrame + step)) {
anim->cyclesCompleted++;
if ((anim->cyclesCompleted > p->cycles) || anim->field_D) {
anim->lastPart = anim->curPart;
if ((p->nextPart == -1) || (anim->field_D && p->field_A)) {
anim->enable = 0;
anim->field_D = 0;
return;
}
anim->nextFrame += (p->partDelay * _vm->_tickLength);
anim->curPart = p->nextPart;
p = &anim->parts[anim->curPart];
anim->curFrame = p->firstFrame;
anim->cyclesCompleted = 0;
} else {
anim->curFrame = p->firstFrame;
}
}
if (p->sfxIndex != -1 && p->sfxFrame == anim->curFrame)
_vm->snd_playSoundEffect(p->sfxIndex, -1);
anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
anim->nextFrame += _system->getMillis();
}
void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {
Animation *anim = &_animations[animIndex];
int step = (lastFrame >= firstFrame) ? 1 : -1;
for (int i = firstFrame; i != (lastFrame + step) ; i += step) {
uint32 next = _system->getMillis() + delay * _vm->_tickLength;
if (anim->wsaCopyParams & 0x4000) {
_screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2);
anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_transparencyTable1, _vm->_transparencyTable2);
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
_screen->updateScreen();
} else {
anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0);
_screen->updateScreen();
}
int32 del = (int32)(next - _system->getMillis());
if (del > 0)
_vm->delay(del, true);
}
}
int TIMInterpreter_LoL::resetAnimationLastPart(int animIndex) {
Animation *anim = &_animations[animIndex];
int8 res = -1;
SWAP(res, anim->lastPart);
return res;
}
void TIMInterpreter_LoL::drawDialogueButtons() {
int cp = _screen->setCurPage(0);
Screen::FontId of = _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
@ -1316,10 +1152,7 @@ void TIMInterpreter_LoL::checkSpeechProgress() {
_currentTim->dlgFunc = _currentFunc;
advanceToOpcode(21);
_currentTim->dlgFunc = -1;
_animations[5].field_D = 0;
_animations[5].enable = 0;
delete _animations[5].wsa;
_animations[5].wsa = 0;
_animator->reset(5, false);
}
}
}
@ -1387,10 +1220,7 @@ int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) {
_currentTim->procFunc = -1;
_currentTim->clickedButton = res;
_animations[5].field_D = 0;
_animations[5].enable = 0;
delete _animations[5].wsa;
_animations[5].wsa = 0;
_animator->reset(5, false);
if (_currentTim->procParam)
advanceToOpcode(21);

View File

@ -36,6 +36,63 @@ namespace Kyra {
class WSAMovie_v2;
class Screen_v2;
class LoLEngine;
class TimAnimator {
public:
struct AnimPart {
uint16 firstFrame;
uint16 lastFrame;
uint16 cycles;
int16 nextPart;
int16 partDelay;
uint16 field_A;
int16 sfxIndex;
uint16 sfxFrame;
};
struct Animation {
Movie *wsa;
int16 x, y;
uint32 nextFrame;
uint8 enable;
uint8 field_D;
uint8 frameDelay;
int8 curPart;
uint8 curFrame;
uint8 cyclesCompleted;
uint16 wsaCopyParams;
int8 lastPart;
AnimPart *parts;
};
TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts);
~TimAnimator();
Animation *getAnimPtr(int index) { return (index >= 0 && index < 6) ? &_animations[index] : 0; }
void init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay);
void reset(int animIndex, bool clearStruct);
void displayFrame(int animIndex, int page, int frame);
void setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
void start(int animIndex, int part);
void stop(int animIndex);
void update(int animIndex);
void playPart(int animIndex, int firstFrame, int lastFrame, int delay);
int resetLastPart(int animIndex);
private:
LoLEngine *_vm;
Screen_v2 *_screen;
OSystem *_system;
Animation *_animations;
const bool _useParts;
};
struct TIM;
typedef Common::Functor2<const TIM*, const uint16*, int> TIMOpcode;
@ -89,32 +146,6 @@ struct TIM {
class TIMInterpreter {
public:
struct AnimPart {
uint16 firstFrame;
uint16 lastFrame;
uint16 cycles;
int16 nextPart;
int16 partDelay;
uint16 field_A;
int16 sfxIndex;
uint16 sfxFrame;
};
struct Animation {
Movie *wsa;
int16 x, y;
uint32 nextFrame;
uint8 enable;
uint8 field_D;
uint8 frameDelay;
int8 curPart;
uint8 curFrame;
uint8 cyclesCompleted;
uint16 wsaCopyParams;
int8 lastPart;
AnimPart *parts;
};
TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system);
virtual ~TIMInterpreter();
@ -123,8 +154,9 @@ public:
bool callback(Common::IFFChunk &chunk);
virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
virtual TimAnimator::Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
virtual int freeAnimStruct(int index);
TimAnimator *animator() { return _animator; }
void setLangData(const char *filename);
void clearLangData() { delete[] _langData; _langData = 0; }
@ -146,14 +178,6 @@ public:
virtual void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {}
virtual uint16 processDialogue() { return 1; }
virtual void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {}
virtual void startBackgroundAnimation(int animIndex, int part) {}
virtual void stopBackgroundAnimation(int animIndex) {}
virtual void updateBackgroundAnimation(int animIndex) {}
virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {}
virtual int resetAnimationLastPart(int animIndex) { return -1; }
virtual void resetDialogueState(TIM *tim) {}
int _drawPage2;
@ -169,6 +193,8 @@ protected:
TIM *_currentTim;
int _currentFunc;
TimAnimator *_animator;
bool _finished;
// used when loading
@ -178,8 +204,6 @@ protected:
Common::String _vocFiles[120];
Animation *_animations;
virtual void update() {}
virtual void checkSpeechProgress() {}
@ -233,24 +257,16 @@ protected:
class LoLEngine;
class Screen_LoL;
class TIMInterpreter_LoL : public TIMInterpreter {
friend class LoLEngine;
public:
TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system);
Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams);
TimAnimator::Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams);
int freeAnimStruct(int index);
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
void resetDialogueState(TIM *tim);
void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
void startBackgroundAnimation(int animIndex, int part);
void stopBackgroundAnimation(int animIndex);
void updateBackgroundAnimation(int animIndex);
void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay);
int resetAnimationLastPart(int animIndex);
private:
void update();
void checkSpeechProgress();