[Scummvm-cvs-logs] SF.net SVN: scummvm:[40420] scummvm/trunk

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Sun May 10 15:40:29 CEST 2009


Revision: 40420
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40420&view=rev
Author:   athrxx
Date:     2009-05-10 13:40:28 +0000 (Sun, 10 May 2009)

Log Message:
-----------
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)

Modified Paths:
--------------
    scummvm/trunk/dists/engine-data/kyra.dat
    scummvm/trunk/engines/kyra/animator_hof.cpp
    scummvm/trunk/engines/kyra/animator_mr.cpp
    scummvm/trunk/engines/kyra/gui.cpp
    scummvm/trunk/engines/kyra/gui_hof.cpp
    scummvm/trunk/engines/kyra/gui_lok.cpp
    scummvm/trunk/engines/kyra/gui_lol.cpp
    scummvm/trunk/engines/kyra/gui_mr.cpp
    scummvm/trunk/engines/kyra/items_lol.cpp
    scummvm/trunk/engines/kyra/kyra_hof.cpp
    scummvm/trunk/engines/kyra/kyra_mr.cpp
    scummvm/trunk/engines/kyra/lol.cpp
    scummvm/trunk/engines/kyra/lol.h
    scummvm/trunk/engines/kyra/resource.h
    scummvm/trunk/engines/kyra/scene_lol.cpp
    scummvm/trunk/engines/kyra/screen_lol.cpp
    scummvm/trunk/engines/kyra/screen_lol.h
    scummvm/trunk/engines/kyra/screen_v2.cpp
    scummvm/trunk/engines/kyra/screen_v2.h
    scummvm/trunk/engines/kyra/script_hof.cpp
    scummvm/trunk/engines/kyra/script_lok.cpp
    scummvm/trunk/engines/kyra/script_lol.cpp
    scummvm/trunk/engines/kyra/script_tim.cpp
    scummvm/trunk/engines/kyra/seqplayer.cpp
    scummvm/trunk/engines/kyra/sequences_hof.cpp
    scummvm/trunk/engines/kyra/sequences_lok.cpp
    scummvm/trunk/engines/kyra/sequences_lol.cpp
    scummvm/trunk/engines/kyra/sound.cpp
    scummvm/trunk/engines/kyra/sound.h
    scummvm/trunk/engines/kyra/sound_towns.cpp
    scummvm/trunk/engines/kyra/sprites_lol.cpp
    scummvm/trunk/engines/kyra/staticres.cpp
    scummvm/trunk/engines/kyra/text_lol.cpp
    scummvm/trunk/engines/kyra/text_lol.h
    scummvm/trunk/engines/kyra/text_mr.cpp
    scummvm/trunk/engines/kyra/timer_lol.cpp
    scummvm/trunk/engines/kyra/wsamovie.cpp
    scummvm/trunk/engines/kyra/wsamovie.h
    scummvm/trunk/tools/create_kyradat/create_kyradat.cpp
    scummvm/trunk/tools/create_kyradat/create_kyradat.h
    scummvm/trunk/tools/create_kyradat/lol_cd.h
    scummvm/trunk/tools/create_kyradat/misc.h

Modified: scummvm/trunk/dists/engine-data/kyra.dat
===================================================================
(Binary files differ)

Modified: scummvm/trunk/engines/kyra/animator_hof.cpp
===================================================================
--- scummvm/trunk/engines/kyra/animator_hof.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/animator_hof.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -298,10 +298,7 @@
 			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);
 	}
 }
 

Modified: scummvm/trunk/engines/kyra/animator_mr.cpp
===================================================================
--- scummvm/trunk/engines/kyra/animator_mr.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/animator_mr.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -125,10 +125,7 @@
 				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);
 		}
 	}
 }

Modified: scummvm/trunk/engines/kyra/gui.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/gui.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -404,7 +404,7 @@
 		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;

Modified: scummvm/trunk/engines/kyra/gui_hof.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_hof.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/gui_hof.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -284,15 +284,11 @@
 	_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();
 		}

Modified: scummvm/trunk/engines/kyra/gui_lok.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_lok.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/gui_lok.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -962,7 +962,7 @@
 	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;
 }

Modified: scummvm/trunk/engines/kyra/gui_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/gui_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -124,8 +124,15 @@
 	}
 }
 
-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 @@
 	_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 @@
 		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 @@
 	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 @@
 		_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 @@
 			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_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 @@
 	} 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 @@
 
 		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 @@
 		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::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;
 }
 

