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

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Sat Apr 25 15:15:06 CEST 2009


Revision: 40144
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40144&view=rev
Author:   athrxx
Date:     2009-04-25 13:15:05 +0000 (Sat, 25 Apr 2009)

Log Message:
-----------
LOL: - Started implementing the fighting system. The damage inflicted is wrong, however (at least the damage inflicted by the monsters). I'm sowewhat clueless about that bug atm.
- added support for monsters with distance attacks (like those orcs in front of roland's house)
- lots of small bug fixes
- Some startup support for the pc-98 16 color version. The intro will run, but the font drawing/coloring is still wrong.

Modified Paths:
--------------
    scummvm/trunk/dists/engine-data/kyra.dat
    scummvm/trunk/engines/kyra/detection.cpp
    scummvm/trunk/engines/kyra/gui_lok.cpp
    scummvm/trunk/engines/kyra/gui_lol.cpp
    scummvm/trunk/engines/kyra/items_lol.cpp
    scummvm/trunk/engines/kyra/kyra_v1.h
    scummvm/trunk/engines/kyra/lol.cpp
    scummvm/trunk/engines/kyra/lol.h
    scummvm/trunk/engines/kyra/resource.h
    scummvm/trunk/engines/kyra/saveload_lok.cpp
    scummvm/trunk/engines/kyra/scene_lol.cpp
    scummvm/trunk/engines/kyra/screen.cpp
    scummvm/trunk/engines/kyra/screen.h
    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/script_lol.cpp
    scummvm/trunk/engines/kyra/script_tim.cpp
    scummvm/trunk/engines/kyra/script_tim.h
    scummvm/trunk/engines/kyra/sequences_lol.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/timer.cpp
    scummvm/trunk/engines/kyra/timer_lol.cpp
    scummvm/trunk/engines/kyra/wsamovie.cpp
    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/detection.cpp
===================================================================
--- scummvm/trunk/engines/kyra/detection.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/detection.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -43,36 +43,35 @@
 
 namespace {
 
-#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id }
-#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, id }
+#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
+#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
 
-#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA1)
-#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, Kyra::GI_KYRA1)
-#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
+#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
 
-#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA2)
-#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
+#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
 
-#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3)
-#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, false, Kyra::GI_KYRA3)
-#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
+#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
 
-#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_LOL)
-#define LOL_PC98_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_LOL)
-#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
+#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
+#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
+#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
 
 const KYRAGameDescription adGameDescs[] = {
 	/* disable these targets until they get supported
@@ -1020,7 +1019,6 @@
 		LOL_FLOPPY_FLAGS
 	},
 
-	/* disable these targets until they get supported
 	{
 		{
 			"lol",
@@ -1030,28 +1028,12 @@
 				{ "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
 				{ 0, 0, 0, 0 }
 			},
-			Common::EN_ANY,
-			Common::kPlatformPC98,
-			ADGF_NO_FLAGS
-		},
-		LOL_PC98_FLAGS
-	},
-
-	{
-		{
-			"lol",
-			0,
-			{
-				{ "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 },
-				{ "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
-				{ 0, 0, 0, 0 }
-			},
 			Common::JA_JPN,
 			Common::kPlatformPC98,
 			ADGF_NO_FLAGS
 		},
 		LOL_PC98_SJIS_FLAGS
-	},*/
+	},
 
 	{
 		{
@@ -1069,7 +1051,7 @@
 	},
 #endif // ENABLE_LOL
 
-	{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) }
+	{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
 };
 
 const PlainGameDescriptor gameList[] = {

Modified: scummvm/trunk/engines/kyra/gui_lok.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_lok.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/gui_lok.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -962,7 +962,7 @@
 	debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeMusic()");
 	updateMenuButton(button);
 
-	_vm->_configMusic = ++_vm->_configMusic % ((_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) ? 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-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/gui_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -473,7 +473,7 @@
 
 	int barHeight = (curPoints * h) / maxPoints;
 
-	if (barHeight < 1 && curPoints < 1)
+	if (barHeight < 1 && curPoints > 0)
 		barHeight = 1;
 
 	_screen->drawClippedLine(x - 1, y - h, x - 1, y, 1);
@@ -1037,6 +1037,46 @@
 }
 
 int LoLEngine::clickedAttackButton(Button *button) {
+	int c = button->data2Val2;
+
+	if (_characters[c].flags & 0x314C)
+		return 1;
+
+	int bl = calcNewBlockPosition(_currentBlock, _currentDirection);
+
+	if (_levelBlockProperties[bl].flags & 0x10) {
+		attackWall(0, 0);
+		return 1;
+	}
+
+	uint16 target = getNearestMonsterFromCharacter(c);
+	int s = 0;
+
+	for (int i = 0; i < 4; i++) {
+		if (!_characters[c].items[i])
+			continue;
+
+		runItemScript(c, _characters[c].items[i], 0x400, target, s);
+		runLevelScriptCustom(_currentBlock, 0x400, c, _characters[c].items[i], target, s);
+		s -= 10;
+	}
+
+	if (!s) {
+		runItemScript(c, 0, 0x400, target, s);
+		runLevelScriptCustom(_currentBlock, 0x400, c, 0, target, s);
+	}
+
+	s = _characters[c].weaponHit ? 4 : calcMonsterSkillLevel(c, 8) + 4;
+
+	// check for Zephyr ring
+	if (itemEquipped(c, 230))
+		s >>= 1;
+
+	_characters[c].flags |= 4;
+	gui_highlightPortraitFrame(c);
+
+	setCharacterUpdateEvent(c, 1, s, 1);
+
 	return 1;
 }
 
@@ -1074,7 +1114,7 @@
 		// TODO
 		///
 		/*if (processSpellcast(c, _availableSpells[_selectedSpell], spellLevel)) {
-			setFaceFramesUnkArrays(c, 1, 8, 1);
+			setCharacterUpdateEvent(c, 1, 8, 1);
 			sub_718F(c, 2, spellLevel * spellLevel);
 		} else {*/
 			_characters[c].flags &= 0xfffb;
@@ -1130,6 +1170,23 @@
 }
 
 int LoLEngine::clickedPortraitEtcRight(Button *button) {
+	if (!_itemInHand)
+		return 1;
+
+	int flg = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].flags;
+	int c = button->data2Val2;
+
+	if (flg & 1) {
+		if (!(_characters[c].flags & 8) || (flg & 0x20)) {
+			runItemScript(c, _itemInHand, 0x400, 0, 0);
+			runLevelScriptCustom(_currentBlock, 0x400, c, _itemInHand, 0, 0);			
+		} else {
+			_txt->printMessage(2, getLangString(0x402c), _characters[c].name);
+		}
+		return 1;
+	}
+
+	_txt->printMessage(2, getLangString((flg & 8) ? 0x4029 : ((flg & 0x10) ? 0x402a : 0x402b)));
 	return 1;
 }
 
@@ -1389,8 +1446,10 @@
 
 int LoLEngine::clickedSequenceWindow(Button *button) {
 	runLevelScript(calcNewBlockPosition(_currentBlock, _currentDirection), 0x40);
-	if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2))
+	if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2)) {
 		_seqTrigger = 0;
+		removeInputTop();
+	}
 	return 1;
 }
 
@@ -1418,7 +1477,7 @@
 	uint16 y = 0;
 	calcCoordinates(x, y, _currentBlock, 0x80, 0x80);
 
-	if (throwItem(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
+	if (launchObject(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
 		snd_playSoundEffect(18, -1);
 		setHandItem(0);
 	}

Modified: scummvm/trunk/engines/kyra/items_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/items_lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/items_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -181,14 +181,14 @@
 void LoLEngine::placeMoveLevelItem(int itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight) {
 	calcCoordinates(_itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, block, xOffs, yOffs);
 
-	if (_itemsInPlay[itemIndex].blockPropertyIndex)
-		removeLevelItem(itemIndex, _itemsInPlay[itemIndex].blockPropertyIndex);
+	if (_itemsInPlay[itemIndex].block)
+		removeLevelItem(itemIndex, _itemsInPlay[itemIndex].block);
 
 	if (_currentLevel == level) {
 		setItemPosition(itemIndex, _itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, flyingHeight, 1);
 	} else {
 		_itemsInPlay[itemIndex].level = level;
-		_itemsInPlay[itemIndex].blockPropertyIndex = block;
+		_itemsInPlay[itemIndex].block = block;
 		_itemsInPlay[itemIndex].flyingHeight = flyingHeight;
 		_itemsInPlay[itemIndex].shpCurFrame_flg |= 0x4000;
 	}
@@ -289,6 +289,24 @@
 	_screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(itemIndex));
 }
 
+bool LoLEngine::itemEquipped(int charNum, uint16 itemType) {
+	if (charNum < 0 || charNum > 3)
+		return false;
+
+	if (!(_characters[charNum].flags & 1))
+		return false;
+
+	for (int i = 0; i < 11; i++) {
+		if (!_characters[charNum].items[i])
+			continue;
+
+		if (_itemsInPlay[_characters[charNum].items[i]].itemPropertyIndex == itemType)
+			return true;
+	}
+
+	return false;
+}
+
 void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b) {
 	if (!flyingHeight) {
 		x = (x & 0xffc0) | 0x40;
@@ -298,7 +316,7 @@
 	uint16 block = calcBlockIndex(x, y);
 	_itemsInPlay[item].x = x;
 	_itemsInPlay[item].y = y;
-	_itemsInPlay[item].blockPropertyIndex = block;
+	_itemsInPlay[item].block = block;
 	_itemsInPlay[item].flyingHeight = flyingHeight;
 
 	if (b)
@@ -320,12 +338,12 @@
 	removeAssignedObjectFromBlock(&_levelBlockProperties[block], item);
 	removeDrawObjectFromBlock(&_levelBlockProperties[block], item);
 	runLevelScriptCustom(block, 0x100, -1, item, 0, 0);
-	_itemsInPlay[item].blockPropertyIndex = 0;
+	_itemsInPlay[item].block = 0;
 	_itemsInPlay[item].level = 0;
 }
 
-bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c) {
-	int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, x, y);
+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);
 	FlyingObject *t = _flyingObjects;
 	int slot = -1;
 	int i = 0;
@@ -348,31 +366,31 @@
 		i = slot;
 
 		t = &_flyingObjects[i];
-		endObjectFlight(t, x, y, 8);
+		endObjectFlight(t, startX, startY, 8);
 	}
 
 	if (i == 8)
 		return false;
 
 	t->enable = 1;
-	t->a = a;
+	t->objectType = objectType;
 	t->item = item;
-	t->x = x;
-	t->y = y;
+	t->x = startX;
+	t->y = startY;
 	t->flyingHeight = flyingHeight;
 	t->direction = direction;
 	t->distance = 255;
-	t->charNum = charNum;
+	t->attackerId = attackerId;
 	t->flags = 7;
 	t->wallFlags = 2;
 	t->c = c;	
 
