[Scummvm-cvs-logs] SF.net SVN: scummvm:[42737] scummvm/trunk/engines/scumm

Kirben at users.sourceforge.net Kirben at users.sourceforge.net
Sat Jul 25 08:27:41 CEST 2009


Revision: 42737
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42737&view=rev
Author:   Kirben
Date:     2009-07-25 06:27:41 +0000 (Sat, 25 Jul 2009)

Log Message:
-----------
Add patch #2821100 - MM C64 Objects / Verb fixes, with minor clean up applied.

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/object.cpp
    scummvm/trunk/engines/scumm/saveload.cpp
    scummvm/trunk/engines/scumm/saveload.h
    scummvm/trunk/engines/scumm/script.cpp
    scummvm/trunk/engines/scumm/script_v0.cpp
    scummvm/trunk/engines/scumm/scumm.cpp
    scummvm/trunk/engines/scumm/scumm.h
    scummvm/trunk/engines/scumm/scumm_v0.h
    scummvm/trunk/engines/scumm/scumm_v2.h
    scummvm/trunk/engines/scumm/vars.cpp
    scummvm/trunk/engines/scumm/verbs.cpp

Modified: scummvm/trunk/engines/scumm/object.cpp
===================================================================
--- scummvm/trunk/engines/scumm/object.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/object.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -181,7 +181,11 @@
 		// 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);
 				_inventory[i] = 0;
@@ -286,7 +290,7 @@
 		// it. Fortunately this does not prevent frustrated players from
 		// blowing up the mansion, should they feel the urge to.
 
-		if (_game.id == GID_MANIAC && (obj == 182 || obj == 193))
+		if (_game.id == GID_MANIAC && _game.version != 0 && (obj == 182 || obj == 193))
 			_objectStateTable[obj] |= kObjectState_08;
 	}
 
@@ -317,6 +321,15 @@
 	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;
 
@@ -326,7 +339,7 @@
 	if (object < 1)
 		return WIO_NOT_FOUND;
 
-	if (_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;
@@ -334,7 +347,7 @@
 	}
 
 	for (i = (_numLocalObjects-1); i > 0; i--)
-		if (_objs[i].obj_nr == object) {
+		if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) {
 			if (_objs[i].fl_object_index)
 				return WIO_FLOBJECT;
 			return WIO_ROOM;
@@ -379,7 +392,7 @@
  * 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,7 +447,7 @@
 		dir = oldDirToNewDir(od.actordir & 3);
 }
 
-static int getDist(int x, int y, int x2, int y2) {
+int ScummEngine::getDist(int x, int y, int x2, int y2) {
 	int a = ABS(y - y2);
 	int b = ABS(x - x2);
 	return MAX(a, b);
@@ -475,6 +488,14 @@
 	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;
@@ -505,7 +526,10 @@
 #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)
-					return _objs[i].obj_nr;
+					if (_game.version == 0 && _v0ObjectIndex)
+						return i;
+					else
+						return _objs[i].obj_nr;
 				break;
 			}
 		} while ((_objs[b].state & mask) == a);
@@ -811,6 +835,9 @@
 		if (_dumpScripts) {
 			char buf[32];
 			sprintf(buf, "roomobj-%d-", _roomResource);
+			if (_game.version == 0)
+				sprintf(buf + 11, "%d-", od->flags);
+
 			dumpResource(buf, od->obj_nr, room + od->OBCDoffset);
 		}
 	}
@@ -1033,6 +1060,10 @@
 	int i;
 	ObjectData *od = &_objs[1];
 	for (i = 1; i < _numLocalObjects; i++, od++) {
+		// 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)
 			od->state = getState(od->obj_nr);
 	}