Modified: scummvm/trunk/engines/kyra/gui_mr.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_mr.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/gui_mr.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -363,16 +363,10 @@
 		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,21 +707,12 @@
 	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);
+	if (_album.rightPage.wsa->opened())
+		_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
 
-		_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000);
-	}
-
 	printAlbumPageText();
 	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
@@ -887,21 +872,12 @@
 			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);
+			if (_album.rightPage.wsa->opened())
+				_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000);
 
-				_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000);
-			}
-
 			printAlbumPageText();
 
 			snd_playSoundEffect(0x85, 0x80);
@@ -955,11 +931,7 @@
 
 	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 @@
 
 	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::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);
 	}

Modified: scummvm/trunk/engines/kyra/items_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/items_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/items_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -44,7 +44,7 @@
 		if (t > credits)
 			t = credits;
 
-		if (_credits < 60 && t >= 0) {
+		if (_credits < 60 && t > 0) {
 			cnt = 0;
 
 			do {
@@ -86,7 +86,7 @@
 		if (t > credits)
 			t = credits;
 
-		if (_credits - t < 60 && t >= 0) {
+		if (_credits - t < 60 && t > 0) {
 			cnt = 0;
 
 			do {
@@ -97,7 +97,7 @@
 					_moneyColumnHeight[d]--;
 				}
 			} while (++cnt < t);
-		} else if (_credits - t < 60) {
+		} else if (_credits - t >= 60) {
 			_credits -= t;
 		}
 
@@ -343,7 +343,7 @@
 }
 
 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 @@
 			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 @@
 	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 {

Modified: scummvm/trunk/engines/kyra/kyra_hof.cpp
===================================================================
--- scummvm/trunk/engines/kyra/kyra_hof.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/kyra_hof.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -1612,10 +1612,7 @@
 	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 @@
 	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);

Modified: scummvm/trunk/engines/kyra/kyra_mr.cpp
===================================================================
--- scummvm/trunk/engines/kyra/kyra_mr.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/kyra_mr.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -274,14 +274,14 @@
 
 		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 @@
 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);

Modified: scummvm/trunk/engines/kyra/lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -72,6 +72,7 @@
 		break;
 	}
 
+	_chargenFrameTable = _flags.isTalkie ? _chargenFrameTableTalkie : _chargenFrameTableFloppy;
 	_chargenWSA = 0;
 	_lastUsedStringBuffer = 0;
 	_landsFile = 0;
@@ -89,6 +90,7 @@
 	_itemProperties = 0;
 	_itemInHand = 0;
 	memset(_inventory, 0, sizeof(_inventory));
+	memset(_invSkillFlags, 0, sizeof(_invSkillFlags));
 	_inventoryCurItem = 0;
 	_currentControlMode = 0;
 	_specialSceneFlag = 0;
@@ -102,6 +104,7 @@
 	memset(_monsterAnimType, 0, 3);
 	_pageSavedFlag = false;
 	_healOverlay = 0;
+	_swarmSpellStatus = 0;
 
 	_ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0;
 
@@ -110,7 +113,7 @@
 	_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 @@
 	_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 @@
 	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 @@
 	_floatingCursorsEnabled = false;
 
 	memset(_lvlTempData, 0, sizeof(_lvlTempData));
-	_unkIceSHpFlag = 0;
+	_freezeStateFlags = 0;
 
 	_mapOverlay = 0;
 	_automapShapes = 0;
@@ -389,6 +393,7 @@
 	delete[] _defaultLegendData;
 	delete[] _mapCursorOverlay;
 	delete[] _mapOverlay;