-	if (charNum != -1) {
-		if (charNum & 0x8000) {
+	if (attackerId != -1) {
+		if (attackerId & 0x8000) {
 			t->flags &= 0xfd;
 		} else {
 			t->flags &= 0xfb;
-			increaseExperience(charNum, 1, 2);
+			increaseExperience(attackerId, 1, 2);
 		}
 	}
 
@@ -393,7 +411,7 @@
 		cy = t->y;
 	}
 
-	if (t->a == 0 || t->a == 1) {
+	if (t->objectType == 0 || t->objectType == 1) {
 		objectFlightProcessHits(t, cx, cy, objectOnNextBlock);
 		t->x = (cx & 0xffc0) | 0x40;
 		t->y = (cy & 0xffc0) | 0x40;
@@ -416,9 +434,9 @@
 }
 
 void LoLEngine::updateObjectFlightPosition(FlyingObject *t) {
-	if (t->a == 0) {
+	if (t->objectType == 0) {
 		setItemPosition(t->item, t->x, t->y, t->flyingHeight, (t->flyingHeight == 0) ? 1 : 0);
-	} else if (t->a == 1) {
+	} else if (t->objectType == 1) {
 		if (t->flyingHeight == 0) {
 			deleteItem(t->item);
 			checkSceneUpdateNeed(calcBlockIndex(t->x, t->y));
@@ -432,23 +450,23 @@
 	uint16 r = 0;
 
 	if (objectOnNextBlock == 1) {
-		runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
+		runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].block, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
 		return;
 
 	} else if (objectOnNextBlock == 2) {
 		if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
-			int o = _levelBlockProperties[_itemsInPlay[t->item].blockPropertyIndex].assignedObjects;
+			int o = _levelBlockProperties[_itemsInPlay[t->item].block].assignedObjects;
 			
 			while (o & 0x8000) {
 				ItemInPlay *i = findObject(o);
 				o = i->nextAssignedObject;
-				runItemScript(t->charNum, t->item, 0x8000, o, 0);
+				runItemScript(t->attackerId, t->item, 0x8000, o, 0);
 			}
 			
 			return;
 
 		} else {
-			r = getClosestMonster(x, y);
+			r = getNearestMonsterFromPos(x, y);
 		}
 
 	} else if (objectOnNextBlock == 4) {
@@ -456,19 +474,19 @@
 		if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
 			for (int i = 0; i < 4; i++) {
 				if (_characters[i].flags & 1)
-					runItemScript(t->charNum, t->item, 0x8000, i, 0);
+					runItemScript(t->attackerId, t->item, 0x8000, i, 0);
 			}
 			return;
 
 		} else {
-			r = getClosestPartyMember(x, y);
+			r = getNearestPartyMemberFromPos(x, y);
 		}
 	}
 
-	runItemScript(t->charNum, t->item, 0x8000, r, 0);
+	runItemScript(t->attackerId, t->item, 0x8000, r, 0);
 }
 
-void LoLEngine::updateFlyingObjects(FlyingObject *t) {
+void LoLEngine::updateFlyingObject(FlyingObject *t) {
 	int x = 0;
 	int y = 0;
 	getNextStepCoords(t->x, t->y, x, y, t->direction);

Modified: scummvm/trunk/engines/kyra/kyra_v1.h
===================================================================
--- scummvm/trunk/engines/kyra/kyra_v1.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/kyra_v1.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -56,6 +56,7 @@
 	bool useAltShapeHeader		: 1;	// alternative shape header (uses 2 bytes more, those are unused though)
 	bool isTalkie				: 1;
 	bool useHiResOverlay		: 1;
+	bool use16ColorMode			: 1;
 	bool useDigSound			: 1;
 	bool useInstallerPackage	: 1;
 
@@ -70,10 +71,11 @@
 };
 
 struct AudioDataStruct {
-	const char * const *_fileList;
-	int _fileListLen;
-	const void * _cdaTracks;
-	int _cdaNumTracks;
+	const char *const *fileList;
+	int fileListLen;
+	const void *cdaTracks;
+	int cdaNumTracks;
+	int extraOffset;
 };
 
 // TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable

Modified: scummvm/trunk/engines/kyra/lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -63,6 +63,9 @@
 		_lang = 2;
 		break;
 
+	case Common::JA_JPN:
+		_lang = 0;
+
 	default:
 		warning("unsupported language, switching back to English");
 		_lang = 0;
@@ -91,13 +94,14 @@
 	_specialSceneFlag = 0;
 	_lastCharInventory = -1;
 
-	_itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = 0;
+	_itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0;
 	_levelShpList = _levelDatList = 0;
 	_monsterShapes = _monsterPalettes = 0;
 	_monsterShapesEx = 0;
 	_gameShapeMap = 0;
 	memset(_monsterUnk, 0, 3);
 	_pageSavedFlag = false;
+	_healOverlay = 0;
 
 	_ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0;
 
@@ -181,7 +185,11 @@
 	_curMusicTheme = -1;
 	_curMusicFileExt = 0;
 	_curMusicFileIndex = -1;
-	_environmentSfx = _environmentSfxVol = _environmentSfxDistThreshold = 0;
+	_environmentSfx = _environmentSfxVol = _envSfxDistThreshold = 0;
+	_envSfxUseQueue = false;
+	_envSfxNumTracksInQueue = 0;
+	memset (_envSfxQueuedTracks, 0, sizeof(_envSfxQueuedTracks));
+	memset (_envSfxQueuedBlocks, 0, sizeof(_envSfxQueuedBlocks));
 
 	_sceneDrawVarDown = _sceneDrawVarRight = _sceneDrawVarLeft = _wllProcessFlag = 0;
 	_partyPosX = _partyPosY = 0;
@@ -198,7 +206,7 @@
 
 	memset(_charStatsTemp, 0, sizeof(_charStatsTemp));
 
-	_compassBroken = _unkBt2 = 0;
+	_compassBroken = _drainMagic = 0;
 	_dialogueField = false;
 
 	_rndSpecial = 0x12349876;
@@ -220,6 +228,8 @@
 	_defaultLegendData = 0;
 
 	_compassTimer = 0;
+	_timer3Para = 0;
+	_partyDeathFlag = -1;
 }
 
 LoLEngine::~LoLEngine() {
@@ -250,32 +260,49 @@
 			delete[]  _itemIconShapes[i];
 		delete[] _itemIconShapes;
 	}
+
 	if (_itemShapes) {
 		for (int i = 0; i < _numItemShapes; i++)
 			delete[]  _itemShapes[i];
 		delete[] _itemShapes;
 	}
+
 	if (_gameShapes) {
 		for (int i = 0; i < _numGameShapes; i++)
 			delete[]  _gameShapes[i];
 		delete[] _gameShapes;
 	}
+
 	if (_thrownShapes) {
 		for (int i = 0; i < _numThrownShapes; i++)
 			delete[]  _thrownShapes[i];
 		delete[] _thrownShapes;
 	}
+
 	if (_effectShapes) {
 		for (int i = 0; i < _numEffectShapes; i++)
 			delete[]  _effectShapes[i];
 		delete[] _effectShapes;
 	}
+
 	if (_fireballShapes) {
 		for (int i = 0; i < _numFireballShapes; i++)
 			delete[]  _fireballShapes[i];
 		delete[] _fireballShapes;
 	}
 
+	if (_healShapes) {
+		for (int i = 0; i < _numHealShapes; i++)
+			delete[]  _healShapes[i];
+		delete[] _healShapes;
+	}
+
+	if (_healiShapes) {
+		for (int i = 0; i < _numHealiShapes; i++)
+			delete[]  _healiShapes[i];
+		delete[] _healiShapes;
+	}
+
 	if (_monsterShapes) {
 		for (int i = 0; i < 48; i++)
 			delete[]  _monsterShapes[i];
@@ -357,6 +384,8 @@
 		}
 	}
 
+	delete[] _healOverlay;
+
 	delete[] _defaultLegendData;
 	delete[] _mapCursorOverlay;
 	delete[] _mapOverlay;
@@ -378,7 +407,7 @@
 	KyraEngine_v1::init();
 	initStaticResource();
 
-	_environmentSfxDistThreshold = (MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB) == MD_ADLIB || ConfMan.getBool("multi_midi")) ? 15 : 3;
+	_envSfxDistThreshold = (MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB) == MD_ADLIB || ConfMan.getBool("multi_midi")) ? 15 : 3;
 
 	_gui = new GUI_LoL(this);
 	assert(_gui);
@@ -475,6 +504,7 @@
 
 Common::Error LoLEngine::go() {
 	setupPrologueData(true);
+	_sound->setSoundList(&_soundData[kMusicIntro]);
 
 	if (!saveFileLoadable(0))
 		showIntro();
@@ -532,7 +562,7 @@
 		return Common::kNoError;
 
 	if (processSelection == 0) {
-		_sound->loadSoundFile("LOREINTR");
+		_sound->loadSoundFile(0);
 		_sound->playTrack(6);
 		chooseCharacter();
 		_sound->playTrack(1);
@@ -541,6 +571,9 @@
 
 	setupPrologueData(false);
 
+	_sound->setSoundList(&_soundData[kMusicIngame]);
+	_sound->loadSoundFile(0);
+
 	_tim = new TIMInterpreter_LoL(this, _screen, _system);
 	assert(_tim);
 
@@ -637,15 +670,27 @@
 
 	bool hasSave = saveFileLoadable(0);
 
-	MainMenu::StaticData data = {
-		{ 0, 0, 0, 0, 0 },
-		{ 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F },
-		{ 0x2C, 0x19, 0x48, 0x2C },
-		Screen::FID_9_FNT, 1
+	MainMenu::StaticData data[] = {
+		// 256 color mode
+		{
+			{ 0, 0, 0, 0, 0 },
+			{ 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F },
+			{ 0x2C, 0x19, 0x48, 0x2C },
+			Screen::FID_9_FNT, 1
+		},
+		// 16 color mode
+		{
+			{ 0, 0, 0, 0, 0 },
+			{ 0x01, 0x04, 0x0C, 0x03, 0x00, 0xC1, 0xE1 },
+			{ 0xCC, 0xDD, 0xDD, 0xDD },
+			Screen::FID_9_FNT, 1
+		}
 	};
 
+	int dataIndex = _flags.use16ColorMode ? 1 : 0;
+
 	if (hasSave)
-		++data.menuTable[3];
+		++data[dataIndex].menuTable[3];
 
 	static const uint16 mainMenuStrings[4][5] = {
 		{ 0x4248, 0x4249, 0x42DD, 0x424A, 0x0000 },
@@ -658,14 +703,14 @@
 
 	for (int i = 0; i < 5; ++i) {
 		if (hasSave)
-			data.strings[i] = getLangString(mainMenuStrings[1 + tableOffs][i]);
+			data[dataIndex].strings[i] = getLangString(mainMenuStrings[1 + tableOffs][i]);
 		else
-			data.strings[i] = getLangString(mainMenuStrings[tableOffs][i]);
+			data[dataIndex].strings[i] = getLangString(mainMenuStrings[tableOffs][i]);
 	}
 
 	MainMenu *menu = new MainMenu(this);
 	assert(menu);
-	menu->init(data, MainMenu::Animation());
+	menu->init(data[dataIndex], MainMenu::Animation());
 
 	int selection = menu->handle(_flags.isTalkie ? (hasSave ? 12 : 6) : (hasSave ? 6 : 13));
 	delete menu;
@@ -735,6 +780,20 @@
 	for (int i = 0; i < _numFireballShapes; i++)
 		_fireballShapes[i] = _screen->makeShapeCopy(shp, i);
 
+	_screen->loadBitmap("HEAL.SHP", 3, 3, 0);
+	shp = _screen->getCPagePtr(3);
+	_numHealShapes = READ_LE_UINT16(shp);
+	_healShapes = new uint8*[_numHealShapes];
+	for (int i = 0; i < _numHealShapes; i++)
+		_healShapes[i] = _screen->makeShapeCopy(shp, i);
+
+	_screen->loadBitmap("HEALI.SHP", 3, 3, 0);
+	shp = _screen->getCPagePtr(3);
+	_numHealiShapes = READ_LE_UINT16(shp);
+	_healiShapes = new uint8*[_numHealiShapes];
+	for (int i = 0; i < _numHealiShapes; i++)
+		_healiShapes[i] = _screen->makeShapeCopy(shp, i);
+
 	memset(_itemsInPlay, 0, 400 * sizeof(ItemInPlay));
 	for (int i = 0; i < 400; i++)
 		_itemsInPlay[i].shpCurFrame_flg |= 0x8000;
@@ -814,10 +873,10 @@
 		else
 			updateEnvironmentalSfx(0);
 
-		/*if (_partyDeathFlag != -1) {
-			checkForPartyDeath(_partyDeathFlag);
+		if (_partyDeathFlag != -1) {
+			checkForPartyDeath();
 			_partyDeathFlag = -1;
-		}*/
+		}
 
 		delay(_tickLength);
 	}
@@ -864,8 +923,12 @@
 	char *string = (char *)getTableEntry(buffer, realId);
 
 	char *srcBuffer = _stringBuffer[_lastUsedStringBuffer];
-	Util::decodeString1(string, srcBuffer);
-	Util::decodeString2(srcBuffer, srcBuffer);
+	if (_flags.lang != Common::JA_JPN) {
+		Util::decodeString1(string, srcBuffer);
+		Util::decodeString2(srcBuffer, srcBuffer);
+	} else {
+		decodeSjis(string, srcBuffer);
+	}
 
 	++_lastUsedStringBuffer;
 	_lastUsedStringBuffer %= ARRAYSIZE(_stringBuffer);
@@ -881,6 +944,36 @@
 	return buffer + READ_LE_UINT16(buffer + (id<<1));
 }
 
+void LoLEngine::decodeSjis(const char *src, char *dst) {
+	char s[2];
+	char d[3];
+	s[1] = 0;
+
+	uint8 cmd = *src++;
+
+	while (cmd) {
+		if (cmd == 27) {
+			cmd = *src & 0x7f;
+			src++;
+
+			for (int i = 0; i < cmd; i ++) {
+				*dst++ = *src++;
+				*dst++ = *src++;
+			}
+			cmd = *src++;
+			
+		} else {
+			s[0] = *src++;
+			Util::decodeString1(s, d);
+			*dst++ = d[0];
+			cmd = *src++;
+		}
+	}
+
+	if (!cmd)
+		*dst = 0;
+}
+
 bool LoLEngine::addCharacter(int id) {
 	const uint16 *cdf[] = { _charDefsMan, _charDefsMan, _charDefsMan, _charDefsWoman,
 		_charDefsMan, _charDefsMan, _charDefsWoman, _charDefsKieran, _charDefsAkshel };
@@ -913,29 +1006,30 @@
 
 	calcCharPortraitXpos();
 	if (numChars > 0)
-		setFaceFrames(numChars, 2, 6, 0);
+		setTemporaryFaceFrame(numChars, 2, 6, 0);
 
 	return true;
 }
 
-void LoLEngine::setFaceFrames(int charNum, int defaultFrame, int unk2, int redraw) {
-	_characters[charNum].defaultFaceFrame = defaultFrame;
-	if (defaultFrame || unk2)
-		setFaceFramesUnkArrays(charNum, 6, unk2, 1);
+void LoLEngine::setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw) {
+	_characters[charNum].defaultFaceFrame = frame;
+	if (frame || updateDelay)
+		setCharacterUpdateEvent(charNum, 6, updateDelay, 1);
 	if (redraw)
 		gui_drawCharPortraitWithStats(charNum);
 }
 
-void LoLEngine::setFaceFramesUnkArrays(int charNum, int unk1, int unk2, int unk3) {
+void LoLEngine::setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite) {
 	LoLCharacter *l = &_characters[charNum];
 	for (int i = 0; i < 5; i++) {
-		if (l->arrayUnk2[i] && (!unk3 || l->arrayUnk2[i] != unk1))
+		if (l->characterUpdateEvents[i] && (!overwrite || l->characterUpdateEvents[i] != updateType))
 			continue;
 
-		l->arrayUnk2[i] = unk1;
-		l->arrayUnk1[i] = unk2;
+		l->characterUpdateEvents[i] = updateType;
+		l->characterUpdateDelay[i] = updateDelay;
 		_timer->setNextRun(3, _system->getMillis());
 		_timer->enable(3);
+		break;
 	}
 }
 
@@ -1057,10 +1151,10 @@
 
 void LoLEngine::faceFrameRefresh(int charNum) {
 	if (_characters[charNum].curFaceFrame == 1)
-		setFaceFrames(charNum, 0, 0, 0);
+		setTemporaryFaceFrame(charNum, 0, 0, 0);
 	else if (_characters[charNum].curFaceFrame == 6)
 		if (_characters[charNum].defaultFaceFrame != 5)
-			setFaceFrames(charNum, 0, 0, 0);
+			setTemporaryFaceFrame(charNum, 0, 0, 0);
 		else
 			_characters[charNum].curFaceFrame = 5;
 	else
@@ -1114,7 +1208,7 @@
 		c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8;
 	} else {
 		// Character
-		c = _characters[index].itemsProtection + _characters[index].protection;
+		c = _characters[index].itemProtection + _characters[index].protection;
 		c = (c * _characters[index].defaultModifiers[2]) >> 8;
 		c = (c * _characters[index].totalProtectionModifier) >> 8;
 	}
@@ -1122,6 +1216,74 @@
 	return c;
 }
 
