[Scummvm-cvs-logs] scummvm master -> 5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3

fuzzie fuzzie at fuzzie.org
Sun Jan 29 08:59:15 CET 2012


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
5407bb8fcd SCUMM: Revert accidentally-committed 0ceeee8148..f0172ba15.


Commit: 5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3
    https://github.com/scummvm/scummvm/commit/5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3
Author: Alyssa Milburn (fuzzie at fuzzie.org)
Date: 2012-01-28T23:57:42-08:00

Commit Message:
SCUMM: Revert accidentally-committed 0ceeee8148..f0172ba15.

Changed paths:
    engines/scumm/actor.cpp
    engines/scumm/actor.h
    engines/scumm/object.cpp
    engines/scumm/object.h
    engines/scumm/saveload.cpp
    engines/scumm/script.cpp
    engines/scumm/script_v0.cpp
    engines/scumm/script_v2.cpp
    engines/scumm/script_v5.cpp
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/scumm_v0.h
    engines/scumm/scumm_v2.h
    engines/scumm/scumm_v5.h
    engines/scumm/vars.cpp
    engines/scumm/verbs.cpp
    engines/scumm/verbs.h



diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 70e051e..eb23c30 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -1323,23 +1323,23 @@ static const byte v0ActorSounds[24] = {
 	0x06, // Bernard
 	0x06, // Wendy
 	0x00, // Jeff
-	0x46, // Radiation Suit
+	0x46, // ???
 	0x06, // Dr Fred
 	0x06, // Nurse Edna
 	0x06, // Weird Ed
 	0x06, // Dead Cousin Ted
 	0xFF, // Purple Tentacle
 	0xFF, // Green Tentacle
-	0x06, // Meteor police
-	0xC0, // Meteor
-	0x06, // Mark Eteer
-	0x06, // Talkshow Host
-	0x00, // Plant
-	0xC0, // Meteor Radiation
-	0xC0, // Edsel (small, outro)
-	0x00, // Meteor (small, intro)
-	0x06, // Sandy (Lab)
-	0x06, // Sandy (Cut-Scene)
+	0x06, // Meteor
+	0xC0, // Plant
+	0x06, // ???
+	0x06, // ???
+	0x00, // ???
+	0xC0, // ???
+	0xC0, // ???
+	0x00, // ???
+	0x06, // Sandy
+	0x06, // ???
 };
 
 /* Used in Scumm v5 only. Play sounds associated with actors */
@@ -1355,10 +1355,7 @@ void ScummEngine::playActorSounds() {
 			} else {
 				sound = _actors[i]->_sound[0];
 			}
-			// fast mode will flood the queue with walk sounds
-			if (!_fastMode) {
-				_sound->addSoundToQueue(sound);
-			}
+			_sound->addSoundToQueue(sound);
 			for (j = 1; j < _numActors; j++) {
 				_actors[j]->_cost.soundCounter = 0;
 			}