+	_spellProcs.clear();
 }
 
 Screen *LoLEngine::screen() {
@@ -499,6 +504,24 @@
 	_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 @@
 	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::initTextFading(int textType, int clearField) {
-	if (_textColourFlag == textType || !textType) {
+	if (_textColorFlag == textType || !textType) {
 		_fadeText = true;
 		_palUpdateTimer = _system->getMillis();
 	}
@@ -1546,7 +1569,7 @@
 	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::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,11 +1713,12 @@
 	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_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 @@
 		}
 	}
 
-	_fadeText = 0;
+	_fadeText = false;
 	if (!skipAnim)
 		updatePortraitSpeechAnim();
 
@@ -1996,15 +2026,29 @@
 	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;
+	}
+}
+
 uint8 LoLEngine::getRandomNumberSpecial() {
 	uint8 a = _rndSpecial & 0xff;
 	uint8 b = (_rndSpecial >> 8) & 0xff;
@@ -2035,7 +2079,181 @@
 	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 @@
 
 	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 @@
 	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 @@
 			_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 @@
 	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 @@
 	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 @@
 	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 @@
 	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;

Modified: scummvm/trunk/engines/kyra/lol.h
===================================================================
--- scummvm/trunk/engines/kyra/lol.h	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/lol.h	2009-05-10 13:40:28 UTC (rev 40420)
@@ -78,7 +78,11 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	int _updatePortraitSpeechAnimDuration;
 	int _portraitSpeechAnimMode;
 	int _updateCharV3;
-	int _textColourFlag;
+	int _textColorFlag;
 	bool _fadeText;
 	int _needSceneRestore;
 	uint32 _palUpdateTimer;
@@ -1070,6 +1096,7 @@
 	int _currentControlMode;
 	int _specialSceneFlag;
 	int _lastCharInventory;
+	uint16 _invSkillFlags[6];
 
 	FlyingObject *_flyingObjects;
 
@@ -1107,7 +1134,7 @@
 	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 @@
 	uint8 **_monsterShapesEx;
 	uint8 _monsterAnimType[3];
 	uint16 _monsterCurBlock;
-	int _monsterLastWalkDirection;
+	int _objectLastDirection;
 	int _monsterCountUnk;
 	int _monsterShiftAlt;
 
@@ -1163,7 +1190,8 @@
 	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 @@
 	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 @@
 	uint8 **_healiShapes;
 	int _numHealiShapes;
 
+	const uint8 *_updateSpellBookCoords;
+	int _updateSpellBookCoordsSize;
+	const uint8 *_updateSpellBookAnimData;
+	int _updateSpellBookAnimDataSize;
 	const uint8 *_healShapeFrames;
 	int _healShapeFramesSize;
 
@@ -1202,7 +1270,7 @@
 	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 @@
 	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);
 

Modified: scummvm/trunk/engines/kyra/resource.h
===================================================================
--- scummvm/trunk/engines/kyra/resource.h	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/resource.h	2009-05-10 13:40:28 UTC (rev 40420)
@@ -287,6 +287,8 @@
 	lolMapStringId,
 	//lolMapPal,
 
+	lolSpellbookAnim,
+	lolSpellbookCoords,
 	lolHealShapeFrames,
 #endif // ENABLE_LOL
 

Modified: scummvm/trunk/engines/kyra/scene_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/scene_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/scene_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -398,7 +398,7 @@
 		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 @@
 	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 @@
 		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 @@
 
 		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;
 		}

Modified: scummvm/trunk/engines/kyra/screen_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/screen_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -148,7 +148,7 @@
 	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 @@
 	}
 
 	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 @@
 
 	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 @@
 	_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 @@
 	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,13 +714,41 @@
 
 	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();
+
+	return res;
+}
+
 uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) {
 	debugC(9, kDebugLevelScreen, "Screen_LoL::getShapePaletteSize(%p)", (const void *)shp);
 

Modified: scummvm/trunk/engines/kyra/screen_lol.h
===================================================================
--- scummvm/trunk/engines/kyra/screen_lol.h	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/screen_lol.h	2009-05-10 13:40:28 UTC (rev 40420)
@@ -64,11 +64,12 @@
 
 	// 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]; }
 

Modified: scummvm/trunk/engines/kyra/screen_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/screen_v2.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -90,12 +90,12 @@
 	}
 }
 
-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++;

Modified: scummvm/trunk/engines/kyra/screen_v2.h
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.h	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/screen_v2.h	2009-05-10 13:40:28 UTC (rev 40420)
@@ -45,7 +45,7 @@
 	// 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);
 

Modified: scummvm/trunk/engines/kyra/script_hof.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_hof.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/script_hof.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -187,10 +187,7 @@
 
 	_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 @@
 	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 @@
 		} 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 @@
 	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 @@
 	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 @@
 
 	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();

Modified: scummvm/trunk/engines/kyra/script_lok.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_lok.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/script_lok.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -426,11 +426,8 @@
 	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 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 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 @@
 
 	_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 @@
 	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 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 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 @@
 	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 @@
 			if (code == 14)
 				snd_playSoundEffect(0x73);
 
