aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
authorFlorian Kagerer2009-05-10 13:40:28 +0000
committerFlorian Kagerer2009-05-10 13:40:28 +0000
commitdd84aaf648b57220180b84a9aa0825d16bcea5bc (patch)
tree2be68b4e4892d1a4d19509a46ebe64206e83e3f4 /engines/kyra
parent3592801a5707f42c71971321b26e2cc1da775c25 (diff)
downloadscummvm-rg350-dd84aaf648b57220180b84a9aa0825d16bcea5bc.tar.gz
scummvm-rg350-dd84aaf648b57220180b84a9aa0825d16bcea5bc.tar.bz2
scummvm-rg350-dd84aaf648b57220180b84a9aa0825d16bcea5bc.zip
LOL: - added some spell casting (spark, heal, swarm)
- fixed several bugs (not the one in the fighting system though) - added several opcodes. there shouldn't be any real show stoppers in the draracle cave now. - simplified wsa code (which required 4 lines of code for displaying a frame) - added support for wsa animations that don't have a last frame (apparently kyra 2 and 3 don't have this type of wsa file) svn-id: r40420
Diffstat (limited to 'engines/kyra')
-rw-r--r--engines/kyra/animator_hof.cpp5
-rw-r--r--engines/kyra/animator_mr.cpp5
-rw-r--r--engines/kyra/gui.cpp2
-rw-r--r--engines/kyra/gui_hof.cpp6
-rw-r--r--engines/kyra/gui_lok.cpp2
-rw-r--r--engines/kyra/gui_lol.cpp83
-rw-r--r--engines/kyra/gui_mr.cpp68
-rw-r--r--engines/kyra/items_lol.cpp13
-rw-r--r--engines/kyra/kyra_hof.cpp10
-rw-r--r--engines/kyra/kyra_mr.cpp7
-rw-r--r--engines/kyra/lol.cpp636
-rw-r--r--engines/kyra/lol.h98
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/scene_lol.cpp18
-rw-r--r--engines/kyra/screen_lol.cpp54
-rw-r--r--engines/kyra/screen_lol.h9
-rw-r--r--engines/kyra/screen_v2.cpp4
-rw-r--r--engines/kyra/screen_v2.h2
-rw-r--r--engines/kyra/script_hof.cpp25
-rw-r--r--engines/kyra/script_lok.cpp35
-rw-r--r--engines/kyra/script_lol.cpp230
-rw-r--r--engines/kyra/script_tim.cpp52
-rw-r--r--engines/kyra/seqplayer.cpp9
-rw-r--r--engines/kyra/sequences_hof.cpp75
-rw-r--r--engines/kyra/sequences_lok.cpp46
-rw-r--r--engines/kyra/sequences_lol.cpp56
-rw-r--r--engines/kyra/sound.cpp7
-rw-r--r--engines/kyra/sound.h7
-rw-r--r--engines/kyra/sound_towns.cpp6
-rw-r--r--engines/kyra/sprites_lol.cpp24
-rw-r--r--engines/kyra/staticres.cpp44
-rw-r--r--engines/kyra/text_lol.cpp32
-rw-r--r--engines/kyra/text_lol.h6
-rw-r--r--engines/kyra/text_mr.cpp6
-rw-r--r--engines/kyra/timer_lol.cpp4
-rw-r--r--engines/kyra/wsamovie.cpp38
-rw-r--r--engines/kyra/wsamovie.h14
37 files changed, 1236 insertions, 504 deletions
diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp
index 5cc44f1b38..410bbaafa9 100644
--- a/engines/kyra/animator_hof.cpp
+++ b/engines/kyra/animator_hof.cpp
@@ -298,10 +298,7 @@ void KyraEngine_HoF::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer)
y = obj->yPos2;
}
- _sceneAnimMovie[obj->animNum]->setX(x);
- _sceneAnimMovie[obj->animNum]->setY(y);
- _sceneAnimMovie[obj->animNum]->setDrawPage(2);
- _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, int(flags | layer), 0, 0);
+ _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, int(flags | layer), 0, 0);
}
}
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
index 5a26f9bcfd..20c84ced11 100644
--- a/engines/kyra/animator_mr.cpp
+++ b/engines/kyra/animator_mr.cpp
@@ -125,10 +125,7 @@ void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
flags |= 0x8000;
x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd();
y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd();
- _sceneAnimMovie[obj->animNum]->setDrawPage(2);
- _sceneAnimMovie[obj->animNum]->setX(x);
- _sceneAnimMovie[obj->animNum]->setY(y);
- _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, flags | layer);
+ _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer);
}
}
}
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index 259cf88965..28d5bbd11d 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -404,7 +404,7 @@ void MainMenu::updateAnimation() {
if (now > _nextUpdate) {
_nextUpdate = now + _anim.delay * _vm->tickLength();
- _anim.anim->displayFrame(_animIntern.curFrame, 0);
+ _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0);
_animIntern.curFrame += _animIntern.direction ;
if (_animIntern.curFrame < _anim.startFrame) {
_animIntern.curFrame = _anim.startFrame;
diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp
index 7930dbf2a0..4d2046c35d 100644
--- a/engines/kyra/gui_hof.cpp
+++ b/engines/kyra/gui_hof.cpp
@@ -284,15 +284,11 @@ void KyraEngine_HoF::scrollInventoryWheel() {
_screen->showMouse();
snd_playSoundEffect(0x25);
- movie.setDrawPage(0);
- movie.setX(0);
- movie.setY(0);
-
bool breakFlag = false;
for (int i = 0; i <= 6 && !breakFlag; ++i) {
if (movie.opened()) {
_screen->hideMouse();
- movie.displayFrame(i % frames, 0, 0);
+ movie.displayFrame(i % frames, 0, 0, 0, 0);
_screen->showMouse();
_screen->updateScreen();
}
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index baf39c0954..3f289784f3 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -962,7 +962,7 @@ int GUI_LoK::controlsChangeMusic(Button *button) {
debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeMusic()");
updateMenuButton(button);
- _vm->_configMusic = ++_vm->_configMusic % (_vm->gameFlags().platform == Common::kPlatformFMTowns ? 3 : 2);
+ _vm->_configMusic = ++_vm->_configMusic % ((_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 3 : 2);
setupControls(_menu[5]);
return 0;
}
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index ade70c8a85..e8a9526793 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -124,8 +124,15 @@ void LoLEngine::gui_drawScroll() {
}
}
-void LoLEngine::gui_highlightSelectedSpell(int unk) {
-
+void LoLEngine::gui_highlightSelectedSpell(bool mode) {
+ int y = 15;
+ for (int i = 0; i < 7; i++) {
+ if (_availableSpells[i] == -1)
+ continue;
+ uint8 col = (mode && (i == _selectedSpell)) ? 132 : 1;
+ _screen->fprintString(getLangString(_spellProperties[_availableSpells[i]].spellNameCode), 24, y, col, 0, 0);
+ y += 9;
+ }
}
void LoLEngine::gui_displayCharInventory(int charNum) {
@@ -160,8 +167,8 @@ void LoLEngine::gui_displayCharInventory(int charNum) {
_screen->fprintString(getLangString(0x4033), 182, 103, 172, 0, 5);
static const uint16 skillFlags[] = { 0x0080, 0x0000, 0x1000, 0x0002, 0x100, 0x0001, 0x0000, 0x0000 };
- uint16 tmp[6];
- memset(tmp, -1, 6);
+
+ memset(_invSkillFlags, -1, 6);
int x = 0;
int32 c = 0;
@@ -172,7 +179,7 @@ void LoLEngine::gui_displayCharInventory(int charNum) {
uint8 *shp = _gameShapes[skillFlags[(i << 1) + 1]];
_screen->drawShape(_screen->_curPage, shp, 108 + x, 98, 0, 0);
x += (shp[3] + 2);
- tmp[c] = skillFlags[(i << 1) + 1];
+ _invSkillFlags[c] = skillFlags[(i << 1) + 1];
c++;
}
@@ -354,7 +361,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
if (_availableSpells[_selectedSpell] != -1) {
for (int i = 0; i < 4; i++) {
if (_spellProperties[_availableSpells[_selectedSpell]].mpRequired[i] <= _characters[charNum].magicPointsCur &&
- _spellProperties[_availableSpells[_selectedSpell] + 1].unkArr[i] <= _characters[charNum].hitPointsCur)
+ _spellProperties[_availableSpells[_selectedSpell]].hpRequired[i] <= _characters[charNum].hitPointsCur)
spellLevels++;
}
}
@@ -386,7 +393,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
_screen->drawShape(_screen->_curPage, _gameShapes[72 + _characters[charNum].field_41], 44, 17, 0, 0);
if (spellLevels == 0)
- _screen->drawGridBox(44, 17, 22, 15, 1);
+ _screen->drawGridBox(44, 17, 22, 16, 1);
}
uint16 f = _characters[charNum].flags & 0x314C;
@@ -726,10 +733,10 @@ void LoLEngine::gui_updateInput() {
if (_weaponsDisabled || _availableSpells[1] == -1)
return;
- gui_highlightSelectedSpell(0);
+ gui_highlightSelectedSpell(false);
if (_availableSpells[++_selectedSpell] == -1)
_selectedSpell = 0;
- gui_highlightSelectedSpell(1);
+ gui_highlightSelectedSpell(true);
gui_drawAllCharPortraitsWithStats();
break;
@@ -887,7 +894,11 @@ void LoLEngine::gui_initCharInventorySpecialButtons(int charNum) {
}
void LoLEngine::gui_initMagicScrollButtons() {
-
+ for (int i = 0; i < 7; i++) {
+ if (_availableSpells[i] == -1)
+ continue;
+ gui_initButton(71 + i, -1, -1, i);
+ }
}
void LoLEngine::gui_initMagicSubmenu(int charNum) {
@@ -1110,16 +1121,14 @@ int LoLEngine::clickedMagicSubmenu(Button *button) {
} else {
_characters[c].flags |= 4;
_characters[c].flags &= 0xffef;
- ///
- // TODO
- ///
- /*if (processSpellcast(c, _availableSpells[_selectedSpell], spellLevel)) {
+
+ if (castSpell(c, _availableSpells[_selectedSpell], spellLevel)) {
setCharacterUpdateEvent(c, 1, 8, 1);
- sub_718F(c, 2, spellLevel * spellLevel);
- } else {*/
+ increaseExperience(c, 2, spellLevel * spellLevel);
+ } else {
_characters[c].flags &= 0xfffb;
gui_drawCharPortraitWithStats(c);
- //}
+ }
}
_unkCharNum = -1;
@@ -1345,9 +1354,6 @@ int LoLEngine::clickedInventorySlot(Button *button) {
WSAMovie_v2 *wsa = new WSAMovie_v2(this, _screen);
wsa->open("truth.wsa", 0, 0);
- wsa->setDrawPage(2);
- wsa->setX(0);
- wsa->setY(0);
_screen->hideMouse();
@@ -1359,7 +1365,7 @@ int LoLEngine::clickedInventorySlot(Button *button) {
for (int i = 0; i < 25; i++) {
_smoothScrollTimer = _system->getMillis() + 7 * _tickLength;
_screen->copyRegion(button->x, button->y - 3, 0, 0, 25, 27, 2, 2);
- wsa->displayFrame(i, 0x4000);
+ wsa->displayFrame(i, 2, 0, 0, 0x4000);
_screen->copyRegion(0, 0, button->x, button->y - 3, 25, 27, 2, 0);
_screen->updateScreen();
delayUntil(_smoothScrollTimer);
@@ -1454,14 +1460,45 @@ int LoLEngine::clickedSequenceWindow(Button *button) {
}
int LoLEngine::clickedScroll(Button *button) {
+ if (_selectedSpell == button->data2Val2)
+ return 1;
+
+ gui_highlightSelectedSpell(false);
+ _selectedSpell = button->data2Val2;
+ gui_highlightSelectedSpell(true);
+ gui_drawAllCharPortraitsWithStats();
+
return 1;
}
-int LoLEngine::clickedUnk23(Button *button) {
+int LoLEngine::clickedSpellTargetCharacter(Button *button) {
+ int t = button->data2Val2;
+ _txt->printMessage(0, "%s.\r", _characters[t].name);
+
+ if ((_spellProperties[_activeSpell.spell].flags & 0xff) == 1) {
+ _activeSpell.target = t;
+ castHealOnSingleCharacter(&_activeSpell);
+ }
+
+ gui_enableDefaultPlayfieldButtons();
return 1;
}
-int LoLEngine::clickedUnk24(Button *button) {
+int LoLEngine::clickedSpellTargetScene(Button *button) {
+ LoLCharacter *c = &_characters[_activeSpell.charNum];
+ _txt->printMessage(0, getLangString(0x4041));
+
+ c->magicPointsCur += _activeSpell.p->mpRequired[_activeSpell.level];
+ if (c->magicPointsCur > c->magicPointsMax)
+ c->magicPointsCur = c->magicPointsMax;
+
+ c->hitPointsCur += _activeSpell.p->hpRequired[_activeSpell.level];
+ if (c->hitPointsCur > c->hitPointsMax)
+ c->hitPointsCur = c->hitPointsMax;
+
+ gui_drawCharPortraitWithStats(_activeSpell.charNum);
+ gui_enableDefaultPlayfieldButtons();
+
return 1;
}
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index 38b8c5a5a3..902977bdf6 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -363,16 +363,10 @@ void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) {
frame = 13;
if (page == 0) {
- _invWsa->setX(0);
- _invWsa->setY(0);
- _invWsa->setDrawPage(0);
- _invWsa->displayFrame(frame, 0);
+ _invWsa->displayFrame(frame, 0, 0, 0, 0);
_screen->updateScreen();
} else if (page == 30) {
- _invWsa->setX(0);
- _invWsa->setY(-144);
- _invWsa->setDrawPage(2);
- _invWsa->displayFrame(frame, 0);
+ _invWsa->displayFrame(frame, 2, 0, -144, 0);
}
_invWsaFrame = frame;
@@ -713,20 +707,11 @@ void KyraEngine_MR::showAlbum() {
loadAlbumPage();
loadAlbumPageWSA();
- if (_album.leftPage.wsa->opened()) {
- _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]);
- _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]);
- _album.leftPage.wsa->setDrawPage(2);
+ if (_album.leftPage.wsa->opened())
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000);
- }
- if (_album.rightPage.wsa->opened()) {
- _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]);
- _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]);
- _album.rightPage.wsa->setDrawPage(2);
-
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000);
- }
+ if (_album.rightPage.wsa->opened())
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
printAlbumPageText();
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -887,20 +872,11 @@ void KyraEngine_MR::processAlbum() {
loadAlbumPage();
loadAlbumPageWSA();
- if (_album.leftPage.wsa->opened()) {
- _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]);
- _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]);
- _album.leftPage.wsa->setDrawPage(2);
-
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000);
- }
- if (_album.rightPage.wsa->opened()) {
- _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]);
- _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]);
- _album.rightPage.wsa->setDrawPage(2);
+ if (_album.leftPage.wsa->opened())
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000);
- }
+ if (_album.rightPage.wsa->opened())
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
printAlbumPageText();
@@ -955,11 +931,7 @@ void KyraEngine_MR::albumUpdateAnims() {
nextRun = _album.leftPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) {
- _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]);
- _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]);
- _album.leftPage.wsa->setDrawPage(2);
-
- _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000);
+ _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000);
_screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK);
++_album.leftPage.curFrame;
@@ -978,11 +950,7 @@ void KyraEngine_MR::albumUpdateAnims() {
nextRun = _album.rightPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) {
- _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]);
- _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]);
- _album.rightPage.wsa->setDrawPage(2);
-
- _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000);
+ _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
_screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK);
++_album.rightPage.curFrame;
@@ -999,32 +967,26 @@ void KyraEngine_MR::albumUpdateAnims() {
void KyraEngine_MR::albumAnim1() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim1()");
- _album.wsa->setX(-100);
- _album.wsa->setY(90);
- _album.wsa->setDrawPage(2);
for (int i = 6; i >= 3; --i) {
albumRestoreRect();
- _album.wsa->displayFrame(i, 0x4000);
+ _album.wsa->displayFrame(i, 2, -100, 90, 0x4000);
albumUpdateRect();
delayWithTicks(1);
}
albumRestoreRect();
- _album.wsa->displayFrame(14, 0x4000);
+ _album.wsa->displayFrame(14, 2, -100, 90, 0x4000);
albumUpdateRect();
delayWithTicks(1);
}
void KyraEngine_MR::albumAnim2() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim2()");
- _album.wsa->setX(-100);
- _album.wsa->setY(90);
- _album.wsa->setDrawPage(2);
for (int i = 3; i <= 6; ++i) {
albumRestoreRect();
- _album.wsa->displayFrame(i, 0x4000);
+ _album.wsa->displayFrame(i, 2, -100, 90, 0x4000);
albumUpdateRect();
delayWithTicks(1);
}
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 02c8e50410..765747f687 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -44,7 +44,7 @@ void LoLEngine::giveCredits(int credits, int redraw) {
if (t > credits)
t = credits;
- if (_credits < 60 && t >= 0) {
+ if (_credits < 60 && t > 0) {
cnt = 0;
do {
@@ -86,7 +86,7 @@ void LoLEngine::takeCredits(int credits, int redraw) {
if (t > credits)
t = credits;
- if (_credits - t < 60 && t >= 0) {
+ if (_credits - t < 60 && t > 0) {
cnt = 0;
do {
@@ -97,7 +97,7 @@ void LoLEngine::takeCredits(int credits, int redraw) {
_moneyColumnHeight[d]--;
}
} while (++cnt < t);
- } else if (_credits - t < 60) {
+ } else if (_credits - t >= 60) {
_credits -= t;
}
@@ -343,7 +343,7 @@ void LoLEngine::removeLevelItem(int item, int block) {
}
bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c) {
- int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, startX, startY);
+ int sp = checkDrawObjectSpace(_partyPosX, _partyPosY, startX, startY);
FlyingObject *t = _flyingObjects;
int slot = -1;
int i = 0;
@@ -354,7 +354,7 @@ bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, i
break;
}
- int csp = checkDrawObjectSpace(_partyPosX, _partyPosX, t->x, t->y);
+ int csp = checkDrawObjectSpace(_partyPosX, _partyPosY, t->x, t->y);
if (csp > sp){
sp = csp;
slot = i;
@@ -490,7 +490,8 @@ void LoLEngine::updateFlyingObject(FlyingObject *t) {
int x = 0;
int y = 0;
getNextStepCoords(t->x, t->y, x, y, t->direction);
- int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 256 : 63, t->flags, t->wallFlags);
+ // WORKAROUND: The next line seems to be bugged in the original code. I have fixed it in a way that at least seems to work fine.
+ int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 127 : 63, t->flags, t->wallFlags);
if (objectOnNextBlock) {
endObjectFlight(t, x, y, objectOnNextBlock);
} else {
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index c040f3ab3d..ff0ee80456 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -1612,10 +1612,7 @@ void KyraEngine_HoF::updateInvWsa() {
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);
+ _invWsa.wsa->displayFrame(_invWsa.curFrame, _invWsa.page, 0, 0, 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);
@@ -1653,10 +1650,7 @@ void KyraEngine_HoF::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);
+ _invWsa.wsa->displayFrame(_invWsa.lastFrame-1, _invWsa.page, 0, 0, 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);
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index 6baa90ea8f..a227d16937 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -274,14 +274,14 @@ Common::Error KyraEngine_MR::go() {
for (int i = 0; i < 64 && !shouldQuit(); ++i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
- _menuAnim->displayFrame(i, 0);
+ _menuAnim->displayFrame(i, 0, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
for (int i = 64; i > 29 && !shouldQuit(); --i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
- _menuAnim->displayFrame(i, 0);
+ _menuAnim->displayFrame(i, 0, 0, 0, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
@@ -330,9 +330,6 @@ Common::Error KyraEngine_MR::go() {
void KyraEngine_MR::initMainMenu() {
_menuAnim = new WSAMovie_v2(this, _screen);
_menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0));
- _menuAnim->setX(0);
- _menuAnim->setY(0);
- _menuAnim->setDrawPage(0);
memset(_screen->getPalette(0), 0, 3);
_menu = new MainMenu(this);
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index acf4be35dc..bdc0364c5a 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -72,6 +72,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
break;
}
+ _chargenFrameTable = _flags.isTalkie ? _chargenFrameTableTalkie : _chargenFrameTableFloppy;
_chargenWSA = 0;
_lastUsedStringBuffer = 0;
_landsFile = 0;
@@ -89,6 +90,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_itemProperties = 0;
_itemInHand = 0;
memset(_inventory, 0, sizeof(_inventory));
+ memset(_invSkillFlags, 0, sizeof(_invSkillFlags));
_inventoryCurItem = 0;
_currentControlMode = 0;
_specialSceneFlag = 0;
@@ -102,6 +104,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_monsterAnimType, 0, 3);
_pageSavedFlag = false;
_healOverlay = 0;
+ _swarmSpellStatus = 0;
_ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0;
@@ -110,7 +113,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_spellProperties = 0;
_updateFlags = 0;
_selectedSpell = 0;
- _updateCharNum = _updatePortraitSpeechAnimDuration = _portraitSpeechAnimMode = _updateCharV3 = _textColourFlag = _needSceneRestore = 0;
+ _updateCharNum = _updatePortraitSpeechAnimDuration = _portraitSpeechAnimMode = _updateCharV3 = _textColorFlag = _needSceneRestore = 0;
_fadeText = false;
_palUpdateTimer = _updatePortraitNext = 0;
_lampStatusTimer = 0xffffffff;
@@ -155,7 +158,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_flyingObjects = 0;
_monsters = 0;
_lastMouseRegion = 0;
- _monsterLastWalkDirection = _monsterCountUnk = _monsterShiftAlt = 0;
+ _objectLastDirection = _monsterCountUnk = _monsterShiftAlt = 0;
_monsterCurBlock = 0;
_seqWindowX1 = _seqWindowY1 = _seqWindowX2 = _seqWindowY2 = _seqTrigger = 0;
_spsWindowX = _spsWindowY = _spsWindowW = _spsWindowH = 0;
@@ -200,6 +203,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_activeTim, 0, sizeof(_activeTim));
memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile));
memset(_openDoorState, 0, sizeof(_openDoorState));
+ memset(&_activeSpell, 0, sizeof(_activeSpell));
_activeVoiceFileTotalTime = 0;
_pageBuffer1 = _pageBuffer2 = 0;
@@ -221,7 +225,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_floatingCursorsEnabled = false;
memset(_lvlTempData, 0, sizeof(_lvlTempData));
- _unkIceSHpFlag = 0;
+ _freezeStateFlags = 0;
_mapOverlay = 0;
_automapShapes = 0;
@@ -389,6 +393,7 @@ LoLEngine::~LoLEngine() {
delete[] _defaultLegendData;
delete[] _mapCursorOverlay;
delete[] _mapOverlay;
+ _spellProcs.clear();
}
Screen *LoLEngine::screen() {
@@ -499,6 +504,24 @@ Common::Error LoLEngine::init() {
_automapShapes = new const uint8*[109];
_mapOverlay = new uint8[256];
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSpark));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHeal));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castIce));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFireball));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHandOfFate));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castMistOfDoom));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castLightning));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFog));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSwarm));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castUnk));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, 0));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castGuardian));
+
return Common::kNoError;
}
@@ -736,7 +759,7 @@ int LoLEngine::mainMenu() {
assert(menu);
menu->init(data[dataIndex], MainMenu::Animation());
- int selection = menu->handle(_flags.isTalkie ? (hasSave ? 12 : 6) : (hasSave ? 6 : 13));
+ int selection = menu->handle(_flags.isTalkie ? (hasSave ? 17 : 6) : (hasSave ? 6 : 18));
delete menu;
_screen->setScreenDim(0);
@@ -1153,7 +1176,7 @@ void LoLEngine::updatePortraits() {
}
void LoLEngine::initTextFading(int textType, int clearField) {
- if (_textColourFlag == textType || !textType) {
+ if (_textColorFlag == textType || !textType) {
_fadeText = true;
_palUpdateTimer = _system->getMillis();
}
@@ -1546,7 +1569,7 @@ void LoLEngine::fadeText() {
if (!_fadeText)
return;
- if (_screen->fadeColour(192, 252, _system->getMillis() - _palUpdateTimer, 60 * _tickLength))
+ if (_screen->fadeColor(192, 252, _system->getMillis() - _palUpdateTimer, 60 * _tickLength))
return;
if (_needSceneRestore)
@@ -1567,7 +1590,7 @@ void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifie
void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) {
memcpy(dst, src, 0x300);
- _screen->loadSpecialColours(dst);
+ _screen->loadSpecialColors(dst);
brightness = (8 - brightness) << 5;
if (modifier >= 0 && modifier < 8 && _gameFlags[15] & 0x800) {
brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8);
@@ -1690,10 +1713,11 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
if (playList.empty())
return false;
- while (_sound->voiceIsPlaying(_activeVoiceFile)) {
- update();
- delay(_tickLength);
- };
+ while (_sound->voiceIsPlaying(_activeVoiceFile))
+ delay(_tickLength, true, false);
+
+ while (_sound->allVoiceChannelsPlaying())
+ delay(_tickLength, false, true);
strcpy(_activeVoiceFile, *playList.begin());
_activeVoiceFileTotalTime = _sound->voicePlayFromList(playList);
@@ -1826,6 +1850,12 @@ void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) {
}
}
+void LoLEngine::snd_playQueuedEffects() {
+ for (int i = 0; i < _envSfxNumTracksInQueue; i++)
+ snd_processEnvironmentalSoundEffect(_envSfxQueuedTracks[i], _envSfxQueuedBlocks[i]);
+ _envSfxNumTracksInQueue = 0;
+}
+
void LoLEngine::snd_loadSoundFile(int track) {
if (_sound->musicEnabled()) {
char filename[13];
@@ -1969,7 +1999,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str
}
}
- _fadeText = 0;
+ _fadeText = false;
if (!skipAnim)
updatePortraitSpeechAnim();
@@ -1996,12 +2026,26 @@ uint16 *LoLEngine::getCharacterOrMonsterProtectionAgainstItems(int id) {
return (id & 0x8000) ? _monsters[id & 0x7fff].properties->protectionAgainstItems : _characters[id].protectionAgainstItems;
}
-void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) {
- uint32 endTime = _system->getMillis() + millis;
- while (endTime > _system->getMillis()) {
+void LoLEngine::delay(uint32 millis, bool cUpdate, bool iUpdate) {
+ int del = (int)(millis);
+ while (del > 0) {
if (cUpdate)
update();
- _system->delayMillis(4);
+ if (iUpdate)
+ updateInput();
+ int step = del >= _tickLength ? _tickLength : del;
+ _system->delayMillis(step);
+ del -= step;
+ }
+}
+
+void LoLEngine::delayUntil(uint32 timeStamp) {
+ int del = (int)(timeStamp - _system->getMillis());
+ while (del > 0) {
+ updateInput();
+ int step = del >= _tickLength ? _tickLength : del;
+ _system->delayMillis(step);
+ del -= step;
}
}
@@ -2035,7 +2079,181 @@ void LoLEngine::updateEnvironmentalSfx(int soundId) {
snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
}
-void LoLEngine::processMagicHeal(int charNum, int points) {
+// spells
+
+int LoLEngine::castSpell(int charNum, int spellType, int spellLevel) {
+ _activeSpell.charNum = charNum;
+ _activeSpell.spell = spellType;
+ _activeSpell.p = &_spellProperties[spellType];
+
+ _activeSpell.level = spellLevel < 0 ? -spellLevel : spellLevel;
+
+ if ((_spellProperties[spellType].flags & 0x100) && testWallFlag(calcNewBlockPosition(_currentBlock, _currentDirection), _currentDirection, 1)) {
+ _txt->printMessage(2, getLangString(0x4257));
+ return 0;
+ }
+
+ if (charNum < 0) {
+ _activeSpell.charNum = (charNum * -1) - 1;
+ if (_spellProcs[spellType]->isValid())
+ return (*_spellProcs[spellType])(&_activeSpell);
+ } else {
+ if (_activeSpell.p->mpRequired[spellLevel] > _characters[charNum].magicPointsCur)
+ return 0;
+
+ if (_activeSpell.p->hpRequired[spellLevel] >= _characters[charNum].hitPointsCur)
+ return 0;
+
+ setCharacterMagicOrHitPoints(charNum, 1, -_activeSpell.p->mpRequired[spellLevel], 1);
+ setCharacterMagicOrHitPoints(charNum, 0, -_activeSpell.p[1].hpRequired[spellLevel], 1);
+ gui_drawCharPortraitWithStats(charNum);
+
+ if (_spellProcs[spellType]->isValid())
+ (*_spellProcs[spellType])(&_activeSpell);
+ }
+
+ return 1;
+}
+
+int LoLEngine::castSpark(ActiveSpell *a) {
+ processMagicSpark(a->charNum, a->level);
+ return 1;
+}
+
+int LoLEngine::castHeal(ActiveSpell *a) {
+ if (a->level < 3)
+ processMagicHealSelectTarget();
+ else
+ processMagicHeal(-1, a->level);
+
+ return 1;
+}
+
+int LoLEngine::castIce(ActiveSpell *a) {
+ processMagicIce(a->charNum, a->level);
+ return 1;
+}
+
+int LoLEngine::castFireball(ActiveSpell *a) {
+ processMagicFireball(a->charNum, a->level);
+ return 1;
+}
+
+int LoLEngine::castHandOfFate(ActiveSpell *a) {
+ return 1;
+}
+
+int LoLEngine::castMistOfDoom(ActiveSpell *a) {
+ processMagicMistOfDoom(a->charNum, a->level);
+ return 1;
+}
+
+int LoLEngine::castLightning(ActiveSpell *a) {
+ return 1;
+}
+
+int LoLEngine::castFog(ActiveSpell *a) {
+ return 1;
+}
+
+int LoLEngine::castSwarm(ActiveSpell *a) {
+ processMagicSwarm(a->charNum, 10);
+ return 1;
+}
+
+int LoLEngine::castUnk(ActiveSpell *a) {
+ return 1;
+}
+
+int LoLEngine::castGuardian(ActiveSpell *a) {
+ return 1;
+}
+
+int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) {
+ processMagicHeal(a->target, a->level);
+ return 1;
+}
+
+void LoLEngine::processMagicSpark(int charNum, int spellLevel) {
+ WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ _screen->copyPage(0, 12);
+
+ mov->open("spark1.wsa", 0, 0);
+ if (!mov->opened())
+ error("SPARK: Unable to load SPARK1.WSA");
+ snd_playSoundEffect(72, -1);
+ playSpellAnimation(mov, 0, 7, 4, _activeCharsXpos[charNum] - 2, 138, 0, 0, 0, 0, false);
+ mov->close();
+
+ _screen->copyPage(12, 0);
+ _screen->updateScreen();
+
+ uint16 targetBlock = 0;
+ int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 4, targetBlock);
+ uint16 target = getNearestMonsterFromCharacterForBlock(targetBlock, charNum);
+
+ static const uint8 dmg[] = { 7, 15, 25, 60 };
+ if (target != 0xffff) {
+ inflictMagicalDamage(target, charNum, dmg[spellLevel], 5, 0);
+ updateDrawPage2();
+ gui_drawScene(0);
+ _screen->copyPage(0, 12);
+ }
+
+ int numFrames = mov->open("spark2.wsa", 0, 0);
+ if (!mov->opened())
+ error("SPARK: Unable to load SPARK2.WSA");
+
+ uint16 wX[6];
+ uint16 wY[6];
+ uint16 wFrames[6];
+ const uint16 width = mov->width();
+ const uint16 height = mov->height();
+
+ for (int i = 0; i < 6; i++) {
+ wX[i] = (_rnd.getRandomNumber(0x7fff) % 64) + ((176 - width) >> 1) + 80;
+ wY[i] = (_rnd.getRandomNumber(0x7fff) % 32) + ((120 - height) >> 1) - 16;
+ wFrames[i] = i << 1;
+ }
+
+ for (int i = 0, d = ((spellLevel << 1) + 12); i < d; i++) {
+ _smoothScrollTimer = _system->getMillis() + 4 * _tickLength;
+ _screen->copyPage(12, 2);
+
+ for (int ii = 0; ii <= spellLevel; ii++) {
+ if (wFrames[ii] >= i || wFrames[ii] + 13 <= i)
+ continue;
+
+ if ((i - wFrames[ii]) == 1)
+ snd_playSoundEffect(162, -1);
+
+ mov->displayFrame(((i - wFrames[ii]) + (dist << 4)) % numFrames, 2, wX[ii], wY[ii], 0x5000, _trueLightTable1, _trueLightTable2);
+ _screen->copyRegion(wX[ii], wY[ii], wX[ii], wY[ii], width, height, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+
+ if (i < d - 1)
+ delayUntil(_smoothScrollTimer);
+ }
+
+ mov->close();
+
+ _screen->copyPage(12, 2);
+ updateDrawPage2();
+
+ _sceneUpdateRequired = true;
+
+ delete mov;
+}
+
+void LoLEngine::processMagicHealSelectTarget() {
+ _txt->printMessage(0, getLangString(0x4040));
+ gui_resetButtonList();
+ gui_setFaceFramesControlButtons(81, 0);
+ gui_initButtonsFromList(_buttonList8);
+}
+
+void LoLEngine::processMagicHeal(int charNum, int spellLevel) {
if (!_healOverlay) {
_healOverlay = new uint8[256];
_screen->generateGrayOverlay(_screen->getPalette(1), _healOverlay, 52, 22, 20, 0, 256, true);
@@ -2043,28 +2261,28 @@ void LoLEngine::processMagicHeal(int charNum, int points) {
const uint8 *healShpFrames = 0;
const uint8 *healiShpFrames = 0;
- bool resetFlag = false;
- int maxDiff = 0;
+ bool curePoison = false;
+ int points = 0;
- if (points == 0) {
- maxDiff = 25;
+ if (spellLevel == 0) {
+ points = 25;
healShpFrames = _healShapeFrames;
healiShpFrames = _healShapeFrames + 32;
- } else if (points == 1) {
- maxDiff = 45;
+ } else if (spellLevel == 1) {
+ points = 45;
healShpFrames = _healShapeFrames + 16;
healiShpFrames = _healShapeFrames + 48;
- } else if (points > 3) {
- resetFlag = true;
- maxDiff = points;
+ } else if (spellLevel > 3) {
+ curePoison = true;
+ points = spellLevel;
healShpFrames = _healShapeFrames + 16;
healiShpFrames = _healShapeFrames + 64;
} else {
- resetFlag = true;
- maxDiff = 10000;
+ curePoison = true;
+ points = 10000;
healShpFrames = _healShapeFrames + 16;
healiShpFrames = _healShapeFrames + 64;
@@ -2087,13 +2305,15 @@ void LoLEngine::processMagicHeal(int charNum, int points) {
memset(pts, 0, sizeof(pts));
while (charNum < n) {
- if (!(_characters[charNum].flags & 1))
+ if (!(_characters[charNum].flags & 1)) {
+ charNum++;
continue;
+ }
pX[charNum] = _activeCharsXpos[charNum] - 6;
_characters[charNum].damageSuffered = 0;
int dmg = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur;
- diff[charNum] = (dmg < maxDiff) ? dmg : maxDiff;
+ diff[charNum] = (dmg < points) ? dmg : points;
_screen->copyRegion(pX[charNum], pY, charNum * 77, 32, 77, 44, 0, 2, Screen::CR_NO_P_CHECK);
charNum++;
}
@@ -2125,20 +2345,17 @@ void LoLEngine::processMagicHeal(int charNum, int points) {
_screen->updateScreen();
}
- while ((int)(_smoothScrollTimer - _system->getMillis()) > 0) {
- updateInput();
- delay(_tickLength);
- }
+ delayUntil(_smoothScrollTimer);
}
for (charNum = ch; charNum < n; charNum++) {
if (!(_characters[charNum].flags & 1))
- continue;
+ continue;
_screen->copyRegion(charNum * 77, 32, pX[charNum], pY, 77, 44, 2, 2, Screen::CR_NO_P_CHECK);
- if (resetFlag)
- resetCharacterState(&_characters[charNum], 4, 4);
+ if (curePoison)
+ removeCharacterEffects(&_characters[charNum], 4, 4);
gui_drawCharPortraitWithStats(charNum);
_screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK);
@@ -2149,12 +2366,317 @@ void LoLEngine::processMagicHeal(int charNum, int points) {
updateDrawPage2();
}
+void LoLEngine::processMagicIce(int charNum, int spellLevel) {
+ int cp = _screen->setCurPage(2);
+
+ disableSysTimer(2);
+
+ gui_drawScene(0);
+ _screen->copyPage(0, 12);
+
+ //uint8 pal2[768];
+ //uint8 pal3[768];
+
+ if (_currentLevel = 11 && !(_freezeStateFlags & 4)) {
+ for (int i = 1; i < 384; i++) {
+
+ ///////// TODO
+
+ }
+
+ _freezeStateFlags |= 4;
+ static const uint8 freezeTimes[] = { 20, 28, 40, 60 };
+ setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1);
+ }
+
+ ////////// TODO
+ generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect);
+
+ ////////// TODO
+
+ _screen->setCurPage(cp);
+}
+
+void LoLEngine::processMagicFireball(int charNum, int spellLevel) {
+
+}
+
+void LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
+
+}
+
+void LoLEngine::processMagicSwarm(int charNum, int damage) {
+ int cp = _screen->setCurPage(2);
+ _screen->copyPage(0, 12);
+ snd_playSoundEffect(74, -1);
+
+ uint16 destIds[6];
+ uint8 destModes[6];
+ int8 destTicks[6];
+
+ memset(destIds, 0, sizeof(destIds));
+ memset(destModes, 8, sizeof(destModes));
+ memset(destTicks, 0, sizeof(destTicks));
+
+ int t = 0;
+ uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects;
+ while (o & 0x8000) {
+ o &= 0x7fff;
+ if (_monsters[o].mode != 13) {
+ destIds[t++] = o;
+
+ if (!(_monsters[o].flags & 0x2000)) {
+ _envSfxUseQueue = true;
+ inflictMagicalDamage(o | 0x8000, charNum, damage, 0, 0);
+ _envSfxUseQueue = false;
+ _monsters[o].flags &= 0xffef;
+ }
+ }
+ o = _monsters[o].nextAssignedObject;
+ }
+
+ for (int i = 0; i < t; i++) {
+ SWAP(destModes[i], _monsters[destIds[i]].mode);
+ SWAP(destTicks[i], _monsters[destIds[i]].fightCurTick);
+ }
+
+ gui_drawScene(_screen->_curPage);
+ _screen->copyRegion(112, 0, 112, 0, 176, 120, _screen->_curPage, 7);
+
+ for (int i = 0; i < t; i++) {
+ _monsters[destIds[i]].mode = destModes[i];
+ _monsters[destIds[i]].fightCurTick = destTicks[i];
+ }
+
+ WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+
+ mov->open("swarm.wsa", 0, 0);
+ if (!mov->opened())
+ error("Swarm: Unable to load SWARM.WSA");
+ _screen->hideMouse();
+ playSpellAnimation(mov, 0, 37, 2, 0, 0, 0, 0, 0, 0, false);
+ playSpellAnimation(mov, 38, 41, 8, 0, 0, &LoLEngine::callbackProcessMagicSwarm, 0, 0, 0, false);
+ _screen->showMouse();
+ mov->close();
+
+ _screen->copyPage(12, 0);
+ updateDrawPage2();
+
+ snd_playQueuedEffects();
+
+ _screen->setCurPage(cp);
+ delete mov;
+}
+
+void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) {
+ if (_swarmSpellStatus)
+ _screen->copyRegion(112, 0, 112, 0, 176, 120, 6, _screen->_curPage);
+ _swarmSpellStatus ^= 1;
+}
+
+void LoLEngine::addSpellToScroll(int spell, int charNum) {
+ bool assigned = false;
+ int slot = 0;
+ for (int i = 0; i < 7; i++) {
+ if (!assigned && _availableSpells[i] == -1) {
+ assigned = true;
+ slot = i;
+ }
+
+ if (_availableSpells[i] == spell) {
+ _txt->printMessage(2, getLangString(0x42d0));
+ return;
+ }
+ }
+
+ if (spell > 1)
+ transferSpellToScollAnimation(charNum, spell, slot - 1);
+
+ _availableSpells[slot] = spell;
+ gui_enableDefaultPlayfieldButtons();
+}
+
+void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) {
+ int cX = 16 + _activeCharsXpos[charNum];
+
+ if (slot != 1) {
+ _screen->loadBitmap("playfld.cps", 3, 3, 0);
+ _screen->copyRegion(8, 0, 216, 0, 96, 120, 3, 3, Screen::CR_NO_P_CHECK);
+ _screen->copyPage(3, 10);
+ for (int i = 0; i < 9; i++) {
+ int h = (slot + 1) * 9 + i + 1;
+ _smoothScrollTimer = _system->getMillis() + _tickLength;
+ _screen->copyPage(10, 3);
+ _screen->copyRegion(216, 0, 8, 0, 96, 120, 3, 3, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(112, 0, 12, 0, 87, 15, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(201, 1, 17, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(208, 1, 89, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK);
+ int cp = _screen->setCurPage(2);
+ _screen->fillRect(21, 15, 89, h + 15, 206);
+ _screen->copyRegion(112, 16, 12, h + 15, 87, 14, 2, 2, Screen::CR_NO_P_CHECK);
+
+ int y = 15;
+ for (int ii = 0; ii < 7; ii++) {
+ if (_availableSpells[ii] == -1)
+ continue;
+ uint8 col = (ii == _selectedSpell) ? 132 : 1;
+ _screen->fprintString(getLangString(_spellProperties[_availableSpells[ii]].spellNameCode), 24, y, col, 0, 0);
+ y += 9;
+ }
+
+ _screen->setCurPage(cp);
+ _screen->copyRegion(8, 0, 8, 0, 96, 120, 3, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(_smoothScrollTimer);
+ }
+ }
+
+ _screen->hideMouse();
+
+ _screen->copyPage(0, 12);
+ int vX = _updateSpellBookCoords[slot << 1] + 32;
+ int vY = _updateSpellBookCoords[(slot << 1) + 1] + 5;
+
+ char wsaFile[13];
+ snprintf(wsaFile, 13, "write%0d%c.wsa", spell, (_lang == 1) ? 'f' : (_lang == 0 ? 'e' : 'g'));
+ snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1);
+ snd_playSoundEffect(95, -1);
+
+ WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+
+ mov->open("getspell.wsa", 0, 0);
+ if (!mov->opened())
+ error("SpellBook: Unable to load getspell anim");
+ snd_playSoundEffect(128, -1);
+ playSpellAnimation(mov, 0, 25, 5, _activeCharsXpos[charNum], 148, 0, 0, 0, 0, true);
+ snd_playSoundEffect(128, -1);
+ playSpellAnimation(mov, 26, 52, 5, _activeCharsXpos[charNum], 148, 0, 0, 0, 0, true);
+
+ for (int i = 16; i > 0; i--) {
+ _smoothScrollTimer = _system->getMillis() + _tickLength;
+ _screen->copyPage(12, 2);
+
+ int wsaX = vX + (((((cX - vX) << 8) / 16) * i) >> 8) - 16;
+ int wsaY = vY + (((((160 - vY) << 8) / 16) * i) >> 8) - 16;
+
+ mov->displayFrame(51, 2, wsaX, wsaY, 0x5000, _trueLightTable1, _trueLightTable2);
+
+ _screen->copyRegion(wsaX, wsaY, wsaX, wsaY, mov->width() + 48, mov->height() + 48, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(_smoothScrollTimer);
+ }
+
+ mov->close();
+
+ mov->open("spellexp.wsa", 0, 0);
+ if (!mov->opened())
+ error("SpellBook: Unable to load spellexp anim");
+ snd_playSoundEffect(168, -1);
+ playSpellAnimation(mov, 0, 8, 3, vX - 44, vY - 38, 0, 0, 0, 0, true);
+ mov->close();
+
+ mov->open("writing.wsa", 0, 0);
+ if (!mov->opened())
+ error("SpellBook: Unable to load writing anim");
+ playSpellAnimation(mov, 0, 6, 5, _updateSpellBookCoords[slot << 1], _updateSpellBookCoords[(slot << 1) + 1], 0, 0, 0, 0, false);
+ mov->close();
+
+ mov->open(wsaFile, 0, 0);
+ if (!mov->opened())
+ error("SpellBook: Unable to load spellbook anim");
+ snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1);
+ playSpellAnimation(mov, _updateSpellBookAnimData[(spell << 2) + 1], _updateSpellBookAnimData[(spell << 2) + 2], _updateSpellBookAnimData[spell << 2], _updateSpellBookCoords[slot << 1], _updateSpellBookCoords[(slot << 1) + 1], 0, 0, 0, 0, false);
+ mov->close();
+
+ gui_drawScene(2);
+ updateDrawPage2();
+
+ _screen->showMouse();
+
+ delete mov;
+}
+
+void LoLEngine::playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFrame, int frameDelay, int x, int y, SpellProcCallback callback, uint8 *pal1, uint8 *pal2, int fadeDelay, bool restoreScreen) {
+ int w = 0;
+ int h = 0;
+
+ if (mov) {
+ w = mov->width();
+ h = mov->height();
+ }
+
+ int w2 = w;
+ int h2 = h;
+ uint32 startTime = _system->getMillis();
+
+ if (x < 0)
+ w2 += x;
+ if (y < 0)
+ h2 += y;
+
+ int dir = lastFrame >= firstFrame ? 1 : -1;
+ int curFrame = firstFrame;
+
+ bool fin = false;
+
+ while (!fin) {
+ _smoothScrollTimer = _system->getMillis() + _tickLength * frameDelay;
+
+ if (mov || callback)
+ _screen->copyPage(12, 2);
+
+ if (callback)
+ (this->*callback)(mov, x, y);
+
+ if (mov)
+ mov->displayFrame(curFrame % mov->frames(), 2, x, y, 0x5000, _trueLightTable1, _trueLightTable2);
+
+ if (mov || callback) {
+ _screen->copyRegion(x, y, x, y, w2, h2, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+
+ int del = _smoothScrollTimer - _system->getMillis();
+ do {
+
+ int step = del > _tickLength ? _tickLength : del;
+
+ if (!pal1 || !pal2) {
+ delay(step);
+ del -= step;
+ continue;
+ }
+
+ if (!_screen->fadePalSpecial(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov)
+ return;
+
+ delay(step);
+ del -= step;
+ } while (del > 0);
+
+ if (!mov)
+ continue;
+
+ curFrame += dir;
+ if (curFrame == lastFrame)
+ fin = true;
+ }
+
+ if (restoreScreen && (mov || callback)) {
+ _screen->copyPage(12, 2);
+ _screen->copyRegion(x, y, x, y, w2, h2, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+}
+
int LoLEngine::checkMagic(int charNum, int spellNum, int spellLevel) {
if (_spellProperties[spellNum].mpRequired[spellLevel] > _characters[charNum].magicPointsCur) {
if (characterSays(0x4043, _characters[charNum].id, true))
_txt->printMessage(6, getLangString(0x4043), _characters[charNum].name);
return 1;
- } else if (_spellProperties[spellNum + 1].unkArr[spellLevel] >= _characters[charNum].hitPointsCur) {
+ } else if (_spellProperties[spellNum].hpRequired[spellLevel] >= _characters[charNum].hitPointsCur) {
_txt->printMessage(2, getLangString(0x4179), _characters[charNum].name);
return 1;
}
@@ -2162,6 +2684,35 @@ int LoLEngine::checkMagic(int charNum, int spellNum, int spellLevel) {
return 0;
}
+int LoLEngine::getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock) {
+ targetBlock = 0xffff;
+ uint16 c = calcNewBlockPosition(currentBlock, direction);
+
+ int i = 0;
+ for (; i < maxDistance; i++) {
+ if (_levelBlockProperties[currentBlock].assignedObjects & 0x8000) {
+ targetBlock = currentBlock;
+ return i;
+ }
+
+ if (_wllWallFlags[_levelBlockProperties[c].walls[direction ^ 2]] & 7) {
+ targetBlock = c;
+ return i;
+ }
+
+ currentBlock = c;
+ c = calcNewBlockPosition(currentBlock, direction);
+ }
+
+ return i;
+}
+
+void LoLEngine::inflictMagicalDamage(int target, int attacker, int damage, int index, int hitType) {
+ hitType = hitType ? 1 : 2;
+ damage = calcInflictableDamagePerItem(attacker, target, damage, index, hitType);
+ inflictDamage(target, damage, attacker, 2, index);
+}
+
// fight
int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
@@ -2296,11 +2847,11 @@ void LoLEngine::characterHitpointsZero(int16 charNum, int deathFlag) {
LoLCharacter *c = &_characters[charNum];
c->hitPointsCur = 0;
c->flags |= 8;
- resetCharacterState(c, 1, 5);
+ removeCharacterEffects(c, 1, 5);
_partyDeathFlag = deathFlag;
}
-void LoLEngine::resetCharacterState(LoLCharacter *c, int first, int last) {
+void LoLEngine::removeCharacterEffects(LoLCharacter *c, int first, int last) {
for (int i = first; i <= last; i++) {
switch (i - 1) {
case 0:
@@ -2614,13 +3165,16 @@ uint16 LoLEngine::getNearestMonsterFromCharacter(int charNum) {
return getNearestMonsterFromCharacterForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum);
}
-uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(int block, int charNum) {
+uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charNum) {
uint16 cX = 0;
uint16 cY = 0;
uint16 id = 0xffff;
int minDist = 0x7fff;
+ if (block == 0xffff)
+ return id;
+
calcCoordinatesForSingleCharacter(charNum, cX, cY);
int o = _levelBlockProperties[block].assignedObjects;
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index dce5a81a25..495641fa04 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -78,7 +78,11 @@ struct LoLCharacter {
struct SpellProperty {
uint16 spellNameCode;
uint16 mpRequired[4];
- uint16 unkArr[8];
+ uint16 field_a;
+ uint16 field_c;
+ uint16 hpRequired[4];
+ uint16 field_16;
+ uint16 field_18;
uint16 flags;
};
@@ -209,6 +213,14 @@ struct OpenDoorState {
int8 state;
};
+struct ActiveSpell {
+ uint8 spell;
+ const SpellProperty *p;
+ uint8 charNum;
+ uint8 level;
+ uint8 target;
+};
+
struct FlyingObject {
uint8 enable;
uint8 objectType;
@@ -311,7 +323,9 @@ private:
static const CharacterPrev _charPreviews[];
WSAMovie_v2 *_chargenWSA;
- static const uint8 _chargenFrameTable[];
+ static const uint8 _chargenFrameTableTalkie[];
+ static const uint8 _chargenFrameTableFloppy[];
+ const uint8 *_chargenFrameTable;
int chooseCharacter();
void kingSelectionIntro();
@@ -377,6 +391,7 @@ private:
void snd_playSoundEffect(int track, int volume);
void snd_processEnvironmentalSoundEffect(int soundId, int block);
void snd_queueEnvironmentalSoundEffect(int soundId, int block);
+ void snd_playQueuedEffects();
void snd_loadSoundFile(int track);
int snd_playTrack(int track);
int snd_stopMusic();
@@ -430,7 +445,7 @@ private:
void gui_drawInventoryItem(int index);
void gui_drawCompass();
void gui_drawScroll();
- void gui_highlightSelectedSpell(int unk);
+ void gui_highlightSelectedSpell(bool mode);
void gui_displayCharInventory(int charNum);
void gui_printCharInventoryStats(int charNum);
void gui_printCharacterStats(int index, int redraw, int value);
@@ -502,8 +517,8 @@ private:
int clickedWall(Button *button);
int clickedSequenceWindow(Button *button);
int clickedScroll(Button *button);
- int clickedUnk23(Button *button);
- int clickedUnk24(Button *button);
+ int clickedSpellTargetCharacter(Button *button);
+ int clickedSpellTargetScene(Button *button);
int clickedSceneThrowItem(Button *button);
int clickedOptions(Button *button);
int clickedRestParty(Button *button);
@@ -559,6 +574,7 @@ private:
int olol_setWallType(EMCState *script);
int olol_getWallType(EMCState *script);
int olol_drawScene(EMCState *script);
+ int olol_moveParty(EMCState *script);
int olol_delay(EMCState *script);
int olol_setGameFlag(EMCState *script);
int olol_testGameFlag(EMCState *script);
@@ -580,6 +596,7 @@ private:
int olol_playAnimationPart(EMCState *script);
int olol_freeAnimStruct(EMCState *script);
int olol_getDirection(EMCState *script);
+ int olol_characterSurpriseFeedback(EMCState *script);
int olol_setMusicTrack(EMCState *script);
int olol_setSequenceButtons(EMCState *script);
int olol_setDefaultButtonState(EMCState *script);
@@ -635,12 +652,15 @@ private:
int olol_changeMonsterStat(EMCState *script);
int olol_getMonsterStat(EMCState *script);
int olol_playCharacterScriptChat(EMCState *script);
+ int olol_playEnvironmentalSfx(EMCState *script);
int olol_update(EMCState *script);
int olol_healCharacter(EMCState *script);
int olol_drawExitButton(EMCState *script);
int olol_loadSoundFile(EMCState *script);
int olol_playMusicTrack(EMCState *script);
int olol_countBlockItems(EMCState *script);
+ int olol_characterSkillTest(EMCState *script);
+ int olol_countActiveMonsters(EMCState *script);
int olol_stopCharacterSpeech(EMCState *script);
int olol_setPaletteBrightness(EMCState *script);
int olol_calcInflictableDamage(EMCState *script);
@@ -649,12 +669,17 @@ private:
int olol_printMessage(EMCState *script);
int olol_deleteLevelItem(EMCState *script);
int olol_calcInflictableDamagePerItem(EMCState *script);
+ int olol_distanceAttack(EMCState *script);
+ int olol_removeCharacterEffects(EMCState *script);
int olol_objectLeavesLevel(EMCState *script);
+ int olol_addSpellToScroll(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
int olol_checkMonsterTypeHostility(EMCState *script);
int olol_setNextFunc(EMCState *script);
int olol_dummy1(EMCState *script);
int olol_suspendMonster(EMCState *script);
+ int olol_triggerEventOnMouseButtonRelease(EMCState *script);
+ int olol_printWindowText(EMCState *script);
int olol_setUnkDoorVar(EMCState *script);
int olol_resetTimDialogueState(EMCState *script);
int olol_savePage5(EMCState *script);
@@ -668,6 +693,7 @@ private:
int olol_resetPortraitsAndDisableSysTimer(EMCState *script);
int olol_enableSysTimer(EMCState *script);
int olol_checkNeedSceneRestore(EMCState *script);
+ int olol_castSpell(EMCState *script);
int olol_disableControls(EMCState *script);
int olol_enableControls(EMCState *script);
int olol_characterSays(EMCState *script);
@@ -785,7 +811,7 @@ private:
int _updatePortraitSpeechAnimDuration;
int _portraitSpeechAnimMode;
int _updateCharV3;
- int _textColourFlag;
+ int _textColorFlag;
bool _fadeText;
int _needSceneRestore;
uint32 _palUpdateTimer;
@@ -1070,6 +1096,7 @@ private:
int _currentControlMode;
int _specialSceneFlag;
int _lastCharInventory;
+ uint16 _invSkillFlags[6];
FlyingObject *_flyingObjects;
@@ -1107,7 +1134,7 @@ private:
int checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, int testFlag, int wallFlag);
int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int objectWidth, int testFlag, int wallFlag);
int calcMonsterSkillLevel(int id, int a);
- bool checkBlockOccupiedByParty(int x, int y, int testFlag);
+ int checkBlockOccupiedByParty(int x, int y, int testFlag);
const uint16 *getCharacterOrMonsterStats(int id);
uint16 *getCharacterOrMonsterItemsMight(int id);
uint16 *getCharacterOrMonsterProtectionAgainstItems(int id);
@@ -1145,7 +1172,7 @@ private:
uint8 **_monsterShapesEx;
uint8 _monsterAnimType[3];
uint16 _monsterCurBlock;
- int _monsterLastWalkDirection;
+ int _objectLastDirection;
int _monsterCountUnk;
int _monsterShiftAlt;
@@ -1163,7 +1190,8 @@ private:
int _monsterScaleWHSize;
// misc
- void delay(uint32 millis, bool cUpdate = false, bool isMainLoop = false);
+ void delay(uint32 millis, bool cUpdate = false, bool iUpdate = false);
+ void delayUntil(uint32 timeStamp);
uint8 getRandomNumberSpecial();
uint8 _compassBroken;
@@ -1175,17 +1203,53 @@ private:
uint32 _rndSpecial;
// spells
- void processMagicHeal(int charNum, int points);
- int checkMagic(int charNum, int spellNum, int spellLevel);
-
+ typedef Common::Functor1Mem<ActiveSpell*, int, LoLEngine> SpellProc;
+ Common::Array<const SpellProc*> _spellProcs;
+ typedef void (LoLEngine::*SpellProcCallback)(WSAMovie_v2*, int, int);
+
+ int castSpell(int charNum, int spellType, int spellLevel);
+
+ int castSpark(ActiveSpell *a);
+ int castHeal(ActiveSpell *a);
+ int castIce(ActiveSpell *a);
+ int castFireball(ActiveSpell *a);
+ int castHandOfFate(ActiveSpell *a);
+ int castMistOfDoom(ActiveSpell *a);
+ int castLightning(ActiveSpell *a);
+ int castFog(ActiveSpell *a);
+ int castSwarm(ActiveSpell *a);
+ int castUnk(ActiveSpell *a);
+ int castGuardian(ActiveSpell *a);
+ int castHealOnSingleCharacter(ActiveSpell *a);
+
+ void processMagicSpark(int charNum, int spellLevel);
+ void processMagicHealSelectTarget();
+ void processMagicHeal(int charNum, int spellLevel);
+ void processMagicIce(int charNum, int spellLevel);
+ void processMagicFireball(int charNum, int spellLevel);
+ void processMagicMistOfDoom(int charNum, int spellLevel);
+ void processMagicSwarm(int charNum, int damage);
+
+ void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y);
+
+ void addSpellToScroll(int spell, int charNum);
+ void transferSpellToScollAnimation(int charNum, int spell, int slot);
+
+ void playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFrame, int frameDelay, int x, int y, SpellProcCallback callback, uint8 *pal1, uint8 *pal2, int fadeDelay, bool restoreScreen);
+ int checkMagic(int charNum, int spellNum, int spellLevel);
+ int getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock);
+ void inflictMagicalDamage(int target, int attacker, int damage, int index, int hitType);
+
+ ActiveSpell _activeSpell;
int8 _availableSpells[7];
int _selectedSpell;
const SpellProperty *_spellProperties;
int _spellPropertiesSize;
int _subMenuIndex;
- uint16 _unkIceSHpFlag;
+ uint16 _freezeStateFlags;
uint8 *_healOverlay;
+ uint8 _swarmSpellStatus;
uint8 **_fireballShapes;
int _numFireballShapes;
@@ -1194,6 +1258,10 @@ private:
uint8 **_healiShapes;
int _numHealiShapes;
+ const uint8 *_updateSpellBookCoords;
+ int _updateSpellBookCoordsSize;
+ const uint8 *_updateSpellBookAnimData;
+ int _updateSpellBookAnimDataSize;
const uint8 *_healShapeFrames;
int _healShapeFramesSize;
@@ -1202,7 +1270,7 @@ private:
int calcInflictableDamage(int16 attacker, int16 target, int hitType);
int inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int deathFlag);
void characterHitpointsZero(int16 charNum, int a);
- void resetCharacterState(LoLCharacter *c, int first, int last);
+ void removeCharacterEffects(LoLCharacter *c, int first, int last);
int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType);
void checkForPartyDeath();
@@ -1220,7 +1288,7 @@ private:
void attackWall(int a, int b);
uint16 getNearestMonsterFromCharacter(int charNum);
- uint16 getNearestMonsterFromCharacterForBlock(int block, int charNum);
+ uint16 getNearestMonsterFromCharacterForBlock(uint16 block, int charNum);
uint16 getNearestMonsterFromPos(int x, int y);
uint16 getNearestPartyMemberFromPos(int x, int y);
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 99e0c9981d..98d929d406 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -287,6 +287,8 @@ enum kKyraResources {
lolMapStringId,
//lolMapPal,
+ lolSpellbookAnim,
+ lolSpellbookCoords,
lolHealShapeFrames,
#endif // ENABLE_LOL
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index 2508a3062a..38227cfae5 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -398,7 +398,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
memcpy(_screen->getPalette(2) + 0x180, _screen->_currentPalette, 384);
delete[] swampPal;
- if (_unkIceSHpFlag & 4) {
+ if (_freezeStateFlags & 4) {
uint8 *pal0 = _screen->_currentPalette;
uint8 *pal2 = _screen->getPalette(2);
for (int i = 1; i < 768; i++)
@@ -870,24 +870,23 @@ bool LoLEngine::clickedShape(int shapeIndex) {
return false;
}
-void LoLEngine::processDoorSwitch(uint16 block, int unk) {
+void LoLEngine::processDoorSwitch(uint16 block, int openClose) {
if ((block == _currentBlock) || (_levelBlockProperties[block].assignedObjects & 0x8000))
return;
- int s = 0;
- if (!unk) {
+ if (openClose == 0) {
for (int i = 0; i < 3; i++) {
if (_openDoorState[i].block != block)
continue;
- s = -_openDoorState[i].state;
+ openClose = -_openDoorState[i].state;
break;
}
}
- if (s == 0)
- s = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
+ if (openClose == 0)
+ openClose = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
- openCloseDoor(block, s);
+ openCloseDoor(block, openClose);
}
void LoLEngine::openCloseDoor(uint16 block, int openClose) {
@@ -1255,6 +1254,7 @@ void LoLEngine::drawScene(int pageNum) {
drawScriptShapes(_sceneDrawPage1);
_screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, _sceneDrawPage2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
SWAP(_sceneDrawPage1, _sceneDrawPage2);
}
@@ -1316,7 +1316,7 @@ void LoLEngine::prepareSpecialScene(int fieldType, int hasDialogue, int suspendG
if (fadeFlag) {
memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384);
- _screen->loadSpecialColours(_screen->getPalette(3));
+ _screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
}
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index f24d3a4472..4559edcc09 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -148,7 +148,7 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u
printText(buffer, x, y, c1, c2);
}
-void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours) {
+void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) {
uint8 tmpPal[768];
for (int i = 0; i != lastColor; i++) {
@@ -161,7 +161,7 @@ void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in
}
for (int i = 0; i < lastColor; i++)
- grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColours);
+ grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColors);
}
uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) {
@@ -290,7 +290,7 @@ void Screen_LoL::fadeClearSceneWindow(int delay) {
memcpy(tpal, _currentPalette, 768);
memset(tpal, 0, 384);
- loadSpecialColours(tpal);
+ loadSpecialColors(tpal);
fadePalette(tpal, delay);
fillRect(112, 0, 288, 120, 0);
delete[] tpal;
@@ -658,13 +658,13 @@ void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
_fadeFlag = 2;
}
-void Screen_LoL::loadSpecialColours(uint8 *destPalette) {
+void Screen_LoL::loadSpecialColors(uint8 *destPalette) {
memcpy(destPalette + 0x240, _screenPalette + 0x240, 12);
}
-void Screen_LoL::copyColour(int dstColourIndex, int srcColourIndex) {
- uint8 *s = _screenPalette + srcColourIndex * 3;
- uint8 *d = _screenPalette + dstColourIndex * 3;
+void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) {
+ uint8 *s = _screenPalette + srcColorIndex * 3;
+ uint8 *d = _screenPalette + dstColorIndex * 3;
memcpy(d, s, 3);
uint8 ci[4];
@@ -673,13 +673,13 @@ void Screen_LoL::copyColour(int dstColourIndex, int srcColourIndex) {
ci[2] = (d[2] << 2) | (d[2] & 3);
ci[3] = 0;
- _system->setPalette(ci, dstColourIndex, 1);
+ _system->setPalette(ci, dstColorIndex, 1);
}
-bool Screen_LoL::fadeColour(int dstColourIndex, int srcColourIndex, uint32 elapsedTime, uint32 targetTime) {
- uint8 *dst = _screenPalette + 3 * dstColourIndex;
- uint8 *src = _screenPalette + 3 * srcColourIndex;
- uint8 *p = getPalette(1) + 3 * dstColourIndex;
+bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime) {
+ uint8 *dst = _screenPalette + 3 * dstColorIndex;
+ uint8 *src = _screenPalette + 3 * srcColorIndex;
+ uint8 *p = getPalette(1) + 3 * dstColorIndex;
bool res = false;
@@ -714,7 +714,35 @@ bool Screen_LoL::fadeColour(int dstColourIndex, int srcColourIndex, uint32 elaps
uint8 tpal[768];
memcpy(tpal, _screenPalette, 768);
- memcpy(tpal + dstColourIndex * 3, tmpPalEntry, 3);
+ memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3);
+ setScreenPalette(tpal);
+ updateScreen();
+
+ return res;
+}
+
+bool Screen_LoL::fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) {
+ uint8 tpal[768];
+ uint8 *p1 = _palettes[1];
+
+ bool res = false;
+ for (int i = 0; i < 768; i++) {
+ uint8 out = 0;
+ if (elapsedTime < targetTime) {
+ int d = (pal2[i] & 0x3f) - (pal1[i] & 0x3f);
+ if (d)
+ res = true;
+
+ int val = ((((d << 8) / targetTime) * elapsedTime) >> 8) & 0xff;
+ out = ((pal1[i] & 0x3f) + val) & 0xff;
+ } else {
+ out = p1[i] = (pal2[i] & 0x3f);
+ res = false;
+ }
+
+ tpal[i] = out;
+ }
+
setScreenPalette(tpal);
updateScreen();
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index d7580e1ff8..1c2b6a3b93 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -64,11 +64,12 @@ public:
// palette stuff
void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
- void loadSpecialColours(uint8 *destPalette);
- void copyColour(int dstColourIndex, int srcColourIndex);
- bool fadeColour(int dstColourIndex, int srcColourIndex, uint32 elapsedTime, uint32 targetTime);
+ void loadSpecialColors(uint8 *destPalette);
+ void copyColor(int dstColorIndex, int srcColorIndex);
+ bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime);
+ bool fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime);
- void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours);
+ void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors);
uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index 50333cd44a..ece324fd19 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -90,12 +90,12 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint
}
}
-int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours) {
+int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors) {
int m = 0x7fff;
int r = 0x101;
for (int i = 0; i < numColors; i++) {
- if (skipSpecialColours && i >= 0xc0 && i <= 0xc3)
+ if (skipSpecialColors && i >= 0xc0 && i <= 0xc3)
continue;
int v = paletteEntry[0] - *palette++;
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
index dd001da731..22bab346db 100644
--- a/engines/kyra/screen_v2.h
+++ b/engines/kyra/screen_v2.h
@@ -45,7 +45,7 @@ public:
// palette handling
uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor);
void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay);
- int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours = false);
+ int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors = false);
virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff);
diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp
index 9f6a52a18e..2a55dfa484 100644
--- a/engines/kyra/script_hof.cpp
+++ b/engines/kyra/script_hof.cpp
@@ -187,10 +187,7 @@ int KyraEngine_HoF::o2_displayWsaFrame(EMCState *script) {
_screen->hideMouse();
uint32 endTime = _system->getMillis() + waitTime * _tickLength;
- _wsaSlots[slot]->setX(x);
- _wsaSlots[slot]->setY(y);
- _wsaSlots[slot]->setDrawPage(dstPage);
- _wsaSlots[slot]->displayFrame(frame, copyParam | 0xC000, 0, 0);
+ _wsaSlots[slot]->displayFrame(frame, dstPage, x, y, copyParam | 0xC000, 0, 0);
_screen->updateScreen();
if (backUp)
@@ -222,17 +219,13 @@ int KyraEngine_HoF::o2_displayWsaSequentialFramesLooping(EMCState *script) {
if (maxTimes > 1)
maxTimes = 1;
- _wsaSlots[slot]->setX(x);
- _wsaSlots[slot]->setY(y);
- _wsaSlots[slot]->setDrawPage(0);
-
_screen->hideMouse();
int curTime = 0;
while (curTime < maxTimes) {
if (startFrame < endFrame) {
for (int i = startFrame; i <= endFrame; ++i) {
uint32 endTime = _system->getMillis() + waitTime * _tickLength;
- _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags, 0, 0);
+ _wsaSlots[slot]->displayFrame(i, 0, x, y, 0xC000 | copyFlags, 0, 0);
if (!skipFlag()) {
_screen->updateScreen();
@@ -248,7 +241,7 @@ int KyraEngine_HoF::o2_displayWsaSequentialFramesLooping(EMCState *script) {
} else {
for (int i = startFrame; i >= endFrame; --i) {
uint32 endTime = _system->getMillis() + waitTime * _tickLength;
- _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags, 0, 0);
+ _wsaSlots[slot]->displayFrame(i, 0, x, y, 0xC000 | copyFlags, 0, 0);
if (!skipFlag()) {
_screen->updateScreen();
@@ -286,15 +279,11 @@ int KyraEngine_HoF::o2_displayWsaSequentialFrames(EMCState *script) {
uint16 index = stackPos(5);
uint16 copyParam = stackPos(6) | 0xc000;
- _wsaSlots[index]->setX(stackPos(0));
- _wsaSlots[index]->setY(stackPos(1));
- _wsaSlots[index]->setDrawPage(0);
-
_screen->hideMouse();
while (currentFrame <= lastFrame) {
uint32 endTime = _system->getMillis() + frameDelay;
- _wsaSlots[index]->displayFrame(currentFrame++, copyParam, 0, 0);
+ _wsaSlots[index]->displayFrame(currentFrame++, 0, stackPos(0), stackPos(1), copyParam, 0, 0);
if (!skipFlag()) {
_screen->updateScreen();
delayUntil(endTime);
@@ -315,10 +304,6 @@ int KyraEngine_HoF::o2_displayWsaSequence(EMCState *script) {
const bool doUpdate = (stackPos(4) != 0);
const uint16 copyParam = stackPos(5) | 0xc000;
- _wsaSlots[index]->setX(stackPos(0));
- _wsaSlots[index]->setY(stackPos(1));
- _wsaSlots[index]->setDrawPage(0);
-
_screen->hideMouse();
int currentFrame = 0;
@@ -326,7 +311,7 @@ int KyraEngine_HoF::o2_displayWsaSequence(EMCState *script) {
while (currentFrame <= lastFrame) {
uint32 endTime = _system->getMillis() + frameDelay;
- _wsaSlots[index]->displayFrame(currentFrame++, copyParam, 0, 0);
+ _wsaSlots[index]->displayFrame(currentFrame++, 0, stackPos(0), stackPos(1), copyParam, 0, 0);
if (!skipFlag()) {
if (doUpdate)
update();
diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp
index 4901b5e1c4..5eb86519a8 100644
--- a/engines/kyra/script_lok.cpp
+++ b/engines/kyra/script_lok.cpp
@@ -426,11 +426,8 @@ int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) {
int worldUpdate = stackPos(4);
int wsaFrame = 0;
- _movieObjects[wsaIndex]->setX(xpos);
- _movieObjects[wsaIndex]->setY(ypos);
- _movieObjects[wsaIndex]->setDrawPage(0);
while (running) {
- _movieObjects[wsaIndex]->displayFrame(wsaFrame++);
+ _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos);
_animator->_updateScreen = true;
if (wsaFrame >= _movieObjects[wsaIndex]->frames())
running = false;
@@ -461,10 +458,7 @@ int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) {
int waitTime = stackPos(3);
int wsaIndex = stackPos(4);
_screen->hideMouse();
- _movieObjects[wsaIndex]->setX(xpos);
- _movieObjects[wsaIndex]->setY(ypos);
- _movieObjects[wsaIndex]->setDrawPage(0);
- _movieObjects[wsaIndex]->displayFrame(frame);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
_animator->_updateScreen = true;
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
while (_system->getMillis() < continueTime) {
@@ -504,12 +498,9 @@ int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) {
int endFrame = stackPos(4);
int wsaIndex = stackPos(5);
_screen->hideMouse();
- _movieObjects[wsaIndex]->setX(xpos);
- _movieObjects[wsaIndex]->setY(ypos);
- _movieObjects[wsaIndex]->setDrawPage(0);
for (; startFrame <= endFrame; ++startFrame) {
uint32 nextRun = _system->getMillis() + delayTime * _tickLength;
- _movieObjects[wsaIndex]->displayFrame(startFrame);
+ _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos);
_animator->_updateScreen = true;
while (_system->getMillis() < nextRun) {
_sprites->updateSceneAnims();
@@ -691,10 +682,7 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) {
_screen->hideMouse();
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->setX(xpos);
- _movieObjects[wsaIndex]->setY(ypos);
- _movieObjects[wsaIndex]->setDrawPage(2);
- _movieObjects[wsaIndex]->displayFrame(frame);
+ _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos);
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
_sprites->updateSceneAnims();
@@ -759,17 +747,13 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
if (maxTime - 1 <= 0)
maxTime = 1;
- _movieObjects[wsaIndex]->setX(xpos);
- _movieObjects[wsaIndex]->setY(ypos);
- _movieObjects[wsaIndex]->setDrawPage(0);
-
// Workaround for bug #1498221 "KYRA1: Glitches when meeting Zanthia"
// the original didn't do a forced screen update after displaying a wsa frame
// while we have to do it, which make brandon disappear for a short moment,
// what shouldn't happen. So we're not updating the screen for this special
// case too.
if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) {
- _movieObjects[wsaIndex]->displayFrame(18);
+ _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos);
delay(waitTime * _tickLength);
return 0;
}
@@ -781,7 +765,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
int frame = startFrame;
while (endFrame >= frame) {
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->displayFrame(frame);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
if (waitTime)
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
@@ -799,7 +783,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) {
int frame = startFrame;
while (endFrame <= frame) {
uint32 continueTime = waitTime * _tickLength + _system->getMillis();
- _movieObjects[wsaIndex]->displayFrame(frame);
+ _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos);
if (waitTime)
_animator->_updateScreen = true;
while (_system->getMillis() < continueTime) {
@@ -1276,9 +1260,6 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_makeAmuletAppear(%p) ()", (const void *)script);
WSAMovie_v1 amulet(this);
amulet.open("AMULET.WSA", 1, 0);
- amulet.setX(224);
- amulet.setY(152);
- amulet.setDrawPage(0);
if (amulet.opened()) {
assert(_amuleteAnim);
_screen->hideMouse();
@@ -1297,7 +1278,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) {
if (code == 14)
snd_playSoundEffect(0x73);
- amulet.displayFrame(code);
+ amulet.displayFrame(code, 0, 224, 152);
_animator->_updateScreen = true;
while (_system->getMillis() < nextTime) {
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index d056352b36..13479799c7 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -131,9 +131,70 @@ int LoLEngine::olol_drawScene(EMCState *script) {
return 1;
}
+int LoLEngine::olol_moveParty(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveParty(%p) (%d)", (const void *)script, stackPos(0));
+ int mode = stackPos(0);
+ if (mode > 5 && mode < 10)
+ mode = (mode - 6 - _currentDirection) & 3;
+
+ Button b;
+ memset(&b, 0, sizeof(Button));
+
+ switch (mode) {
+ case 0:
+ clickedUpArrow(&b);
+ break;
+
+ case 1:
+ clickedRightArrow(&b);
+ break;
+
+ case 2:
+ clickedDownArrow(&b);
+ break;
+
+ case 3:
+ clickedLeftArrow(&b);
+ break;
+
+ case 4:
+ clickedTurnLeftArrow(&b);
+ break;
+
+ case 5:
+ clickedTurnRightArrow(&b);
+ break;
+
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ mode = ABS(mode - 10 - _currentDirection);
+ if (mode > 2)
+ mode = (mode ^ 2) * -1;
+
+ while (mode) {
+ if (mode > 0) {
+ clickedTurnRightArrow(&b);
+ mode--;
+ } else {
+ clickedTurnLeftArrow(&b);
+ mode++;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+
int LoLEngine::olol_delay(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_delay(%p) (%d)", (const void *)script, stackPos(0));
- delay(stackPos(0) * _tickLength);
+ delay(stackPos(0) * _tickLength, false, true);
return 1;
}
@@ -461,6 +522,20 @@ int LoLEngine::olol_getDirection(EMCState *script) {
return _currentDirection;
}
+int LoLEngine::olol_characterSurpriseFeedback(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterSurpriseFeedback(%p)", (const void *)script);
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1) || _characters[i].id >= 0)
+ continue;
+ int s = -_characters[i].id;
+ int sfx = (s == 1) ? 136 : ((s == 5) ? 50 : ((s == 8) ? 49 : ((s == 9) ? 48 : 0)));
+ if (sfx)
+ snd_playSoundEffect(sfx, -1);
+ return 1;
+ }
+ return 1;
+}
+
int LoLEngine::olol_setMusicTrack(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setMusicTrack(%p) (%d)", (const void *)script, stackPos(0));
_curMusicTheme = stackPos(0);
@@ -539,7 +614,7 @@ int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) {
int LoLEngine::olol_getGlobalScriptVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getGlobalScriptVar(%p) (%d)", (const void *)script, stackPos(0));
- assert(stackPos(0) < 16);
+ assert(stackPos(0) < 24);
return _globalScriptVars[stackPos(0)];
}
@@ -701,6 +776,8 @@ int LoLEngine::olol_copyRegion(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_copyRegion(%p) (%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));
_screen->copyRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), Screen::CR_NO_P_CHECK);
+ if (!stackPos(7))
+ _screen->updateScreen();
return 1;
}
@@ -765,7 +842,7 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) {
int LoLEngine::olol_fadeSequencePalette(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script);
memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180);
- _screen->loadSpecialColours(_screen->getPalette(3));
+ _screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
return 1;
@@ -1171,6 +1248,13 @@ int LoLEngine::olol_playCharacterScriptChat(EMCState *script) {
return playCharacterScriptChat(stackPos(0), stackPos(1), 1, getLangString(stackPos(2)), script, 0, 3);
}
+int LoLEngine::olol_playEnvironmentalSfx(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playEnvironmentalSfx(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ uint16 block = (stackPos(1) == -1) ? _currentBlock : stackPos(1);
+ snd_processEnvironmentalSoundEffect(stackPos(0), block);
+ return 1;
+}
+
int LoLEngine::olol_update(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_update(%p)", (const void *)script);
update();
@@ -1239,6 +1323,36 @@ int LoLEngine::olol_countBlockItems(EMCState *script) {
return res;
}
+int LoLEngine::olol_characterSkillTest(EMCState *script){
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterSkillTest(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ int skill = stackPos(0);
+ int n = countActiveCharacters();
+ uint m = 0;
+ int c = 0;
+
+ for (int i = 0; i < n ; i++) {
+ uint v = _characters[i].skillModifiers[skill] + _characters[i].skillLevels[skill] + 25;
+ if (v > m) {
+ m = v;
+ c = i;
+ }
+ }
+
+ return (_rnd.getRandomNumberRng(1, 100) > m) ? -1 : c;
+}
+
+int LoLEngine::olol_countActiveMonsters(EMCState *script){
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_countActiveMonsters(%p)", (const void *)script);
+ int res = 0;
+
+ for (int i = 0; i < 30; i++) {
+ if (_monsters[i].hitPoints > 0 && _monsters[i].mode != 13)
+ res++;
+ }
+
+ return res;
+}
+
int LoLEngine::olol_stopCharacterSpeech(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopCharacterSpeech(%p)", (const void *)script);
snd_stopSpeech(1);
@@ -1301,6 +1415,32 @@ int LoLEngine::olol_calcInflictableDamagePerItem(EMCState *script) {
return calcInflictableDamagePerItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
}
+int LoLEngine::olol_distanceAttack(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_distanceAttack(%p) (%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));
+
+ uint16 fX = stackPos(3);
+ uint16 fY = stackPos(4);
+
+ if (!(stackPos(8) & 0x8000))
+ fX = fY = 0x80;
+
+ uint16 x = 0;
+ uint16 y = 0;
+ calcCoordinates(x, y, stackPos(2), fX, fY);
+
+ if (launchObject(stackPos(0), stackPos(1), x, y, stackPos(5), stackPos(6) << 1, stackPos(7), stackPos(8), 0x3f))
+ return 1;
+
+ deleteItem(stackPos(1));
+ return 0;
+}
+
+int LoLEngine::olol_removeCharacterEffects(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_removeCharacterEffects(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ removeCharacterEffects(&_characters[stackPos(0)], stackPos(1), stackPos(2));
+ return 1;
+}
+
int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_objectLeavesLevel(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int o = _levelBlockProperties[stackPos(0)].assignedObjects;
@@ -1347,6 +1487,12 @@ int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
return res;
}
+int LoLEngine::olol_addSpellToScroll(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_addSpellToScroll(%p) (%d)", (const void *)script, stackPos(0));
+ addSpellToScroll(stackPos(0), stackPos(1));
+ return 1;
+}
+
int LoLEngine::olol_playDialogueTalkText(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playDialogueTalkText(%p) (%d)", (const void *)script, stackPos(0));
int track = stackPos(0);
@@ -1388,6 +1534,40 @@ int LoLEngine::olol_suspendMonster(EMCState *script) {
return 1;
}
+int LoLEngine::olol_triggerEventOnMouseButtonRelease(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_triggerEventOnMouseButtonRelease(%p) (%d)", (const void *)script, stackPos(0));
+ gui_notifyButtonListChanged();
+ snd_characterSpeaking();
+
+ int f = checkInput(0);
+ removeInputTop();
+ if (f == 0 || (f & 0x800))
+ return 0;
+
+ int evt = stackPos(0);
+ if (evt) {
+ gui_triggerEvent(evt);
+ _seqTrigger = 1;
+ } else {
+ removeInputTop();
+ }
+
+ return 1;
+}
+
+int LoLEngine::olol_printWindowText(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_printWindowText(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ int dim = stackPos(0);
+ int flg = stackPos(1);
+ _screen->setScreenDim(dim);
+ if (flg & 1)
+ _txt->clearCurDim();
+ if (flg & 3)
+ _txt->resetDimTextPositions(dim);
+ _txt->printDialogueText(dim, getLangString(stackPos(2)), script, 0, 3);
+ return 1;
+}
+
int LoLEngine::olol_setUnkDoorVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setUnkDoorVar(%p) (%d)", (const void *)script, stackPos(0));
_emcDoorState = stackPos(0);
@@ -1476,6 +1656,11 @@ int LoLEngine::olol_checkNeedSceneRestore(EMCState *script) {
return _needSceneRestore;
}
+int LoLEngine::olol_castSpell(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_castSpell(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ return castSpell(stackPos(0), stackPos(1), stackPos(2));
+}
+
int LoLEngine::olol_disableControls(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_disableControls(%p) (%d)", (const void *)script, stackPos(0));
return gui_disableControls(stackPos(0));
@@ -1575,10 +1760,7 @@ int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) {
int w2 = (w1 * factor) / 100;
int h2 = (h1 * factor) / 100;
- anim->wsa->setDrawPage(2);
- anim->wsa->setX(x1);
- anim->wsa->setY(y1);
- anim->wsa->displayFrame(frame, anim->wsaCopyParams & 0xF0FF, 0, 0);
+ anim->wsa->displayFrame(frame, 2, x1, y1, anim->wsaCopyParams & 0xF0FF, 0, 0);
_screen->wsaFrameAnimationStep(x1, y1, x2, y2, w1, h1, w2, h2, 2, 8, 0);
_screen->checkedPageUpdate(8, 4);
_screen->updateScreen();
@@ -1638,7 +1820,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
case 1:
tmp = _screen->getPalette(3);
memcpy(tmp + 0x180, _screen->_currentPalette + 0x180, 0x180);
- _screen->loadSpecialColours(tmp);
+ _screen->loadSpecialColors(tmp);
_screen->fadePalette(tmp, 10);
_screen->_fadeFlag = 0;
break;
@@ -1649,7 +1831,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
case 3:
tmp = _screen->getPalette(3);
- _screen->loadSpecialColours(tmp);
+ _screen->loadSpecialColors(tmp);
_screen->fadePalette(tmp, 10);
_screen->_fadeFlag = 0;
break;
@@ -1664,7 +1846,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
case 5:
tmp = _screen->getPalette(3);
- _screen->loadSpecialColours(tmp);
+ _screen->loadSpecialColors(tmp);
_screen->fadePalette(_screen->getPalette(1), 10);
_screen->_fadeFlag = 0;
break;
@@ -1679,6 +1861,8 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_copyRegion(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_copyRegion(%p, %p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void*)tim, (const void*)param, param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]);
_screen->copyRegion(param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], Screen::CR_NO_P_CHECK);
+ if (!param[7])
+ _screen->updateScreen();
return 1;
}
@@ -1691,8 +1875,8 @@ int LoLEngine::tlol_characterChat(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_drawScene(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_drawScene(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
gui_drawScene(param[0]);
- if (_sceneDrawPage2 != 2 && param[0] == 2)
- _screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage2, 2, Screen::CR_NO_P_CHECK);
+ //if (_sceneDrawPage2 != 2 && param[0] == 2)
+ // _screen->copyRegion(112 << 3, 0, 112 << 3, 0, 176 << 3, 120, _sceneDrawPage2, 2, Screen::CR_NO_P_CHECK);
return 1;
}
@@ -1774,7 +1958,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(o1_getRand);
// 0x04
- OpcodeUnImpl();
+ Opcode(olol_moveParty);
OpcodeUnImpl();
Opcode(olol_delay);
Opcode(olol_setGameFlag);
@@ -1811,7 +1995,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x1C
Opcode(olol_getDirection);
- OpcodeUnImpl();
+ Opcode(olol_characterSurpriseFeedback);
Opcode(olol_setMusicTrack);
Opcode(olol_setSequenceButtons);
@@ -1912,7 +2096,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_update);
// 0x60
- OpcodeUnImpl();
+ Opcode(olol_playEnvironmentalSfx);
Opcode(olol_healCharacter);
Opcode(olol_drawExitButton);
Opcode(olol_loadSoundFile);
@@ -1921,10 +2105,10 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_playMusicTrack);
OpcodeUnImpl();
Opcode(olol_countBlockItems);
- OpcodeUnImpl();
+ Opcode(olol_characterSkillTest);
// 0x68
- OpcodeUnImpl();
+ Opcode(olol_countActiveMonsters);
OpcodeUnImpl();
Opcode(olol_stopCharacterSpeech);
Opcode(olol_setPaletteBrightness);
@@ -1938,8 +2122,8 @@ void LoLEngine::setupOpcodeTable() {
// 0x70
Opcode(olol_deleteLevelItem);
Opcode(olol_calcInflictableDamagePerItem);
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_distanceAttack);
+ Opcode(olol_removeCharacterEffects);
// 0x74
OpcodeUnImpl();
@@ -1948,7 +2132,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
// 0x78
- OpcodeUnImpl();
+ Opcode(olol_addSpellToScroll);
OpcodeUnImpl();
Opcode(olol_playDialogueTalkText);
Opcode(olol_checkMonsterTypeHostility);
@@ -1961,8 +2145,8 @@ void LoLEngine::setupOpcodeTable() {
// 0x80
OpcodeUnImpl();
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_triggerEventOnMouseButtonRelease);
+ Opcode(olol_printWindowText);
OpcodeUnImpl();
// 0x84
@@ -2027,7 +2211,7 @@ void LoLEngine::setupOpcodeTable() {
// 0xAC
OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_castSpell);
OpcodeUnImpl();
OpcodeUnImpl();
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 4165053c15..cae74ef82b 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -420,10 +420,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
screen()->updateScreen();
}
- anim->wsa->setX(x);
- anim->wsa->setY(y);
- anim->wsa->setDrawPage(0);
- anim->wsa->displayFrame(0, 0, 0, 0);
+ anim->wsa->displayFrame(0, 0, 0, 0, 0);
}
if (wsaFlags & 2)
@@ -581,12 +578,9 @@ int TIMInterpreter::cmd_stopFunc(const uint16 *param) {
int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) {
Animation &anim = _animations[param[0]];
const int frame = param[1];
-
- anim.wsa->setX(anim.x);
- anim.wsa->setY(anim.y);
- anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2);
- anim.wsa->displayFrame(frame, anim.wsaCopyParams & 0xF0FF, 0, 0);
- if (!_drawPage2)
+ int page = (anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2;
+ anim.wsa->displayFrame(frame, page, anim.x, anim.y, anim.wsaCopyParams & 0xF0FF, 0, 0);
+ if (!page)
screen()->updateScreen();
return 1;
}
@@ -829,17 +823,11 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
_screen->fadeToBlack(10);
}
- if (wsaFlags & 7) {
- _screen->hideMouse();
- anim->wsa->setDrawPage(0);
- anim->wsa->setX(x);
- anim->wsa->setY(y);
- anim->wsa->displayFrame(0, 0);
- _screen->showMouse();
- }
+ if (wsaFlags & 7)
+ anim->wsa->displayFrame(0, 0, x, y, 0);
if (wsaFlags & 3) {
- _screen->loadSpecialColours(_screen->getPalette(3));
+ _screen->loadSpecialColors(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
}
@@ -938,12 +926,8 @@ void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) {
anim->curFrame = p->firstFrame;
anim->cyclesCompleted = 0;
- if (anim->wsa) {
- anim->wsa->setX(anim->x);
- anim->wsa->setY(anim->y);
- anim->wsa->setDrawPage(0);
- anim->wsa->displayFrame(anim->curFrame - 1, 0, 0);
- }
+ if (anim->wsa)
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0);
}
void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) {
@@ -1002,36 +986,26 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) {
anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
- anim->wsa->setX(anim->x);
- anim->wsa->setY(anim->y);
- anim->wsa->setDrawPage(0);
- anim->wsa->displayFrame(anim->curFrame - 1, 0);
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0);
anim->nextFrame += _system->getMillis();
}
void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {
Animation *anim = &_animations[animIndex];
- anim->wsa->setX(anim->x);
- anim->wsa->setY(anim->y);
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->setDrawPage(2);
- anim->wsa->displayFrame(i - 1, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2);
+ anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2);
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
_screen->updateScreen();
} else {
- anim->wsa->setDrawPage(0);
- anim->wsa->displayFrame(i - 1, 0);
+ anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0);
_screen->updateScreen();
}
- while ((int)(next - _system->getMillis()) > 0) {
- _vm->updateInput();
- _vm->delay(_vm->_tickLength);
- }
+ _vm->delayUntil(next);
}
}
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index 3391c51ab7..cf8476eceb 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -132,7 +132,6 @@ void SeqPlayer::s1_wsaOpen() {
_seqWsaCurDecodePage = _seqMovies[wsaObj].page = (offscreenDecode == 0) ? 0 : 3;
if (!_seqMovies[wsaObj].movie)
_seqMovies[wsaObj].movie = _vm->createWSAMovie();
- _seqMovies[wsaObj].movie->setDrawPage(_seqMovies[wsaObj].page);
_seqMovies[wsaObj].movie->open(_vm->seqWSATable()[wsaObj], offscreenDecode, 0);
_seqMovies[wsaObj].frame = 0;
_seqMovies[wsaObj].numFrames = _seqMovies[wsaObj].movie->frames() - 1;
@@ -152,9 +151,7 @@ void SeqPlayer::s1_wsaPlayFrame() {
_seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2;
_seqMovies[wsaObj].pos.y = *_seqData++;
assert(_seqMovies[wsaObj].movie);
- _seqMovies[wsaObj].movie->setX(_seqMovies[wsaObj].pos.x);
- _seqMovies[wsaObj].movie->setY(_seqMovies[wsaObj].pos.y);
- _seqMovies[wsaObj].movie->displayFrame(frame);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
_seqMovies[wsaObj].frame = frame;
}
@@ -166,7 +163,7 @@ void SeqPlayer::s1_wsaPlayNextFrame() {
frame = 0;
_seqMovies[wsaObj].frame = 0;
}
- _seqMovies[wsaObj].movie->displayFrame(frame);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
}
void SeqPlayer::s1_wsaPlayPrevFrame() {
@@ -177,7 +174,7 @@ void SeqPlayer::s1_wsaPlayPrevFrame() {
frame = _seqMovies[wsaObj].numFrames;
_seqMovies[wsaObj].frame = frame;
} else {
- _seqMovies[wsaObj].movie->displayFrame(frame);
+ _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y);
}
}
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 63239ccf63..3ed022a47a 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -103,10 +103,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
_seqWsa->close();
_seqWsa->open(cseq.wsaFile, 0, _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
- _seqWsa->setX(cseq.xPos);
- _seqWsa->setY(cseq.yPos);
- _seqWsa->setDrawPage(2);
- _seqWsa->displayFrame(0, 0);
+ _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0);
}
if (cseq.flags & 4) {
@@ -178,10 +175,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
if (_seqWsa) {
int f = _seqWsaCurrentFrame % _seqWsa->frames();
- _seqWsa->setX(cseq.xPos);
- _seqWsa->setY(cseq.yPos);
- _seqWsa->setDrawPage(2);
- _seqWsa->displayFrame(f, 0);
+ _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0);
}
_screen->copyPage(2, 12);
@@ -2245,9 +2239,6 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) {
_activeWSA[wsaNum].endFrame = s.endFrame;
_activeWSA[wsaNum].startFrame = _activeWSA[wsaNum].currentFrame = s.startframe;
_activeWSA[wsaNum].frameDelay = s.frameDelay;
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
- _activeWSA[wsaNum].movie->setDrawPage(_screen->_curPage);
_activeWSA[wsaNum].callback = _callbackN[seqNum];
_activeWSA[wsaNum].control = s.wsaControl;
@@ -2274,61 +2265,40 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) {
switch (command) {
case 0:
- _activeWSA[wsaNum].movie->setDrawPage(8);
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->setX(xa);
- _activeWSA[wsaNum].movie->setY(ya);
- _activeWSA[wsaNum].movie->displayFrame(0, 0);
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2);
break;
case 1:
- _activeWSA[wsaNum].movie->setDrawPage(8);
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->setX(xa);
- _activeWSA[wsaNum].movie->setY(ya);
- _activeWSA[wsaNum].movie->displayFrame(0, 0);
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1);
break;
case 2:
seq_waitForTextsTimeout();
- _activeWSA[wsaNum].movie->setDrawPage(8);
xa = -_activeWSA[wsaNum].movie->xAdd();
ya = -_activeWSA[wsaNum].movie->yAdd();
- _activeWSA[wsaNum].movie->setX(xa);
- _activeWSA[wsaNum].movie->setY(ya);
- _activeWSA[wsaNum].movie->displayFrame(0x15, 0);
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
+ _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0);
seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2);
break;
case 3:
_screen->copyPage(2, 10);
- _activeWSA[wsaNum].movie->setDrawPage(2);
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
- _activeWSA[wsaNum].movie->displayFrame(0, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0);
_screen->copyPage(2, 12);
seq_cmpFadeFrame("scene2.cmp");
break;
case 4:
_screen->copyPage(2, 10);
- _activeWSA[wsaNum].movie->setDrawPage(2);
- _activeWSA[wsaNum].movie->setX(0);
- _activeWSA[wsaNum].movie->setY(0);
- _activeWSA[wsaNum].movie->displayFrame(0, 0);
+ _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0);
_screen->copyPage(2, 12);
seq_cmpFadeFrame("scene3.cmp");
break;
@@ -2414,15 +2384,11 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) {
}
if (_activeWSA[wsaNum].movie) {
- _activeWSA[wsaNum].movie->setDrawPage(2);
- _activeWSA[wsaNum].movie->setX(_activeWSA[wsaNum].x);
- _activeWSA[wsaNum].movie->setY(_activeWSA[wsaNum].y);
-
if (_activeWSA[wsaNum].flags & 0x20) {
- _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 0x4000);
+ _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000);
_activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay;
} else {
- _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 0x4000);
+ _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000);
}
}
@@ -2532,12 +2498,8 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i
curframe = firstframe;
_seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
- if (wsa) {
- wsa->setDrawPage(2);
- wsa->setX(wsaXpos);
- wsa->setY(wsaYpos);
- wsa->displayFrame(curframe % wsa->frames(), 0);
- }
+ if (wsa)
+ wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0);
_screen->copyPage(2, 12);
@@ -2794,24 +2756,21 @@ void KyraEngine_HoF::seq_showStarcraftLogo() {
return;
}
_screen->hideMouse();
- ci->setX(0);
- ci->setY(0);
- ci->setDrawPage(2);
- ci->displayFrame(0, 0);
+ ci->displayFrame(0, 2, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->fadeFromBlack();
for (int i = 1; i < endframe; i++) {
_seqEndTime = _system->getMillis() + 50;
if (skipFlag())
break;
- ci->displayFrame(i, 0);
+ ci->displayFrame(i, 2, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(_seqEndTime - _system->getMillis());
}
if (!skipFlag()) {
_seqEndTime = _system->getMillis() + 50;
- ci->displayFrame(0, 0);
+ ci->displayFrame(0, 2, 0, 0, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(_seqEndTime - _system->getMillis());
@@ -2943,16 +2902,12 @@ void KyraEngine_HoF::seq_makeBookAppear() {
_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);
+ _invWsa.wsa->displayFrame(_invWsa.curFrame, _invWsa.page, 0, 0, 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);
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 6f08fd71f2..643d8a1d05 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -984,8 +984,6 @@ int KyraEngine_LoK::seq_playEnd() {
_finalA = new WSAMovie_v1(this);
assert(_finalA);
_finalA->open("finald.wsa", 1, 0);
- _finalA->setX(8); _finalA->setY(8);
- _finalA->setDrawPage(0);
delayUntil(nextTime);
snd_playSoundEffect(0x40);
for (int i = 0; i < 22; ++i) {
@@ -995,7 +993,7 @@ int KyraEngine_LoK::seq_playEnd() {
else if (i == 20)
snd_playSoundEffect(0x0E);
nextTime = _system->getMillis() + 8 * _tickLength;
- _finalA->displayFrame(i);
+ _finalA->displayFrame(i, 0, 8, 8);
_screen->updateScreen();
}
delete _finalA;
@@ -1232,10 +1230,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 2:
if (_system->getMillis() >= timer2) {
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1250,10 +1245,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
if (_system->getMillis() < timer1) {
if (_system->getMillis() >= timer2) {
frame = _rnd.getRandomNumberRng(14, 17);
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
}
@@ -1265,10 +1257,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 4:
if (_system->getMillis() >= timer2) {
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1282,10 +1271,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 5:
if (_system->getMillis() >= timer2) {
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1299,10 +1285,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 6:
if (_unkEndSeqVar4) {
if (frame <= 33 && _system->getMillis() >= timer2) {
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1327,10 +1310,7 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 8:
if (_system->getMillis() >= timer2) {
- _finalA->setX(8);
- _finalA->setY(46);
- _finalA->setDrawPage(0);
- _finalA->displayFrame(frame);
+ _finalA->displayFrame(frame, 0, 8, 46);
_screen->updateScreen();
timer2 = _system->getMillis() + 8 * _tickLength;
++frame;
@@ -1345,12 +1325,9 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 9:
snd_playSoundEffect(12);
snd_playSoundEffect(12);
- _finalC->setX(16);
- _finalC->setY(50);
- _finalC->setDrawPage(0);
for (int i = 0; i < 18; ++i) {
timer2 = _system->getMillis() + 4 * _tickLength;
- _finalC->displayFrame(i);
+ _finalC->displayFrame(i, 0, 16, 50);
_screen->updateScreen();
delayUntil(timer2);
}
@@ -1554,19 +1531,16 @@ int KyraEngine_LoK::handleBeadState() {
if (beadState2.dstX == 290) {
_screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect);
uint32 nextRun = 0;
- _finalB->setX(224);
- _finalB->setY(8);
- _finalB->setDrawPage(0);
for (int i = 0; i < 8; ++i) {
nextRun = _system->getMillis() + _tickLength;
- _finalB->displayFrame(i);
+ _finalB->displayFrame(i, 0, 224, 8);
_screen->updateScreen();
delayUntil(nextRun);
}
snd_playSoundEffect(0x0D);
for (int i = 7; i >= 0; --i) {
nextRun = _system->getMillis() + _tickLength;
- _finalB->displayFrame(i);
+ _finalB->displayFrame(i, 0, 224, 8);
_screen->updateScreen();
delayUntil(nextRun);
}
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index 720e8fdf47..6375b614fe 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -213,10 +213,8 @@ int LoLEngine::chooseCharacter() {
if (!_chargenWSA->open("CHARGEN.WSA", 1, 0))
error("Couldn't load CHARGEN.WSA");
- _chargenWSA->setX(113);
- _chargenWSA->setY(0);
- _chargenWSA->setDrawPage(2);
- _chargenWSA->displayFrame(0, 0, 0, 0);
+
+ _chargenWSA->displayFrame(0, 2, 113, 0, 0, 0, 0);
_screen->setFont(Screen::FID_9_FNT);
_screen->_curPage = 2;
@@ -305,15 +303,11 @@ void LoLEngine::kingSelectionIntro() {
_sound->voicePlay("KING01");
- _chargenWSA->setX(113);
- _chargenWSA->setY(0);
- _chargenWSA->setDrawPage(0);
-
int index = 4;
- while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !shouldQuit() && !skipFlag()) {
+ while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING01"))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) {
index = MAX(index, 4);
- _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0);
+ _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0);
_screen->copyRegion(_selectionPosTable[_selectionChar1IdxTable[index]*2+0], _selectionPosTable[_selectionChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_selectionChar2IdxTable[index]*2+0], _selectionPosTable[_selectionChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_selectionChar3IdxTable[index]*2+0], _selectionPosTable[_selectionChar3IdxTable[index]*2+1], _charPreviews[2].x, _charPreviews[2].y, 32, 32, 4, 0);
@@ -326,12 +320,15 @@ void LoLEngine::kingSelectionIntro() {
_system->delayMillis(10);
}
- index = (index + 1) % 22;
+ if (_speechFlag)
+ index = (index + 1) % 22;
+ else if (++index >= 27)
+ break;
}
resetSkipFlag();
- _chargenWSA->displayFrame(0x10, 0, 0, 0);
+ _chargenWSA->displayFrame(0x10, 0,113, 0, 0, 0, 0);
_screen->updateScreen();
_sound->voiceStop("KING01");
}
@@ -347,13 +344,9 @@ void LoLEngine::kingSelectionReminder() {
_sound->voicePlay("KING02");
- _chargenWSA->setX(113);
- _chargenWSA->setY(0);
- _chargenWSA->setDrawPage(0);
-
int index = 0;
- while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !shouldQuit() && index < 15) {
- _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 0, 0);
+ while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING02"))) && _charSelection == -1 && !shouldQuit() && index < 15) {
+ _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar3IdxTable[index]*2+0], _selectionPosTable[_reminderChar3IdxTable[index]*2+1], _charPreviews[2].x, _charPreviews[2].y, 32, 32, 4, 0);
@@ -366,7 +359,10 @@ void LoLEngine::kingSelectionReminder() {
_system->delayMillis(10);
}
- index = (index + 1) % 22;
+ if (_speechFlag)
+ index = (index + 1) % 22;
+ else if (++index >= 27)
+ break;
}
_sound->voiceStop("KING02");
@@ -377,15 +373,11 @@ void LoLEngine::kingSelectionOutro() {
_sound->voicePlay("KING03");
- _chargenWSA->setX(113);
- _chargenWSA->setY(0);
- _chargenWSA->setDrawPage(0);
-
int index = 0;
- while (_sound->voiceIsPlaying("KING03") && !shouldQuit() && !skipFlag()) {
+ while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING03"))) && !shouldQuit() && !skipFlag()) {
index = MAX(index, 4);
- _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0);
+ _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0);
_screen->updateScreen();
uint32 waitEnd = _system->getMillis() + 8 * _tickLength;
@@ -394,12 +386,15 @@ void LoLEngine::kingSelectionOutro() {
_system->delayMillis(10);
}
- index = (index + 1) % 22;
+ if (_speechFlag)
+ index = (index + 1) % 22;
+ else if (++index >= 27)
+ break;
}
resetSkipFlag();
- _chargenWSA->displayFrame(0x10, 0, 0, 0);
+ _chargenWSA->displayFrame(0x10, 0, 113, 0, 0, 0, 0);
_screen->updateScreen();
_sound->voiceStop("KING03");
}
@@ -598,10 +593,7 @@ void LoLEngine::showStarcraftLogo() {
return;
}
_screen->hideMouse();
- ci->setX(32);
- ci->setY(80);
- ci->setDrawPage(2);
- ci->displayFrame(0, 0);
+ ci->displayFrame(0, 2, 32, 80, 0);
_screen->copyPage(2, 0);
_screen->fadeFromBlack();
int inputFlag = 0;
@@ -609,7 +601,7 @@ void LoLEngine::showStarcraftLogo() {
inputFlag = checkInput(0) & 0xff;
if (shouldQuit() || inputFlag)
break;
- ci->displayFrame(i, 0);
+ ci->displayFrame(i, 2, 32, 80, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(4 * _tickLength);
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 4aacd40658..14e63c81a6 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -188,6 +188,13 @@ bool Sound::voiceIsPlaying(const char *file) {
return res;
}
+bool Sound::allVoiceChannelsPlaying() {
+ for (int i = 0; i < kNumChannelHandles; ++i)
+ if (!_mixer->isSoundHandleActive(_soundChannels[i].channelHandle))
+ return false;
+ return true;
+}
+
uint32 Sound::voicePlayedTime(const char *file) {
if (!file)
return 0;
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 565e02e917..52334806ad 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -213,6 +213,13 @@ public:
bool voiceIsPlaying(const char *file = 0);
/**
+ * Checks if all voice handles are used.
+ *
+ * @return false when a handle is free, else true
+ */
+ bool allVoiceChannelsPlaying();
+
+ /**
* Checks how long a voice has been playing
*
* @return time in milliseconds
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 7f43f8e5b1..de81b667f4 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -2714,7 +2714,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
}
- finOut /= 4;
+ finOut >>= 1;
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
}
@@ -2887,7 +2887,7 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
finOut += _rhChan[ii].out;
}
- finOut *= 3;
+ finOut <<= 2;
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
@@ -3381,7 +3381,7 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) {
break;
};
- int32 finOut = ((output * 3) / ((_numChan + _numSSG - 3) / 3));
+ int32 finOut = ((output << 2) / ((_numChan + _numSSG - 3) / 3));
if (_chanInternal[i].enableLeft)
*leftSample += finOut;
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index daff86545c..acef7cd426 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -372,7 +372,7 @@ void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, int id) {
}
int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, int testFlag, int wallFlag) {
- _monsterLastWalkDirection = 0;
+ _objectLastDirection = 0;
int x2 = 0;
int y2 = 0;
int xOffs = 0;
@@ -390,7 +390,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in
if (x & 0x80) {
if (((x & 0xff) + objectWidth) & 0xff00) {
xOffs = 1;
- _monsterLastWalkDirection = 2;
+ _objectLastDirection = 2;
x2 = x + objectWidth;
r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, objectWidth, testFlag, wallFlag);
@@ -406,7 +406,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in
} else {
if (((x & 0xff) - objectWidth) & 0xff00) {
xOffs = -1;
- _monsterLastWalkDirection = 6;
+ _objectLastDirection = 6;
x2 = x - objectWidth;
r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, objectWidth, testFlag, wallFlag);
@@ -424,7 +424,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in
if (y & 0x80) {
if (((y & 0xff) + objectWidth) & 0xff00) {
yOffs = 1;
- _monsterLastWalkDirection = 4;
+ _objectLastDirection = 4;
y2 = y + objectWidth;
r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, objectWidth, testFlag, wallFlag);
@@ -434,13 +434,14 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in
r = checkBlockOccupiedByParty(x, y + yOffs, testFlag);
if (r)
return 4;
+ flag &= 1;
} else {
flag = 0;
}
} else {
if (((y & 0xff) - objectWidth) & 0xff00) {
yOffs = -1;
- _monsterLastWalkDirection = 0;
+ _objectLastDirection = 0;
y2 = y - objectWidth;
r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, objectWidth, testFlag, wallFlag);
@@ -450,6 +451,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in
r = checkBlockOccupiedByParty(x, y + yOffs, testFlag);
if (r)
return 4;
+ flag &= 1;
} else {
flag = 0;
}
@@ -517,11 +519,11 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) {
return (r- (r >> 1));
}
-bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) {
+int LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) {
if ((testFlag & 4) && (_currentBlock == calcBlockIndex(x, y)))
- return true;
+ return 1;
- return false;
+ return 0;
}
void LoLEngine::drawBlockObjects(int blockArrayIndex) {
@@ -1191,8 +1193,8 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
if (walkMonsterCheckDest(monster->x, monster->y, monster, 4) != 1)
return;
- _monsterLastWalkDirection ^= 4;
- setMonsterDirection(monster, _monsterLastWalkDirection);
+ _objectLastDirection ^= 4;
+ setMonsterDirection(monster, _objectLastDirection);
} else {
setMonsterDirection(monster, s);
if (monster->numDistAttacks) {
@@ -1208,7 +1210,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
int fx = 0;
int fy = 0;
- getNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _monsterLastWalkDirection : s);
+ getNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _objectLastDirection : s);
placeMonster(monster, fx, fy);
}
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 02c3c4316e..921402b582 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -44,7 +44,7 @@
namespace Kyra {
-#define RESFILE_VERSION 45
+#define RESFILE_VERSION 46
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -449,7 +449,9 @@ bool StaticResource::init() {
{ lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" },
//{ lolMapPal, kRawData, "MAP.PAL" },
- { lolHealShapeFrames, kRawData, "MHEAL.SHP" },
+ { lolSpellbookAnim, kRawData, "MBOOKA.DEF" },
+ { lolSpellbookCoords, kRawData, "MBOOKC.DEF" },
+ { lolHealShapeFrames, kRawData, "MHEAL.SHP" },
{ 0, 0, 0 }
};
@@ -1047,8 +1049,12 @@ bool StaticResource::loadSpellData(const char *filename, void *&ptr, int &size)
t->spellNameCode = file->readUint16LE();
for (int ii = 0; ii < 4; ii++)
t->mpRequired[ii] = file->readUint16LE();
- for (int ii = 0; ii < 8; ii++)
- t->unkArr[ii] = file->readUint16LE();
+ t->field_a = file->readUint16LE();
+ t->field_c = file->readUint16LE();
+ for (int ii = 0; ii < 4; ii++)
+ t->hpRequired[ii] = file->readUint16LE();
+ t->field_16 = file->readUint16LE();
+ t->field_18 = file->readUint16LE();
t->flags = file->readUint16LE();
};
@@ -1849,6 +1855,8 @@ void LoLEngine::initStaticResource() {
memcpy (_mapCursorOverlay, tmp, tmpSize);
_staticres->unloadId(lolMapCursorOvl);
+ _updateSpellBookCoords = _staticres->loadRawData(lolSpellbookCoords, _updateSpellBookCoordsSize);
+ _updateSpellBookAnimData = _staticres->loadRawData(lolSpellbookAnim, _updateSpellBookAnimDataSize);
_healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize);
// assign music data
@@ -1962,11 +1970,11 @@ void LoLEngine::assignButtonCallback(Button *button, int index) {
cb(clickedScroll),
cb(clickedScroll),
cb(clickedScroll),
- cb(clickedUnk23),
- cb(clickedUnk23),
- cb(clickedUnk23),
- cb(clickedUnk23),
- cb(clickedUnk24),
+ cb(clickedSpellTargetCharacter),
+ cb(clickedSpellTargetCharacter),
+ cb(clickedSpellTargetCharacter),
+ cb(clickedSpellTargetCharacter),
+ cb(clickedSpellTargetScene),
cb(clickedSceneThrowItem),
cb(clickedSceneThrowItem),
cb(clickedOptions),
@@ -2950,6 +2958,11 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = {
{ 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 },
{ 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
{ 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 },
+ { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only)
{ 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (3 entries, floppy version only)
};
@@ -2967,6 +2980,11 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = {
{ 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 },
{ 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
{ 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 },
+ { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here)
{ 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 } // Main menu box (3 entries)
};
@@ -2986,7 +3004,7 @@ const LoLEngine::CharacterPrev LoLEngine::_charPreviews[] = {
{ "Conrad", 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } }
};
-const uint8 LoLEngine::_chargenFrameTable[] = {
+const uint8 LoLEngine::_chargenFrameTableTalkie[] = {
0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x04, 0x03, 0x02, 0x01,
0x00, 0x00, 0x01, 0x02, 0x03,
@@ -2995,6 +3013,12 @@ const uint8 LoLEngine::_chargenFrameTable[] = {
0x0E, 0x0F, 0x10, 0x11, 0x12
};
+const uint8 LoLEngine::_chargenFrameTableFloppy[] = {
+ 0, 1, 2, 3, 4, 5, 4, 3, 2,
+ 1, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
const uint16 LoLEngine::_selectionPosTable[] = {
0x6F, 0x00, 0x8F, 0x00, 0xAF, 0x00, 0xCF, 0x00,
0xEF, 0x00, 0x6F, 0x20, 0x8F, 0x20, 0xAF, 0x20,
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
index 9616596710..1091fd3a4c 100644
--- a/engines/kyra/text_lol.cpp
+++ b/engines/kyra/text_lol.cpp
@@ -33,7 +33,7 @@
namespace Kyra {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen),
- _scriptParameter(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true), _lineCount(0),
+ _scriptParameter(0), _animWidth(0), _animColor1(0), _animColor2(0), _animFlag(true), _lineCount(0),
_printFlag(false), _lineWidth(0), _numCharsTotal(0), _numCharsLeft(0), _numCharsPrinted(0) {
memset(_stringParameters, 0, 15 * sizeof(char*));
@@ -102,7 +102,7 @@ void TextDisplayer_LoL::expandField() {
if (_vm->textEnabled()) {
_vm->_fadeText = false;
- _vm->_textColourFlag = 0;
+ _vm->_textColorFlag = 0;
_vm->_timer->disable(11);
_screen->setScreenDim(clearDim(3));
_screen->copyRegionToBuffer(3, 0, 0, 320, 10, tmp);
@@ -146,13 +146,13 @@ void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, ui
if (str) {
_animString = str;
_animWidth = x;
- _animColour1 = col1;
- _animColour2 = col2;
+ _animColor1 = col1;
+ _animColor2 = col2;
} else {
_animString = defaultStr;
_animWidth = 7;
- _animColour1 = 0;
- _animColour2 = 0;
+ _animColor1 = 0;
+ _animColor2 = 0;
}
}
@@ -163,17 +163,21 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script,
if (_vm->_updateFlags & 2) {
oldDim = clearDim(4);
_textDimData[4].color1 = 254;
+ _textDimData[4].color2 = _screen->_curDim->unkA;
} else {
oldDim = clearDim(3);
_textDimData[3].color1 = 192;
- _screen->copyColour(192, 254);
+ _textDimData[3].color2 = _screen->_curDim->unkA;
+ _screen->copyColor(192, 254);
_vm->enableTimer(11);
- _vm->_textColourFlag = 0;
+ _vm->_textColorFlag = 0;
_vm->_fadeText = false;
}
} else {
- oldDim = clearDim(dim);
+ oldDim = _screen->curDimIndex();
+ _screen->setScreenDim(dim);
_textDimData[dim].color1 = 254;
+ _textDimData[dim].color2 = _screen->_curDim->unkA;
}
int cp = _screen->setCurPage(0);
@@ -190,15 +194,15 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script,
_vm->_fadeText = false;
}
-void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) {
- static uint8 textColours[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F };
+void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) {
+ static uint8 textColors[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F };
static uint8 soundEffect[] = { 0x0B, 0x00, 0x2B, 0x1B, 0x00 };
if (type & 4)
type ^= 4;
else
_vm->updatePortraits();
- uint16 col = textColours[type & 0x7fff];
+ uint16 col = textColors[type & 0x7fff];
int od = _screen->curDimIndex();
@@ -207,7 +211,7 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) {
_textDimData[4].color1 = col;
} else {
clearDim(3);
- _screen->copyColour(192, col);
+ _screen->copyColor(192, col);
_textDimData[3].color1 = 192;
_vm->enableTimer(11);
}
@@ -228,7 +232,7 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) {
_vm->sound()->playSoundEffect(soundEffect[type]);
}
- _vm->_textColourFlag = type & 0x7fff;
+ _vm->_textColorFlag = type & 0x7fff;
_vm->_fadeText = false;
}
diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h
index 776965117e..157e5a5852 100644
--- a/engines/kyra/text_lol.h
+++ b/engines/kyra/text_lol.h
@@ -50,7 +50,7 @@ public:
void resetDimTextPositions(int dim);
void printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
- void printMessage(uint16 type, char *str, ...);
+ void printMessage(uint16 type, const char *str, ...);
int16 _scriptParameter;
@@ -82,8 +82,8 @@ private:
const char *_animString;
int16 _animWidth;
- uint8 _animColour1;
- uint8 _animColour2;
+ uint8 _animColor1;
+ uint8 _animColor2;
bool _animFlag;
bool _printFlag;
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index 57bf717906..220208e313 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -603,12 +603,8 @@ void KyraEngine_MR::albumChatWaitToFinish() {
if (frame > 22)
frame = 13;
- _album.wsa->setX(-100);
- _album.wsa->setY(90);
- _album.wsa->setDrawPage(2);
-
albumRestoreRect();
- _album.wsa->displayFrame(frame, 0x4000);
+ _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000);
albumUpdateRect();
nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength;
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index 79bb8d1c2d..05e8e75144 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -53,7 +53,7 @@ void LoLEngine::setupTimers() {
void LoLEngine::enableTimer(int id) {
_timer->enable(id);
- _timer->setNextRun(id, _system->getMillis() + _timer->getDelay(id) * _tickLength);
+ _timer->setCountdown(id, _timer->getDelay(id));
}
void LoLEngine::enableSysTimer(int sysTimer) {
@@ -249,7 +249,7 @@ void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) {
}
void LoLEngine::timerUpdateLampState(int timerNum) {
- if ((_gameFlags[15] & 0x800) && (_gameFlags[15] & 0x400) && _lampOilStatus)
+ if ((_gameFlags[15] & 0x800) && (_gameFlags[15] & 0x400) && _lampOilStatus > 0)
_lampOilStatus--;
}
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index 50d17659a4..97f31e80ae 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -134,11 +134,15 @@ void WSAMovie_v1::close() {
}
}
-void WSAMovie_v1::displayFrame(int frameNum, ...) {
- debugC(9, kDebugLevelMovie, "WSAMovie_v1::displayFrame(%d, ...)", frameNum);
+void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
+ debugC(9, kDebugLevelMovie, "WSAMovie_v1::displayFrame(%d, %d, %d, %d, ...)", frameNum, pageNum, x, y);
if (frameNum >= _numFrames || !_opened)
return;
+ _x = x;
+ _y = y;
+ _drawPage = pageNum;
+
uint8 *dst;
if (_flags & WF_OFFSCREEN_DECODE)
dst = _offscreenBuffer;
@@ -236,11 +240,15 @@ void WSAMovieAmiga::close() {
WSAMovie_v1::close();
}
-void WSAMovieAmiga::displayFrame(int frameNum, ...) {
- debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d)", frameNum);
+void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
+ debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d, %d, %d, %d,...)", frameNum, pageNum, x, y);
if (frameNum >= _numFrames || frameNum < 0 || !_opened)
return;
+ _x = x;
+ _y = y;
+ _drawPage = pageNum;
+
uint8 *dst;
dst = _buffer;
memset(_buffer, 0, _width*_height);
@@ -415,16 +423,26 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
_flags |= WF_NO_FIRST_FRAME;
}
- for (int i = 1; i < _numFrames + 2; ++i) {
+ for (int i = 1; i < _numFrames; ++i) {
_frameOffsTable[i] = READ_LE_UINT32(wsaData) - frameDataOffs;
wsaData += 4;
}
+ _frameOffsTable[_numFrames] = READ_LE_UINT32(wsaData);
+ wsaData += 4;
+ _frameOffsTable[_numFrames + 1] = READ_LE_UINT32(wsaData);
+ wsaData += 4;
+ if (_frameOffsTable[_numFrames + 1])
+ _frameOffsTable[_numFrames] -= frameDataOffs;
+ else
+ _frameOffsTable[_numFrames] = 0;
+
// skip palette
wsaData += offsPal;
// read frame data
const int frameDataSize = p + fileSize - wsaData;
+
_frameData = new uint8[frameDataSize];
memcpy(_frameData, wsaData, frameDataSize);
@@ -438,11 +456,15 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
return _numFrames;
}
-void WSAMovie_v2::displayFrame(int frameNum, ...) {
- debugC(9, kDebugLevelMovie, "WSAMovie_v2::displayFrame(%d, ...)", frameNum);
+void WSAMovie_v2::displayFrame(int frameNum, int pageNum, int x, int y, ...) {
+ debugC(9, kDebugLevelMovie, "WSAMovie_v2::displayFrame(%d, %d, %d, %d,...)", frameNum, pageNum, x, y);
if (frameNum >= _numFrames || frameNum < 0 || !_opened)
return;
+ _x = x + _xAdd;
+ _y = y + _yAdd;
+ _drawPage = pageNum;
+
uint8 *dst = 0;
if (_flags & WF_OFFSCREEN_DECODE)
dst = _offscreenBuffer;
@@ -503,7 +525,7 @@ void WSAMovie_v2::displayFrame(int frameNum, ...) {
_screen->_curPage = _drawPage;
va_list args;
- va_start(args, frameNum);
+ va_start(args, y);
int copyParam = va_arg(args, int);
int plotFunc = (copyParam & 0xFF00) >> 12;
diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h
index 1db8ee8474..a1e0562f60 100644
--- a/engines/kyra/wsamovie.h
+++ b/engines/kyra/wsamovie.h
@@ -47,11 +47,8 @@ public:
virtual int frames() = 0;
- virtual void displayFrame(int frameNum, ...) = 0;
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...) = 0;
- virtual void setX(int x) { _x = x; }
- virtual void setY(int y) { _y = y; }
- virtual void setDrawPage(int page) { _drawPage = page; }
protected:
KyraEngine_v1 *_vm;
bool _opened;
@@ -70,7 +67,7 @@ public:
virtual int frames() { return _opened ? _numFrames : -1; }
- virtual void displayFrame(int frameNum, ...);
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...);
enum WSAFlags {
WF_OFFSCREEN_DECODE = 0x10,
@@ -100,7 +97,7 @@ public:
int open(const char *filename, int offscreen, uint8 *palette);
void close();
- void displayFrame(int frameNum, ...);
+ void displayFrame(int frameNum, int pageNum, int x, int y, ...);
private:
void processFrame(int frameNum, uint8 *dst);
@@ -113,10 +110,7 @@ public:
int open(const char *filename, int unk1, uint8 *palette);
- virtual void displayFrame(int frameNum, ...);
-
- void setX(int x) { _x = x + _xAdd; }
- void setY(int y) { _y = y + _yAdd; }
+ virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...);
int xAdd() const { return _xAdd; }
int yAdd() const { return _yAdd; }