@@ -2298,23 +2295,22 @@ static const char *const v0ActorNames_English[25] = {
 	"Bernard",
 	"Wendy",
 	"Jeff",
-	"", // Radiation Suit
+	"",
 	"Dr Fred",
 	"Nurse Edna",
 	"Weird Ed",
 	"Dead Cousin Ted",
 	"Purple Tentacle",
 	"Green Tentacle",
-	"", // Meteor Police
 	"Meteor",
-	"", // Mark Eteer
-	"", // Talkshow Host
+	"",
+	"",
+	"",
 	"Plant",
-	"", // Meteor Radiation
-	"", // Edsel (small, outro)
-	"", // Meteor (small, intro)
-	"Sandy", // (Lab)
-	"", // Sandy (Cut-Scene)
+	"",
+	"",
+	"",
+	"Sandy"
 };
 
 static const char *const v0ActorNames_German[25] = {
@@ -2332,16 +2328,15 @@ static const char *const v0ActorNames_German[25] = {
 	"Ted",
 	"Lila Tentakel",
 	"Gr<nes Tentakel",
-	"",
 	"Meteor",
 	"",
 	"",
-	"Pflanze",
 	"",
+	"Pflanze",
 	"",
 	"",
-	"Sandy",
 	"",
+	"Sandy"
 };
 
 const byte *Actor::getActorName() {
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index d8e3692..1584d0a 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -335,21 +335,10 @@ protected:
 	virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
 };
 
-enum ActorC64MiscFlags {
-	kActorMiscFlagStrong   = 0x01, // Kid is strong (Hunk-O-Matic used)
-	kActorMiscFlag_02      = 0x02, // ???
-	kActorMiscFlag_04      = 0x04, // ???
-	kActorMiscFlagEdsEnemy = 0x08, // Kid is not Weird Ed's friend
-	kActorMiscFlag_10      = 0x10, // ???
-	kActorMiscFlag_20      = 0x20, // ???
-	kActorMiscFlagFreeze   = 0x40, // Stop moving
-	kActorMiscFlagHide     = 0x80, // Hide actor (e.g. dead or wearing radiation suit)
-};
-
 class ActorC64 : public Actor_v2 {
 public:
 	byte _costCommand, _costFrame;
-	byte _miscflags;
+	byte _miscflags; // 0x1: strong, 0x8: Ed's enemy, 0x40: stop moving, 0x80: hide(dead/radiation suit)
 	byte _speaking, _speakingPrev;
 
 public:
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 86d9065..da238dc 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -178,7 +178,10 @@ void ScummEngine::clearOwnerOf(int obj) {
 		// Alternatively, scan the inventory to see if the object is in there...
 		for (i = 0; i < _numInventory; i++) {
 			if (_inventory[i] == obj) {
-				assert(WIO_INVENTORY == whereIsObject(obj));
+				if (_game.version == 0)
+					assert(WIO_INVENTORY == whereIsObjectInventory(obj));
+				else
+					assert(WIO_INVENTORY == whereIsObject(obj));
 
 				// Found the object! Nuke it from the inventory.
 				_res->nukeResource(rtInventory, i);
@@ -307,50 +310,52 @@ int ScummEngine::getObjectRoom(int obj) const {
 
 int ScummEngine::getObjectIndex(int object) const {
 	int i;
-	int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
 
-	if (nr < 1)
+	if (object < 1)
 		return -1;
 
 	for (i = (_numLocalObjects-1); i > 0; i--) {
-		if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
-			continue;
+		if (_game.version == 0 )
+			if( _objs[i].flags != _v0ObjectFlag )
+				continue;
 
-		if (_objs[i].obj_nr == nr)
+		if (_objs[i].obj_nr == object)
 			return i;
 	}
 	return -1;
 }
 
+int ScummEngine::whereIsObjectInventory(int object) {
+	int res = 0;
+	_v0ObjectInInventory = true;
+	res = whereIsObject(object);
+	_v0ObjectInInventory = false;
+
+	return res;
+}
+
 int ScummEngine::whereIsObject(int object) const {
 	int i;
 
-	// Note: in MMC64 bg objects are greater _numGlobalObjects
-	if (_game.version != 0 && object >= _numGlobalObjects)
+	if (object >= _numGlobalObjects)
 		return WIO_NOT_FOUND;
 
 	if (object < 1)
 		return WIO_NOT_FOUND;
 
-	if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) &&
-		 _objectOwnerTable[object] != OF_OWNER_ROOM) 
-	{
+	if ((_objectOwnerTable[object] != OF_OWNER_ROOM && _game.version != 0) || _v0ObjectInInventory) {
 		for (i = 0; i < _numInventory; i++)
 			if (_inventory[i] == object)
 				return WIO_INVENTORY;
 		return WIO_NOT_FOUND;
 	}
 
-	for (i = (_numLocalObjects-1); i > 0; i--) {
-		int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
-		if (_objs[i].obj_nr == nr) {
-			if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
-				continue;
+	for (i = (_numLocalObjects-1); i > 0; i--)
+		if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) {
 			if (_objs[i].fl_object_index)
 				return WIO_FLOBJECT;
 			return WIO_ROOM;
 		}
-	}
 
 	return WIO_NOT_FOUND;
 }
@@ -391,7 +396,7 @@ int ScummEngine::getObjectOrActorXY(int object, int &x, int &y) {
  * Returns X, Y and direction in angles
  */
 void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
-	int idx = getObjectIndex(object);
+	int idx = (_v0ObjectIndex) ? object : getObjectIndex(object);
 	assert(idx >= 0);
 	ObjectData &od = _objs[idx];
 	int state;
@@ -434,15 +439,8 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
 			y = od.y_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].y);
 		}
 	} else if (_game.version <= 2) {
-		if (od.actordir) {
-			x = od.walk_x;
-			y = od.walk_y;
-		} else {
-			x = od.x_pos + od.width/2;
-			y = od.y_pos + od.height/2;
-		}
-		x = x >> V12_X_SHIFT;
-		y = y >> V12_Y_SHIFT;
+		x = od.walk_x >> V12_X_SHIFT;
+		y = od.walk_y >> V12_Y_SHIFT;
 	} else {
 		x = od.walk_x;
 		y = od.walk_y;
@@ -494,6 +492,14 @@ int ScummEngine::getObjActToObjActDist(int a, int b) {
 	return getDist(x, y, x2, y2);
 }
 
+int ScummEngine_v0::findObjectIndex(int x, int y) {
+	int objIdx;
+	_v0ObjectIndex = true;
+	objIdx = findObject(x, y);
+	_v0ObjectIndex = false;
+	return objIdx;
+}
+
 int ScummEngine::findObject(int x, int y) {
 	int i, b;
 	byte a;
@@ -504,7 +510,7 @@ int ScummEngine::findObject(int x, int y) {
 			continue;
 
 		if (_game.version == 0) {
-			if (_objs[i].obj_type == 0 && _objs[i].state & kObjectStateUntouchable)
+			if (_objs[i].flags == 0 && _objs[i].state & kObjectStateUntouchable)
 				continue;
 		} else {
 			if (_game.version <= 2 && _objs[i].state & kObjectStateUntouchable)
@@ -524,8 +530,11 @@ int ScummEngine::findObject(int x, int y) {
 #endif
 				if (_objs[i].x_pos <= x && _objs[i].width + _objs[i].x_pos > x &&
 				    _objs[i].y_pos <= y && _objs[i].height + _objs[i].y_pos > y) {
+					// MMC64: Set the object search flag
 					if (_game.version == 0)
-						return OBJECT_V0(_objs[i].obj_nr, _objs[i].obj_type);
+						_v0ObjectFlag = _objs[i].flags;
+					if (_game.version == 0 && _v0ObjectIndex)
+						return i;
 					else
 						return _objs[i].obj_nr;
 				}
@@ -835,7 +844,7 @@ void ScummEngine_v3old::resetRoomObjects() {
 			char buf[32];
 			sprintf(buf, "roomobj-%d-", _roomResource);
 			if (_game.version == 0)
-				sprintf(buf + 11, "%d-", od->obj_type);
+				sprintf(buf + 11, "%d-", od->flags);
 
 			dumpResource(buf, od->obj_nr, room + od->OBCDoffset);
 		}
@@ -903,7 +912,7 @@ void ScummEngine_v0::resetRoomObject(ObjectData *od, const byte *room, const byt
 	ptr -= 2;
 
 	od->obj_nr = *(ptr + 6);
-	od->obj_type = *(ptr + 7);
+	od->flags = *(ptr + 7);
 
 	od->x_pos = *(ptr + 8) * 8;
 	od->y_pos = ((*(ptr + 9)) & 0x7F) * 8;
@@ -1063,8 +1072,8 @@ void ScummEngine::updateObjectStates() {
 	int i;
 	ObjectData *od = &_objs[1];
 	for (i = 1; i < _numLocalObjects; i++, od++) {
-		// V0 MM, objects with type == 1 are room objects (room specific objects, non-pickup)
-		if (_game.version == 0 && od->obj_type == 1)
+		// V0 MM, Room objects with Flag == 1 are objects with 'no-state' (room specific objects, non-pickup)
+		if (_game.version == 0 && od->flags == 1)
 			continue;
 
 		if (od->obj_nr > 0)
@@ -1164,7 +1173,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) {
 		}
 	}
 
-	objptr = getOBCDFromObject(obj, true);
+	objptr = getOBCDFromObject(obj);
 	if (objptr == NULL)
 		return NULL;
 
@@ -1217,15 +1226,15 @@ void ScummEngine::setObjectName(int obj) {
 uint32 ScummEngine::getOBCDOffs(int object) const {
 	int i;
 
-	if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) &&
-		_objectOwnerTable[object] != OF_OWNER_ROOM)
+	if ((_objectOwnerTable[object] != OF_OWNER_ROOM && (_game.version != 0))  || _v0ObjectInInventory)
 		return 0;
 
+	// V0 MM Return by Index
+	if (_v0ObjectIndex)
+		return _objs[object].OBCDoffset;
+
 	for (i = (_numLocalObjects-1); i > 0; i--) {
-		int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
-		if (_objs[i].obj_nr == nr) {
-			if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
-				continue;
+		if (_objs[i].obj_nr == object) {
 			if (_objs[i].fl_object_index != 0)
 				return 8;
 			return _objs[i].OBCDoffset;
@@ -1234,25 +1243,21 @@ uint32 ScummEngine::getOBCDOffs(int object) const {
 	return 0;
 }
 
-byte *ScummEngine::getOBCDFromObject(int obj, bool v0CheckInventory) {
+byte *ScummEngine::getOBCDFromObject(int obj) {
+	bool useInventory = _v0ObjectInInventory;
 	int i;
 	byte *ptr;
 
-	if ((_game.version != 0 || OBJECT_V0_TYPE(obj) == 0) &&
-		_objectOwnerTable[obj] != OF_OWNER_ROOM) 
-	{
-		if (_game.version == 0 && !v0CheckInventory)
-			return 0;
+	_v0ObjectInInventory = false;
+
+	if ((_objectOwnerTable[obj] != OF_OWNER_ROOM && (_game.version != 0)) || useInventory) {
 		for (i = 0; i < _numInventory; i++) {
 			if (_inventory[i] == obj)
 				return getResourceAddress(rtInventory, i);
 		}
 	} else {
 		for (i = (_numLocalObjects-1); i > 0; --i) {
-			int nr = (_game.version != 0) ? obj : OBJECT_V0_NR(obj);
-			if (_objs[i].obj_nr == nr) {
-				if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(obj))
-					continue;
+			if ((_objs[i].obj_nr == obj && !_v0ObjectIndex) || (_v0ObjectIndex && i == obj)) {
 				if (_objs[i].fl_object_index) {
 					assert(_objs[i].OBCDoffset == 8);
 					ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index);
diff --git a/engines/scumm/object.h b/engines/scumm/object.h
index 7e4a5b5..cdf8b09 100644
--- a/engines/scumm/object.h
+++ b/engines/scumm/object.h
@@ -24,14 +24,6 @@
 
 namespace Scumm {
 
-static inline int OBJECT_V0(int id, byte type) {
-	assert(id < 255);
-	return (type << 8 | id);
-}
-#define OBJECT_V0_NR(obj)	(obj & 0xFF)
-#define OBJECT_V0_TYPE(obj)	((obj >> 8) & 0xFF)
-
-
 enum ObjectClass {
 	kObjectClassNeverClip = 20,
 	kObjectClassAlwaysClip = 21,
@@ -70,12 +62,7 @@ struct ObjectData {
 	byte parentstate;
 	byte state;
 	byte fl_object_index;
-	// extra engine specific data
-	union {
-		byte extra;
-		byte obj_type; // v0
-		byte flags; // v8
-	};
+	byte flags;
 };
 
 #include "common/pack-start.h"	// START STRUCT PACKING
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 1713562..38dbd82 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -822,7 +822,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
 		MKLINE(ObjectData, parent, sleByte, VER(8)),
 		MKLINE(ObjectData, state, sleByte, VER(8)),
 		MKLINE(ObjectData, fl_object_index, sleByte, VER(8)),
-		MKLINE(ObjectData, extra, sleByte, VER(46)),
+		MKLINE(ObjectData, flags, sleByte, VER(46)),
 		MKEND()
 	};
 
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index eb0f7bf..37ea3a9 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -28,7 +28,6 @@
 #include "scumm/object.h"
 #include "scumm/resource.h"
 #include "scumm/util.h"
-#include "scumm/scumm_v0.h"
 #include "scumm/scumm_v2.h"
 #include "scumm/sound.h"
 #include "scumm/verbs.h"
@@ -132,6 +131,8 @@ void ScummEngine::runObjectScript(int object, int entry, bool freezeResistant, b
 
 	initializeLocals(slot, vars);
 
+	// V0 Ensure we don't try and access objects via index inside the script
+	_v0ObjectIndex = false;
 	runScriptNested(slot);
 }
 
@@ -195,10 +196,9 @@ int ScummEngine::getVerbEntrypoint(int obj, int entry) {
 		return verboffs + 8 + READ_LE_UINT32(ptr + 1);
 	} else if (_game.version <= 2) {
 		do {
-			const int kFallbackEntry = (_game.version == 0 ? 0x0F : 0xFF);
 			if (!*verbptr)
 				return 0;
-			if (*verbptr == entry || *verbptr == kFallbackEntry)
+			if (*verbptr == entry || *verbptr == 0xFF)
 				break;
 			verbptr += 2;
 		} while (1);
@@ -1130,128 +1130,6 @@ void ScummEngine::checkAndRunSentenceScript() {
 		runScript(sentenceScript, 0, 0, localParamList);
 }
 
-void ScummEngine_v0::walkToActorOrObject(int object) {
-	int x, y, dir;
-	ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "walkToObject");
-
-	_walkToObject = object;
-	_walkToObjectIdx = getObjectIndex(object);
-
-	if (OBJECT_V0_TYPE(object) == kObjectTypeActor) {
-		walkActorToActor(VAR(VAR_EGO), OBJECT_V0_NR(object), 4);
-		x = a->getRealPos().x;
-		y = a->getRealPos().y;
-	} else {
-		walkActorToObject(VAR(VAR_EGO), object);
-		getObjectXYPos(object, x, y, dir);
-	}
-
-	VAR(6) = x;
-	VAR(7) = y;
-
-	if (!(a->_miscflags & kActorMiscFlagFreeze)) {
-		// FIXME: walking already started -> should be stopped if condition not true
-		//actorStartWalk();
-	}
-}
-
-void ScummEngine_v0::checkAndRunSentenceScript() {
-	if (_walkToObjectIdx) {
-		ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "checkAndRunSentenceScript");
-		if (a->_moving)
-			return;
-		// TODO: change actor facing
-		_walkToObjectIdx = 0;
-		runSentenceScript();
-		return;
-	}
-
-	if (!_sentenceNum || _sentence[_sentenceNum - 1].freezeCount)
-		return;
-
-	SentenceTab &st = _sentence[_sentenceNum - 1];
-
-	if (st.preposition && st.objectB == st.objectA) {
-		_sentenceNum--;
-		return;
-	}
-
-	// FIXME: should this be executed?
-	//_currentScript = 0xFF;
-
-	int obj1Nr = OBJECT_V0_NR(st.objectA);
-	int obj1Type = OBJECT_V0_TYPE(st.objectA);
-	int obj2Nr = OBJECT_V0_NR(st.objectB);
-	int obj2Type = OBJECT_V0_TYPE(st.objectB);
-	assert(obj1Nr);
-
-	// If two objects are involved, at least one must be in the actors inventory
-	if (obj2Nr &&
-		(obj1Type != kObjectTypeFG || _objectOwnerTable[obj1Nr] != VAR(VAR_EGO)) &&
-	    (obj2Type != kObjectTypeFG || _objectOwnerTable[obj2Nr] != VAR(VAR_EGO)))
-	{
-		if (getVerbEntrypoint(st.objectA, kVerbPickUp))
-			doSentence(kVerbPickUp, st.objectA, 0);
-		else if (getVerbEntrypoint(st.objectB, kVerbPickUp))
-			doSentence(kVerbPickUp, st.objectB, 0);
-		else
-			_sentenceNum--;
-		return;
-	}
-
-	_cmdVerb = st.verb;
-	_cmdObjectNr = obj1Nr;
-	_cmdObjectType = obj1Type;
-	_cmdObject2Nr = obj2Nr;
-	_cmdObject2Type = obj2Type;
-	_sentenceNum--;
-
-	// TODO: check sentenceNum
-
-	if (whereIsObject(st.objectA) != WIO_INVENTORY) {
-		if (_currentMode != kModeKeypad) {
-			walkToActorOrObject(st.objectA);
-			return;
-		}
-	} else if (st.objectB && whereIsObject(st.objectB) != WIO_INVENTORY) {
-		walkToActorOrObject(st.objectB);
-		return;
-	}
-
-	runSentenceScript();
-	if (_currentMode == kModeKeypad) {
-		_walkToObjectIdx = 0;
-	}
-}
-
-void ScummEngine_v0::runSentenceScript() {
-	int obj = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
-
-	drawSentenceLine();
-
-	if (getVerbEntrypoint(obj, _cmdVerb) != 0) {
-		// do not read in the dark
-		if (!(_cmdVerb == kVerbRead && _currentLights == 0)) {
-			VAR(VAR_ACTIVE_OBJECT2) = _cmdObject2Nr;
-			runObjectScript(obj, _cmdVerb, false, false, NULL);
-			return;
-		}
-	} else {
-		if (_cmdVerb == kVerbGive) {
-			// no "give to"-script: give to other kid or ignore
-			if (_cmdObject2Nr < 8)
-				setOwnerOf(obj, _cmdObject2Nr);
-			return;
-		}
-	}
-
-	if (_cmdVerb != kVerbWalkTo) {
-		// perform verb's fallback action
-		VAR(VAR_ACTIVE_VERB) = _cmdVerb;
-		runScript(3, 0, 0, 0);
-	}
-}
-
 void ScummEngine_v2::runInputScript(int clickArea, int val, int mode) {
 	int args[24];
 	int verbScript;
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index cd2e896..e2d3f40 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -79,7 +79,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0x22, o4_saveLoadGame);
 	OPCODE(0x23, o_stopCurrentScript);
 	/* 24 */
-	OPCODE(0x24, o_ifNotEqualActiveObject2);
+	OPCODE(0x24, o_unknown2);
 	OPCODE(0x25, o5_loadRoom);
 	OPCODE(0x26, o_getClosestObjActor);
 	OPCODE(0x27, o2_getActorY);
@@ -159,7 +159,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0x62, o2_stopScript);
 	OPCODE(0x63, o_stopCurrentScript);
 	/* 64 */
-	OPCODE(0x64, o_ifEqualActiveObject2);
+	OPCODE(0x64, o_ifActiveObject);
 	OPCODE(0x65, o_stopCurrentScript);
 	OPCODE(0x66, o_getClosestObjActor);
 	OPCODE(0x67, o5_getActorFacing);
@@ -177,7 +177,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0x70, o_lights);
 	OPCODE(0x71, o_getBitVar);
 	OPCODE(0x72, o_nop);
-	OPCODE(0x73, o_getObjectOwner);
+	OPCODE(0x73, o5_getObjectOwner);
 	/* 74 */
 	OPCODE(0x74, o5_getDist);
 	OPCODE(0x75, o_printEgo_c64);
@@ -239,7 +239,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0xa2, o4_saveLoadGame);
 	OPCODE(0xa3, o_stopCurrentScript);
 	/* A4 */
-	OPCODE(0xa4, o_ifNotEqualActiveObject2);
+	OPCODE(0xa4, o_unknown2);
 	OPCODE(0xa5, o5_loadRoom);
 	OPCODE(0xa6, o_stopCurrentScript);
 	OPCODE(0xa7, o2_getActorY);
@@ -319,7 +319,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0xe2, o2_stopScript);
 	OPCODE(0xe3, o_stopCurrentScript);
 	/* E4 */
-	OPCODE(0xe4, o_ifEqualActiveObject2);
+	OPCODE(0xe4, o_ifActiveObject);
 	OPCODE(0xe5, o_loadRoomWithEgo);
 	OPCODE(0xe6, o_stopCurrentScript);
 	OPCODE(0xe7, o5_getActorFacing);
@@ -337,7 +337,7 @@ void ScummEngine_v0::setupOpcodes() {
 	OPCODE(0xf0, o_lights);
 	OPCODE(0xf1, o_getBitVar);
 	OPCODE(0xf2, o_nop);
-	OPCODE(0xf3, o_getObjectOwner);
+	OPCODE(0xf3, o5_getObjectOwner);
 	/* F4 */
 	OPCODE(0xf4, o5_getDist);
 	OPCODE(0xf5, o_stopCurrentScript);
@@ -365,7 +365,7 @@ uint ScummEngine_v0::fetchScriptWord() {
 
 int ScummEngine_v0::getActiveObject() {
 	if (_opcode & PARAM_2)
-		return _cmdObjectNr;
+		return _activeObject;
 
 	return fetchScriptByte();
 }
@@ -406,16 +406,136 @@ void ScummEngine_v0::decodeParseString() {
 	actorTalk(buffer);
 }
 
-void ScummEngine_v0::clearSentenceLine() {
-	Common::Rect sentenceline;
-	sentenceline.top = _virtscr[kVerbVirtScreen].topline;
-	sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
-	sentenceline.left = 0;
-	sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
-	restoreBackground(sentenceline);
+void ScummEngine_v0::drawSentenceWord(int object, bool usePrep, bool objInInventory) {
+	const byte *temp;
+	int sentencePrep = 0;
+
+	// If object not in inventory, we except an index
+	if (!objInInventory)
+		_v0ObjectIndex = true;
+	else
+		_v0ObjectInInventory = true;
+
+	temp = getObjOrActorName(object);
+
+	_v0ObjectInInventory = false;
+	_v0ObjectIndex = false;
+
+	// Append the 'object-name'
+	if (temp) {
+		_sentenceBuf += " ";
+		_sentenceBuf += (const char *)temp;
+	}
+
+	// Append the modifier? (With / On / To / In)
+	if (!usePrep)
+		return;
+
+	if (_verbs[_activeVerb].prep == 0xFF) {
+		_v0ObjectInInventory = objInInventory;
+		sentencePrep = verbPrep(object);
+	} else {
+		sentencePrep = _verbs[_activeVerb].prep;
+	}
+
+	if (sentencePrep > 0 && sentencePrep <= 4) {
+		// The prepositions, like the fonts, were hard code in the engine. Thus
+		// we have to do that, too, and provde localized versions for all the
+		// languages MM/Zak are available in.
+		static const char *const prepositions[][5] = {
+			{ " ", " in", " with", " on", " to" },   // English
+			{ " ", " mit", " mit", " mit", " zu" },  // German
+			{ " ", " dans", " avec", " sur", " <" }, // French
+			{ " ", " in", " con", " su", " a" },     // Italian
+			{ " ", " en", " con", " en", " a" },     // Spanish
+			};
+		int lang;
+		switch (_language) {
+		case Common::DE_DEU:
+			lang = 1;
+			break;
+		case Common::FR_FRA:
+			lang = 2;
+			break;
+		case Common::IT_ITA:
+			lang = 3;
+			break;
+		case Common::ES_ESP:
+			lang = 4;
+			break;
+		default:
+			lang = 0;	// Default to english
+		}
+
+		_sentenceBuf += prepositions[lang][sentencePrep];
+	}
 }
 
-void ScummEngine_v0::flushSentenceLine() {
+void ScummEngine_v0::drawSentence() {
+	Common::Rect sentenceline;
+	bool		 inventoryFirst = false;
+
+	if (!(_userState & 32))
+		return;
+
+	// Current Verb, Walk/Use
+	if (getResourceAddress(rtVerb, _activeVerb)) {
+		_sentenceBuf = (char *)getResourceAddress(rtVerb, _activeVerb);
+	} else {
+		return;
+	}
+
+	// If using inventory first, draw it first
+	if (_activeInvExecute && _activeInventory) {
+		drawSentenceWord(_activeInventory, true, true);
+	} else {
+		// Not using inventory, use selected object
+		if (_activeObject)
+			drawSentenceWord(_activeObjectIndex, true, false);
+		else
+			inventoryFirst = true;
+	}
+
+
+	// Draw the inventory?
+	if (_activeInventory > 0 && _activeObject2 == 0) {
+		// Only if inventory isnt first (it will already be drawn by now)
+		if (!_activeInvExecute) {
+			drawSentenceWord(_activeInventory, inventoryFirst, true);
+		} else {
+			// Draw the active object, which could be inventory based, or room based
+			if (_activeObject && !_activeObjectIndex) {
+				drawSentenceWord(_activeObject, inventoryFirst, true);
+			} else // Room based
+				drawSentenceWord(_activeObjectIndex, inventoryFirst, false);
+		}
+
+	// Draw the 2nd active object
+	} else if (_activeObject2) {
+
+		// 2nd Object is in inventory
+		if (_activeObject2Inv) {
+			_v0ObjectInInventory = true;
+			drawSentenceWord(_activeObject2, inventoryFirst, true);
+		} else {
+			drawSentenceWord(_activeObject2Index, inventoryFirst, false);
+		}
+	}
+
+	// Draw the active actor
+	if (_activeActor) {
+		Actor *a = derefActor(_activeActor, "");
+
+		_sentenceBuf += " ";
+		_sentenceBuf += (const char *)a->getActorName();
+	}
+
+	_string[2].charset = 1;
+	_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
+	_string[2].xpos = 0;
+	_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+	_string[2].color = 16;
+
 	byte string[80];
 	const char *ptr = _sentenceBuf.c_str();
 	int i = 0, len = 0;
@@ -434,77 +554,24 @@ void ScummEngine_v0::flushSentenceLine() {
 	}
 	string[i] = 0;
 
-	_string[2].charset = 1;
-	_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
-	_string[2].xpos = 0;
-	_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
-	_string[2].color = 16;
-	drawString(2, (byte *)string);
-}
+	sentenceline.top = _virtscr[kVerbVirtScreen].topline;
+	sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
+	sentenceline.left = 0;
+	sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
+	restoreBackground(sentenceline);
 
-void ScummEngine_v0::drawSentenceObject(int object) {
-	const byte *temp;
-	temp = getObjOrActorName(object);
-	if (temp) {
-		_sentenceBuf += " ";
-		_sentenceBuf += (const char *)temp;
-	}
+	drawString(2, (byte *)string);
 }
 
+void ScummEngine_v0::o_stopCurrentScript() {
+	int script;
 
-void ScummEngine_v0::drawSentenceLine() {
-	if (!(_userState & 32))
-		return;
-
-	clearSentenceLine();
-
-	if (_activeVerb == kVerbNewKid) {
-		_sentenceBuf = "";
-		for (int i = 0; i < 3; ++i) {
-			Actor *a = derefActor(VAR(97 + i), "drawSentence");
-			_sentenceBuf += Common::String::format("%-13s", a->getActorName());
-		}
-		flushSentenceLine();
-		return;
-	}
-
-	// Current Verb
-	if (_activeVerb == kVerbNone)
-		_activeVerb = kVerbWalkTo;
-
-	char *verbName = (char *)getResourceAddress(rtVerb, _activeVerb);
-	assert(verbName);
-	_sentenceBuf = verbName;
-
-	if (_activeObjectNr) {
-		// Draw the 1st active object
-		drawSentenceObject(OBJECT_V0(_activeObjectNr, _activeObjectType));
-
-		// Append verb preposition
-		int sentencePrep = activeVerbPrep();
-		if (sentencePrep) {
-			drawPreposition(sentencePrep);
-
-			// Draw the 2nd active object
-			if (_activeObject2Nr) {
-				// 2nd Object is an actor
-				if (_activeObject2Type == kObjectTypeActor) {
-					Actor *a = derefActor(_activeObject2Nr, "");
-					_sentenceBuf += " ";
-					_sentenceBuf += (const char *)a->getActorName();
-				// 2nd Object is an inventory or room object
-				} else {
-					drawSentenceObject(OBJECT_V0(_activeObject2Nr, _activeObject2Type));
-				}
-			}
-		}
-	}
-
-	flushSentenceLine();
-}
+	script = vm.slot[_currentScript].number;
 
-void ScummEngine_v0::o_stopCurrentScript() {
-	stopScriptCommon(0);
+	if (_currentScript != 0 && vm.slot[_currentScript].number == script)
+		stopObjectCode();
+	else
+		stopScript(script);
 }
 
 void ScummEngine_v0::o_loadSound() {
@@ -558,16 +625,16 @@ void ScummEngine_v0::o_loadRoom() {
 }
 
 void ScummEngine_v0::o_loadRoomWithEgo() {
-	ActorC64 *a;
+	Actor *a;
 	int obj, room, x, y, dir;
 
 	obj = fetchScriptByte();
 	room = fetchScriptByte();
 
-	a = (ActorC64 *)derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo");
+	a = derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo");
 
 	//0x634F
-	if (a->_miscflags & kActorMiscFlagFreeze) {
+	if (((ActorC64 *)a)->_miscflags & 0x40) {
 		// TODO: Check if this is the correct function
 		// to be calling here
 		stopObjectCode();
@@ -618,15 +685,15 @@ void ScummEngine_v0::o_cursorCommand() {
 
 	_currentMode = fetchScriptByte();
 	switch (_currentMode) {
-	case kModeCutscene:
+	case 0:
 		state = 15;
 		break;
-	case kModeKeypad:
+	case 1:
 		state = 31;
 		break;
-	case kModeNoNewKid:
+	case 2:
 		break;
-	case kModeNormal:
+	case 3:
 		state = 247;
 		break;
 	}
@@ -708,13 +775,21 @@ void ScummEngine_v0::o_putActorAtObject() {
 }
 
 void ScummEngine_v0::o_pickupObject() {
-	int objNr = fetchScriptByte();
-	int obj = OBJECT_V0((objNr ? objNr : _cmdObjectNr), 0);
+	int obj = fetchScriptByte();
+	if (obj == 0) {
+		obj = _activeObject;
+	}
+
+	if (obj < 1) {
+		error("pickupObject received invalid index %d (script %d)", obj, vm.slot[_currentScript].number);
+	}
 
-	/* Don't take an object twice */
-	if (whereIsObject(obj) == WIO_INVENTORY)
+	if (getObjectIndex(obj) == -1)
 		return;
 
+	if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY)	/* Don't take an */
+		return;					/* object twice */
+
 	addObjectToInventory(obj, _roomResource);
 	markObjectRectAsDirty(obj);
 	putOwner(obj, VAR(VAR_EGO));
@@ -750,20 +825,14 @@ void ScummEngine_v0::o_setActorBitVar() {
 		a->_miscflags &= ~mask;
 
 	// This flag causes the actor to stop moving (used by script #158, Green Tentacle 'Oomph!')
-	if (a->_miscflags & kActorMiscFlagFreeze)
+	if (a->_miscflags & 0x40)
 		a->stopActorMoving();
-	if (a->_miscflags & kActorMiscFlagHide)
+	if (a->_miscflags & 0x80)
 		a->setActorCostume(0);
 
 	debug(0, "o_setActorBitVar(%d, %d, %d)", act, mask, mod);
 }
 
-void ScummEngine_v0::o_getObjectOwner() {
-	getResultPos();
-	int obj = getVarOrDirectWord(PARAM_1);
-	setResult(getOwner(obj ? obj : _cmdObjectNr));
-}
-
 void ScummEngine_v0::o_getActorBitVar() {
 	getResultPos();
 	byte act = getVarOrDirectByte(PARAM_1);
@@ -809,46 +878,22 @@ void ScummEngine_v0::o_printEgo_c64() {
 }
 
 void ScummEngine_v0::o_doSentence() {
-	byte verb = fetchScriptByte();
-	int obj, obj2;
-	byte b;
-
-	b = fetchScriptByte();
-	if (b == 0xFF) {
-		obj = OBJECT_V0(_cmdObject2Nr, _cmdObject2Type);
-	} else if (b == 0xFE) {
-		obj = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
-	} else {
-		obj = OBJECT_V0(b, (_opcode & 0x80) ? 1 : 0);
-	}
-
-	b = fetchScriptByte();
-	if (b == 0xFF) {
-		obj2 = OBJECT_V0(_cmdObject2Nr, _cmdObject2Type);
-	} else if (b == 0xFE) {
-		obj2 = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
-	} else {
-		obj2 = OBJECT_V0(b, (_opcode & 0x40) ? 1 : 0);
-	}
+	byte entry = fetchScriptByte();
+	byte obj = fetchScriptByte();
+	fetchScriptByte();
 
-	doSentence(verb, obj, obj2);
+	runObjectScript(obj, entry, false, false, NULL);
 }
 
-bool ScummEngine_v0::ifEqualActiveObject2Common(bool ignoreType) {
-	byte obj = fetchScriptByte();
-	if (!ignoreType || (_cmdObject2Type == kObjectTypeFG))
-		return (obj == _cmdObject2Nr);
-	return false;
+void ScummEngine_v0::o_unknown2() {
+	byte var1 = fetchScriptByte();
+	error("STUB: o_unknown2(%d)", var1);
 }
 
-void ScummEngine_v0::o_ifEqualActiveObject2() {
-	bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0);
-	jumpRelative(equal);
-}
+void ScummEngine_v0::o_ifActiveObject() {
+	byte obj = fetchScriptByte();
 
-void ScummEngine_v0::o_ifNotEqualActiveObject2() {
-	bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0);
-	jumpRelative(!equal);
+	jumpRelative(obj == _activeInventory);
 }
 
 void ScummEngine_v0::o_getClosestObjActor() {
@@ -934,26 +979,33 @@ void ScummEngine_v0::o_setOwnerOf() {
 	owner = getVarOrDirectByte(PARAM_2);
 
 	if (obj == 0)
-		obj = _cmdObjectNr;
-
-	// FIXME: the original interpreter seems to set the owner of 
-	// an item to remove (new owner 0) to 13 (purple tentacle).
-	// Ignore this behavior for now.
-	/*
-	if (owner == 0)
-		owner = 13;
-	*/
+		obj = _activeInventory;
 
 	setOwnerOf(obj, owner);
 }
 
 void ScummEngine_v0::resetSentence(bool walking) {
-	_activeVerb = kVerbWalkTo;
-	_activeObjectNr = 0;
-	_activeObjectType = kObjectTypeBG;
-	_activeObject2Nr = 0;
-	_activeObject2Type = kObjectTypeBG;
-	_walkToObjectIdx = 0;
+	_activeVerb = 13;
+
+	// If the actor is walking, or the screen is a keypad (no sentence verbs/objects are drawn)
+	// Then reset all active objects (stops the radio crash, bug #3077966)
+	if (!walking || !(_userState & 32)) {
+		_v0ObjectFlag = 0;
+		_activeInventory = 0;
+		_activeObject = 0;
+		_activeObject2 = 0;
+		_activeObjectIndex = 0;
+		_activeObject2Index = 0;
+	}
+
+	_verbExecuting = false;
+	_verbPickup = false;
+
+	_activeActor = 0;
+	_activeInvExecute = false;
+	_activeObject2Inv = false;
+	_activeObjectObtained = false;
+	_activeObject2Obtained = false;
 }
 
 } // End of namespace Scumm
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 6f6138d..edb046d 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -953,41 +953,6 @@ void ScummEngine_v2::o2_doSentence() {
 	}
 }
 
-void ScummEngine_v2::drawPreposition(int index) {
-		// The prepositions, like the fonts, were hard code in the engine. Thus
-		// we have to do that, too, and provde localized versions for all the
-		// languages MM/Zak are available in.
-		const char *prepositions[][5] = {
-			{ " ", " in", " with", " on", " to" },   // English
-			{ " ", " mit", " mit", " mit", " zu" },  // German
-			{ " ", " dans", " avec", " sur", " <" }, // French
-			{ " ", " in", " con", " su", " a" },     // Italian
-			{ " ", " en", " con", " en", " a" },     // Spanish
-			};
-		int lang;
-		switch (_language) {
-		case Common::DE_DEU:
-			lang = 1;
-			break;
-		case Common::FR_FRA:
-			lang = 2;
-			break;
-		case Common::IT_ITA:
-			lang = 3;
-			break;
-		case Common::ES_ESP:
-			lang = 4;
-			break;
-		default:
-			lang = 0;	// Default to english
-		}
-
-		if (_game.platform == Common::kPlatformNES) {
-			_sentenceBuf += (const char *)(getResourceAddress(rtCostume, 78) + VAR(VAR_SENTENCE_PREPOSITION) * 8 + 2);
-		} else
-			_sentenceBuf += prepositions[lang][index];
-}
-
 void ScummEngine_v2::o2_drawSentence() {
 	Common::Rect sentenceline;
 	const byte *temp;
@@ -1021,7 +986,38 @@ void ScummEngine_v2::o2_drawSentence() {
 	}
 
 	if (0 < VAR(VAR_SENTENCE_PREPOSITION) && VAR(VAR_SENTENCE_PREPOSITION) <= 4) {
-		drawPreposition(VAR(VAR_SENTENCE_PREPOSITION));
+		// The prepositions, like the fonts, were hard code in the engine. Thus
+		// we have to do that, too, and provde localized versions for all the
+		// languages MM/Zak are available in.
+		const char *prepositions[][5] = {
+			{ " ", " in", " with", " on", " to" },   // English
+			{ " ", " mit", " mit", " mit", " zu" },  // German
+			{ " ", " dans", " avec", " sur", " <" }, // French
+			{ " ", " in", " con", " su", " a" },     // Italian
+			{ " ", " en", " con", " en", " a" },     // Spanish
+			};
+		int lang;
+		switch (_language) {
+		case Common::DE_DEU:
+			lang = 1;
+			break;
+		case Common::FR_FRA:
+			lang = 2;
+			break;
+		case Common::IT_ITA:
+			lang = 3;
+			break;
+		case Common::ES_ESP:
+			lang = 4;
+			break;
+		default:
+			lang = 0;	// Default to english
+		}
+
+		if (_game.platform == Common::kPlatformNES) {
+			_sentenceBuf += (const char *)(getResourceAddress(rtCostume, 78) + VAR(VAR_SENTENCE_PREPOSITION) * 8 + 2);
+		} else
+			_sentenceBuf += prepositions[lang][VAR(VAR_SENTENCE_PREPOSITION)];
 	}
 
 	if (VAR(VAR_SENTENCE_OBJECT2) > 0) {
@@ -1190,7 +1186,11 @@ void ScummEngine_v2::o2_startScript() {
 	runScript(script, 0, 0, 0);
 }
 
-void ScummEngine_v2::stopScriptCommon(int script) {
+void ScummEngine_v2::o2_stopScript() {
+	int script;
+
+	script = getVarOrDirectByte(PARAM_1);
+
 	if (_game.id == GID_MANIAC && _roomResource == 26 && vm.slot[_currentScript].number == 10001) {
 	// FIXME: Nasty hack for bug #915575
 	// Don't let the exit script for room 26 stop the script (116), when
@@ -1211,31 +1211,26 @@ void ScummEngine_v2::stopScriptCommon(int script) {
 		stopScript(script);
 }
 
-void ScummEngine_v2::o2_stopScript() {
-	stopScriptCommon(getVarOrDirectByte(PARAM_1));
-}
-
 void ScummEngine_v2::o2_panCameraTo() {
 	panCameraTo(getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER, 0);
 }
 
-void ScummEngine_v2::walkActorToObject(int actor, int obj) {
-	int x, y, dir;
-	getObjectXYPos(obj, x, y, dir);
-
-	Actor *a = derefActor(actor, "walkActorToObject");
-	AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
-	x = r.x;
-	y = r.y;
+void ScummEngine_v2::o2_walkActorToObject() {
+	int obj;
+	Actor *a;
 
-	a->startWalkActor(x, y, dir);
-}
+	_v0ObjectFlag = 0;
 
-void ScummEngine_v2::o2_walkActorToObject() {
-	int actor = getVarOrDirectByte(PARAM_1);
-	int obj = getVarOrDirectWord(PARAM_2);
+	a = derefActor(getVarOrDirectByte(PARAM_1), "o2_walkActorToObject");
+	obj = getVarOrDirectWord(PARAM_2);
 	if (whereIsObject(obj) != WIO_NOT_FOUND) {
-		walkActorToObject(actor, obj);
+		int x, y, dir;
+		getObjectXYPos(obj, x, y, dir);
+		AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
+		x = r.x;
+		y = r.y;
+
+		a->startWalkActor(x, y, dir);
 	}
 }
 
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 707c3c2..6426b75 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -2464,40 +2464,8 @@ void ScummEngine_v5::o5_walkActorTo() {
 	a->startWalkActor(x, y, -1);
 }
 
-void ScummEngine_v5::walkActorToActor(int actor, int toActor, int dist) {
-	Actor *a = derefActor(actor, "walkActorToActor");
-	Actor *to = derefActor(toActor, "walkActorToActor(2)");
-
-	if (_game.version <= 2) {
-		dist *= V12_X_MULTIPLIER;
-	} else if (dist == 0xFF) {
-		dist = a->_scalex * a->_width / 0xFF;
-		dist += (to->_scalex * to->_width / 0xFF) / 2;
-	}
-	int x = to->getPos().x;
-	int y = to->getPos().y;
-	if (x < a->getPos().x)
-		x += dist;
-	else
-		x -= dist;
-
-	if (_game.version <= 2) {
-		x /= V12_X_MULTIPLIER;
-		y /= V12_Y_MULTIPLIER;
-	}
-	if (_game.version <= 3) {
-		AdjustBoxResult abr = a->adjustXYToBeInBox(x, y);
-		x = abr.x;
-		y = abr.y;
-	}
-	a->startWalkActor(x, y, -1);
-
-	// WORKAROUND: See bug #2971126 for details on why this is here.
-	if (_game.version == 0)
-		o5_breakHere();
-}
-
 void ScummEngine_v5::o5_walkActorToActor() {
+	int x, y;
 	Actor *a, *a2;
 	int nr = getVarOrDirectByte(PARAM_1);
 	int nr2 = getVarOrDirectByte(PARAM_2);
@@ -2531,7 +2499,33 @@ void ScummEngine_v5::o5_walkActorToActor() {
 	if (!a2->isInCurrentRoom())
 		return;
 
-	walkActorToActor(nr, nr2, dist);
+	if (_game.version <= 2) {
+		dist *= V12_X_MULTIPLIER;
+	} else if (dist == 0xFF) {
+		dist = a->_scalex * a->_width / 0xFF;
+		dist += (a2->_scalex * a2->_width / 0xFF) / 2;
+	}
+	x = a2->getPos().x;
+	y = a2->getPos().y;
+	if (x < a->getPos().x)
+		x += dist;
+	else
+		x -= dist;
+
+	if (_game.version <= 2) {
+		x /= V12_X_MULTIPLIER;
+		y /= V12_Y_MULTIPLIER;
+	}
+	if (_game.version <= 3) {
+		AdjustBoxResult abr = a->adjustXYToBeInBox(x, y);
+		x = abr.x;
+		y = abr.y;
+	}
+	a->startWalkActor(x, y, -1);
+
+	// WORKAROUND: See bug #2971126 for details on why this is here.
+	if (_game.version == 0)
+		o5_breakHere();
 }
 
 void ScummEngine_v5::o5_walkActorToObject() {
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2eda5ca..d3cc218 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -151,6 +151,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 	_fileHandle = 0;
 
 	// Init all vars
+	_v0ObjectIndex = false;
+	_v0ObjectInInventory = false;
+	_v0ObjectFlag = 0;
 	_imuse = NULL;
 	_imuseDigital = NULL;
 	_musicEngine = NULL;
@@ -698,6 +701,10 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
 
 	_inventoryOffset = 0;
 
+	_activeInventory = 0;
+	_activeObject = 0;
+	_activeVerb = 0;
+
 	VAR_SENTENCE_VERB = 0xFF;
 	VAR_SENTENCE_OBJECT1 = 0xFF;
 	VAR_SENTENCE_OBJECT2 = 0xFF;
@@ -712,21 +719,19 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
 ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
 	: ScummEngine_v2(syst, dr) {
 
+	_verbExecuting = false;
+	_verbPickup = false;
 	_currentMode = 0;
 
-	_activeVerb = kVerbNone;
-	_activeObjectNr = 0;
-	_activeObjectType = 0;
-	_activeObject2Nr = 0;
-	_activeObject2Type = 0;
-
-	_cmdVerb = kVerbNone;
-	_cmdObjectNr = 0;
-	_cmdObjectType = 0;
-	_cmdObject2Nr = 0;
-	_cmdObject2Type = 0;
+	_activeObject2 = 0;
+	_activeObjectIndex = 0;
+	_activeObject2Index = 0;
+	_activeInvExecute = false;
+	_activeObject2Inv = false;
+	_activeObjectObtained = false;
+	_activeObject2Obtained = false;
 
-	VAR_ACTIVE_OBJECT2 = 0xFF;
+	VAR_ACTIVE_ACTOR = 0xFF;
 	VAR_IS_SOUND_RUNNING = 0xFF;
 	VAR_ACTIVE_VERB = 0xFF;
 }
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index fadc390..d9237b2 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -502,6 +502,10 @@ protected:
 	int32 *_scummVars;
 	byte *_bitVars;
 
+	bool _v0ObjectIndex;			// V0 Use object index, instead of object number
+	bool _v0ObjectInInventory;		// V0 Use object number from inventory
+	byte _v0ObjectFlag;
+
 	/* Global resource tables */
 	int _numVariables, _numBitVariables, _numLocalObjects;
 	int _numGlobalObjects, _numArray, _numVerbs, _numFlObject;
@@ -642,7 +646,7 @@ protected:
 	void updateScriptPtr();
 	virtual void runInventoryScript(int i);
 	void inventoryScriptIndy3Mac();
-	virtual void checkAndRunSentenceScript();
+	void checkAndRunSentenceScript();
 	void runExitScript();
 	void runEntryScript();
 	void runAllScripts();
@@ -795,6 +799,7 @@ protected:
 	int getObjNewDir(int obj);
 	int getObjectIndex(int object) const;
 	int getObjectImageCount(int object);
+	int whereIsObjectInventory(int object);
 	int whereIsObject(int object) const;
 	int findObject(int x, int y);
 	void findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint object, uint room);
@@ -815,7 +820,7 @@ protected:
 	virtual void clearDrawQueues();
 
 	uint32 getOBCDOffs(int object) const;
-	byte *getOBCDFromObject(int obj, bool v0CheckInventory = true);
+	byte *getOBCDFromObject(int obj);
 	const byte *getOBIMFromObjectData(const ObjectData &od);
 	const byte *getObjectImage(const byte *ptr, int state);
 	virtual int getObjectIdFromOBIM(const byte *obim);
diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h
index c2af6d4..af481df 100644
--- a/engines/scumm/scumm_v0.h
+++ b/engines/scumm/scumm_v0.h
@@ -32,43 +32,20 @@ namespace Scumm {
  */
 class ScummEngine_v0 : public ScummEngine_v2 {
 protected:
-	enum CurrentMode {
-		kModeCutscene = 0,   // cutscene active
-		kModeKeypad = 1,     // kid selection / dial pad / save-load dialog
-		kModeNoNewKid = 2,   // verb "new kid" disabled (e.g. when entering lab)
-		kModeNormal = 3,     // normal playing mode
-	};
-
-	enum ObjectType {
-		kObjectTypeFG = 0,    // foreground object
-		                      //   - with owner/state, might (but has not to) be pickupable
-		                      //     -> with entry in _objectOwner/StateTable
-		                      //     -> all objects in _inventory have this type
-		                      //   - image can be exchanged (background overlay)
-		kObjectTypeBG = 1,    // background object
-		                      //   - without owner/state, not pickupable  (room only)
-		                      //     -> without entry in _objectOwner/StateTable
-		                      //   - image cannot be exchanged (part of background image)
-		kObjectTypeActor = 2  // object is an actor
-	};
-
-protected:
 	byte _currentMode;
+	bool _verbExecuting;			// is a verb executing
+	bool _verbPickup;				// are we picking up an object during a verb execute
 
-	int _activeVerb;
-	int _activeObjectNr;			// 1st Object Number
-	int _activeObjectType;			// 1st Object Type (0: inventory (or room), 1: room)
-	int _activeObject2Nr;			// 2nd Object Number
-	int _activeObject2Type;			// 2nd Object Type (0: inventory (or room), 1: room, 2: actor)
+	int _activeActor;				// Actor Number
+	int _activeObject2;				// 2nd Object Number
 
-	int _cmdVerb;
-	int _cmdObjectNr;
-	int _cmdObjectType;
-	int _cmdObject2Nr;
-	int _cmdObject2Type;
+	bool _activeInvExecute;			// is activeInventory first to be executed
+	bool _activeObject2Inv;			// is activeobject2 in the inventory
+	bool _activeObjectObtained;		// collected _activeobject?
+	bool _activeObject2Obtained;	// collected _activeObject2?
 
-	int _walkToObject;
-	int _walkToObjectIdx;
+	int _activeObjectIndex;
+	int _activeObject2Index;
 
 public:
 	ScummEngine_v0(OSystem *syst, const DetectorResult &dr);
@@ -87,26 +64,26 @@ protected:
 
 	virtual void processInput();
 
+	virtual void runObject(int obj, int entry);
 	virtual void saveOrLoad(Serializer *s);
 
 	// V0 MM Verb commands
-	int getVerbPrepId();
-	int activeVerbPrep();
-	void walkToActorOrObject(int object);
-	void verbExec();
-
-	virtual void runSentenceScript();
-	virtual void checkAndRunSentenceScript();
-	bool checkSentenceComplete();
+	int  verbPrep(int object);
+	bool verbMove(int object, int objectIndex, bool invObject);
+	bool verbMoveToActor(int actor);
+	bool verbObtain(int object, int objIndex);
+	bool verbExecutes(int object, bool inventory = false);
+	bool verbExec();
+
+	int findObjectIndex(int x, int y);
+
 	virtual void checkExecVerbs();
 	virtual void handleMouseOver(bool updateInventory);
-	int verbPrepIdType(int verbid);
 	void resetVerbs();
+	void setNewKidVerbs();
 
-	void clearSentenceLine();
-	void flushSentenceLine();
-	void drawSentenceObject(int object);
-	void drawSentenceLine();
+	void drawSentenceWord(int object, bool usePrep, bool objInInventory);
+	void drawSentence();
 
 	void switchActor(int slot);
 
@@ -119,8 +96,6 @@ protected:
 
 	virtual bool areBoxesNeighbors(int box1nr, int box2nr);
 
-	bool ifEqualActiveObject2Common(bool ignoreType);
-
 	/* Version C64 script opcodes */
 	void o_stopCurrentScript();
 	void o_loadSound();
@@ -143,14 +118,13 @@ protected:
 	void o_unlockScript();
 	void o_decrement();
 	void o_nop();
-	void o_getObjectOwner();
 	void o_getActorBitVar();
 	void o_setActorBitVar();
 	void o_getBitVar();
 	void o_setBitVar();
 	void o_doSentence();
-	void o_ifEqualActiveObject2();
-	void o_ifNotEqualActiveObject2();
+	void o_unknown2();
+	void o_ifActiveObject();
 	void o_getClosestObjActor();
 	void o_printEgo_c64();
 	void o_print_c64();
@@ -161,7 +135,7 @@ protected:
 	void o_beginOverride();
 	void o_setOwnerOf();
 
-	byte VAR_ACTIVE_OBJECT2;
+	byte VAR_ACTIVE_ACTOR;
 	byte VAR_IS_SOUND_RUNNING;
 	byte VAR_ACTIVE_VERB;
 };
diff --git a/engines/scumm/scumm_v2.h b/engines/scumm/scumm_v2.h
index b407fd3..47c5fa2 100644
--- a/engines/scumm/scumm_v2.h
+++ b/engines/scumm/scumm_v2.h
@@ -44,13 +44,17 @@ protected:
 	Common::String _sentenceBuf;
 	uint16 _inventoryOffset;
 
+	int _activeInventory;
+	int _activeObject;
+	int _activeVerb;
+
 public:
 	ScummEngine_v2(OSystem *syst, const DetectorResult &dr);
 
 	virtual void resetScumm();
 
 	void checkV2MouseOver(Common::Point pos);
-	int checkV2Inventory(int x, int y);
+	void checkV2Inventory(int x, int y);
 	void redrawV2Inventory();
 
 protected:
@@ -85,7 +89,6 @@ protected:
 	void ifNotStateCommon(byte type);
 	void setStateCommon(byte type);
 	void clearStateCommon(byte type);
-	void stopScriptCommon(int script);
 
 	virtual void resetSentence(bool walking);
 	void setUserState(byte state);
@@ -97,10 +100,6 @@ protected:
 
 	virtual void setBuiltinCursor(int index);
 
-	void drawPreposition(int index);
-
-	void walkActorToObject(int actor, int obj);
-
 	/* Version 2 script opcodes */
 	void o2_actorFromPos();
 	void o2_actorOps();
diff --git a/engines/scumm/scumm_v5.h b/engines/scumm/scumm_v5.h
index 0eef04b..b8a61c1 100644
--- a/engines/scumm/scumm_v5.h
+++ b/engines/scumm/scumm_v5.h
@@ -87,8 +87,6 @@ protected:
 
 	void drawFlashlight();
 
-	void walkActorToActor(int actor, int toActor, int dist);
-
 	/**
 	 * Fetch the next script word, then if cond is *false*, perform a relative jump.
 	 * So this corresponds to a "jne" jump instruction.
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 6365a72..26a6a2f 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -115,7 +115,7 @@ void ScummEngine_v0::setupScummVars() {
 	VAR_CAMERA_POS_X = 2;
 	VAR_HAVE_MSG = 3;
 	VAR_ROOM = 4;
-	VAR_ACTIVE_OBJECT2 = 5;
+	VAR_ACTIVE_ACTOR = 5;
 	VAR_OVERRIDE = 6;
 	VAR_IS_SOUND_RUNNING = 8;
 	VAR_ACTIVE_VERB = 9;
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 30d0d02..67ed17c 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -41,59 +41,47 @@ struct VerbSettings {
 	int id;
 	int x_pos;
 	int y_pos;
+	int prep;
 	const char *name;
 };
 
 static const VerbSettings v0VerbTable_English[] = {
-	{kVerbOpen,     8, 0, "Open"},
-	{kVerbClose,    8, 1, "Close"},
-	{kVerbGive,     0, 2, "Give"},
-	{kVerbTurnOn,  32, 0, "Turn on"},
-	{kVerbTurnOff, 32, 1, "Turn off"},
-	{kVerbFix,     32, 2, "Fix"},
-	{kVerbNewKid,  24, 0, "New Kid"},
-	{kVerbUnlock,  24, 1, "Unlock"},
-	{kVerbPush,     0, 0, "Push"},
-	{kVerbPull,     0, 1, "Pull"},
-	{kVerbUse,     24, 2, "Use"},
-	{kVerbRead,     8, 2, "Read"},
-	{kVerbWalkTo,  15, 0, "Walk to"},
-	{kVerbPickUp,  15, 1, "Pick up"},
-	{kVerbWhatIs,  15, 2, "What is"}
+	{ 1,  8, 0,   0, "Open"},
+	{ 2,  8, 1,   0, "Close"},
+	{ 3,  0, 2,   4, "Give"},
+	{ 4, 32, 0,   0, "Turn on"},
+	{ 5, 32, 1,   0, "Turn off"},
+	{ 6, 32, 2,   2, "Fix"},
+	{ 7, 24, 0,   0, "New Kid"},
+	{ 8, 24, 1,   2, "Unlock"},
+	{ 9,  0, 0,   0, "Push"},
+	{10,  0, 1,   0, "Pull"},
+	{11, 24, 2, 255, "Use"},
+	{12,  8, 2,   0, "Read"},
+	{13, 15, 0,   0, "Walk to"},
+	{14, 15, 1,   0, "Pick up"},
+	{15, 15, 2,   0, "What is"}
 };
 
 // FIXME: Replace * with the correct character
 static const VerbSettings v0VerbTable_German[] = {
-	{kVerbOpen,     7, 0, "$ffne"},
-	{kVerbClose,   13, 1, "Schlie*e"},
-	{kVerbGive,     0, 2, "Gebe"},
-	{kVerbTurnOn,  37, 1, "Ein"},
-	{kVerbTurnOff, 37, 0, "Aus"},
-	{kVerbFix,     23, 1, "Repariere"},
-	{kVerbNewKid,  34, 2, "Person"},
-	{kVerbUnlock,  23, 0, "Schlie*e auf"},
-	{kVerbPush,     0, 0, "Dr<cke"},
-	{kVerbPull,     0, 1, "Ziehe"},
-	{kVerbUse,     23, 2, "Benutz"},
-	{kVerbRead,     7, 2, "Lese"},
-	{kVerbWalkTo,  13, 0, "Gehe zu"},
-	{kVerbPickUp,   7, 1, "Nimm"},
-	{kVerbWhatIs,  13, 2, "Was ist"}
+	{ 1,  7, 0,   0, "$ffne"},
+	{ 2, 13, 1,   0, "Schlie*e"},
+	{ 3,  0, 2,   4, "Gebe"},
+	{ 4, 37, 1,   0, "Ein"},
+	{ 5, 37, 0,   0, "Aus"},
+	{ 6, 23, 1,   2, "Repariere"},
+	{ 7, 34, 2,   0, "Person"},
+	{ 8, 23, 0,   2, "Schlie*e auf"},
+	{ 9,  0, 0,   0, "Dr<cke"},
+	{10,  0, 1,   0, "Ziehe"},
+	{11, 23, 2, 255, "Benutz"},
+	{12,  7, 2,   0, "Lese"},
+	{13, 13, 0,   0, "Gehe zu"},
+	{14,  7, 1,   0, "Nimm"},
+	{15, 13, 2,   0, "Was ist"}
 };
 
-int ScummEngine_v0::verbPrepIdType(int verbid) {
-	switch (verbid) {
-	case kVerbUse: // depends on object1
-		return kVerbPrepObject;
-	case kVerbGive: 
-		return kVerbPrepTo;
-	case kVerbUnlock: case kVerbFix:
-		return kVerbPrepWith;
-	default:
-		return kVerbPrepNone;
-	}
-}
-
 void ScummEngine_v0::resetVerbs() {
 	VirtScreen *virt = &_virtscr[kVerbVirtScreen];
 	VerbSlot *vs;
@@ -124,13 +112,44 @@ void ScummEngine_v0::resetVerbs() {
 		vs->key = 0;
 		vs->center = 0;
 		vs->imgindex = 0;
-		vs->prep = verbPrepIdType(vtable[i - 1].id);
+		vs->prep = vtable[i - 1].prep;
 		vs->curRect.left = vtable[i - 1].x_pos * 8;
 		vs->curRect.top = vtable[i - 1].y_pos * 8 + virt->topline + 8;
 		loadPtrToResource(rtVerb, i, (const byte*)vtable[i - 1].name);
 	}
 }
 
+void ScummEngine_v0::setNewKidVerbs() {
+	VirtScreen *virt = &_virtscr[kVerbVirtScreen];
+	VerbSlot *vs;
+	int i;
+
+	for (i = 1; i < 16; i++)
+		killVerb(i);
+
+	for (i = 1; i < 4; i++) {
+		vs = &_verbs[i];
+		vs->verbid = i;
+		vs->color = 5;
+		vs->hicolor = 7;
+		vs->dimcolor = 11;
+		vs->type = kTextVerbType;
+		vs->charset_nr = _string[0]._default.charset;
+		vs->curmode = 1;
+		vs->saveid = 0;
+		vs->key = 0;
+		vs->center = 0;
+		vs->imgindex = 0;
+		vs->prep = 0;
+		vs->curRect.left = (i * 8) * 8;
+		vs->curRect.top = virt->topline + 8;
+
+		Actor *a = derefActor(VAR(96 + i), "setNewKidVerbs");
+		loadPtrToResource(rtVerb, i, (const byte*)a->getActorName());
+	}
+	setUserState(191);
+}
+
 void ScummEngine_v0::switchActor(int slot) {
 	resetSentence(false);
 
@@ -142,7 +161,7 @@ void ScummEngine_v0::switchActor(int slot) {
 		return;
 
 	// verbs disabled? or just new kid button?
-	if (_currentMode == kModeCutscene || _currentMode == kModeKeypad || _currentMode == kModeNoNewKid)
+	if (_currentMode == 0 || _currentMode == 1 || _currentMode == 2)
 		return;
 
 	VAR(VAR_EGO) = VAR(97 + slot);
@@ -335,14 +354,14 @@ void ScummEngine_v2::checkV2MouseOver(Common::Point pos) {
 	}
 }
 
-int ScummEngine_v2::checkV2Inventory(int x, int y) {
+void ScummEngine_v2::checkV2Inventory(int x, int y) {
 	int inventoryArea = (_game.platform == Common::kPlatformNES) ? 48: 32;
 	int object = 0;
 
 	y -= _virtscr[kVerbVirtScreen].topline;
 
 	if ((y < inventoryArea) || !(_mouseAndKeyboardStat & MBS_LEFT_CLICK))
-		return 0;
+		return;
 
 	if (_mouseOverBoxesV2[kInventoryUpArrow].rect.contains(x, y)) {
 		if (_inventoryOffset >= 2) {
@@ -363,9 +382,18 @@ int ScummEngine_v2::checkV2Inventory(int x, int y) {
 	}
 
 	if (object >= 4)
-		return 0;
+		return;
+
+	object = findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
 
-	return findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
+	if (object > 0) {
+		if (_game.version == 0) {
+			_activeInventory = object;
+
+		} else {
+			runInputScript(kInventoryClickArea, object, 0);
+		}
+	}
 }
 
 void ScummEngine_v2::redrawV2Inventory() {
@@ -403,7 +431,9 @@ void ScummEngine_v2::redrawV2Inventory() {
 		_string[1].right = _mouseOverBoxesV2[i].rect.right - 1;
 		_string[1].color = _mouseOverBoxesV2[i].color;
 
+		_v0ObjectInInventory = true;
 		const byte *tmp = getObjOrActorName(obj);
+		_v0ObjectInInventory = false;
 		assert(tmp);
 
 		// Prevent inventory entries from overflowing by truncating the text
@@ -486,7 +516,7 @@ void ScummEngine_v2::handleMouseOver(bool updateInventory) {
 }
 
 void ScummEngine_v0::handleMouseOver(bool updateInventory) {
-	//drawSentence();
+	drawSentence();
 	ScummEngine_v2::handleMouseOver(updateInventory);
 }
 
@@ -644,8 +674,15 @@ void ScummEngine_v2::checkExecVerbs() {
 
 		if (object != -1) {
 			object = findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
-			if (object > 0)
-				runInputScript(kInventoryClickArea, object, 0);
+
+			if (object > 0) {
+				if (_game.version == 0) {
+					_activeInventory = object;
+
+				} else {
+					runInputScript(kInventoryClickArea, object, 0);
+				}
+			}
 			return;
 		}
 
@@ -666,9 +703,7 @@ void ScummEngine_v2::checkExecVerbs() {
 			runInputScript(kSentenceClickArea, 0, 0);
 		} else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + inventoryArea) {
 			// Click into V2 inventory
-			int object = checkV2Inventory(_mouse.x, _mouse.y);
-			if (object > 0)
-				runInputScript(kInventoryClickArea, object, 0);
+			checkV2Inventory(_mouse.x, _mouse.y);
 		} else {
 			over = findVerbAtPos(_mouse.x, _mouse.y);
 			if (over != 0) {
@@ -682,62 +717,313 @@ void ScummEngine_v2::checkExecVerbs() {
 	}
 }
 
-int ScummEngine_v0::getVerbPrepId() {
-	if (_verbs[_activeVerb].prep != 0xFF) {
-		return _verbs[_activeVerb].prep;
+void ScummEngine_v0::runObject(int obj, int entry) {
+	bool prev = _v0ObjectInInventory;
+
+	if (getVerbEntrypoint(obj, entry) == 0) {
+		// If nothing was found, attempt to find the 'WHAT-IS' verb script
+		// (which is not really the what-is script, as this verb never actually executes
+		//  it merely seems to be some type of fallback)
+		if (getVerbEntrypoint(obj, 0x0F) != 0) {
+			entry = 0x0F;
+		}
+	}
+
+	_v0ObjectInInventory = prev;
+
+	if (getVerbEntrypoint(obj, entry) != 0) {
+		_v0ObjectInInventory = prev;
+		runObjectScript(obj, entry, false, false, NULL);
+	} else if (entry != 13 && entry != 15) {
+		if (_activeVerb != 3) {
+			VAR(VAR_ACTIVE_VERB) = entry;
+			runScript(3, 0, 0, 0);
+
+		// For some reasons, certain objects don't have a "give" script
+		} else if (VAR(VAR_ACTIVE_ACTOR) > 0 && VAR(VAR_ACTIVE_ACTOR) < 8) {
+			if (_activeInventory)
+				setOwnerOf(_activeInventory, VAR(VAR_ACTIVE_ACTOR));
+		}
+	}
+}
+
+bool ScummEngine_v0::verbMoveToActor(int actor) {
+	Actor *a = derefActor(VAR(VAR_EGO), "verbMoveToActor");
+	Actor *a2 = derefActor(actor, "verbMoveToActor");
+	int dist = getDist(a->getRealPos().x, a->getRealPos().y, a2->getRealPos().x, a2->getRealPos().y);
+
+	if (!a->_moving && dist > 4) {
+		a->startWalkActor(a2->getRealPos().x, a2->getRealPos().y, -1);
 	} else {
-		byte *ptr = getOBCDFromObject(OBJECT_V0(_activeObjectNr, _activeObjectType), true);
-		assert(ptr);
-		return (*(ptr + 11) >> 5);
+		if (dist <= 4) {
+			a->stopActorMoving();
+			return false;
+		}
 	}
+
+	return true;
 }
 
-int ScummEngine_v0::activeVerbPrep() {
-	if (!_activeVerb || !_activeObjectNr)
-		return 0;
-	return getVerbPrepId();
+bool ScummEngine_v0::verbMove(int object, int objectIndex, bool invObject) {
+	int x, y, dir;
+	Actor *a = derefActor(VAR(VAR_EGO), "verbMove");
+
+	if (_currentMode != 3 && _currentMode != 2)
+		return false;
+
+	_v0ObjectIndex = true;
+	getObjectXYPos(objectIndex, x, y, dir);
+	_v0ObjectIndex = false;
+
+	// Detect distance from target object
+	int dist =  getDist(a->getRealPos().x, a->getRealPos().y, x, y);
+
+	if (a->_moving)
+		return true;
+
+	if (dist > 5) {
+		a->startWalkActor(x, y, dir);
+		VAR(6) = x;
+		VAR(7) = y;
+		return true;
+	} else {
+		// Finished walk, are we picking up the item?
+		if (_verbPickup) {
+			int oldActive = _activeObject, oldIndex = _activeObjectIndex;
+			_activeObject = object;
+			_activeObjectIndex = objectIndex;
+
+			_v0ObjectIndex = true;
+			// Execute pickup
+			runObject(objectIndex, 14);
+			_v0ObjectIndex = false;
+
+			_activeObject = oldActive;
+			_activeObjectIndex = oldIndex;
+
+			// Finished picking up
+			_verbPickup = false;
+		}
+	}
+
+	return false;
 }
 
-void ScummEngine_v0::verbExec() {
-	if (_activeVerb == kVerbWhatIs)
-		return;
-		
-	if (_activeVerb != kVerbWalkTo || _activeObjectNr != 0) {		
-		doSentence(_activeVerb, 
-			OBJECT_V0(_activeObjectNr, _activeObjectType), 
-			OBJECT_V0(_activeObject2Nr, _activeObject2Type));
-		if (_activeVerb != kVerbWalkTo) {
-			_activeVerb = kVerbWalkTo;
-			_activeObjectNr = 0;
-			_activeObjectType = 0;
-			_activeObject2Nr = 0;
-			_activeObject2Type = 0;
+bool ScummEngine_v0::verbObtain(int obj, int objIndex) {
+	bool didPickup = false;
+
+	int prep, where = whereIsObjectInventory(obj);
+
+	if (objIndex == 0)
+		return false;
+
+	// Object in inventory ?
+	if (where != WIO_INVENTORY) {
+		_v0ObjectIndex = true;
+		prep = verbPrep(objIndex);
+
+		if (prep == 1 || prep == 4) {
+			if (_activeVerb != 13 && _activeVerb != 14) {
+				_verbPickup = true;
+				didPickup = true;
+			}
+		} else {
+			_verbPickup = false;
 		}
-		_walkToObjectIdx = 0;
-		return;
+
+		// Ignore verbs?
+		Actor *a = derefActor(VAR(VAR_EGO), "verbObtain");
+		if (((ActorC64 *)a)->_miscflags & 0x40) {
+			resetSentence(false);
+			return false;
+		}
+
+		//attempt move to object
+		if (verbMove(obj, objIndex, false))
+			return true;
+
+		if (didPickup && (prep == 1 || prep == 4))
+			if (_activeVerb != 13 && _activeVerb != 14) {
+				_v0ObjectInInventory = true;
+
+				if (whereIsObject(obj) == WIO_INVENTORY)
+					_activeInventory = obj;
+				else
+					resetSentence(false);
+
+				_v0ObjectInInventory = false;
+			}
 	}
 
-	ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "verbExec");
-	int x = _virtualMouse.x / V12_X_MULTIPLIER;
-	int y = _virtualMouse.y / V12_Y_MULTIPLIER;
-	//actorSetPosInBox();
+	return false;
+}
 
-	// 0xB31
-	VAR(6) = x;
-	VAR(7) = y;
+int ScummEngine_v0::verbPrep(int object) {
+	if (!_v0ObjectInInventory)
+		_v0ObjectIndex = true;
+	else
+		_v0ObjectIndex = false;
 
-	if (a->_miscflags & kActorMiscFlagFreeze)
-		return;
+	byte *ptr = getOBCDFromObject(object);
+	_v0ObjectIndex = false;
+	assert(ptr);
+	return (*(ptr + 11) >> 5);
+}
+
+bool ScummEngine_v0::verbExecutes(int object, bool inventory) {
+	_v0ObjectInInventory = inventory;
+	int prep = verbPrep(object);
 
-	a->stopActorMoving();
-	a->startWalkActor(VAR(6), VAR(7), -1);
+	if (prep == 2 || prep == 0) {
+		return true;
+	}
+
+	return false;
 }
 
-bool ScummEngine_v0::checkSentenceComplete() {
-	if (_activeVerb && _activeVerb != kVerbWalkTo && _activeVerb != kVerbWhatIs) {
-		if (_activeObjectNr && (!activeVerbPrep() || _activeObject2Nr))
+bool ScummEngine_v0::verbExec() {
+	int prep = 0;
+	int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15;
+
+	if ((!_activeInvExecute && _activeObject && getObjectIndex(_activeObject) == -1)) {
+		resetSentence(false);
+		return false;
+	}
+
+	// Lets try walk to the object
+	if (_activeObject && _activeObjectIndex && !_activeObjectObtained && _currentMode != 0) {
+		prep = verbPrep(_activeObjectIndex);
+
+		if (verbObtain(_activeObject, _activeObjectIndex))
+			return true;
+
+		_activeObjectObtained = true;
+	}
+
+	// Attempt to obtain/reach object2
+	if (_activeObject2 && _activeObject2Index && !_activeObject2Obtained && _currentMode != 0) {
+		prep = verbPrep(_activeObject2Index);
+
+		_v0ObjectInInventory = false;
+		if (verbObtain(_activeObject2, _activeObject2Index))
+			return true;
+
+		if (prep != 1 && prep != 4) {
+			_activeInventory = _activeObject;
+			_activeObject = _activeObject2;
+			_activeObjectIndex = _activeObject2Index;
+			_activeObject2 = 0;
+			_activeObject2Index = 0;
+		}
+
+		_activeObject2Obtained = true;
+	}
+
+	// Give-To
+	if (_activeVerb == 3 && _activeInventory && _activeActor) {
+		// FIXME: Actors need to turn and face each other
+		if (verbMoveToActor(_activeActor)) {
+			// Ignore verbs?
+			Actor *a = derefActor(VAR(VAR_EGO), "verbExec");
+			if (((ActorC64 *)a)->_miscflags & 0x40) {
+				resetSentence(false);
+				return false;
+			}
+
 			return true;
+		}
+		_v0ObjectInInventory = true;
+		VAR(VAR_ACTIVE_ACTOR) = _activeActor;
+		runObject(_activeInventory , 3);
+		_v0ObjectInInventory = false;
+
+		resetSentence(false);
+		return false;
+	}
+
+	// Where we performing an action on an actor?
+	if (_activeActor) {
+		_v0ObjectIndex = true;
+		runObject(_activeActor, entry);
+		_v0ObjectIndex = false;
+		_verbExecuting = false;
+
+		resetSentence(false);
+		return false;
+	}
+
+	// If we've finished walking (now near target), execute the action
+	if (_activeObject && _activeObjectIndex && verbPrep(_activeObjectIndex) == 2) {
+		_v0ObjectIndex = true;
+		runObject(_activeObjectIndex, entry);
+		_v0ObjectIndex = false;
+		_verbExecuting = false;
+
+		if ((_currentMode == 3 || _currentMode == 2) && _activeVerb == 13)
+			return false;
+
+		resetSentence(false);
+		return false;
 	}
+
+	// We acted on an inventory item
+	if (_activeInventory && verbExecutes(_activeInventory, true) && _activeVerb != 3) {
+		_v0ObjectInInventory = true;
+		_activeObject = _activeInventory;
+		runObject(_activeInventory, _activeVerb);
+
+		_verbExecuting = false;
+
+		if (_currentMode == 3 && _activeVerb == 13) {
+			resetSentence(true);
+			return false;
+		}
+
+		resetSentence(false);
+		return false;
+	}
+
+	// Item not in inventory is executed
+	if (_activeObject) {
+		_v0ObjectIndex = true;
+		runObject(_activeObjectIndex, entry);
+		_v0ObjectIndex = false;
+	} else if (_activeInventory) {
+		// Not sure this is the correct way to do this,
+		// however its working for most situations - segra
+		if (verbExecutes(_activeInventory, true) == false) {
+			if (_activeObject2 && _activeObject2Inv && verbExecutes(_activeObject2, true)) {
+				_v0ObjectInInventory = true;
+
+				_activeObject = _activeInventory;
+				_activeInventory = _activeObject2;
+
+				runObject(_activeObject, _activeVerb);
+			} else {
+				_v0ObjectInInventory = true;
+
+				if (_activeObject2) {
+					_activeObject = _activeObject2;
+
+					runObject(_activeObject, _activeVerb);
+				} else
+					runObject(_activeInventory, _activeVerb);
+			}
+		} else {
+			_v0ObjectInInventory = true;
+			runObject(_activeInventory, _activeVerb);
+		}
+	}
+
+	_verbExecuting = false;
+
+	if (_activeVerb == 13) {
+		resetSentence(true);
+		return false;
+	}
+
+	resetSentence(false);
+
 	return false;
 }
 
@@ -745,154 +1031,231 @@ void ScummEngine_v0::checkExecVerbs() {
 	ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "checkExecVerbs");
 	VirtScreen *zone = findVirtScreen(_mouse.y);
 
-	int sentenceLineChanged = false;
-	bool execute = false;
-
-	//if (_userPut <= 0)
-	//	return;
-
-	if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
-		int over = findVerbAtPos(_mouse.x, _mouse.y);
-		// click region: verbs
-		if (over) {
-			if (_activeVerb != over) { // new verb
-				// keep first object if no preposition is used yet
-				if (activeVerbPrep()) {
-					_activeObjectNr = 0;
-					_activeObjectType = 0;
-				}
-				_activeObject2Nr = 0;
-				_activeObject2Type = 0;
+	// Is a verb currently executing
+	if (_verbExecuting) {
+		// Check if mouse click
+		if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
+			int over = findVerbAtPos(_mouse.x, _mouse.y);
+			int act  = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
+			int obj  = findObject(_virtualMouse.x, _virtualMouse.y);
+
+			if (over && over != _activeVerb) {
 				_activeVerb = over;
-				sentenceLineChanged = true;
+				_verbExecuting = false;
+				return;
+			}
+
+			if (!obj && !act && !over) {
+				resetSentence(false);
 			} else {
-				// execute sentence if complete
-				if (checkSentenceComplete())
-					execute = true;
+				a->stopActorMoving();
 			}
+		} else {
+
+			if (_verbExecuting && !verbExec())
+				return;
 		}
 	}
 
-	if (a->_miscflags & kActorMiscFlagHide) {
-		if (_activeVerb != kVerbNewKid) {
-			_activeVerb = kVerbNone;
-		}
+	// What-Is selected, any object we hover over is selected, on mouse press we set to WalkTo
+	if (_activeVerb == 15) {
+		int obj = findObject(_virtualMouse.x, _virtualMouse.y);
+		int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
+		_activeObject = obj;
+		_activeObjectIndex = objIdx;
+
+		if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK))
+			_activeVerb = 13;	// Walk-To
+
+		return;
 	}
 
-	if (_currentMode != kModeCutscene) {
-		if (_currentMode == kModeKeypad) {
-			_activeVerb = kVerbPush;
-		}
+	if (_userPut <= 0 || _mouseAndKeyboardStat == 0)
+		return;
+
+	if (_mouseAndKeyboardStat < MBS_MAX_KEY) {
+		/* Check keypresses */
+		// TODO
+	} else if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
+		if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
+			// TODO
+		} else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
+			int prevInventory = _activeInventory;
+			int invOff = _inventoryOffset;
+
+			// Click into V2 inventory
+			checkV2Inventory(_mouse.x, _mouse.y);
+
+			// Did the Inventory position changed (arrows pressed, do nothing)
+			if (invOff != _inventoryOffset)
+				return;
 
-		if (_mouseAndKeyboardStat > 0 && _mouseAndKeyboardStat < MBS_MAX_KEY) {
-			// TODO: check keypresses
-		} else if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK) || _activeVerb == kVerbWhatIs) {
-			// click region: sentence line
-			if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
-				if (_activeVerb == kVerbNewKid) {
-					if (_currentMode == kModeNormal) {
-						int kid;
-						int lineX = _mouse.x >> V12_X_SHIFT;
-						if (lineX < 11)
-							kid = 0;
-						else if (lineX < 25)
-							kid = 1;
-						else
-							kid = 2;
-						_activeVerb = kVerbWalkTo;
-						drawSentenceLine();
-						switchActor(kid);
+			// No inventory selected?
+			if (!_activeInventory)
+				return;
+
+			// Did we just change the selected inventory item?
+			if (prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) {
+				_v0ObjectInInventory = true;
+				int prep = verbPrep(_activeInventory);
+				_v0ObjectInInventory = true;
+				int prep2 = verbPrep(prevInventory);
+
+				// Should the new inventory object remain as the secondary selected object
+				// Or should the new inventory object become primary?
+				if (prep != prep2 || prep != 1) {
+					if (prep == 1 || prep == 3) {
+						int tmp = _activeInventory;
+						_activeInventory = prevInventory;
+						prevInventory = tmp;
 					}
-					_activeVerb = kVerbWalkTo;
+				}
+
+				// Setup object2
+				_activeObject = 0;
+				_activeInvExecute = true;
+				_activeObject2Inv = true;
+				_activeObject2 = _activeInventory;
+				_activeInventory = prevInventory;
+				return;
+			}
+
+			// is the new selected inventory the same as the last selected?, reset to previous if it is
+			if (_activeInventory == _activeObject2)
+				_activeInventory = prevInventory;
+
+			// Inventory Selected changed
+			if (prevInventory != _activeInventory)
+				if (!_activeObject2 || prevInventory != _activeObject2)
+					return;
+
+			if (_activeVerb == 11 && !(((_activeObject || _activeInventory)) || !_activeObject2))
+				return;
+		} else {
+			int over = findVerbAtPos(_mouse.x, _mouse.y);
+			int act  = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
+			int obj  = findObject(_virtualMouse.x, _virtualMouse.y);
+			int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
+
+			// If we already have an object selected, and we just clicked an actor
+			// Clear any object we may of also clicked on
+			if ((_activeObject || _activeInventory) && act) {
+				obj = 0;
+				objIdx = 0;
+			}
+
+			if (a->_miscflags & 0x80) {
+				if (_activeVerb != 7 && over != 7) {
+					_activeVerb = 0;
+					over = 0;
+				}
+			}
+
+			// Handle New Kid verb options
+			if (_activeVerb == 7 || over == 7) {
+				// Disable New-Kid (in the secret lab)
+				if (_currentMode == 2 || _currentMode == 0)
+					return;
+
+				if (_activeVerb == 7 && over) {
+					_activeVerb = 13;
+					switchActor(_verbs[over].verbid - 1);
 					return;
-				} else {
-					// execute sentence if complete
-					if (checkSentenceComplete())
-						execute = true;
 				}
-			// click region: inventory or main screen
-			} else if ((zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) ||
-			           (zone->number == kMainVirtScreen))
-			{
-				int obj = 0;
-
-				// click region: inventory
-				if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
-					// click into inventory
-					int invOff = _inventoryOffset;
-					obj = checkV2Inventory(_mouse.x, _mouse.y);
-					if (invOff != _inventoryOffset) {
-						// inventory position changed (arrows pressed, do nothing)
+
+				setNewKidVerbs();
+				_activeVerb = 7;
+
+				return;
+			}
+
+			// Clicked on nothing, walk here?
+			if (!over && !act && _activeVerb == 13 && !obj && _currentMode != 0) {
+				// Clear all selected
+				resetSentence(false);
+
+				// 0xB31
+				VAR(6) = _virtualMouse.x / V12_X_MULTIPLIER;
+				VAR(7) = _virtualMouse.y / V12_Y_MULTIPLIER;
+
+				if (zone->number == kMainVirtScreen) {
+					// Ignore verbs?
+					if (a->_miscflags & 0x40) {
+						resetSentence(false);
 						return;
 					}
-				// click region: main screen
-				} else if (zone->number == kMainVirtScreen) {
-					// click into main screen
-					if (_activeVerb == kVerbGive && _activeObjectNr) {
-						obj = OBJECT_V0(getActorFromPos(_virtualMouse.x, _virtualMouse.y), kObjectTypeActor);
-					} else {
-						obj = findObject(_virtualMouse.x, _virtualMouse.y);
-					}
+					a->stopActorMoving();
+					a->startWalkActor(VAR(6), VAR(7), -1);
+					_verbExecuting = true;
 				}
+				return;
+			}
 
-				int id = OBJECT_V0_NR(obj);
-				int type = OBJECT_V0_TYPE(obj);
-				debug("found 0x%03x", obj);
+			// No new verb, use previous
+			if (over == 0)
+				over = _activeVerb;
 
-				if (!id) {
-					if (_activeVerb == kVerbWalkTo) {
-						_activeObjectNr = 0;
-						_activeObjectType = 0;
-						_activeObject2Nr = 0;
-						_activeObject2Type = 0;
+			// No verb selected, use walk-to
+			if (!_activeVerb)
+				_activeVerb = over = 13;		// Walk-To
+
+			// New verb selected
+			if (_activeVerb != over) {
+				_activeVerb = over;
+				if (_activeVerb == 13) {
+					resetSentence(false);
+				}
+				return;
+			}
+
+			// Only allowing targetting actors if its the GIVE/USE verb
+			if (_activeVerb == 3 || _activeVerb == 11) {
+				// Different actor selected?
+				if (act) {
+					if (_activeActor != act) {
+						_activeActor = act;
+						return;
 					}
-				} else {
-					if (activeVerbPrep() == kVerbPrepNone) {
-						if (id == _activeObjectNr && type == _activeObjectType) {
-							execute = true;
+				}
+			}
+
+			if (obj && obj != _activeObject) {
+				if (!_activeObject)
+					if (_activeInventory)
+						_activeInvExecute = true;
+
+				// USE
+				if (_activeVerb == 11 || _activeVerb == 8) {
+					if (obj != _activeObject || obj != _activeObject2) {
+						if (!_activeObject || _activeInventory) {
+							_activeObject = obj;
+							_activeObjectIndex = objIdx;
+							return;
 						} else {
-							_activeObjectNr = id;
-							_activeObjectType = type;
-						}
-						// immediately execute action in keypad/selection mode
-						if (_currentMode == kModeKeypad)
-							execute = true;
-					} else {
-						if (id == _activeObject2Nr && type == _activeObject2Type)
-							execute = true;
-						if (!(id == _activeObjectNr && type == _activeObjectType)) {
-							_activeObject2Nr = id;
-							_activeObject2Type = type;
-							if (_currentMode == kModeKeypad)
-								execute = true;
+							if (_activeObject2 != obj) {
+								_activeObject2 = obj;
+								_activeObject2Index = objIdx;
+								return;
+							}
 						}
 					}
-				}
+				} else {
+					a->stopActorMoving();
+
+					_activeObject = obj;
+					_activeObjectIndex = objIdx;
 
-				sentenceLineChanged = true;
-				if (_activeVerb == kVerbWalkTo && zone->number == kMainVirtScreen) {
-					_walkToObjectIdx = 0;
-					execute = true;
+					if (_activeVerb != 13)
+						return;
+
+					//return;
 				}
 			}
 		}
-	}
-
-	if (sentenceLineChanged) {
-		drawSentenceLine();
-		sentenceLineChanged = false;
-	}
 
-	if (!execute || !_activeVerb)
-		return;
+		_verbExecuting = true;
 
-	if (_activeVerb == kVerbWalkTo)
-		verbExec();
-	else if (_activeObjectNr) {
-		// execute if we have a 1st object and either have or do not need a 2nd
-		if (activeVerbPrep() == kVerbPrepNone || _activeObject2Nr)
-			verbExec();
-	}
+	}	// mouse k/b action
 }
 
 void ScummEngine::verbMouseOver(int verb) {
diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h
index fce260e..fb4dc96 100644
--- a/engines/scumm/verbs.h
+++ b/engines/scumm/verbs.h
@@ -57,34 +57,6 @@ struct VerbSlot {
 	uint16 imgindex;
 };
 
-enum VerbsV0 {
-	kVerbNone    = 0,
-	kVerbOpen    = 1,
-	kVerbClose   = 2,
-	kVerbGive    = 3,
-	kVerbTurnOn  = 4,
-	kVerbTurnOff = 5,
-	kVerbFix     = 6,
-	kVerbNewKid  = 7,
-	kVerbUnlock  = 8,
-	kVerbPush    = 9,
-	kVerbPull    = 10,
-	kVerbUse     = 11,
-	kVerbRead    = 12,
-	kVerbWalkTo  = 13,
-	kVerbPickUp  = 14,
-	kVerbWhatIs  = 15
-};
-
-enum VerbPrepsV0 {
-	kVerbPrepNone   = 0,
-	kVerbPrepIn     = 1,
-	kVerbPrepWith   = 2,
-	kVerbPrepOn     = 3,
-	kVerbPrepTo     = 4,
-	kVerbPrepObject = 0xFF, // prep depends on object (USE)
-};
-
 } // End of namespace Scumm
 
 #endif






More information about the Scummvm-git-logs mailing list