+void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode) {
+	static const uint16 barData[2][5] = {
+		// xPos, bar color, text color, flag, string id
+		{ 0x27, 0x9A, 0x98, 0x01, 0x4254 },
+		{ 0x21, 0xA2, 0xA0, 0x00, 0x4253 }
+	};
+
+	LoLCharacter *c = &_characters[charNum];
+	if (!(c->flags & 1))
+		return;
+
+	int pointsMax = type ? c->magicPointsMax : c->hitPointsMax;
+	int pointsCur = type ? c->magicPointsCur : c->hitPointsCur;
+
+	int newVal = (mode == 2) ? (pointsMax + points) : (mode ? (pointsCur + points) : points);
+	newVal = CLIP(newVal, 0, pointsMax);
+
+	if (type) {
+		c->magicPointsCur = newVal;
+	} else {
+		c->hitPointsCur = newVal;
+		if (c->hitPointsCur < 1)
+			c->flags |= 8;		
+	}
+
+	if (_updateFlags & 2)
+		return;
+
+	Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
+	int cp = _screen->setCurPage(0);
+
+	int s = 8192 / pointsMax;	
+	pointsMax = (s * pointsMax) >> 8;
+	pointsCur = (s * pointsCur) >> 8;
+	newVal = (s * newVal) >> 8;
+	int newValScl = CLIP(newVal, 0, pointsMax);
+
+	int step = (newVal > pointsCur) ? 2 : -2;
+	newVal = CLIP(newVal + step, 0, pointsMax);
+
+	if (newVal != pointsCur) {
+		step = (newVal >= pointsCur) ? 2 : -2;
+		
+		for (int i = pointsCur; i != newVal || newVal != newValScl;) {
+			if (ABS(i - newVal) < ABS(step))
+				step >>= 1;
+
+			i += step;
+
+			_smoothScrollTimer = _system->getMillis() + _tickLength;
+
+			gui_drawLiveMagicBar(barData[type][0] + _activeCharsXpos[charNum], 175, i, 0, pointsMax, 5, 32, barData[type][1], 1, barData[type][3]);
+			_screen->printText(getLangString(barData[type][4]), barData[type][0] + _activeCharsXpos[charNum], 144, barData[type][2], 0);
+			_screen->updateScreen();
+
+			if (i == newVal) {
+				newVal = newValScl;
+				step = -step;
+			}			
+
+			delayUntil(_smoothScrollTimer);
+		}
+	}
+
+	_screen->setFont(cf);
+	_screen->setCurPage(cp);
+}
+
 void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) {
 	if (charNum & 0x8000)
 		return;
@@ -1174,6 +1336,17 @@
 	}
 }
 
+void LoLEngine::increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath) {
+	if (_characters[charNum].hitPointsCur <= 0 && !ignoreDeath)
+		return;
+
+	if (points <= 1)
+		points = 1;
+
+	_characters[charNum].hitPointsCur = CLIP<int16>(_characters[charNum].hitPointsCur + points, 1, _characters[charNum].hitPointsMax);
+	_characters[charNum].flags &= 0xfff7;
+}
+
 void LoLEngine::setupScreenDims() {
 	if (textEnabled()) {
 		_screen->modifyScreenDim(4, 11, 124, 28, 45);
@@ -1590,7 +1763,7 @@
 	int dist = 0;
 	if (block) {
 		dist = getMonsterDistance(_currentBlock, block);
-		if (dist > _environmentSfxDistThreshold) {
+		if (dist > _envSfxDistThreshold) {
 			_environmentSfx = 0;
 			return;
 		}
@@ -1619,6 +1792,16 @@
 	snd_processEnvironmentalSoundEffect(0, 0);
 }
 
+void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) {
+	if (_envSfxUseQueue && _envSfxNumTracksInQueue < 10) {
+		_envSfxQueuedTracks[_envSfxNumTracksInQueue] = soundId;
+		_envSfxQueuedBlocks[_envSfxNumTracksInQueue] = block;
+		_envSfxNumTracksInQueue++;
+	} else {
+		snd_processEnvironmentalSoundEffect(soundId, block);
+	}
+}
+
 void LoLEngine::snd_loadSoundFile(int track) {
 	if (_sound->musicEnabled()) {
 		char filename[13];
@@ -1781,6 +1964,14 @@
 	return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
 }
 
+uint16 *LoLEngine::getCharacterOrMonsterItemsMight(int id) {
+	return (id & 0x8000) ? _monsters[id & 0x7fff].properties->itemsMight : _characters[id].itemsMight;
+}
+
+uint16 *LoLEngine::getCharacterOrMonsterProtectionAgainstItems(int id) {
+	return (id & 0x8000) ? _monsters[id & 0x7fff].properties->protectionAgainstItems : _characters[id].protectionAgainstItems;
+}
+
 void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) {
 	uint32 endTime = _system->getMillis() + millis;
 	while (endTime > _system->getMillis()) {
@@ -1820,6 +2011,120 @@
 	snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
 }
 
+void LoLEngine::processMagicHeal(int charNum, int points) {
+	if (!_healOverlay) {
+		_healOverlay = new uint8[256];
+		_screen->generateGrayOverlay(_screen->getPalette(1), _healOverlay, 52, 22, 20, 0, 256, true);
+	}
+
+	const uint8 *healShpFrames = 0;
+	const uint8 *healiShpFrames = 0;
+	bool resetFlag = false;
+	int maxDiff = 0;
+
+	if (points == 0) {
+		maxDiff = 25;
+		healShpFrames = _healShapeFrames;
+		healiShpFrames = _healShapeFrames + 32;
+
+	} else if (points == 1) {
+		maxDiff = 45;
+		healShpFrames = _healShapeFrames + 16;
+		healiShpFrames = _healShapeFrames + 48;
+
+	} else if (points > 3) {
+		resetFlag = true;
+		maxDiff = points;
+		healShpFrames = _healShapeFrames + 16;
+		healiShpFrames = _healShapeFrames + 64;
+
+	} else {
+		resetFlag = true;
+		maxDiff = 10000;
+		healShpFrames = _healShapeFrames + 16;
+		healiShpFrames = _healShapeFrames + 64;
+
+	}
+
+	int ch = 0;
+	int n = 4;
+
+	if (charNum != -1){
+		ch = charNum;
+		n = charNum + 1;
+	}
+
+	charNum = ch;
+
+	uint16 pX[4];
+	uint16 pY = 138;
+	uint16 diff[4];
+	uint16 pts[4];
+	memset(pts, 0, sizeof(pts));
+
+	while (charNum < n) {
+		if (!(_characters[charNum].flags & 1))
+			continue;
+
+		pX[charNum] = _activeCharsXpos[charNum] - 6;
+		_characters[charNum].damageSuffered = 0;
+		int dmg = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur;
+		diff[charNum] = (dmg < maxDiff) ? dmg : maxDiff;
+		_screen->copyRegion(pX[charNum], pY, charNum * 77, 32, 77, 44, 0, 2, Screen::CR_NO_P_CHECK);
+		charNum++;
+	}
+
+	int cp = _screen->setCurPage(2);
+	snd_playSoundEffect(68, -1);
+
+	for (int i = 0; i < 16; i++) {
+		_smoothScrollTimer = _system->getMillis() + 4 * _tickLength;
+
+		for (charNum = ch; charNum < n; charNum++) {
+			if (!(_characters[charNum].flags & 1))
+				continue;
+
+			_screen->copyRegion(charNum * 77, 32, pX[charNum], pY, 77, 44, 2, 2, Screen::CR_NO_P_CHECK);
+
+			pts[charNum] &= 0xff;
+			pts[charNum] += ((diff[charNum] << 8) / 16);
+			increaseCharacterHitpoints(ch, pts[charNum] / 256, true);
+			gui_drawCharPortraitWithStats(charNum);
+
+			_screen->drawShape(2, _healShapes[healShpFrames[i]], pX[charNum], pY, 0, 0x1000, _trueLightTable1, _trueLightTable2);
+			_screen->fillRect(0, 0, 31, 31, 0);
+
+			_screen->drawShape(_screen->_curPage, _healiShapes[healiShpFrames[i]], 0, 0, 0, 0);
+			_screen->applyOverlaySpecial(_screen->_curPage, 0, 0, 2, pX[charNum] + 7, pY + 6, 32, 32, 0, 0, _healOverlay);
+
+			_screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK);
+			_screen->updateScreen();
+		}
+
+		while ((int)(_smoothScrollTimer - _system->getMillis()) > 0) {
+			updateInput();
+			delay(_tickLength);
+		}
+	}
+
+	for (charNum = ch; charNum < n; charNum++) {
+		if (!(_characters[charNum].flags & 1))
+				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);
+
+		gui_drawCharPortraitWithStats(charNum);
+		_screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->updateScreen();
+	}
+
+	_screen->setCurPage(cp);
+	updateDrawPage2();
+}
+
 bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
 	if (_spellProperties[spellNum].mpRequired[spellLevel] > _characters[charNum].magicPointsCur) {
 		if (characterSays(0x4043, _characters[charNum].id, true))
@@ -1833,6 +2138,8 @@
 	return false;
 }
 
+// fight
+
 int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
 	if (target == -1)
 		return 0;
@@ -1879,31 +2186,443 @@
 }
 
 int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType) {
-	const uint16 *s = getCharacterOrMonsterStats(attacker);
+	const uint16 *s = getCharacterOrMonsterItemsMight(attacker);
 
-	int res = 0;
+	// The original code looks somewhat like the commented out part of the next line.
+	// In the end the value is always set to zero. I do not know whether this is done on purpose or not.
+	// It might be a bug in the original code.
+	int res = 0/*attacker & 0x8000 ? 0 : _characters[attacker].might*/;
 	for (int i = 0; i < 8; i++)
-		res += calcInflictableDamagePerStat(attacker, target, s[2 + i], i, hitType);
+		res += calcInflictableDamagePerItem(attacker, target, s[i], i, hitType);
 
 	return res;
 }
 
-void LoLEngine::battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b) {
+int LoLEngine::inflictDamage(int16 target, int damage, int16 attacker, int skill, int deathFlag) {
+	MonsterInPlay *m = 0;
+	LoLCharacter *c = 0;
 
+	if (target & 0x8000) {
+		m = &_monsters[target & 0x7fff];
+		if (m->mode >= 13)
+			return 0;
+
+		if (damage > 0) {
+			m->hitPoints -= damage;
+			m->damageReceived = 0x8000 | damage;
+			m->flags |= 0x10;
+			m->hitOffsX = _rnd.getRandomNumberRng(1, 24);
+			m->hitOffsX -= 12;
+			m->hitOffsY = _rnd.getRandomNumberRng(1, 24);
+			m->hitOffsY -= 12;
+			m->hitPoints = CLIP<int16>(m->hitPoints, 0, m->properties->hitPoints);
+
+			if (!(attacker & 0x8000))
+				applyMonsterDefenseSkill(m, attacker, deathFlag, skill, damage);
+
+			snd_queueEnvironmentalSoundEffect(m->properties->sounds[2], m->block);
+			checkSceneUpdateNeed(m->block);
+			
+			if (m->hitPoints <= 0) {
+				m->hitPoints = 0;
+				if (!(attacker & 0x8000))
+					increaseExperience(attacker, skill, m->properties->hitPoints);
+				setMonsterMode(m, 13);
+			}
+		} else {
+			m->hitPoints -= damage;
+			m->hitPoints = CLIP<int16>(m->hitPoints, 1, m->properties->hitPoints);
+		}
+
+	} else {
+		c = &_characters[target];
+		if (!(c->flags & 1) || (c->flags & 8))
+			return 0;
+
+		if (!(c->flags & 0x1000))
+			snd_playSoundEffect(c->screamSfx, -1);
+
+		setTemporaryFaceFrame(target, 6, 4, 0);
+
+		// check for equipped cloud ring
+		if (deathFlag == 4 && itemEquipped(target, 229))
+			damage >>= 2;
+
+		setCharacterMagicOrHitPoints(target, 0, -damage, 1);
+
+		if (c->hitPointsCur <= 0) {
+			characterHitpointsZero(target, deathFlag);
+		} else {
+			_characters[target].damageSuffered = damage;
+			setCharacterUpdateEvent(target, 2, 4, 1);
+		}
+		gui_drawCharPortraitWithStats(target);
+	}
+
+	if (!(attacker & 0x8000)) {
+		if (!skill)
+			_characters[attacker].weaponHit = damage;
+		increaseExperience(attacker, skill, damage);
+	}
+
+	return damage;
 }
 
-void LoLEngine::battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted) {
+void LoLEngine::characterHitpointsZero(int16 charNum, int deathFlag) {
+	LoLCharacter *c = &_characters[charNum];
+	c->hitPointsCur = 0;
+	c->flags |= 8;
+	resetCharacterState(c, 1, 5);
+	_partyDeathFlag = deathFlag;
+}
 
+void LoLEngine::resetCharacterState(LoLCharacter *c, int first, int last) {
+	for (int i = first; i <= last; i++) {
+		switch (i - 1) {
+			case 0:
+				c->weaponHit = 0;
+				break;
+
+			case 1:
+				c->damageSuffered = 0;
+				break;
+
+			case 2:
+				c->flags &= 0xffbf;
+				break;
+
+			case 3:
+				c->flags &= 0xff7f;
+				break;
+
+			case 4:
+				c->flags &= 0xfeff;
+				break;
+
+			case 6:
+				c->flags &= 0xefff;
+				break;
+
+			default:
+				break;
+		}
+
+		for (int ii = 0; ii < 5; ii++) {
+			if (i != c->characterUpdateEvents[ii])
+				continue;
+
+			c->characterUpdateEvents[ii] = 0;
+			c->characterUpdateDelay[ii] = 0;
+		}
+	}
+
+	_timer3Para = 1;
+	_timer->enable(3);
 }
 
-int LoLEngine::calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType) {
-	return 1;
+int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType) {
+	int dmg = (attacker == -1) ? 0x100 : getCharacterOrMonsterStats(attacker)[1];
+	const uint16 *st_t = getCharacterOrMonsterProtectionAgainstItems(target);
+
+	dmg = (dmg * itemMight) >> 8;
+	if (!dmg)
+		return 0;
+
+	if (!(attacker & 0x8000)) {
+		dmg = (dmg * _characters[attacker].totalMightModifier) >> 8;	
+		if (!dmg)
+			return 0;
+	}
+
+	int d = (index & 0x80) ? st_t[7] : st_t[index];
+	int r = (dmg * ABS(d)) >> 8;
+	dmg = d < 0 ? -r : r;
+
+	if (hitType == 2 || !dmg)
+		return (dmg == 1) ? 2 : dmg;
+
+
+	int p = (calculateProtection(target) << 7) / dmg;
+	if (p > 217)
+		p = 217;
+
+	d = 256 - p;
+	r = (dmg * ABS(d)) >> 8;
+	dmg = d < 0 ? -r : r;
+
+	return (dmg < 2) ? 2 : dmg;
 }
 
