From 2e46b741a350716eb674a3ea18938ef23329f43f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 12 Nov 2007 17:56:49 +0000 Subject: - Implemented opcodes: -> o2_removeHandItem 43 -> o2_makeBookOrCauldronAppear 42 - Implemented inventory WSA functionality svn-id: r29485 --- engines/kyra/kyra_v2.cpp | 123 ++++++++++++++++++++++++++++++++++++++++-- engines/kyra/kyra_v2.h | 24 +++++++++ engines/kyra/script_v2.cpp | 12 ++++- engines/kyra/sequences_v2.cpp | 109 +++++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+), 5 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 7e573d69f3..33c3ddc6c0 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -85,6 +85,8 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngi _currentTalkSections.TLKTim = NULL; _currentTalkSections.ENDTim = NULL; + _invWsa.wsa = 0; + memset(&_sceneScriptData, 0, sizeof(_sceneScriptData)); } @@ -96,6 +98,7 @@ KyraEngine_v2::~KyraEngine_v2() { delete _text; _text = 0; delete _debugger; + delete _invWsa.wsa; } Movie *KyraEngine_v2::createWSAMovie() { @@ -492,7 +495,7 @@ void KyraEngine_v2::update() { updateSpecialSceneScripts(); _timer->update(); //sub_274C0(); - //updateInvWsa(); + updateInvWsa(); //sub_1574C(); _screen->updateScreen(); } @@ -505,7 +508,7 @@ void KyraEngine_v2::updateWithText() { updateSpecialSceneScripts(); _timer->update(); //sub_274C0(); - //updateInvWsa(); + updateInvWsa(); restorePage3(); drawAnimObjects(); @@ -1542,6 +1545,118 @@ void KyraEngine_v2::playVoice(int high, int low) { #pragma mark - +void KyraEngine_v2::loadInvWsa(const char *filename, int run, int delayTime, int page, int sfx, int sFrame, int flags) { + int wsaFlags = 1; + if (flags) + wsaFlags |= 2; + + if (!_invWsa.wsa) + _invWsa.wsa = new WSAMovieV2(this); + + if (!_invWsa.wsa->open(filename, wsaFlags, 0)) + error("Couldn't open inventory WSA file '%s'", filename); + + _invWsa.curFrame = 0; + _invWsa.lastFrame = _invWsa.wsa->frames(); + + _invWsa.x = _invWsa.wsa->xAdd(); + _invWsa.y = _invWsa.wsa->yAdd(); + _invWsa.w = _invWsa.wsa->width(); + _invWsa.h = _invWsa.wsa->height(); + _invWsa.x2 = _invWsa.x + _invWsa.w - 1; + _invWsa.y2 = _invWsa.y + _invWsa.h - 1; + + _invWsa.delay = delayTime; + _invWsa.page = page; + _invWsa.sfx = sfx; + + _invWsa.specialFrame = sFrame; + + if (_invWsa.page) + _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, 0, _invWsa.page, Screen::CR_NO_P_CHECK); + + _invWsa.running = true; + _invWsa.timer = _system->getMillis(); + + if (run) { + while (_invWsa.running && !_skipFlag && !_quitFlag) { + update(); + //XXX delay? + } + } +} + +void KyraEngine_v2::closeInvWsa() { + _invWsa.wsa->close(); + delete _invWsa.wsa; + _invWsa.wsa = 0; + _invWsa.running = false; +} + +void KyraEngine_v2::updateInvWsa() { + if (!_invWsa.running || !_invWsa.wsa) + return; + + if (_invWsa.timer > _system->getMillis()) + return; + + _invWsa.wsa->setX(0); + _invWsa.wsa->setY(0); + _invWsa.wsa->setDrawPage(_invWsa.page); + _invWsa.wsa->displayFrame(_invWsa.curFrame, 0, 0, 0); + + if (_invWsa.page) + _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); + + _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength; + + ++_invWsa.curFrame; + if (_invWsa.curFrame >= _invWsa.lastFrame) + displayInvWsaLastFrame(); + + if (_invWsa.curFrame == _invWsa.specialFrame) + snd_playSoundEffect(_invWsa.sfx); + + if (_invWsa.sfx == -2) { + switch (_invWsa.curFrame) { + case 9: case 27: case 40: + snd_playSoundEffect(0x39); + break; + + case 18: case 34: case 44: + snd_playSoundEffect(0x33); + break; + + case 48: + snd_playSoundEffect(0x38); + break; + + default: + break; + } + } +} + +void KyraEngine_v2::displayInvWsaLastFrame() { + if (!_invWsa.wsa) + return; + + _invWsa.wsa->setX(0); + _invWsa.wsa->setY(0); + _invWsa.wsa->setDrawPage(_invWsa.page); + _invWsa.wsa->displayFrame(_invWsa.lastFrame-1, 0, 0, 0); + + if (_invWsa.page) + _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); + + closeInvWsa(); + + int32 countdown = _rnd.getRandomNumberRng(45, 80); + _timer->setCountdown(2, countdown * 60); +} + +#pragma mark - + typedef Functor1Mem OpcodeV2; #define Opcode(x) OpcodeV2(this, &KyraEngine_v2::x) #define OpcodeUnImpl() OpcodeV2(this, 0) @@ -1601,7 +1716,7 @@ void KyraEngine_v2::setupOpcodeTable() { Opcode(o2_resetGameFlag), Opcode(o2_setGameFlag), Opcode(o2_setHandItem), - OpcodeUnImpl(), + Opcode(o2_removeHandItem), // 0x2c Opcode(o2_handItemSet), Opcode(o2_hideMouse), @@ -1725,7 +1840,7 @@ void KyraEngine_v2::setupOpcodeTable() { // 0x8c Opcode(o2_deinitObject), OpcodeUnImpl(), - OpcodeUnImpl(), + Opcode(o2_makeBookOrCauldronAppear), Opcode(o2_setSpecialSceneScriptState), // 0x90 Opcode(o2_clearSpecialSceneScriptState), diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 008c508050..bdefcc6f1e 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -693,6 +693,28 @@ protected: byte* loadTIMFile(const char *filename, byte *buffer, int32 bufferSize); void freeTIM(byte *buffer); + // ingame static sequence handling + void seq_makeBookOrCauldronAppear(int type); + void seq_makeBookAppear(); + + struct InventoryWsa { + int x, y, x2, y2, w, h; + int page; + int curFrame, lastFrame, specialFrame; + int sfx; + int delay; + bool running; + uint32 timer; + WSAMovieV2 *wsa; + } _invWsa; + + // TODO: move inside KyraEngine_v2::InventoryWsa? + void loadInvWsa(const char *filename, int run, int delay, int page, int sfx, int sFrame, int flags); + void closeInvWsa(); + + void updateInvWsa(); + void displayInvWsaLastFrame(); + // opcodes int o2_setCharacterFacingRefresh(ScriptState *script); int o2_setCharacterPos(ScriptState *script); @@ -716,6 +738,7 @@ protected: int o2_resetGameFlag(ScriptState *script); int o2_setGameFlag(ScriptState *script); int o2_setHandItem(ScriptState *script); + int o2_removeHandItem(ScriptState *script); int o2_handItemSet(ScriptState *script); int o2_hideMouse(ScriptState *script); int o2_addSpecialExit(ScriptState *script); @@ -750,6 +773,7 @@ protected: int o2_countItemInstances(ScriptState *script); int o2_initObject(ScriptState *script); int o2_deinitObject(ScriptState *script); + int o2_makeBookOrCauldronAppear(ScriptState *script); int o2_setSpecialSceneScriptState(ScriptState *script); int o2_clearSpecialSceneScriptState(ScriptState *script); int o2_querySpecialSceneScriptState(ScriptState *script); diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp index f984dbb66b..e3bdfe198a 100644 --- a/engines/kyra/script_v2.cpp +++ b/engines/kyra/script_v2.cpp @@ -305,6 +305,12 @@ int KyraEngine_v2::o2_setHandItem(ScriptState *script) { return 0; } +int KyraEngine_v2::o2_removeHandItem(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_removeHandItem(%p) ()", (const void *)script); + removeHandItem(); + return 0; +} + int KyraEngine_v2::o2_handItemSet(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "o2_handItemSet(%p) ()", (const void *)script); return _handItemSet; @@ -670,14 +676,18 @@ int KyraEngine_v2::o2_countItemInstances(ScriptState *script) { int KyraEngine_v2::o2_initObject(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "o2_initObject(%p) (%d)", (const void *)script, stackPos(0)); initTalkObject(stackPos(0)); - return 0; } int KyraEngine_v2::o2_deinitObject(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "o2_deinitObject(%p) (%d)", (const void *)script, stackPos(0)); deinitTalkObject(stackPos(0)); + return 0; +} +int KyraEngine_v2::o2_makeBookOrCauldronAppear(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_makeBookOrCauldronAppear(%p) (%d)", (const void *)script, stackPos(0)); + seq_makeBookOrCauldronAppear(stackPos(0)); return 0; } diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp index 206342e2e8..f6f92eb169 100644 --- a/engines/kyra/sequences_v2.cpp +++ b/engines/kyra/sequences_v2.cpp @@ -29,6 +29,7 @@ #include "kyra/wsamovie.h" #include "kyra/sound.h" #include "kyra/text_v2.h" +#include "kyra/timer.h" #include "common/system.h" @@ -2173,6 +2174,114 @@ void KyraEngine_v2::seq_uninit() { _seqWsa = NULL; } +#pragma mark - +#pragma mark - Ingame sequences +#pragma mark - + +void KyraEngine_v2::seq_makeBookOrCauldronAppear(int type) { + _screen->hideMouse(); + showMessage(0, 0xCF); + + if (type == 1) { + seq_makeBookAppear(); + } else if (type == 2) { + loadInvWsa("CAULDRON.WSA", 1, 6, 0, -2, -2, 1); + } + + _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _screenBuffer); + _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0); + + static int16 bookCauldronRects[] = { + 0x46, 0x90, 0x7F, 0x2B, // unknown rect (maybe unused?) + 0xCE, 0x90, 0x2C, 0x2C, // book rect + 0xFA, 0x90, 0x46, 0x2C // cauldron rect + }; + + int x = bookCauldronRects[type*4+0]; + int y = bookCauldronRects[type*4+1]; + int w = bookCauldronRects[type*4+2]; + int h = bookCauldronRects[type*4+3]; + _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK); + + _screen->copyBlockToPage(2, 0, 0, 320, 200, _screenBuffer); + + if (type == 2) { + int32 countdown = _rnd.getRandomNumberRng(45, 80); + _timer->setCountdown(2, countdown * 60); + } + + _screen->showMouse(); +} + +void KyraEngine_v2::seq_makeBookAppear() { + _screen->hideMouse(); + + displayInvWsaLastFrame(); + + showMessage(0, 0xCF); + + loadInvWsa("BOOK2.WSA", 0, 4, 2, -1, -1, 0); + + uint8 *rect = new uint8[_screen->getRectSize(_invWsa.w, _invWsa.h)]; + assert(rect); + + _screen->copyRegionToBuffer(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); + + _invWsa.running = false; + snd_playSoundEffect(0xAF); + + _invWsa.wsa->setX(0); + _invWsa.wsa->setY(0); + _invWsa.wsa->setDrawPage(_invWsa.page); + + while (true) { + _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength; + + _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); + + _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0); + + if (_invWsa.page) + _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); + + ++_invWsa.curFrame; + + if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag) + break; + + switch (_invWsa.curFrame) { + case 39: + snd_playSoundEffect(0xCA); + break; + + case 50: + snd_playSoundEffect(0x6A); + break; + + case 72: + snd_playSoundEffect(0xCB); + break; + + case 85: + snd_playSoundEffect(0x38); + break; + + default: + break; + } + + do { + update(); + } while (_invWsa.timer > _system->getMillis() && !_skipFlag); + } + + closeInvWsa(); + delete [] rect; + _invWsa.running = false; + + _screen->showMouse(); +} + // static res // TODO: move to staticres.cpp -- cgit v1.2.3