@@ -1155,7 +1186,7 @@
 void ScummEngine::setObjectName(int obj) {
 	int i;
 
-	if (obj < _numActors)
+	if (obj < _numActors && _game.version != 0)
 		error("Can't set actor %d name with new-name-of", obj);
 
 	for (i = 0; i < _numNewNames; i++) {
@@ -1181,8 +1212,13 @@
 uint32 ScummEngine::getOBCDOffs(int object) const {
 	int i;
 
-	if (_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--) {
 		if (_objs[i].obj_nr == object) {
 			if (_objs[i].fl_object_index != 0)
@@ -1194,17 +1230,20 @@
 }
 
 byte *ScummEngine::getOBCDFromObject(int obj) {
+	bool useInventory = _v0ObjectInInventory;
 	int i;
 	byte *ptr;
 
-	if (_objectOwnerTable[obj] != OF_OWNER_ROOM) {
+	_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) {
-			if (_objs[i].obj_nr == obj) {
+			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);

Modified: scummvm/trunk/engines/scumm/saveload.cpp
===================================================================
--- scummvm/trunk/engines/scumm/saveload.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/saveload.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -1384,9 +1384,12 @@
 void ScummEngine_v0::saveOrLoad(Serializer *s) {
 	ScummEngine::saveOrLoad(s);
 
-	// TODO: Save additional variables
-	// _currentMode
-	// _currentLights
+	const SaveLoadEntry v0Entrys[] = {
+		MKLINE(ScummEngine_v0, _currentMode, sleByte, VER(78)),
+		MKLINE(ScummEngine_v0, _currentLights, sleByte, VER(78)),
+		MKEND()
+	};
+ 	s->saveLoadEntries(this, v0Entrys);
 }
 
 void ScummEngine_v5::saveOrLoad(Serializer *s) {

Modified: scummvm/trunk/engines/scumm/saveload.h
===================================================================
--- scummvm/trunk/engines/scumm/saveload.h	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/saveload.h	2009-07-25 06:27:41 UTC (rev 42737)
@@ -50,7 +50,7 @@
  * only saves/loads those which are valid for the version of the savegame
  * which is being loaded/saved currently.
  */
-#define CURRENT_VER 77
+#define CURRENT_VER 78
 
 /**
  * An auxillary macro, used to specify savegame versions. We use this instead

Modified: scummvm/trunk/engines/scumm/script.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/script.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -133,6 +133,8 @@
 
 	initializeLocals(slot, vars);
 
+	// V0 Ensure we don't try and access objects via index inside the script
+	_v0ObjectIndex = false;
 	runScriptNested(slot);
 }
 

Modified: scummvm/trunk/engines/scumm/script_v0.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script_v0.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/script_v0.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -410,41 +410,43 @@
 	actorTalk(buffer);
 }
 
-void ScummEngine_v0::drawSentence() {
-	Common::Rect 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;
 
-	if (!(_userState & 32))
-		return;
+	temp = getObjOrActorName(object);
 
-	if (getResourceAddress(rtVerb, _activeVerb)) {
-		strcpy(_sentenceBuf, (char*)getResourceAddress(rtVerb, _activeVerb));
-	} else {
-		return;
+	_v0ObjectInInventory = false;
+	_v0ObjectIndex = false;
+
+	// Append the 'object-name'
+	if (temp) {
+		strcat(_sentenceBuf, " ");
+		strcat(_sentenceBuf, (const char*)temp);
 	}
 
-	if (_activeObject > 0) {
-		temp = getObjOrActorName(_activeObject);
-		if (temp) {
-			strcat(_sentenceBuf, " ");
-			strcat(_sentenceBuf, (const char*)temp);
-		}
+	// Append the modifier? (With / On / To / In)
+	if (!usePrep)
+		return;
 
-		if (_verbs[_activeVerb].prep == 0xFF) {
-			byte *ptr = getOBCDFromObject(_activeObject);
-			assert(ptr);
-			sentencePrep = (*(ptr + 11) >> 5);
-		} else {
-			sentencePrep = _verbs[_activeVerb].prep;
-		}
+	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.
-		const char *prepositions[][5] = {
+		static const char *prepositions[][5] = {
 			{ " ", " in", " with", " on", " to" },   // English
 			{ " ", " mit", " mit", " mit", " zu" },  // German
 			{ " ", " dans", " avec", " sur", " <" }, // French
@@ -471,15 +473,67 @@
 
 		strcat(_sentenceBuf, prepositions[lang][sentencePrep]);
 	}
+}
 
-	if (_activeInventory > 0) {
-		temp = getObjOrActorName(_activeInventory);
-		if (temp) {
-			strcat(_sentenceBuf, " ");
-			strcat(_sentenceBuf, (const char*)temp);
+void ScummEngine_v0::drawSentence() {
+	Common::Rect sentenceline;
+	bool		 inventoryFirst = false;
+
+	if (!(_userState & 32))
+		return;
+
+	// Current Verb, Walk/Use
+	if (getResourceAddress(rtVerb, _activeVerb)) {
+		strcpy(_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, "");
+		
+		strcat(_sentenceBuf, " ");
+		strcat(_sentenceBuf, (const char*)a->getActorName());
+	}
+
 	_string[2].charset = 1;
 	_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
 	_string[2].xpos = 0;
@@ -664,6 +718,7 @@
 	int act = getVarOrDirectByte(PARAM_1);
 	int anim = getVarOrDirectByte(PARAM_2);
 	int unk = fetchScriptByte();
+
 	debug(0,"o_animateActor: unk %d", unk);
 
 	ActorC64 *a = (ActorC64*) derefActor(act, "o_animateActor");
@@ -725,9 +780,9 @@
 	if (getObjectIndex(obj) == -1)
 		return;
 
-	if (whereIsObject(obj) == WIO_INVENTORY)	/* Don't take an */
+	if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY)	/* Don't take an */
 		return;					/* object twice */
-
+	
 	addObjectToInventory(obj, _roomResource);
 	markObjectRectAsDirty(obj);
 	putOwner(obj, VAR(VAR_EGO));
@@ -917,10 +972,25 @@
 	setOwnerOf(obj, owner);
 }
 
-void ScummEngine_v0::resetSentence() {
-	_activeInventory = 0;
-	_activeObject = 0;
+void ScummEngine_v0::resetSentence(bool walking) {
 	_activeVerb = 13;
+
+	if (!walking) {
+		_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

Modified: scummvm/trunk/engines/scumm/scumm.cpp
===================================================================
--- scummvm/trunk/engines/scumm/scumm.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/scumm.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -134,6 +134,8 @@
 
 
 	// Init all vars
+	_v0ObjectIndex = false;
+	_v0ObjectInInventory = false;
 	_imuse = NULL;
 	_imuseDigital = NULL;
 	_musicEngine = NULL;
@@ -664,7 +666,17 @@
 ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
 	: ScummEngine_v2(syst, dr) {
 
+	_verbExecuting = false;
+	_verbPickup = false;
 	_currentMode = 0;
+
+	_activeObject2 = 0;
+	_activeObjectIndex = 0;
+	_activeObject2Index = 0;
+	_activeInvExecute = false;
+	_activeObject2Inv = false;
+	_activeObjectObtained = false;
+	_activeObject2Obtained = false;
 }
 
 ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)

Modified: scummvm/trunk/engines/scumm/scumm.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm.h	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/scumm.h	2009-07-25 06:27:41 UTC (rev 42737)
@@ -565,6 +565,9 @@
 	int32 *_scummVars;
 	byte *_bitVars;
 
+	bool _v0ObjectIndex;			// V0 Use object index, instead of object number
+	bool _v0ObjectInInventory;		// V0 Use object number from inventory
+
 	/* Global resource tables */
 	int _numVariables, _numBitVariables, _numLocalObjects;
 	int _numGlobalObjects, _numArray, _numVerbs, _numFlObject;
@@ -858,12 +861,14 @@
 	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);
 public:
 	int getObjectOrActorXY(int object, int &x, int &y);	// Used in actor.cpp, hence public
 protected:
+	int getDist(int x, int y, int x2, int y2);
 	int getObjActToObjActDist(int a, int b); // Not sure how to handle
 	const byte *getObjOrActorName(int obj);		 // these three..
 	void setObjectName(int obj);

Modified: scummvm/trunk/engines/scumm/scumm_v0.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm_v0.h	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/scumm_v0.h	2009-07-25 06:27:41 UTC (rev 42737)
@@ -35,8 +35,21 @@
  */
 class ScummEngine_v0 : public ScummEngine_v2 {
 protected:
-	int _currentMode;
+	byte _currentMode;
+	bool _verbExecuting;			// is a verb executing
+	bool _verbPickup;				// are we picking up an object during a verb execute
 
+	int _activeActor;				// Actor Number
+	int _activeObject2;				// 2nd Object Number
+
+	bool _activeInvExecute;			// is activeInventory first to be executed
+	bool _activeObject2Inv;			// is activeobject2 in the inventory
+	bool _activeObjectObtained;		// collected _activeobject?
+	bool _activeObject2Obtained;	// collected _activeObject2?
+
+	int _activeObjectIndex;
+	int _activeObject2Index;
+
 public:
 	ScummEngine_v0(OSystem *syst, const DetectorResult &dr);
 
@@ -53,12 +66,25 @@
 
 	virtual void processInput();
 
+	virtual void runObject(int obj, int entry);
 	virtual void saveOrLoad(Serializer *s);
 
+	// V0 MM Verb commands
+	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);
 	void resetVerbs();
 	void setNewKidVerbs();
+
+	void drawSentenceWord(int object, bool usePrep, bool objInInventory);
 	void drawSentence();
 
 	void switchActor(int slot);
@@ -68,7 +94,7 @@
 
 	virtual int getActiveObject();
 
-	virtual void resetSentence();
+	virtual void resetSentence(bool walking = false);
 
 	/* Version C64 script opcodes */
 	void o_stopCurrentScript();

Modified: scummvm/trunk/engines/scumm/scumm_v2.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm_v2.h	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/scumm_v2.h	2009-07-25 06:27:41 UTC (rev 42737)
@@ -100,7 +100,7 @@
 
 	virtual void setBuiltinCursor(int index);
 
-	void runObject(int obj, int entry);
+	virtual void runObject(int obj, int entry);
 
 	/* Version 2 script opcodes */
 	void o2_actorFromPos();

Modified: scummvm/trunk/engines/scumm/vars.cpp
===================================================================
--- scummvm/trunk/engines/scumm/vars.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/vars.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -538,9 +538,7 @@
 #endif
 
 void ScummEngine_v0::resetScummVars() {
-	_activeInventory = 0;
-	_activeObject = 0;
-	_activeVerb = 13;
+	resetSentence();
 
 	VAR(VAR_EGO) = 3;
 

Modified: scummvm/trunk/engines/scumm/verbs.cpp
===================================================================
--- scummvm/trunk/engines/scumm/verbs.cpp	2009-07-25 05:39:57 UTC (rev 42736)
+++ scummvm/trunk/engines/scumm/verbs.cpp	2009-07-25 06:27:41 UTC (rev 42737)
@@ -155,6 +155,7 @@
 	VAR(VAR_EGO) = VAR(97 + slot);
 	actorFollowCamera(VAR(VAR_EGO));
 	resetVerbs();
+	resetSentence(false);
 	setUserState(247);
 }
 
@@ -376,14 +377,8 @@
 
 	if (object > 0) {
 		if (_game.version == 0) {
-			if (_activeInventory != object) {
 				_activeInventory = object;
-			} else if (_activeVerb != 3 && _activeVerb != 13) {
-				if (_activeObject)
-					runObject(_activeObject, _activeVerb);
-				else
-					runObject(_activeInventory, _activeVerb);
-			}
+
 		} else {
 			runInputScript(kInventoryClickArea, object, 0);
 		}
@@ -425,7 +420,9 @@
 		_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
@@ -666,6 +663,25 @@
 	}
 }
 
+void ScummEngine_v0::runObject(int obj, int entry) {
+	int prev = _v0ObjectInInventory;
+
+	if (getVerbEntrypoint(obj, entry) != 0) {
+		_v0ObjectInInventory = prev;
+		runObjectScript(obj, entry, false, false, NULL);
+	} else if (entry != 13 && entry != 15) {
+		if (_activeVerb != 3) {
+			VAR(9) = entry;
+			runScript(3, 0, 0, 0);
+
+		// For some reasons, certain objects don't have a "give" script
+		} else if (VAR(5) > 0 && VAR(5) < 8) {
+			if (_activeInventory)
+				setOwnerOf(_activeInventory, VAR(5));
+		}
+	}
+}
+
 void ScummEngine_v2::runObject(int obj, int entry) {
 	if (getVerbEntrypoint(obj, entry) != 0) {
 		runObjectScript(obj, entry, false, false, NULL);
@@ -679,10 +695,299 @@
 	_activeVerb = 13;
 }
 
+bool ScummEngine_v0::verbMoveToActor(int actor) {
+	Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
+	Actor *a2 =derefActor(actor, "checkExecVerbs");
+
+
+	if (!a->_moving) {
+		int dist =  getDist(a->getRealPos().x, a->getRealPos().y, a2->getRealPos().x, a2->getRealPos().y);
+
+		if (dist>5)
+			a->startWalkActor(a2->getRealPos().x, a2->getRealPos().y, 1);
+		else
+			return false;
+
+		return true;
+	} 
+
+	return true;
+}
+
+bool ScummEngine_v0::verbMove(int object, int objectIndex, bool invObject) {
+	int x, y, dir;
+	Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
+
+	if (_currentMode != 3 && _currentMode != 2)
+		return false;
+
+	if (a->_moving)
+		return true;
+
+	_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);
+
+	// FIXME: This should be changed once the walkbox problem is fixed
+	if (dist>0x5) {
+		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;
+}
+
+bool ScummEngine_v0::verbObtain(int obj, int objIndex) {
+	bool didPickup = false;
+
+	int prep, where = whereIsObjectInventory(obj);
+
+	if (objIndex == 0)
+		return false;
+
+	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;
+		}
+
+		if (verbMove(obj, objIndex, false))
+			return true;
+
+		if (didPickup && (prep == 1 || prep == 4))
+			if (_activeVerb != 13 && _activeVerb != 14)
+				_activeInventory = obj;
+	}
+
+	return false;
+}
+
+int ScummEngine_v0::verbPrep(int object) {
+	if (!_v0ObjectInInventory) 	
+		_v0ObjectIndex = true;
+	else
+		_v0ObjectIndex = false;
+	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);
+
+	if (prep == 2 || prep == 0) {
+		return true;
+	}
+
+	return false;
+}
+
+bool ScummEngine_v0::verbExec() {
+	int prep = 0;
+	int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15;
+
+	if ((!_activeInvExecute && _activeObject && getObjectIndex(_activeObject) == -1)) {
+		resetSentence();
+		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;
+	}
+
+	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
+		// And walk to each other
+		//
+		if (verbMoveToActor(_activeActor))
+			return true;
+
+		_v0ObjectInInventory = true;
+		VAR(5) = _activeActor;
+		runObject(_activeInventory , 3);
+		_v0ObjectInInventory = false;
+
+		resetSentence();
+		return false;
+	}
+
+	if (_activeActor) {
+		_v0ObjectIndex = true;
+		runObject(_activeActor, entry);
+		_v0ObjectIndex = false;
+		_verbExecuting = false;
+
+		resetSentence();
+		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();
+		return false;
+	}
+
+	// We acted on an inventory item
+	if (_activeInventory && verbExecutes(_activeInventory, true) && _activeVerb != 3) {
+		_v0ObjectInInventory = true;
+		runObject(_activeInventory, _activeVerb);
+
+		_verbExecuting = false;
+
+		if (_currentMode == 3 && _activeVerb == 13) {
+			resetSentence(true);
+			return false;
+		}
+		
+		resetSentence();
+		return false;
+	}
+
+	if (_activeObject) {
+		_v0ObjectIndex = true;
+		runObject(_activeObjectIndex, entry);
+		_v0ObjectIndex = false;
+	} else if (_activeInventory) {
+		if (verbExecutes(_activeInventory, true) == false) {
+			
+			if (_activeObject2 && verbExecutes(_activeObject2, true)) {
+				_v0ObjectInInventory = true;
+				
+				_activeObject = _activeInventory;
+				_activeInventory = _activeObject2;
+				
+				runObject(_activeObject, _activeVerb);
+			} else {
+				_v0ObjectInInventory = true;
+				runObject(_activeInventory, _activeVerb);
+			}
+		} else {
+			runObject(_activeInventory, _activeVerb);
+			_v0ObjectInInventory = true;
+		}
+	}
+
+	_verbExecuting = false;
+
+	if (_activeVerb == 13) {
+		resetSentence(true);
+		return false;
+	}
+
+	resetSentence();
+
+	return false;
+}
+
 void ScummEngine_v0::checkExecVerbs() {
 	Actor *a;
 	VirtScreen *zone = findVirtScreen(_mouse.y);
 
+	// 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;
+				_verbExecuting = false;
+				return;
+			}
+
+			if (!obj && !act && !over) {
+				resetSentence(false);	
+			} else {
+				a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
+				a->stopActorMoving();
+			}
+		} else {
+			if (_verbExecuting && !verbExec())
+				return;
+		}
+	}
+
+	// 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 (_userPut <= 0 || _mouseAndKeyboardStat == 0)
 		return;
 