-uint16 LoLEngine::getClosestMonster(int x, int y) {
+void LoLEngine::checkForPartyDeath() {
+
+}
+
+void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) {
+	if (_rnd.getRandomNumberRng(1, 100) > monster->properties->attackSkillChance)
+		return;
+
+	int t = 0;
+
+	switch (monster->properties->attackSkillType - 1) {
+		case 0:
+			t = removeCharacterItem(target, 0x7ff);
+			if (t) {
+				giveItemToMonster(monster, t);
+				if (characterSays(0x4019, _characters[target].id, true))
+					_txt->printMessage(6, getLangString(0x4019));
+			}
+			break;
+
+		case 1:
+			// poison character
+			paralyzePoisonCharacter(target, 0x80, 0x88, 100, 1);
+			break;
+
+		case 2:
+			t = removeCharacterItem(target, 0x20);
+			if (t) {
+				deleteItem(t);
+				if (characterSays(0x401b, _characters[target].id, true))
+					_txt->printMessage(6, getLangString(0x401b));
+			}
+			break;
+
+		case 3:
+			t = removeCharacterItem(target, 0x0f);
+			if (t) {
+				if (characterSays(0x401e, _characters[target].id, true))
+					_txt->printMessage(6, getLangString(0x401e), _characters[target].name);
+				setItemPosition(t, monster->x, monster->y, 0, 1);
+			}
+			break;
+
+		case 5:
+			if (_characters[target].magicPointsCur <= 0)
+				return;
+
+			monster->hitPoints += _characters[target].magicPointsCur;
+			_characters[target].magicPointsCur = 0;
+			gui_drawCharPortraitWithStats(target);
+			if (characterSays(0x4020, _characters[target].id, true))
+				_txt->printMessage(6, getLangString(0x4020), _characters[target].name);
+			break;
+
+		case 7:
+			stunCharacter(target);
+			break;
+
+		case 8:
+			monster->hitPoints += damage;
+			if (monster->hitPoints > monster->properties->hitPoints)
+				monster->hitPoints = monster->properties->hitPoints;
+
+			break;
+
+		case 9:
+			// paralyze party (spider web)
+			paralyzePoisonAllCharacters(0x40, 0x48, 100);
+			break;
+
+		default:
+			break;
+	}
+}
+
+void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage) {
+	if (_rnd.getRandomNumberRng(1, 100) > monster->properties->defenseSkillChance)
+		return;
+
+	int itm = 0;
+
+	switch (monster->properties->defenseSkillType - 1) {
+		case 0:
+		case 1:
+			if ((deathFlag & 0x3f) == 2 || skill)
+				return;
+
+			for (int i = 0; i < 3 ; i++) {
+				itm = _characters[attacker].items[i];
+				if (!itm)
+					continue;
+				if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3f) != deathFlag)
+					continue;
+
+				removeCharacterItem(attacker, 0x7fff);
+
+				if (monster->properties->defenseSkillType == 1) {
+					deleteItem(itm);
+					if (characterSays(0x401d, _characters[attacker].id, true))
+						_txt->printMessage(6, getLangString(0x401d));
+				} else {
+					giveItemToMonster(monster, itm);
+					if (characterSays(0x401c, _characters[attacker].id, true))
+						_txt->printMessage(6, getLangString(0x401c));
+				}
+			}
+			break;
+
+		case 2:
+			if (!(deathFlag & 0x80))
+				return;
+			monster->flags |= 8;
+			monster->direction = calcMonsterDirection(monster->x, monster->y, _partyPosX, _partyPosY) ^ 4;
+			setMonsterMode(monster, 9);
+			monster->fightCurTick = 30;
+			break;
+
+		case 3:
+			if (deathFlag != 3)
+				return;
+			monster->hitPoints += damage;
+			if (monster->hitPoints > monster->properties->hitPoints)
+				monster->hitPoints = monster->properties->hitPoints;
+
+
+			break;
+
+		case 4:
+			if (!(deathFlag & 0x80))
+				return;			
+			monster->hitPoints += damage;
+			if (monster->hitPoints > monster->properties->hitPoints)
+				monster->hitPoints = monster->properties->hitPoints;
+			break;
+
+		case 5:
+			if ((deathFlag & 0x84) == 0x84)
+				monster->numDistAttacks++;
+			break;
+
+		default:
+			break;
+	}
+}
+
+int LoLEngine::removeCharacterItem(int charNum, int itemFlags) {
+	for (int i = 0; i < 11; i++) {
+		int s = _characters[charNum].items[i];
+		if (!((1 << i) & itemFlags) || !s)
+			continue;
+
+		_characters[charNum].items[i] = 0;
+		runItemScript(charNum, s, 0x100, 0, 0);
+
+		return s;
+	}
+
+	return 0;
+}
+
+bool LoLEngine::paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw) {
+	if (!(_characters[charNum].flags & 1) || (_characters[charNum].flags & immunityFlags))
+		return 0;
+
+	if ((int)_rnd.getRandomNumberRng(1, 100) > hitChance)
+		return 0;
+
+	int r = false;
+	
+	if (typeFlag == 0x40) {
+		_characters[charNum].flags |= 0x40;
+		setCharacterUpdateEvent(charNum, 3, 3600, 1);
+		r = true;
+
+	// check for bezel ring
+	} else if (typeFlag == 0x80 && !itemEquipped(charNum, 225)) {
+		_characters[charNum].flags |= 0x80;
+		setCharacterUpdateEvent(charNum, 4, 10, 1);
+		if (characterSays(0x4021, _characters[charNum].id, true))
+			_txt->printMessage(6, getLangString(0x4021), _characters[charNum].name);
+		r = true;
+
+	} else if (typeFlag == 0x1000) {
+		_characters[charNum].flags |= 0x1000;
+		setCharacterUpdateEvent(charNum, 7, 120, 1);		
+		r = true;
+	}
+
+	if (r && redraw)
+		gui_drawCharPortraitWithStats(charNum);
+
+	return r;
+}
+
+void LoLEngine::paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance) {
+	bool r = false;
+	for (int i = 0; i < 4; i++) {
+		if (paralyzePoisonCharacter(i, typeFlag, immunityFlags, hitChance, 0))
+			r = true;
+	}
+	if (r)
+		gui_drawAllCharPortraitsWithStats();
+}
+
+void LoLEngine::stunCharacter(int charNum) {
+	if (!(_characters[charNum].flags & 1) || (_characters[charNum].flags & 0x108))
+		return;
+
+	_characters[charNum].flags |= 0x100;
+
+	setCharacterUpdateEvent(charNum, 5, 20, 1);
+	gui_drawCharPortraitWithStats(charNum);
+
+	_txt->printMessage(6, getLangString(0x4026), _characters[charNum].name);
+}
+
+void LoLEngine::level11specialUnk() {
+
+}
+
+void LoLEngine::distObj1Sub(int a, int b, int c, int d) {
+
+}
+
+void LoLEngine::launchMagicViper() {
+
+}
+
+void LoLEngine::attackWall(int a, int b) {
+
+}
+
+uint16 LoLEngine::getNearestMonsterFromCharacter(int charNum) {
+	return getNearestMonsterFromCharacterForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum);
+}
+
+uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(int block, int charNum) {
+	uint16 cX = 0;
+	uint16 cY = 0;
+
 	uint16 id = 0xffff;
 	int minDist = 0x7fff;
 
+	calcCoordinatesForSingleCharacter(charNum, cX, cY);
+
+	int o = _levelBlockProperties[block].assignedObjects;
+
+	while (o & 0x8000) {
+		MonsterInPlay *m = &_monsters[o & 0x7fff];
+		if (m->mode >= 13) {
+			o = m->nextAssignedObject;
+			continue;
+		}
+
+		int d = ABS(cX - m->x) + ABS(cY - m->y);
+		if (d < minDist) {
+			minDist = d;
+			id = o;
+		}
+
+		o = m->nextAssignedObject;
+	}
+
+	return id;
+}
+
+uint16 LoLEngine::getNearestMonsterFromPos(int x, int y) {
+	uint16 id = 0xffff;
+	int minDist = 0x7fff;
+
 	for (int i = 0; i < 30; i++) {
 		if (_monsters[i].mode > 13)
 			continue;
@@ -1918,7 +2637,7 @@
 	return id;
 }
 
-uint16 LoLEngine::getClosestPartyMember(int x, int y) {
+uint16 LoLEngine::getNearestPartyMemberFromPos(int x, int y) {
 	uint16 id = 0xffff;
 	int minDist = 0x7fff;
 
@@ -1940,50 +2659,6 @@
 	return id;
 }
 
-void LoLEngine::generateTempData() {
-	int l = _currentLevel - 1;
-	if (_lvlTempData[l]) {
-		delete[] _lvlTempData[l]->wallsXorData;
-		delete[] _lvlTempData[l]->flags;
-		delete[] _lvlTempData[l]->monsters;
-		delete[] _lvlTempData[l]->flyingObjects;
-		delete _lvlTempData[l];
-	}
-
-	_lvlTempData[l] = new LevelTempData;
-
-	_lvlTempData[l]->wallsXorData = new uint8[4096];
-	_lvlTempData[l]->flags = new uint8[1024];
-	_lvlTempData[l]->monsters = new MonsterInPlay[30];
-	_lvlTempData[l]->flyingObjects = new FlyingObject[8];
-
-	char filename[13];
-	snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel);
-
-	_screen->loadBitmap(filename, 3, 3, 0);
-	const uint8 *p = _screen->getCPagePtr(2);
-	uint16 len = READ_LE_UINT16(p + 4);
-	p += 6;
-
-	memset(_lvlTempData[l]->wallsXorData, 0, 4096);
-	memset(_lvlTempData[l]->flags, 0, 1024);
-	uint8 *d = _lvlTempData[l]->wallsXorData;
-	uint8 *df = _lvlTempData[l]->flags;
-
-	for (int i = 0; i < 1024; i++) {
-		for (int ii = 0; ii < 4; ii++)
-			*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
-		*df++ = _levelBlockProperties[i].flags;
-	}
-
-	memcpy(_lvlTempData[l]->monsters, _monsters,  sizeof(MonsterInPlay) * 30);
-	memcpy(_lvlTempData[l]->flyingObjects, _flyingObjects,  sizeof(FlyingObject) * 8);
-
-	_lvlTempData[l]->monsterDifficulty =_monsterDifficulty;
-
-	_hasTempDataFlags |= (1 << l);
-}
-
 // magic atlas
 
 void LoLEngine::displayAutomap() {
@@ -2056,7 +2731,7 @@
 			exitAutomap = true;
 		}
 
-		delay (_tickLength);
+		delay(_tickLength);
 	}
 
 	_screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT");
@@ -2468,6 +3143,50 @@
 	_screen->setCurPage(cp);
 }
 
+void LoLEngine::generateTempData() {
+	int l = _currentLevel - 1;
+	if (_lvlTempData[l]) {
+		delete[] _lvlTempData[l]->wallsXorData;
+		delete[] _lvlTempData[l]->flags;
+		delete[] _lvlTempData[l]->monsters;
+		delete[] _lvlTempData[l]->flyingObjects;
+		delete _lvlTempData[l];
+	}
+
+	_lvlTempData[l] = new LevelTempData;
+
+	_lvlTempData[l]->wallsXorData = new uint8[4096];
+	_lvlTempData[l]->flags = new uint8[1024];
+	_lvlTempData[l]->monsters = new MonsterInPlay[30];
+	_lvlTempData[l]->flyingObjects = new FlyingObject[8];
+
+	char filename[13];
+	snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel);
+
+	_screen->loadBitmap(filename, 3, 3, 0);
+	const uint8 *p = _screen->getCPagePtr(2);
+	uint16 len = READ_LE_UINT16(p + 4);
+	p += 6;
+
+	memset(_lvlTempData[l]->wallsXorData, 0, 4096);
+	memset(_lvlTempData[l]->flags, 0, 1024);
+	uint8 *d = _lvlTempData[l]->wallsXorData;
+	uint8 *df = _lvlTempData[l]->flags;
+
+	for (int i = 0; i < 1024; i++) {
+		for (int ii = 0; ii < 4; ii++)
+			*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
+		*df++ = _levelBlockProperties[i].flags;
+	}
+
+	memcpy(_lvlTempData[l]->monsters, _monsters,  sizeof(MonsterInPlay) * 30);
+	memcpy(_lvlTempData[l]->flyingObjects, _flyingObjects,  sizeof(FlyingObject) * 8);
+
+	_lvlTempData[l]->monsterDifficulty =_monsterDifficulty;
+
+	_hasTempDataFlags |= (1 << l);
+}
+
 } // end of namespace Kyra
 
 #endif // ENABLE_LOL