-			amulet.displayFrame(code);
+			amulet.displayFrame(code, 0, 224, 152);
 			_animator->_updateScreen = true;
 
 			while (_system->getMillis() < nextTime) {

Modified: scummvm/trunk/engines/kyra/script_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/script_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -131,9 +131,70 @@
 	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 @@
 	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_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 @@
 	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_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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 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 @@
 		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 @@
 
 		case 3:
 			tmp = _screen->getPalette(3);
-			_screen->loadSpecialColours(tmp);
+			_screen->loadSpecialColors(tmp);
 			_screen->fadePalette(tmp, 10);
 			_screen->_fadeFlag = 0;
 			break;
@@ -1664,7 +1846,7 @@
 
 		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_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_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,8 +1958,8 @@
 	Opcode(o1_getRand);
 
 	// 0x04
+	Opcode(olol_moveParty);
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 	Opcode(olol_delay);
 	Opcode(olol_setGameFlag);
 
@@ -1811,7 +1995,7 @@
 
 	// 0x1C
 	Opcode(olol_getDirection);
-	OpcodeUnImpl();
+	Opcode(olol_characterSurpriseFeedback);
 	Opcode(olol_setMusicTrack);
 	Opcode(olol_setSequenceButtons);
 
@@ -1912,7 +2096,7 @@
 	Opcode(olol_update);
 
 	// 0x60
-	OpcodeUnImpl();
+	Opcode(olol_playEnvironmentalSfx);
 	Opcode(olol_healCharacter);
 	Opcode(olol_drawExitButton);
 	Opcode(olol_loadSoundFile);
@@ -1921,11 +2105,11 @@
 	Opcode(olol_playMusicTrack);
 	OpcodeUnImpl();
 	Opcode(olol_countBlockItems);
-	OpcodeUnImpl();
+	Opcode(olol_characterSkillTest);
 
 	// 0x68
+	Opcode(olol_countActiveMonsters);
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 	Opcode(olol_stopCharacterSpeech);
 	Opcode(olol_setPaletteBrightness);
 
@@ -1938,8 +2122,8 @@
 	// 0x70
 	Opcode(olol_deleteLevelItem);
 	Opcode(olol_calcInflictableDamagePerItem);
-	OpcodeUnImpl();
-	OpcodeUnImpl();
+	Opcode(olol_distanceAttack);
+	Opcode(olol_removeCharacterEffects);
 
 	// 0x74
 	OpcodeUnImpl();
@@ -1948,8 +2132,8 @@
 	OpcodeUnImpl();
 
 	// 0x78
+	Opcode(olol_addSpellToScroll);
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 	Opcode(olol_playDialogueTalkText);
 	Opcode(olol_checkMonsterTypeHostility);
 
@@ -1961,9 +2145,9 @@
 
 	// 0x80
 	OpcodeUnImpl();
+	Opcode(olol_triggerEventOnMouseButtonRelease);
+	Opcode(olol_printWindowText);
 	OpcodeUnImpl();
-	OpcodeUnImpl();
-	OpcodeUnImpl();
 
 	// 0x84
 	OpcodeUnImpl();
@@ -2027,9 +2211,9 @@
 
 	// 0xAC
 	OpcodeUnImpl();
+	Opcode(olol_castSpell);
 	OpcodeUnImpl();
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 
 	// 0xB0
 	OpcodeUnImpl();

Modified: scummvm/trunk/engines/kyra/script_tim.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_tim.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/script_tim.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -420,10 +420,7 @@
 				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_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 @@
 		_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 @@
 	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 @@
 
 	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);
 	}
 }
 

Modified: scummvm/trunk/engines/kyra/seqplayer.cpp
===================================================================
--- scummvm/trunk/engines/kyra/seqplayer.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/seqplayer.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -132,7 +132,6 @@
 	_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 @@
 	_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 @@
 		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 @@
 		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);
 	}
 }
 

Modified: scummvm/trunk/engines/kyra/sequences_hof.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sequences_hof.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/sequences_hof.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -103,10 +103,7 @@
 			_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 @@
 
 				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 @@
 	_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 @@
 
 	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 @@
 	}
 
 	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 @@
 			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 @@
 		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 @@
 	_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);

Modified: scummvm/trunk/engines/kyra/sequences_lok.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sequences_lok.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/sequences_lok.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -984,8 +984,6 @@
 			_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 @@
 				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 @@
 
 	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 @@
 		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 @@
 
 	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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 				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);
 					}

Modified: scummvm/trunk/engines/kyra/sequences_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sequences_lol.cpp	2009-05-10 13:15:14 UTC (rev 40419)
+++ scummvm/trunk/engines/kyra/sequences_lol.cpp	2009-05-10 13:40:28 UTC (rev 40420)
@@ -213,11 +213,9 @@
 
 	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 @@
 
 	_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 @@
 			_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 @@
 
 	_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 @@
 			_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 @@
 
 	_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 @@
 			_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 @@
 		return;

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list