@@ -693,61 +998,149 @@
 		if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
 			// TODO
 		} else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
+			int prevInventory = _activeInventory;
+
 			// Click into V2 inventory
 			checkV2Inventory(_mouse.x, _mouse.y);
+			if (!_activeInventory)
+				return;
+			
+			// Did we just change the selected inventory item?
+			if (prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) {
+				_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 ((_activeObject || _activeInventory) && act) {
+				obj = 0;
+				objIdx = 0;
+			}
+
 			// Handle New Kid verb options
-			if (_activeVerb == 7) {
+			if (_activeVerb == 7 || over == 7) {
+				// Disable New-Kid (in the secret lab)
+				if (_currentMode == 2 || _currentMode == 0)
+					return;
+
+				if (_activeVerb != 7) {
+					_activeVerb = over;
+					over = 0;
+				} 
+
 				if (over) {
 					_activeVerb = 13;
 					switchActor(_verbs[over].verbid - 1);
+					return;
 				}
+
+				setNewKidVerbs();
+
 				return;
 			}
+			
+			// Clicked on nothing, walk here?
+			if (!over && !act && _activeVerb == 13 && !obj && _currentMode != 0) {
 
-			if (over) {
-				_activeVerb = _verbs[over].verbid;
-				// Selected New Kid verb
-				if (_activeVerb == 7)
-					setNewKidVerbs();
+				// Clear all selected
+				resetSentence();
 
+				// 0xB31
+				VAR(6) = _virtualMouse.x / V12_X_MULTIPLIER;
+				VAR(7) = _virtualMouse.y / V12_Y_MULTIPLIER;
+
+				if (zone->number == kMainVirtScreen) {
+					a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
+					a->stopActorMoving();
+					a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
+				}
 				return;
 			}
 
-			int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
-			int obj = findObject(_virtualMouse.x, _virtualMouse.y);
-			if (act != 0 && _activeVerb == 3 && _activeInventory != 0) {
-				// Give inventory item to actor
-				VAR(5) = act;
-				runObject(_activeInventory, _activeVerb);
-			} else if (obj) {
-				if (_currentMode == 3 && _activeVerb != 13 && obj != _activeObject) {
-					_activeObject = obj;
-					return;
+			// No new verb, use previous
+			if (over == 0)
+				over = _activeVerb;
+
+			// 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();
 				}
+				return;
+			}
 
-				_activeObject = obj;
-				if (_currentMode == 3) {
-					int x, y, dir;
-					a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
-					getObjectXYPos(obj, x, y, dir);
-					a->startWalkActor(x, y, dir);
+			// 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;
+					}
 				}
+			}
 
-				int entry = (_currentMode == 3) ? _activeVerb : 15;
-				runObject(_activeObject, entry);
-			} else if (zone->number == kMainVirtScreen) {
-				a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
-				a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
+			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 {
+							if (_activeObject2 != obj) {
+								_activeObject2 = obj;
+								_activeObject2Index = objIdx;
+								return;
+							}
+						}
+					}
+				} else {
+					_activeObject = obj;
+					_activeObjectIndex = objIdx;
+						
+					if (_activeVerb != 13)
+						return;
+					
+					//return;
+				}
 			}
+		}
 
-			_activeInventory = 0;
-			_activeObject = 0;
-			_activeVerb = 13;
-		}
-	}
+		_verbExecuting = true;
+
+	}	// mouse k/b action
 }
 
 void ScummEngine::verbMouseOver(int verb) {


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