Modified: scummvm/trunk/engines/kyra/lol.h
===================================================================
--- scummvm/trunk/engines/kyra/lol.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/lol.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -50,18 +50,11 @@
 	int16 id;
 	uint8 curFaceFrame;
 	uint8 defaultFaceFrame;
-	uint8 field_12;
+	uint8 screamSfx;
 	const uint16 *defaultModifiers;
 	uint16 itemsMight[8];
-	uint16 field_27[2];
-	uint8 field_2B;
-	uint16 field_2C;
-	uint16 field_2E;
-	uint16 field_30;
-	uint16 field_32;
-	uint16 field_34;
-	uint8 field_36;
-	uint16 itemsProtection;
+	uint16 protectionAgainstItems[8];
+	uint16 itemProtection;
 	int16 hitPointsCur;
 	uint16 hitPointsMax;
 	int16 magicPointsCur;
@@ -78,8 +71,8 @@
 	uint8 skillLevels[3];
 	uint8 skillModifiers[3];
 	int32 experiencePts[3];
-	uint8 arrayUnk2[5];
-	uint8 arrayUnk1[5];
+	uint8 characterUpdateEvents[5];
+	uint8 characterUpdateDelay[5];
 };
 
 struct SpellProperty {
@@ -100,17 +93,22 @@
 struct MonsterProperty {
 	uint8 shapeIndex;
 	uint8 maxWidth;
-	uint16 fightingStats[10];
-	uint16 unk2[8];
-	uint16 unk3[8];
+	uint16 fightingStats[9];
+	uint16 itemsMight[8];
+	uint16 protectionAgainstItems[8];
 	uint16 itemProtection;
-	uint16 might;
+	uint16 hitPoints;
 	uint8 speedTotalWaitTicks;
 	uint8 skillLevel;
 	uint16 flags;
 	uint16 unk5;
-	uint16 unk6[5];
-	uint8 unk7[4];
+	uint16 numDistAttacks;
+	uint16 numDistWeapons;
+	uint16 distWeapons[3];
+	uint8 attackSkillChance;
+	uint8 attackSkillType;
+	uint8 defenseSkillChance;
+	uint8 defenseSkillType;
 	uint8 sounds[3];
 };
 
@@ -118,15 +116,15 @@
 	uint16 nextAssignedObject;
 	uint16 nextDrawObject;
 	uint8 flyingHeight;
-	uint16 blockPropertyIndex;
+	uint16 block;
 	uint16 x;
 	uint16 y;
 	int8 shiftStep;
 	uint16 destX;
 	uint16 destY;
 	uint8 destDirection;
-	uint8 anon8;
-	uint8 anonh;
+	int8 hitOffsX;
+	int8 hitOffsY;
 	uint8 currentSubFrame;
 
 	uint8 mode;
@@ -135,15 +133,15 @@
 	uint8 direction;
 	uint8 facing;
 	uint16 flags;
-	uint8 field_1B;
-	uint8 field_1C;
-	int16 might;
+	uint16 damageReceived;
+	//uint8 field_1C;
+	int16 hitPoints;
 	uint8 speedTick;
 	uint8 type;
 	MonsterProperty *properties;
-	uint8 field_25;
-	uint8 field_26;
-	uint8 field_27;
+	uint8 numDistAttacks;
+	uint8 curDistWeapon;
+	int8 distAttackTick;
 	uint16 assignedItems;
 	uint8 field_2A[4];
 };
@@ -152,15 +150,15 @@
 	uint16 nextAssignedObject;
 	uint16 nextDrawObject;
 	uint8 flyingHeight;
-	uint16 blockPropertyIndex;
+	uint16 block;
 	uint16 x;
 	uint16 y;
 	int8 level;
 	uint16 itemPropertyIndex;
 	uint16 shpCurFrame_flg;
 	uint8 destDirection;
-	uint8 anon8;
-	uint8 anonh;
+	int8 hitOffsX;
+	int8 hitOffsY;
 	uint8 currentSubFrame;
 };
 
@@ -213,8 +211,8 @@
 
 struct FlyingObject {
 	uint8 enable;
-	uint8 a;
-	uint16 charNum;
+	uint8 objectType;
+	uint16 attackerId;
 	uint16 item;
 	uint16 x;
 	uint16 y;
@@ -324,6 +322,8 @@
 
 	int getCharSelection();
 	int selectionCharAccept();
+	
+	void showStarcraftLogo();
 
 	int _charSelection;
 	int _charSelectionInfoResult;
@@ -354,16 +354,17 @@
 
 	void timerProcessDoors(int timerNum);
 	void timerProcessMonsters(int timerNum);
-	void timerSub3(int timerNum);
+	void timerSpecialCharacterUpdate(int timerNum);
 	void timerProcessFlyingObjects(int timerNum);
 	void timerRunSceneAnimScript(int timerNum);
-	void timerSub6(int timerNum);
+	void timerRegeneratePoints(int timerNum);
 	void timerUpdatePortraitAnimations(int skipUpdate);
 	void timerUpdateLampState(int timerNum);
 	void timerFadeMessageText(int timerNum);
 
 	static const uint8 _clock2Timers[];
 	static const uint8 _numClock2Timers;
+	int _timer3Para;
 
 	// sound
 	void loadTalkFile(int index);
@@ -373,6 +374,7 @@
 	void snd_stopSpeech(bool setFlag);
 	void snd_playSoundEffect(int track, int volume);
 	void snd_processEnvironmentalSoundEffect(int soundId, int block);
+	void snd_queueEnvironmentalSoundEffect(int soundId, int block);
 	void snd_loadSoundFile(int track);
 	int snd_playTrack(int track);
 	int snd_stopMusic();
@@ -387,7 +389,11 @@
 	char _curMusicFileExt;
 	int _environmentSfx;
 	int _environmentSfxVol;
-	int _environmentSfxDistThreshold;
+	int _envSfxDistThreshold;
+	bool _envSfxUseQueue;
+	int _envSfxNumTracksInQueue;
+	uint16 _envSfxQueuedTracks[10];
+	uint16 _envSfxQueuedBlocks[10];
 	int _nextSpeechId;
 	int _nextSpeaker;
 
@@ -405,9 +411,9 @@
 	int _ingameGMSoundIndexSize;
 	const uint8 *_ingameMT32SoundIndex;
 	int _ingameMT32SoundIndexSize;
-	/*const uint8 *_ingameADLSoundIndex;
-	int _ingameADLSoundIndexSize;*/
 
+	AudioDataStruct _soundData[3];
+
 	// gui
 	void gui_drawPlayField();
 	void gui_drawScene(int pageNum);
@@ -597,15 +603,18 @@
 	int olol_fadeSequencePalette(EMCState *script);
 	int olol_redrawPlayfield(EMCState *script);
 	int olol_loadNewLevel(EMCState *script);
+	int olol_getNearestMonsterFromCharacter(EMCState *script);
 	int olol_dummy0(EMCState *script);
 	int olol_loadMonsterProperties(EMCState *script);
 	int olol_battleHitSkillTest(EMCState *script);
+	int olol_inflictDamage(EMCState *script);
 	int olol_moveMonster(EMCState *script);
 	int olol_dialogueBox(EMCState *script);
 	int olol_giveTakeMoney(EMCState *script);
 	int olol_checkMoney(EMCState *script);
 	int olol_setScriptTimer(EMCState *script);
 	int olol_createHandItem(EMCState *script);
+	int olol_playAttackSound(EMCState *script);
 	int olol_characterJoinsParty(EMCState *script);
 	int olol_loadTimScript(EMCState *script);
 	int olol_runTimScript(EMCState *script);
@@ -619,18 +628,23 @@
 	int olol_processDialogue(EMCState *script);
 	int olol_stopTimScript(EMCState *script);
 	int olol_getWallFlags(EMCState *script);
-	int olol_changeMonsterSettings(EMCState *script);
+	int olol_changeMonsterStat(EMCState *script);
+	int olol_getMonsterStat(EMCState *script);
 	int olol_playCharacterScriptChat(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_stopCharacterSpeech(EMCState *script);
 	int olol_setPaletteBrightness(EMCState *script);
+	int olol_calcInflictableDamage(EMCState *script);
+	int olol_getInflictedDamage(EMCState *script);
 	int olol_checkForCertainPartyMember(EMCState *script);
 	int olol_printMessage(EMCState *script);
 	int olol_deleteLevelItem(EMCState *script);
+	int olol_calcInflictableDamagePerItem(EMCState *script);
 	int olol_objectLeavesLevel(EMCState *script);
 	int olol_playDialogueTalkText(EMCState *script);
 	int olol_checkMonsterTypeHostility(EMCState *script);
@@ -638,7 +652,7 @@
 	int olol_dummy1(EMCState *script);
 	int olol_suspendMonster(EMCState *script);
 	int olol_setDoorState(EMCState *script);
-	int olol_processButtonClick(EMCState *script);
+	int olol_resetTimDialogueState(EMCState *script);
 	int olol_savePage5(EMCState *script);
 	int olol_restorePage5(EMCState *script);
 	int olol_initDialogueSequence(EMCState *script);
@@ -699,6 +713,7 @@
 								// Maybe we can someday reduce the size.
 	char *getLangString(uint16 id);
 	uint8 *getTableEntry(uint8 *buffer, uint16 id);
+	void decodeSjis(const char *src, char *dst);
 
 	static const char * const _languageExt[];
 
@@ -728,8 +743,6 @@
 	int _numThrownShapes;
 	uint8 **_effectShapes;
 	int _numEffectShapes;
-	uint8 **_fireballShapes;
-	int _numFireballShapes;
 
 	const int8 *_gameShapeMap;
 	int _gameShapeMapSize;
@@ -740,8 +753,8 @@
 
 	// characters
 	bool addCharacter(int id);
-	void setFaceFrames(int charNum, int defaultFrame, int unk2, int redraw);
-	void setFaceFramesUnkArrays(int charNum, int unk1, int unk2, int unk3);
+	void setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw);
+	void setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite);
 	int countActiveCharacters();
 	void loadCharFaceShapes(int charNum, int id);
 	void calcCharPortraitXpos();
@@ -756,7 +769,9 @@
 	int calculateCharacterStats(int charNum, int index);
 	int calculateProtection(int index);
 
+	void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode);
 	void increaseExperience(int charNum, int skill, uint32 points);
+	void increaseCharacterHitpoints(int charNum, int points, bool unk);
 
 	LoLCharacter *_characters;
 	uint16 _activeCharsXpos[3];
@@ -1023,15 +1038,16 @@
 	ItemInPlay *findObject(uint16 index);
 	void runItemScript(int charNum, int item, int sub, int next, int reg4);
 	void setHandItem(uint16 itemIndex);
+	bool itemEquipped(int charNum, uint16 itemType);
 
 	void setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b);
 	void removeLevelItem(int item, int block);
-	bool throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c);
+	bool launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c);
 	void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock);
 	void processObjectFlight(FlyingObject *t, int x, int y);
 	void updateObjectFlightPosition(FlyingObject *t);
 	void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock);
-	void updateFlyingObjects(FlyingObject *t);
+	void updateFlyingObject(FlyingObject *t);
 
 	void assignItemToBlock(uint16 *assignedBlockObjects, int id);
 	int checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY);
@@ -1088,6 +1104,9 @@
 	int calcMonsterSkillLevel(int id, int a);
 	bool checkBlockOccupiedByParty(int x, int y, int testFlag);
 	const uint16 *getCharacterOrMonsterStats(int id);
+	uint16 *getCharacterOrMonsterItemsMight(int id);
+	uint16 *getCharacterOrMonsterProtectionAgainstItems(int id);
+
 	void drawBlockObjects(int blockArrayIndex);
 	void drawMonster(uint16 id);
 	int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);
@@ -1107,7 +1126,7 @@
 	void chasePartyWithCloseAttacks(MonsterInPlay *monster);
 	int walkMonsterCalcNextStep(MonsterInPlay *monster);
 	int getMonsterDistance(uint16 block1, uint16 block2);
-	int walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
+	int checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
 	int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
 	void getNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 direction);
 	void rearrangeAttackingMonster(MonsterInPlay *monster);
@@ -1143,25 +1162,16 @@
 	uint8 getRandomNumberSpecial();
 
 	uint8 _compassBroken;
-	uint8 _unkBt2;
+	uint8 _drainMagic;
 	uint16 _unkWordArraySize8[8];
 
 	uint8 *_pageBuffer1;
 	uint8 *_pageBuffer2;
 	uint32 _rndSpecial;
 
-	// fight
-	int battleHitSkillTest(int16 attacker, int16 target, int skill);
-	int calcInflictableDamage(int16 attacker, int16 target, int hitType);
-	void battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b);
-	void battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted);
-	int calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType);
-
-	uint16 getClosestMonster(int x, int y);
-	uint16 getClosestPartyMember(int x, int y);
-
 	// spells
-	bool notEnoughMagic(int charNum, int spellNum, int spellLevel);
+	void processMagicHeal(int charNum, int points);
+	bool notEnoughMagic(int charNum, int spellNum, int spellLevel);	
 
 	int8 _availableSpells[7];
 	int _selectedSpell;
@@ -1170,18 +1180,47 @@
 	int _subMenuIndex;
 	uint16 _unkIceSHpFlag;
 
-	// unneeded
-	void setWalkspeed(uint8) {}
-	void removeHandItem() {}
-	bool lineIsPassable(int, int) { return false; }
+	uint8 *_healOverlay;
 
-	// save
-	Common::Error loadGameState(int slot) { return Common::kNoError; }
-	Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
+	uint8 **_fireballShapes;
+	int _numFireballShapes;
+	uint8 **_healShapes;
+	int _numHealShapes;
+	uint8 **_healiShapes;
+	int _numHealiShapes;
 
-	void generateTempData();
-	LevelTempData *_lvlTempData[28];
+	const uint8 *_healShapeFrames;
+	int _healShapeFramesSize;
 
