From bee8be58e38c3adadba0a258e84473d360fc2656 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 15 May 2009 06:29:08 +0000 Subject: LOL: implemented pit drop animation svn-id: r40592 --- engines/kyra/lol.cpp | 8 ++-- engines/kyra/lol.h | 4 ++ engines/kyra/scene_lol.cpp | 70 +++++++++++++++++++++++++++++ engines/kyra/screen_lol.cpp | 102 ++++++++++++++++++++++++++++++++++++++++--- engines/kyra/screen_lol.h | 4 +- engines/kyra/script_lol.cpp | 44 ++++++++++++++++--- engines/kyra/sound_towns.cpp | 13 +++--- engines/kyra/sprites_lol.cpp | 2 +- 8 files changed, 222 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index f29499d67e..950dee57ae 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -1795,6 +1795,8 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { return; _lastSfxTrack = track; + if (track == -1) + return; int16 volIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); @@ -2133,7 +2135,7 @@ int LoLEngine::castSpell(int charNum, int spellType, int spellLevel) { if (_activeSpell.p->hpRequired[spellLevel] >= _characters[charNum].hitPointsCur) return 0; - //setCharacterMagicOrHitPoints(charNum, 1, -_activeSpell.p->mpRequired[spellLevel], 1); + setCharacterMagicOrHitPoints(charNum, 1, -_activeSpell.p->mpRequired[spellLevel], 1); setCharacterMagicOrHitPoints(charNum, 0, -_activeSpell.p[1].hpRequired[spellLevel], 1); gui_drawCharPortraitWithStats(charNum); @@ -3178,10 +3180,6 @@ void LoLEngine::level11specialUnk() { } -void LoLEngine::distObj1Sub(int a, int b, int c, int d) { - -} - void LoLEngine::launchMagicViper() { } diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index a842c573ef..c4d849ca6e 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -694,6 +694,7 @@ private: int olol_enableSysTimer(EMCState *script); int olol_checkNeedSceneRestore(EMCState *script); int olol_castSpell(EMCState *script); + int olol_pitDrop(EMCState *script); int olol_paletteFlash(EMCState *script); int olol_disableControls(EMCState *script); int olol_enableControls(EMCState *script); @@ -927,6 +928,9 @@ private: void movePartySmoothScrollTurnLeft(int speed); void movePartySmoothScrollTurnRight(int speed); + void pitDropScroll(int numSteps); + void shakeScene(int duration, int width, int height, int restore); + int smoothScrollDrawSpecialShape(int pageNum); OpenDoorState _openDoorState[3]; diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 38227cfae5..a92f3f8240 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -1228,6 +1228,76 @@ void LoLEngine::movePartySmoothScrollTurnRight(int speed) { } } +void LoLEngine::pitDropScroll(int numSteps) { + _screen->copyRegionSpecial(0, 320, 200, 112, 0, 6, 176, 120, 0, 0, 176, 120, 0); + uint32 ctime = 0; + int del = 0; + + for (int i = 0; i < numSteps; i++) { + ctime = _system->getMillis(); + int ys = ((30720 / numSteps) * i) >> 8; + _screen->copyRegionSpecial(6, 176, 120, 0, ys, 0, 320, 200, 112, 0, 176, 120 - ys, 0); + _screen->copyRegionSpecial(2, 320, 200, 112, 0, 0, 320, 200, 112, 120 - ys, 176, ys, 0); + _screen->updateScreen(); + + del = _tickLength - (_system->getMillis() - ctime); + if (del > 0) + delay(del, false, true); + } + + _screen->copyRegionSpecial(2, 320, 200, 112, 0, 0, 320, 200, 112, 0, 176, 120, 0); + _screen->updateScreen(); + + del = _tickLength - (_system->getMillis() - ctime); + if (del > 0) + delay(del, false, true); + updateDrawPage2(); +} + +void LoLEngine::shakeScene(int duration, int width, int height, int restore) { + _screen->copyRegion(112, 0, 112, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK); + uint32 endTime = _system->getMillis() + duration * _tickLength; + + while (endTime > _system->getMillis()) { + _smoothScrollTimer = _system->getMillis() + 2 * _tickLength; + + int s1 = width ? (getRandomNumberSpecial() % (width << 1)) - width : 0; + int s2 = height ? (getRandomNumberSpecial() % (height << 1)) - height : 0; + + int x1, y1, x2, y2, w, h; + if (s1 >= 0) { + x1 = 112; + x2 = 112; + w = 176 - s1; + } else { + x1 = 112 - s1; + x2 = 112 + s1; + w = 176 + s1; + } + + if (s2 >= 0) { + y1 = 0; + y2 = 0; + h = 120 - s2; + } else { + y1 = -s2; + y2 = s2; + h = 120 + s2; + } + + _screen->copyRegion(x1, y1, x2, y2, w, h, 6, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + delayUntil(_smoothScrollTimer); + } + + if (restore) { + _screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + updateDrawPage2(); + } +} + int LoLEngine::smoothScrollDrawSpecialShape(int pageNum) { // TODO if(!_scriptAssignedLevelShape) diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 81bad0522d..47d526f915 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -528,6 +528,96 @@ void Screen_LoL::smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dst } } +void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, int page2, int w2, int h2, int x2, int y2, int w3, int h3, int mode, ...) { + if (!w3 || !h3) + return; + + uint8 *table1 = 0; + uint8 *table2 = 0; + + if (mode == 2) { + va_list args; + va_start(args, mode); + table1 = va_arg(args, uint8*); + table2 = va_arg(args, uint8*); + va_end(args); + } + + _internDimX = _internDimY = 0; + _internDimW = w1; + _internDimH = h1; + calcBoundariesIntern(x1, y1, w3, h3); + if (_internBlockWidth == -1) + return; + + int iu5_1 = _internDimU5; + int iu6_1 = _internDimU6; + int ibw_1 = _internBlockWidth; + int ibh_1 = _internBlockHeight; + int dx_1 = _internDimDstX; + int dy_1 = _internDimDstY; + + _internDimX = _internDimY = 0; + _internDimW = w2; + _internDimH = h2; + + calcBoundariesIntern(x2, y2, ibw_1, ibh_1); + if (_internBlockWidth == -1) + return; + + int iu5_2 = _internDimU5; + int iu6_2 = _internDimU6; + int ibw_2 = _internBlockWidth; + int ibh_2 = _internBlockHeight; + int dx_2 = _internDimDstX; + int dy_2 = _internDimDstY; + + uint8 *src = getPagePtr(page1) + (dy_1 + iu6_2) * w1; + uint8 *dst = getPagePtr(page2) + (dy_2 + iu6_1) * w2; + + for (int i = 0; i < ibh_2; i++) { + uint8 *s = src + iu5_2 + dx_1; + uint8 *d = dst + iu5_1 + dx_2; + + if (mode == 0) { + memcpy(d, s, ibw_2); + + } else if (mode == 1) { + if (!(i & 1)) { + s++; + d++; + } + + for (int ii = (i & 1) ^ 1; ii < ibw_2; ii += 2 ) { + *d = *s; + d += 2; + s += 2; + } + + } else if (mode == 2) { + for (int ii = 0; ii < ibw_2; ii++) { + uint8 cmd = *s++; + uint8 offs = table1[cmd]; + if (!(offs & 0x80)) + cmd = table2[(offs << 8) | *d]; + *d++ = cmd; + } + + } else if (mode == 3) { + s = s - iu5_2 + ibw_1; + s = s - iu5_2 - 1; + for (int ii = 0; ii < ibw_2; ii++) + *d++ = *s--; + } + + dst += w2; + src += w1; + } + + if (!page2) + addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); +} + void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) { if (!w || !h || !ovl) return; @@ -538,7 +628,7 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, _internDimW = cdim->w << 3; _internDimH = cdim->h; - calcMapBoundaries(x2, y2, w, h); + calcBoundariesIntern(x2, y2, w, h); if (_internBlockWidth == -1) return; @@ -560,7 +650,8 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, src += 320; } - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + if (!page2) + addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); } void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) { @@ -573,7 +664,7 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x _internDimW = cdim->w << 3; _internDimH = cdim->h; - calcMapBoundaries(x2, y2, w, h); + calcBoundariesIntern(x2, y2, w, h); if (_internBlockWidth == -1) return; @@ -597,10 +688,11 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x src += 320; } - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + if (!page2) + addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); } -void Screen_LoL::calcMapBoundaries(int dstX, int dstY, int width, int height) { +void Screen_LoL::calcBoundariesIntern(int dstX, int dstY, int width, int height) { _internBlockWidth = _internBlockWidth2 = width; _internBlockHeight = height; _internDimDstX = dstX; diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index e839f31752..2f230d79a6 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -62,6 +62,8 @@ public: void smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dstPageNum); void smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dstPageNum); + void copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, int page2, int w2, int h2, int x2, int y2, int w3, int h3, int mode, ...); + // palette stuff void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); void fadeToPalette1(int delay); @@ -99,7 +101,7 @@ private: uint8 *_levelOverlays[8]; // magic atlas - void calcMapBoundaries(int dstX, int dstY, int c, int d); + void calcBoundariesIntern(int dstX, int dstY, int c, int d); int _internDimX; int _internDimY; diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 8a44e3c0d3..41dc2b8ef0 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -1663,6 +1663,39 @@ int LoLEngine::olol_castSpell(EMCState *script) { return castSpell(stackPos(0), stackPos(1), stackPos(2)); } +int LoLEngine::olol_pitDrop(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_pitDrop(%p) (%d)", (const void *)script, stackPos(0)); + int m = stackPos(0); + _screen->updateScreen(); + if (m) { + gui_drawScene(2); + pitDropScroll(9); + snd_playSoundEffect(-1, -1); + shakeScene(30, 4, 0, 1); + + } else { + int t = -1; + for (int i = 0; i < 4; i++) { + if (!(_characters[i].flags & 1) || (_characters[i].id >= 0)) + continue; + if (_characters[i].id == -1) + t = 54; + else if (_characters[i].id == -5) + t = 53; + else if (_characters[i].id == -8) + t = 52; + else if (_characters[i].id == -9) + t = 51; + } + + _screen->fillRect(112, 0, 288, 120, 0, 2); + snd_playSoundEffect(t, -1); + pitDropScroll(12); + } + + return 1; +} + int LoLEngine::olol_paletteFlash(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_paletteFlash(%p) (%d)", (const void *)script, stackPos(0)); uint8 *s = _screen->getPalette(1); @@ -1686,13 +1719,10 @@ int LoLEngine::olol_paletteFlash(EMCState *script) { delay(2 * _tickLength); _screen->setScreenPalette(s); - _screen->updateScreen(); - - if (_smoothScrollModeNormal) { + if (_smoothScrollModeNormal) _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); - _screen->updateScreen(); - } - + + _screen->updateScreen(); return 0; } @@ -2247,7 +2277,7 @@ void LoLEngine::setupOpcodeTable() { // 0xAC OpcodeUnImpl(); Opcode(olol_castSpell); - OpcodeUnImpl(); + Opcode(olol_pitDrop); OpcodeUnImpl(); // 0xB0 diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index de81b667f4..9f15d94518 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1485,7 +1485,7 @@ private: class TownsPC98_OpnSquareSineSource { public: - TownsPC98_OpnSquareSineSource(const uint32 timerbase); + TownsPC98_OpnSquareSineSource(const uint32 timerbase, const uint8 levelOutModifier); ~TownsPC98_OpnSquareSineSource(); void init(const int *rsTable, const int *rseTable); @@ -1516,6 +1516,7 @@ private: int32 *_tleTable; const uint32 _tickLength; + const uint8 _levelOutModifier; uint32 _timer; struct Channel { @@ -2553,8 +2554,8 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { } } -TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0), - _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1), +TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase, const uint8 levelOutModifier) : _tlTable(0), + _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _levelOutModifier(levelOutModifier), _ready(0), _reg(0), _rand(1), _outN(1), _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true), _timer(0), _noiseGenerator(0), _chanEnable(0) { @@ -2714,7 +2715,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; } - finOut >>= 1; + finOut >>= _levelOutModifier; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } @@ -2887,7 +2888,7 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut += _rhChan[ii].out; } - finOut <<= 2; + finOut <<= 1; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; @@ -2968,7 +2969,7 @@ bool TownsPC98_OpnCore::init() { } if (_numSSG) { - _ssg = new TownsPC98_OpnSquareSineSource(_timerbase); + _ssg = new TownsPC98_OpnSquareSineSource(_timerbase, _numChan / 3); _ssg->init(&_ssgTables[0], &_ssgTables[16]); } diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index f9890ea9b1..06e974963a 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -1255,7 +1255,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) { if (flyingObject == 1) { snd_playSoundEffect(147, -1); - distObj1Sub(10, 2, 2, 1); + shakeScene(10, 2, 2, 1); for (int i = 0; i < 4; i++) { if (!(_characters[i].flags & 1)) -- cgit v1.2.3