+	// fight
+	int battleHitSkillTest(int16 attacker, int16 target, int skill);
+	int calcInflictableDamage(int16 attacker, int16 target, int hitType);
+	int inflictDamage(int16 target, int damage, int16 attacker, int skill, int deathFlag);
+	void characterHitpointsZero(int16 charNum, int a);
+	void resetCharacterState(LoLCharacter *c, int first, int last);
+	int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType);
+	void checkForPartyDeath();
+
+	void applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage);
+	void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage);
+	int removeCharacterItem(int charNum, int itemFlags);
+	bool paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw);
+	void paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance);
+	void stunCharacter(int charNum);
+	void level11specialUnk();
+
+	void distObj1Sub(int a, int b, int c, int d);
+	void launchMagicViper();
+
+	void attackWall(int a, int b);
+
+	uint16 getNearestMonsterFromCharacter(int charNum);
+	uint16 getNearestMonsterFromCharacterForBlock(int block, int charNum);
+	uint16 getNearestMonsterFromPos(int x, int y);
+	uint16 getNearestPartyMemberFromPos(int x, int y);
+
+	int _partyDeathFlag;
+
 	// magic atlas
 	void displayAutomap();
 	void updateAutoMap(uint16 block);
@@ -1211,6 +1250,18 @@
 	uint8 _automapTopLeftY;
 	static const int8 _mapCoords[12][4];
 	bool _mapUpdateNeeded;
+
+	// unneeded
+	void setWalkspeed(uint8) {}
+	void removeHandItem() {}
+	bool lineIsPassable(int, int) { return false; }
+
+	// save
+	Common::Error loadGameState(int slot) { return Common::kNoError; }
+	Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
+
+	void generateTempData();
+	LevelTempData *_lvlTempData[28];
 };
 
 } // end of namespace Kyra

Modified: scummvm/trunk/engines/kyra/resource.h
===================================================================
--- scummvm/trunk/engines/kyra/resource.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/resource.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -286,6 +286,8 @@
 	lolMapCursorOvl,
 	lolMapStringId,
 	//lolMapPal,
+
+	lolHealShapeFrames,
 #endif // ENABLE_LOL
 
 	kMaxResIDs

Modified: scummvm/trunk/engines/kyra/saveload_lok.cpp
===================================================================
--- scummvm/trunk/engines/kyra/saveload_lok.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/saveload_lok.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -163,7 +163,7 @@
 		// it wasn't made sure that _curSfxFile was initialized
 		// so if it's out of bounds we just set it to 0.
 		if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
-			if (_curSfxFile >= _soundData->_fileListLen || _curSfxFile < 0)
+			if (_curSfxFile >= _soundData->fileListLen || _curSfxFile < 0)
 				_curSfxFile = 0;
 			_sound->loadSoundFile(_curSfxFile);
 		}

Modified: scummvm/trunk/engines/kyra/scene_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/scene_lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/scene_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -105,9 +105,9 @@
 		if (_itemsInPlay[i].level != _currentLevel)
 			continue;
 
-		assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i);
+		assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].block].assignedObjects, i);
 
-		_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5;
+		_levelBlockProperties[_itemsInPlay[i].block].direction = 5;
 		_itemsInPlay[i].nextDrawObject = 0;
 	}
 }
@@ -259,8 +259,8 @@
 	}
 
 	for (int i = 0; i < 30; i++) {
-		if (_monsters[i].blockPropertyIndex) {
-			_monsters[i].blockPropertyIndex = 0;
+		if (_monsters[i].block) {
+			_monsters[i].block = 0;
 			_monsters[i].properties = &_monsterProperties[_monsters[i].type];
 			placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
 		}
@@ -276,14 +276,14 @@
 	uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty];
 
 	for (int i = 0; i < 30; i++) {
-		if (_monsters[i].mode >= 14 || _monsters[i].blockPropertyIndex == 0 || _monsters[i].might <= 0)
+		if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
 			continue;
 
-		_monsters[i].might = (d * _monsters[i].might) >> 8;
+		_monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
 		if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
-			_monsters[i].might++;
-		if (_monsters[i].might == 0)
-			_monsters[i].might = 1;
+			_monsters[i].hitPoints++;
+		if (_monsters[i].hitPoints == 0)
+			_monsters[i].hitPoints = 1;
 	}
 }
 
@@ -470,7 +470,7 @@
 
 		ItemInPlay *it = &_itemsInPlay[id];
 		it->level = _currentLevel;
-		it->blockPropertyIndex = i;
+		it->block = i;
 		if (r)
 			r->nextAssignedObject = 0;
 	}

Modified: scummvm/trunk/engines/kyra/screen.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/screen.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -73,6 +73,8 @@
 	memset(_sjisOverlayPtrs, 0, sizeof(_sjisOverlayPtrs));
 	_useOverlays = false;
 	_useSJIS = false;
+	_use16ColorMode = _vm->gameFlags().use16ColorMode;
+	
 	_sjisTempPage = _sjisFontData = 0;
 
 	if (_vm->gameFlags().useHiResOverlay) {
@@ -432,11 +434,13 @@
 int Screen::fadePalStep(const uint8 *palette, int diff) {
 	debugC(9, kDebugLevelScreen, "Screen::fadePalStep(%p, %d)", (const void *)palette, diff);
 
+	const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3;
+	
 	uint8 fadePal[768];
-	memcpy(fadePal, _screenPalette, 768);
+	memcpy(fadePal, _screenPalette, colors);
 
 	bool needRefresh = false;
-	const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3;
+	
 	for (int i = 0; i < colors; ++i) {
 		int c1 = palette[i];
 		int c2 = fadePal[i];
@@ -495,17 +499,35 @@
 	debugC(9, kDebugLevelScreen, "Screen::setScreenPalette(%p)", (const void *)palData);
 
 	const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
+
+	uint8 screenPal[256 * 4];
 	if (palData != _screenPalette)
 		memcpy(_screenPalette, palData, colors*3);
 
-	uint8 screenPal[256 * 4];
-	for (int i = 0; i < colors; ++i) {
-		screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
-		screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
-		screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
-		screenPal[4 * i + 3] = 0;
-		palData += 3;
+	if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
+		for (int l = 0; l < 1024; l += 64) {
+			const uint8 *tp = palData;
+			for (int i = 0; i < 16; ++i) {
+				screenPal[l + 4 * i + 0] = palData[1];
+				screenPal[l + 4 * i + 1] = palData[0];
+				screenPal[l + 4 * i + 2] = palData[2];
+				screenPal[l + 4 * i + 3] = 0;
+				palData += 3;
+			}
+			palData = tp;
+		}
+	} else {
+		if (palData != _screenPalette)
+			memcpy(_screenPalette, palData, colors*3);
+		for (int i = 0; i < colors; ++i) {
+			screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
+			screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
+			screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
+			screenPal[4 * i + 3] = 0;
+			palData += 3;
+		}
 	}
+
 	_system->setPalette(screenPal, 0, colors);
 }
 
@@ -1242,7 +1264,9 @@
 		&Screen::drawShapePlotType13,		// used by Kyra 1
 		&Screen::drawShapePlotType14,		// used by Kyra 1 (invisibility)
 		&Screen::drawShapePlotType11_15,	// used by Kyra 1 (invisibility)
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0,
+		&Screen::drawShapePlotType20,		// used by LoL (heal spell effect)
+		0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0,
 		&Screen::drawShapePlotType33,		// used by LoL (blood spots on the floor)
 		0, 0, 0,
@@ -1683,7 +1707,6 @@
 }
 
 void Screen::drawShapePlotType1(uint8 *dst, uint8 cmd) {
-	// uint32 relOffs = dst - _dsDstPage;
 	for (int i = 0; i < _dsTableLoopCount; ++i)
 		cmd = _dsTable[cmd];
 
@@ -1705,7 +1728,6 @@
 }
 
 void Screen::drawShapePlotType5(uint8 *dst, uint8 cmd) {
-	// uint32 relOffs = dst - _dsDstPage;
 	cmd = _dsTable2[cmd];
 	for (int i = 0; i < _dsTableLoopCount; ++i)
 		cmd = _dsTable[cmd];
@@ -1812,6 +1834,15 @@
 	*dst = cmd;
 }
 
+void Screen::drawShapePlotType20(uint8 *dst, uint8 cmd) {
+	cmd = _dsTable2[cmd];
+	uint8 tOffs = _dsTable3[cmd];
+	if (!(tOffs & 0x80))
+		cmd = _dsTable4[tOffs << 8 | *dst];
+
+	*dst = cmd;
+}
+
 void Screen::drawShapePlotType33(uint8 *dst, uint8 cmd) {
 	if (cmd == 255) {
 		*dst = _dsTable5[*dst];
@@ -2822,6 +2853,9 @@
 			palData[0] = (col & 0xF) << 2; col >>= 4;
 			palData += 3;
 		}
+	} else if (_use16ColorMode) {
+		for (int i = 0; i < bytes; ++i)
+			palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0);
 	} else {
 		memcpy(palData, data, bytes);
 	}

Modified: scummvm/trunk/engines/kyra/screen.h
===================================================================
--- scummvm/trunk/engines/kyra/screen.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/screen.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -271,6 +271,7 @@
 
 	bool _useOverlays;
 	bool _useSJIS;
+	bool _use16ColorMode;
 
 	uint8 *_sjisFontData;
 	uint8 *_sjisTempPage;
@@ -328,6 +329,7 @@
 	void drawShapePlotType12(uint8 *dst, uint8 cmd);
 	void drawShapePlotType13(uint8 *dst, uint8 cmd);
 	void drawShapePlotType14(uint8 *dst, uint8 cmd);
+	void drawShapePlotType20(uint8 *dst, uint8 cmd);
 	void drawShapePlotType33(uint8 *dst, uint8 cmd);
 	void drawShapePlotType37(uint8 *dst, uint8 cmd);
 	void drawShapePlotType48(uint8 *dst, uint8 cmd);

Modified: scummvm/trunk/engines/kyra/screen_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/screen_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -32,9 +32,6 @@
 namespace Kyra {
 
 Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _vm(vm) {
-	_customDimTable = new ScreenDim*[_screenDimTableCount];
-	memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
-
 	_paletteOverlay1 = new uint8[0x100];
 	_paletteOverlay2 = new uint8[0x100];
 	_grayOverlay = new uint8[0x100];
@@ -48,7 +45,7 @@
 	_fadeFlag = 2;
 	_curDimIndex = 0;
 
-	_mapDimX = _mapDimY = _mapDimW = _mapDimH = _mapDimDstX = _mapBlockWidth = _mapDimDstY = _mapBlockHeight = _mapDimU5 = _mapDimU6 = _mapBlockWidth2 = _mapDimU8 = 0;
+	_internDimX = _internDimY = _internDimW = _internDimH = _internDimDstX = _internBlockWidth = _internDimDstY = _internBlockHeight = _internDimU5 = _internDimU6 = _internBlockWidth2 = _internDimU8 = 0;
 }
 
 Screen_LoL::~Screen_LoL() {
@@ -64,6 +61,17 @@
 	delete[] _grayOverlay;
 }
 
+bool Screen_LoL::init() {
+	if (Screen::init()) {
+		_screenDimTable = _use16ColorMode ? _screenDimTable16C : _screenDimTable256C;
+		_customDimTable = new ScreenDim*[_screenDimTableCount];
+		memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
+		return true;
+	}
+	return false;
+}
+
+
 void Screen_LoL::setScreenDim(int dim) {
 	debugC(9, kDebugLevelScreen, "Screen_LoL::setScreenDim(%d)", dim);
 	assert(dim < _screenDimTableCount);
@@ -525,23 +533,23 @@
 		return;
 
 	const ScreenDim *cdim = getScreenDim(dim);
-	_mapDimX = cdim->sx << 3;
-	_mapDimY = cdim->sy;
-	_mapDimW = cdim->w << 3;
-	_mapDimH = cdim->h;
+	_internDimX = cdim->sx << 3;
+	_internDimY = cdim->sy;
+	_internDimW = cdim->w << 3;
+	_internDimH = cdim->h;
 
 	calcMapBoundaries(x2, y2, w, h);
-	if (_mapBlockWidth == -1)
+	if (_internBlockWidth == -1)
 		return;
 
 	uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
-	uint8 *dst = getPagePtr(page2) + (_mapDimDstY + _mapDimY) * 320;
+	uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
 
-	for (int i = 0; i < _mapBlockHeight; i++) {
-		uint8 *s = src + _mapDimU5;
-		uint8 *d = dst + (_mapDimDstX + _mapDimX);
+	for (int i = 0; i < _internBlockHeight; i++) {
+		uint8 *s = src + _internDimU5;
+		uint8 *d = dst + (_internDimDstX + _internDimX);
 
-		for (int ii = 0; ii < _mapBlockWidth; ii++) {
+		for (int ii = 0; ii < _internBlockWidth; ii++) {
 			uint8 p = ovl[*s++];
 			if (p)
 				*d = p;
@@ -552,60 +560,97 @@
 		src += 320;
 	}
 
-	addDirtyRect(_mapDimDstX + _mapDimX, _mapDimDstY + _mapDimY, _mapBlockWidth, _mapBlockHeight);
+	addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
 }
 
+void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) {
+	if (!w || !h || !ovl)
+		return;
+
+	const ScreenDim *cdim = getScreenDim(dim);
+	_internDimX = cdim->sx << 3;
+	_internDimY = cdim->sy;
+	_internDimW = cdim->w << 3;
+	_internDimH = cdim->h;
+
+	calcMapBoundaries(x2, y2, w, h);
+	if (_internBlockWidth == -1)
+		return;
+
+	uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
+	uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
+
+	for (int i = 0; i < _internBlockHeight; i++) {
+		uint8 *s = src + _internDimU5;
+		uint8 *d = dst + (_internDimDstX + _internDimX);
+
+		if (flag)
+			d += (i >> 1);
+
+		for (int ii = 0; ii < _internBlockWidth; ii++) {
+			if (*s++)
+				*d = ovl[*d];
+			d++;
+		}
+
+		dst += 320;
+		src += 320;
+	}
+
+	addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
+}
+
 void Screen_LoL::calcMapBoundaries(int dstX, int dstY, int width, int height) {
-	_mapBlockWidth = _mapBlockWidth2 = width;
-	_mapBlockHeight = height;
-	_mapDimDstX = dstX;
-	_mapDimDstY = dstY;
+	_internBlockWidth = _internBlockWidth2 = width;
+	_internBlockHeight = height;
+	_internDimDstX = dstX;
+	_internDimDstY = dstY;
 
-	_mapDimU5 = _mapDimU6 = _mapDimU8 = 0;
+	_internDimU5 = _internDimU6 = _internDimU8 = 0;
 
-	int t = _mapDimDstX + _mapBlockWidth;
+	int t = _internDimDstX + _internBlockWidth;
 	if (t <= 0) {
-		_mapBlockWidth = _mapBlockHeight = -1;
+		_internBlockWidth = _internBlockHeight = -1;
 		return;
 	}
 
-	if (t <= _mapDimDstX) {
-		_mapDimU5 = _mapBlockWidth - t;
-		_mapBlockWidth = t;
-		_mapDimDstX = 0;
+	if (t <= _internDimDstX) {
+		_internDimU5 = _internBlockWidth - t;
+		_internBlockWidth = t;
+		_internDimDstX = 0;
 	}
 
-	t = _mapDimW - _mapDimDstX;
+	t = _internDimW - _internDimDstX;
 	if (t <= 0) {
-		_mapBlockWidth = _mapBlockHeight = -1;
+		_internBlockWidth = _internBlockHeight = -1;
 		return;
 	}
 
-	if (t <= _mapBlockWidth)
-		_mapBlockWidth = t;
+	if (t <= _internBlockWidth)
+		_internBlockWidth = t;
 
-	_mapBlockWidth2 -= _mapBlockWidth;
+	_internBlockWidth2 -= _internBlockWidth;
 
-	t = _mapDimDstY + _mapBlockHeight;
+	t = _internDimDstY + _internBlockHeight;
 	if (t <= 0) {
-		_mapBlockWidth = _mapBlockHeight = -1;
+		_internBlockWidth = _internBlockHeight = -1;
 		return;
 	}
 
-	if (t <= _mapDimDstY) {
-		_mapDimU6 = _mapBlockHeight - t;
-		_mapBlockHeight = t;
-		_mapDimDstY = 0;
+	if (t <= _internDimDstY) {
+		_internDimU6 = _internBlockHeight - t;
+		_internBlockHeight = t;
+		_internDimDstY = 0;
 	}
 
-	t = _mapDimH - _mapDimDstY;
+	t = _internDimH - _internDimDstY;
 	if (t <= 0) {
-		_mapBlockWidth = _mapBlockHeight = -1;
+		_internBlockWidth = _internBlockHeight = -1;
 		return;
 	}
 
-	if (t <= _mapBlockHeight)
-		_mapBlockHeight = t;
+	if (t <= _internBlockHeight)
+		_internBlockHeight = t;
 }
 
 void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {

Modified: scummvm/trunk/engines/kyra/screen_lol.h
===================================================================
--- scummvm/trunk/engines/kyra/screen_lol.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/screen_lol.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -39,6 +39,8 @@
 	Screen_LoL(LoLEngine *vm, OSystem *system);
 	~Screen_LoL();
 
+	bool init();
+
 	void setScreenDim(int dim);
 	const ScreenDim *getScreenDim(int dim);
 	int curDimIndex() { return _curDimIndex; }
@@ -60,11 +62,6 @@
 	void smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dstPageNum);
 	void smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dstPageNum);
 
-	// magic atlas
-	// This method basically works like copyRegion, but the pixels
-	// copied also have a palette overlay applied to them.
-	void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
-
 	// palette stuff
 	void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
 	void loadSpecialColours(uint8 *destPalette);
@@ -75,6 +72,9 @@
 	uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
 	uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
 
+	void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
+	void applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl);
+
 	uint8 getShapePaletteSize(const uint8 *shp);
 
 	uint8 *_paletteOverlay1;
@@ -85,9 +85,12 @@
 private:
 	LoLEngine *_vm;
 
-	static const ScreenDim _screenDimTable[];
+	const ScreenDim *_screenDimTable;
 	static const int _screenDimTableCount;
 
+	static const ScreenDim _screenDimTable256C[];
+	static const ScreenDim _screenDimTable16C[];
+
 	ScreenDim **_customDimTable;
 	int _curDimIndex;
 
@@ -96,18 +99,18 @@
 	// magic atlas
 	void calcMapBoundaries(int dstX, int dstY, int c, int d);
 
-	int _mapDimX;
-	int _mapDimY;
-	int _mapDimW;
-	int _mapDimH;
-	int _mapDimDstX;
-	int _mapBlockWidth;
-	int _mapDimDstY;
-	int _mapBlockHeight;
-	int _mapDimU5;
-	int _mapDimU6;
-	int _mapBlockWidth2;
-	int _mapDimU8;
+	int _internDimX;
+	int _internDimY;
+	int _internDimW;
+	int _internDimH;
+	int _internDimDstX;
+	int _internBlockWidth;
+	int _internDimDstY;
+	int _internBlockHeight;
+	int _internDimU5;
+	int _internDimU6;
+	int _internBlockWidth2;
+	int _internDimU8;
 };
 
 } // end of namespace Kyra

Modified: scummvm/trunk/engines/kyra/screen_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/screen_v2.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -119,7 +119,8 @@
 
 	int maxDiff = 0;
 	diff = 0;
-	for (int i = 0; i < 768; ++i) {
+	int len = _use16ColorMode ? 48 : 768;
+	for (int i = 0; i < len; ++i) {
 		diff = ABS(palette[i] - _screenPalette[i]);
 		maxDiff = MAX(maxDiff, diff);
 	}

Modified: scummvm/trunk/engines/kyra/script_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/script_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -231,7 +231,7 @@
 
 	switch (stackPos(1)) {
 	case 0:
-		return i->blockPropertyIndex;
+		return i->block;
 	case 1:
 		return i->x;
 	case 2:
@@ -298,7 +298,7 @@
 		return c->magicPointsMax;
 
 	case 9:
-		return c->itemsProtection;
+		return c->itemProtection;
 
 	case 10:
 		return c->items[d];
@@ -307,7 +307,7 @@
 		return c->skillLevels[d] + c->skillModifiers[d];
 
 	case 12:
-		return c->field_27[d];
+		return c->protectionAgainstItems[d];
 
 	case 13:
 		return (d & 0x80) ? c->itemsMight[7] : c->itemsMight[d];
@@ -341,7 +341,7 @@
 		break;
 
 	case 5:
-		//// TODO
+		setCharacterMagicOrHitPoints(stackPos(0), 0, e, 0);
 		break;
 
 	case 6:
@@ -349,7 +349,7 @@
 		break;
 
 	case 7:
-		//// TODO
+		setCharacterMagicOrHitPoints(stackPos(0), 1, e, 0);
 		break;
 
 	case 8:
@@ -357,7 +357,7 @@
 		break;
 
 	case 9:
-		c->itemsProtection = e;
+		c->itemProtection = e;
 		break;
 
 	case 10:
@@ -369,7 +369,7 @@
 		break;
 
 	case 12:
-		c->field_27[d] = e;
+		c->protectionAgainstItems[d] = e;
 		break;
 
 	case 13:
@@ -577,7 +577,7 @@
 	case 11:
 		return _compassBroken;
 	case 12:
-		return _unkBt2;
+		return _drainMagic;
 	case 13:
 		return _speechFlag;
 	default:
@@ -651,7 +651,7 @@
 		break;
 
 	case 12:
-		_unkBt2 = a & 0xff;
+		_drainMagic = a & 0xff;
 		break;
 
 	default:
@@ -708,7 +708,7 @@
 
 	for (uint8 i = 0; i < 30; i++) {
 		MonsterInPlay *l = &_monsters[i];
-		if (l->might || l->mode == 13)
+		if (l->hitPoints || l->mode == 13)
 			continue;
 
 		memset(l, 0, sizeof(MonsterInPlay));
@@ -719,13 +719,13 @@
 		l->type = stackPos(4);
 		l->properties = &_monsterProperties[l->type];
 		l->direction = l->facing << 1;
-		l->might = (l->properties->might * _monsterModifiers[_monsterDifficulty]) >> 8;
+		l->hitPoints = (l->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8;
 
 		if (_currentLevel == 12 && l->type == 2)
-			l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
+			l->hitPoints = (l->hitPoints * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
 
-		l->field_25 = l->properties->unk6[0];
-		l->field_27 = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
+		l->numDistAttacks = l->properties->numDistAttacks;
+		l->distAttackTick = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
 		l->flyingHeight = 2;
 		l->flags = stackPos(5);
 		l->assignedItems = 0;
@@ -740,7 +740,7 @@
 		for (int ii = 0; ii < 4; ii++)
 			l->field_2A[ii] = stackPos(7 + ii);
 
-		checkSceneUpdateNeed(l->blockPropertyIndex);
+		checkSceneUpdateNeed(l->block);
 		return i;
 	}
 
@@ -779,7 +779,7 @@
 	disableSysTimer(2);
 
 	for (int i = 0; i < 8; i++) {
-		if (!_flyingObjects[i].enable || _flyingObjects[i].a)
+		if (!_flyingObjects[i].enable || _flyingObjects[i].objectType)
 			continue;
 		endObjectFlight(&_flyingObjects[i], _flyingObjects[i].x, _flyingObjects[i].y, 1);
 	}
@@ -800,6 +800,11 @@
 	return 1;
 }
 
+int LoLEngine::olol_getNearestMonsterFromCharacter(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getNearestMonsterFromCharacter(%p) (%d)", (const void *)script, stackPos(0));
+	return getNearestMonsterFromCharacter(stackPos(0));
+}
+
 int LoLEngine::olol_dummy0(EMCState *script) {
 	return 0;
 }
@@ -835,15 +840,14 @@
 	l->fightingStats[6] = (stackPos(7) << 8) / 100;		//
 	l->fightingStats[7] = (stackPos(8) << 8) / 100;		//
 	l->fightingStats[8] = 0;
-	l->fightingStats[9] = 0;
 
 	for (int i = 0; i < 8; i++) {
-		l->unk2[i] = stackPos(9 + i);
-		l->unk3[i] = (stackPos(17 + i) << 8) / 100;
+		l->itemsMight[i] = stackPos(9 + i);
+		l->protectionAgainstItems[i] = (stackPos(17 + i) << 8) / 100;
 	}
 
 	l->itemProtection = stackPos(25);
-	l->might = stackPos(26);
+	l->hitPoints = stackPos(26);
 	l->speedTotalWaitTicks = 1;
 	l->flags = stackPos(27);
 	l->unk5 = stackPos(28);
@@ -851,13 +855,15 @@
 	l->unk5 = stackPos(29);
 	//
 
-	for (int i = 0; i < 5; i++)
-		l->unk6[i] = stackPos(30 + i);
+	l->numDistAttacks = stackPos(30);
+	l->numDistWeapons = stackPos(31);
+	for (int i = 0; i < 3; i++)
+		l->distWeapons[i] = stackPos(32 + i);
 
-	for (int i = 0; i < 2; i++) {
-		l->unk7[i] = stackPos(35 + i);
-		l->unk7[i + 2] = stackPos(37 + i);
-	}
+	l->attackSkillChance = stackPos(35);
+	l->attackSkillType = stackPos(36);
+	l->defenseSkillChance = stackPos(37);
+	l->defenseSkillType = stackPos(38);
 
 	for (int i = 0; i < 3; i++)
 		l->sounds[i] = stackPos(39 + i);
@@ -870,6 +876,18 @@
 	return battleHitSkillTest(stackPos(0), stackPos(1), stackPos(2));
 }
 
+int LoLEngine::olol_inflictDamage(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_inflictDamage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+	if (stackPos(0) == -1) {
+		for (int i = 0; i < 4; i++)
+			inflictDamage(i, stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+	} else {
+		inflictDamage(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+	}
+
+	return 1;
+}
+
 int LoLEngine::olol_moveMonster(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveMonster(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
 	MonsterInPlay *m = &_monsters[stackPos(0)];
@@ -930,6 +948,20 @@
 	return 1;
 }
 
+int LoLEngine::olol_playAttackSound(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAttackSound(%p) (%d)", (const void *)script, stackPos(0));
+	
+	static const uint8 sounds[] = { 12, 62, 63 };
+	int d = stackPos(0);
+
+	if ((d < 70 || d > 74) && (d < 81 || d > 89) && (d < 93 || d > 97) && (d < 102 || d > 106))
+		snd_playSoundEffect(sounds[_itemProperties[d].skill & 3], -1);
+	else
+		snd_playSoundEffect(12, -1);
+
+	return 1;
+}
+
 int LoLEngine::olol_characterJoinsParty(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterJoinsParty(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
 
@@ -1043,8 +1075,8 @@
 	return _wllWallFlags[_levelBlockProperties[stackPos(0)].walls[stackPos(1) & 3]];
 }
 
-int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
-	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterSettings(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+int LoLEngine::olol_changeMonsterStat(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterStat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
 	if (stackPos(0) == -1)
 		return 1;
 
@@ -1060,7 +1092,7 @@
 			break;
 
 		case 1:
-			m->might = d;
+			m->hitPoints = d;
 			break;
 
 		case 2:
@@ -1084,7 +1116,40 @@
 	return 1;
 }
 
+int LoLEngine::olol_getMonsterStat(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getMonsterStat(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+	if (stackPos(0) == -1)
+		return 0;
 
+	MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
+	int d = stackPos(1);
+
+	switch (d) {
+		case 0:
+			return m->mode;
+		case 1:
+			return m->hitPoints;
+		case 2:
+			return m->block;
+		case 3:
+			return m->facing;
+		case 4:
+			return m->type;
+		case 5:
+			return m->properties->hitPoints;
+		case 6:
+			return m->flags;
+		case 7:
+			return m->properties->flags;
+		case 8:
+			return _monsterUnk[m->properties->shapeIndex];
+		default:
+			break;
+	}
+
+	return 0;
+}
+
 int LoLEngine::olol_playCharacterScriptChat(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playCharacterScriptChat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
 	snd_stopSpeech(1);
@@ -1098,6 +1163,18 @@
 	return 1;
 }
 
+int LoLEngine::olol_healCharacter(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_healCharacter(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+	if (stackPos(3)) {
+		processMagicHeal(stackPos(0), stackPos(1));
+	} else {
+		increaseCharacterHitpoints(stackPos(0), stackPos(1), true);
+		if (stackPos(2))
+			gui_drawCharPortraitWithStats(stackPos(0));
+	}
+	return 1;
+}
+
 int LoLEngine::olol_drawExitButton(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drawExitButton(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
 
@@ -1164,6 +1241,17 @@
 	return old;
 }
 
+int LoLEngine::olol_calcInflictableDamage(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamage(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+	return calcInflictableDamage(stackPos(0), stackPos(1), stackPos(2));
+}
+
+int LoLEngine::olol_getInflictedDamage(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getInflictedDamage(%p) (%d)", (const void *)script, stackPos(0));
+	int mx = stackPos(0);	
+	return mx ? _rnd.getRandomNumberRng(2, mx) : 0;
+}
+
 int LoLEngine::olol_checkForCertainPartyMember(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkForCertainPartyMember(%p) (%d)", (const void *)script, stackPos(0));
 	for (int i = 0; i < 4; i++) {
@@ -1186,14 +1274,19 @@
 
 int LoLEngine::olol_deleteLevelItem(EMCState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_deleteLevelItem(%p) (%d)", (const void *)script, stackPos(0));
-	if (_itemsInPlay[stackPos(0)].blockPropertyIndex)
-		removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].blockPropertyIndex);
+	if (_itemsInPlay[stackPos(0)].block)
+		removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].block);
 
 	deleteItem(stackPos(0));
 
 	return 1;
 }
 
+int LoLEngine::olol_calcInflictableDamagePerItem(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamagePerItem(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+	return calcInflictableDamagePerItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+}
+
 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;
@@ -1216,7 +1309,7 @@
 			MonsterInPlay *m = &_monsters[l];
 
 			setMonsterMode(m, 14);
-			checkSceneUpdateNeed(m->blockPropertyIndex);
+			checkSceneUpdateNeed(m->block);
 			placeMonster(m, 0, 0);
 
 			res = 1;
@@ -1276,7 +1369,7 @@
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_suspendMonster(%p) (%d)", (const void *)script, stackPos(0));
 	MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
 	setMonsterMode(m, 14);
-	checkSceneUpdateNeed(m->blockPropertyIndex);
+	checkSceneUpdateNeed(m->block);
 	placeMonster(m, 0, 0);
 	return 1;
 }
@@ -1287,9 +1380,9 @@
 	return _emcDoorState;
 }
 
-int LoLEngine::olol_processButtonClick(EMCState *script) {
-	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_processButtonClick(%p) (%d)", (const void *)script, stackPos(0));
-	_tim->forceDialogue(_activeTim[stackPos(0)]);
+int LoLEngine::olol_resetTimDialogueState(EMCState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetTimDialogueState(%p) (%d)", (const void *)script, stackPos(0));
+	_tim->resetDialogueState(_activeTim[stackPos(0)]);
 	return 1;
 }
 
@@ -1433,7 +1526,7 @@
 int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) {
 	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_loadPalette(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
 	const char *palFile = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1)));
-	_res->loadFileToBuf(palFile, _screen->getPalette(0), 768);
+	_screen->loadPalette(palFile, _screen->getPalette(0));
 	return 1;
 }
 
@@ -1747,15 +1840,15 @@
 
 	// 0x3C
 	Opcode(olol_loadNewLevel);
-	OpcodeUnImpl();
+	Opcode(olol_getNearestMonsterFromCharacter);
 	Opcode(olol_dummy0);
 	Opcode(olol_loadMonsterProperties);
 
 	// 0x40
 	Opcode(olol_battleHitSkillTest);
+	Opcode(olol_inflictDamage);
 	OpcodeUnImpl();
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 
 	// 0x44
 	Opcode(olol_moveMonster);
@@ -1766,7 +1859,7 @@
 	// 0x48
 	Opcode(olol_setScriptTimer);
 	Opcode(olol_createHandItem);
-	OpcodeUnImpl();
+	Opcode(olol_playAttackSound);
 	Opcode(olol_characterJoinsParty);
 
 	// 0x4C
@@ -1791,17 +1884,17 @@
 	Opcode(olol_processDialogue);
 	Opcode(olol_stopTimScript);
 	Opcode(olol_getWallFlags);
-	Opcode(olol_changeMonsterSettings);
+	Opcode(olol_changeMonsterStat);
 
 	// 0x5C
+	Opcode(olol_getMonsterStat);
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 	Opcode(olol_playCharacterScriptChat);
 	Opcode(olol_update);
 
 	// 0x60
 	OpcodeUnImpl();
-	OpcodeUnImpl();
+	Opcode(olol_healCharacter);
 	Opcode(olol_drawExitButton);
 	Opcode(olol_loadSoundFile);
 
@@ -1818,16 +1911,16 @@
 	Opcode(olol_setPaletteBrightness);
 
 	// 0x6C
-	OpcodeUnImpl();
-	OpcodeUnImpl();
+	Opcode(olol_calcInflictableDamage);
+	Opcode(olol_getInflictedDamage);
 	Opcode(olol_checkForCertainPartyMember);
 	Opcode(olol_printMessage);
 
 	// 0x70
 	Opcode(olol_deleteLevelItem);
+	Opcode(olol_calcInflictableDamagePerItem);
 	OpcodeUnImpl();
 	OpcodeUnImpl();
-	OpcodeUnImpl();
 
 	// 0x74
 	OpcodeUnImpl();
@@ -1857,7 +1950,7 @@
 	OpcodeUnImpl();
 	OpcodeUnImpl();
 	Opcode(olol_setDoorState);
-	Opcode(olol_processButtonClick);
+	Opcode(olol_resetTimDialogueState);
 
 	// 0x88
 	OpcodeUnImpl();

Modified: scummvm/trunk/engines/kyra/script_tim.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_tim.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/script_tim.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -618,6 +618,8 @@
 
 	if (index < ARRAYSIZE(_vocFiles) && !_vocFiles[index].empty())
 		vm()->sound()->voicePlay(_vocFiles[index].c_str(), volume, true);
+	else if (index == 7 && !_vm->gameFlags().isTalkie)
+		vm()->sound()->playTrack(index);
 	else
 		vm()->sound()->playSoundEffect(index);
 
@@ -1144,7 +1146,7 @@
 	return res;
 }
 
-void TIMInterpreter_LoL::forceDialogue(TIM *tim) {
+void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
 	if (!tim)
 		return;
 

Modified: scummvm/trunk/engines/kyra/script_tim.h
===================================================================
--- scummvm/trunk/engines/kyra/script_tim.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/script_tim.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -145,7 +145,7 @@
 	virtual void updateBackgroundAnimation(int animIndex) {}
 	virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {}
 
-	virtual void forceDialogue(TIM *tim) {}
+	virtual void resetDialogueState(TIM *tim) {}
 
 	int _drawPage2;
 
@@ -231,7 +231,7 @@
 	
 	void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
 	uint16 processDialogue();
-	void forceDialogue(TIM *tim);
+	void resetDialogueState(TIM *tim);
 
 	void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
 	void startBackgroundAnimation(int animIndex, int part);

Modified: scummvm/trunk/engines/kyra/sequences_lol.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sequences_lol.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/sequences_lol.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -88,6 +88,7 @@
 
 		memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers));
 		memset(_screen->getPalette(1), 0, 768);
+
 	} else {
 		delete _chargenWSA; _chargenWSA = 0;
 		
@@ -114,6 +115,13 @@
 
 		_eventList.clear();
 	}
+
+	// We have three sound.dat files, one for the intro, one for the
+	// end sequence and one for ingame, each contained in a different
+	// PAK file. Therefore a new call to loadSoundFile() is required
+	// whenever the PAK file configuration changes.
+	if (_flags.platform == Common::kPlatformPC98)
+		_sound->loadSoundFile("sound.dat");
 }
 
 void LoLEngine::showIntro() {
@@ -122,13 +130,16 @@
 	_tim = new TIMInterpreter(this, _screen, _system);
 	assert(_tim);
 
+	if (_flags.platform == Common::kPlatformPC98)
+		showStarcraftLogo();
+
 	uint8 *pal = _screen->getPalette(0);
 	memset(pal, 0, 768);
 	_screen->setScreenPalette(pal);
 
 	_screen->clearPage(0);
 	_screen->clearPage(4);
-	_screen->clearPage(8);	
+	_screen->clearPage(8);
 
 	TIM *intro = _tim->load("LOLINTRO.TIM", &_timIntroOpcodes);
 
@@ -226,6 +237,9 @@
 	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->_curPage = 0;
 
+	if (_flags.use16ColorMode)
+		_screen->loadPalette("LOL.NOL", _screen->getPalette(0));
+
 	_screen->fadePalette(_screen->getPalette(0), 30, 0);
 
 	bool kingIntro = true;
@@ -571,6 +585,51 @@
 	return -1;
 }
 
+void LoLEngine::showStarcraftLogo() {
+	WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen);
+	assert(ci);
+
+	_screen->clearPage(0);
+	_screen->clearPage(2);
+
+	int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette);
+	if (!ci->opened()) {
+		delete ci;
+		return;
+	}
+	_screen->hideMouse();
+	ci->setX(32);
+	ci->setY(80);
+	ci->setDrawPage(2);
+	ci->displayFrame(0, 0);
+	_screen->copyPage(2, 0);
+	_screen->fadeFromBlack();
+	int inputFlag = 0;
+	for (int i = 0; i < endframe; i++) {
+		inputFlag = checkInput(0) & 0xff;
+		if (shouldQuit() || inputFlag)
+			break;
+		ci->displayFrame(i, 0);
+		_screen->copyPage(2, 0);
+		_screen->updateScreen();
+		delay(4 * _tickLength);
+	}
+
+	if (!(shouldQuit() || inputFlag)) {
+		_sound->voicePlay("star2");
+		while(_sound->voiceIsPlaying("star2") && !(shouldQuit() || inputFlag)) {
+			inputFlag = checkInput(0) & 0xff;
+			delay(_tickLength);			
+		}
+	}
+
+	_screen->fadeToBlack();
+	_screen->showMouse();
+
+	_eventList.clear();
+	delete ci;
+}
+
 } // end of namespace Kyra
 
 #endif // ENABLE_LOL

Modified: scummvm/trunk/engines/kyra/sound.h
===================================================================
--- scummvm/trunk/engines/kyra/sound.h	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/sound.h	2009-04-25 13:15:05 UTC (rev 40144)
@@ -224,9 +224,11 @@
 	 */
 	void voiceStop(const char *file = 0);
 protected:
-	const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; }
-	const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
-	int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
+	const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->fileListLen) ? _soundDataList->fileList[file] : ""; }
+	int fileListLen() const { return _soundDataList->fileListLen; }
+	const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->cdaTracks : 0; }
+	int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->cdaNumTracks : 0; }
+	int extraOffset() const { return _soundDataList != 0 ? _soundDataList->extraOffset : 0; }
 
 	enum {
 		kNumChannelHandles = 4

Modified: scummvm/trunk/engines/kyra/sound_towns.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound_towns.cpp	2009-04-25 09:16:36 UTC (rev 40143)
+++ scummvm/trunk/engines/kyra/sound_towns.cpp	2009-04-25 13:15:05 UTC (rev 40144)
@@ -2714,7 +2714,7 @@
 				finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
 		}
 
-		finOut /= 2;
+		finOut /= 4;
 		buffer[i << 1] += finOut;
 		buffer[(i << 1) + 1] += finOut;
 	}
@@ -2887,7 +2887,7 @@
 				finOut += _rhChan[ii].out;
 		}
 
-		finOut *= 7;
+		finOut *= 3;
 
 		buffer[i << 1] += finOut;
 		buffer[(i << 1) + 1] += finOut;
@@ -3381,7 +3381,7 @@
 				break;
 			};
 
-			int32 finOut = ((output * 7) / 2);
+			int32 finOut = ((output * 3) / ((_numChan + _numSSG - 3) / 3));
 
 			if (_chanInternal[i].enableLeft)
 				*leftSample += finOut;
@@ -4064,8 +4064,7 @@
 }
 
 void SoundPC98::playTrack(uint8 track) {
-	if (--track >= 56)
-		track -= 55;
+	track += extraOffset();
 
 	if (track == _lastTrack && _musicEnabled)
 		return;
@@ -4074,6 +4073,10 @@
 
 	char musicfile[13];
 	sprintf(musicfile, fileListEntry(0), track);
+	if (fileListLen() == 1)
+		sprintf(musicfile, fileListEntry(0), track);
+	else
+		strcpy(musicfile, fileListEntry(track));
 	delete[] _musicTrackData;
 	_musicTrackData = _vm->resource()->fileData(musicfile, 0);
 	if (_musicEnabled)
@@ -4126,20 +4129,26 @@
 bool SoundTownsPC98_v2::init() {
 	_driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
 		TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
-	_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
-	_vm->checkCD();
-	// FIXME: While checking for 'track1.XXX(X)' looks like
-	// a good idea, we should definitely not be doing this
-	// here. Basically our filenaming scheme could change
-	// or we could add support for other audio formats. Also
-	// this misses the possibility that we play the tracks
-	// right off CD. So we should find another way to
-	// check if we have access to CD audio.
-	Resource *res = _vm->resource();
-	if (_musicEnabled &&
-		(res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
-			_musicEnabled = 2;
+	
+	if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+		_vm->checkCD();
+		// FIXME: While checking for 'track1.XXX(X)' looks like
+		// a good idea, we should definitely not be doing this

@@ 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