From 1c32000a004cc184a8744e2467035a4c7ba2f3a5 Mon Sep 17 00:00:00 2001 From: Tobias Gunkel Date: Sat, 7 Jan 2012 16:08:55 +0100 Subject: SCUMM: start handling object type and id correctly in mm c64 - removed complicated and unnecessary _v0ObjectIndex, _v0ObjectInInventory, _v0ObjectFlag vars - started to merge object id and type into one object value (type<<8|id) - verb preposition ids do not dependent on language -> remove from VerbSettings Note: - objects with type=0 are foreground objects. They have a state, an owner and a bg overlay image. - objects with type=1 are bg objects. They do not have a state or owner and are already contained in the bg image. The do not have an entry in objectState/OwnerTable --- engines/scumm/object.cpp | 74 +++--- engines/scumm/object.h | 8 + engines/scumm/script.cpp | 2 - engines/scumm/script_v0.cpp | 65 ++---- engines/scumm/script_v2.cpp | 2 - engines/scumm/scumm.cpp | 11 +- engines/scumm/scumm.h | 7 +- engines/scumm/scumm_v0.h | 29 ++- engines/scumm/verbs.cpp | 542 ++++++++++++++++++++++---------------------- 9 files changed, 360 insertions(+), 380 deletions(-) diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index a9e2a76345..53dc0151d9 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -178,10 +178,7 @@ 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) { - if (_game.version == 0) - assert(WIO_INVENTORY == whereIsObjectInventory(obj)); - else - assert(WIO_INVENTORY == whereIsObject(obj)); + assert(WIO_INVENTORY == whereIsObject(obj)); // Found the object! Nuke it from the inventory. _res->nukeResource(rtInventory, i); @@ -310,52 +307,50 @@ 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 (object < 1) + if (nr < 1) return -1; for (i = (_numLocalObjects-1); i > 0; i--) { - if (_game.version == 0 ) - if( _objs[i].obj_type != _v0ObjectFlag ) - continue; + if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object)) + continue; - if (_objs[i].obj_nr == object) + if (_objs[i].obj_nr == nr) 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; - if (object >= _numGlobalObjects) + // Note: in MMC64 bg objects are greater _numGlobalObjects + if (_game.version != 0 && object >= _numGlobalObjects) return WIO_NOT_FOUND; if (object < 1) return WIO_NOT_FOUND; - if ((_objectOwnerTable[object] != OF_OWNER_ROOM && _game.version != 0) || _v0ObjectInInventory) { + if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) && + _objectOwnerTable[object] != OF_OWNER_ROOM) + { for (i = 0; i < _numInventory; i++) if (_inventory[i] == object) return WIO_INVENTORY; return WIO_NOT_FOUND; } - for (i = (_numLocalObjects-1); i > 0; i--) - if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) { + 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].fl_object_index) return WIO_FLOBJECT; return WIO_ROOM; } + } return WIO_NOT_FOUND; } @@ -396,7 +391,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 = (_v0ObjectIndex) ? object : getObjectIndex(object); + int idx = getObjectIndex(object); assert(idx >= 0); ObjectData &od = _objs[idx]; int state; @@ -497,6 +492,7 @@ int ScummEngine::findObject(int x, int y) { byte a; const int mask = (_game.version <= 2) ? kObjectState_08 : 0xF; + // FIXME(TOBIAS): <= _numLocalObjects? for (i = 1; i < _numLocalObjects; i++) { if ((_objs[i].obj_nr < 1) || getClass(_objs[i].obj_nr, kObjectClassUntouchable)) continue; @@ -522,11 +518,8 @@ 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) - _v0ObjectFlag = _objs[i].obj_type; - if (_game.version == 0 && _v0ObjectIndex) - return i; + return OBJECT_V0(_objs[i].obj_nr, _objs[i].obj_type); else return _objs[i].obj_nr; } @@ -1165,7 +1158,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) { } } - objptr = getOBCDFromObject(obj); + objptr = getOBCDFromObject(obj, true); if (objptr == NULL) return NULL; @@ -1218,15 +1211,14 @@ void ScummEngine::setObjectName(int obj) { uint32 ScummEngine::getOBCDOffs(int object) const { int i; - if ((_objectOwnerTable[object] != OF_OWNER_ROOM && (_game.version != 0)) || _v0ObjectInInventory) + if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) && + _objectOwnerTable[object] != OF_OWNER_ROOM) 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 (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object)) + continue; if (_objs[i].fl_object_index != 0) return 8; return _objs[i].OBCDoffset; @@ -1235,21 +1227,25 @@ uint32 ScummEngine::getOBCDOffs(int object) const { return 0; } -byte *ScummEngine::getOBCDFromObject(int obj) { - bool useInventory = _v0ObjectInInventory; +byte *ScummEngine::getOBCDFromObject(int obj, bool v0CheckInventory) { int i; byte *ptr; - _v0ObjectInInventory = false; - - if ((_objectOwnerTable[obj] != OF_OWNER_ROOM && (_game.version != 0)) || useInventory) { + if ((_game.version != 0 || OBJECT_V0_TYPE(obj) == 0) && + _objectOwnerTable[obj] != OF_OWNER_ROOM) + { + if (_game.version == 0 && !v0CheckInventory) + return 0; 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 && !_v0ObjectIndex) || (_v0ObjectIndex && i == obj)) { + 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].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 edbff38355..7e4a5b57ab 100644 --- a/engines/scumm/object.h +++ b/engines/scumm/object.h @@ -24,6 +24,14 @@ 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, diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index 37ea3a9a9f..d04c3c0891 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -131,8 +131,6 @@ 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); } diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp index 2bbde617ad..14df89b28d 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -365,7 +365,7 @@ uint ScummEngine_v0::fetchScriptWord() { int ScummEngine_v0::getActiveObject() { if (_opcode & PARAM_2) - return _activeObject; + return _activeObjectNr; return fetchScriptByte(); } @@ -406,22 +406,9 @@ void ScummEngine_v0::decodeParseString() { actorTalk(buffer); } -const byte *ScummEngine_v0::getObjectName(int object, int type) { - const byte *temp; - - if (type == kObjectTypeInventory) - _v0ObjectInInventory = true; - - temp = getObjOrActorName(object); - - _v0ObjectInInventory = false; - - return temp; -} - void ScummEngine_v0::drawSentenceObject(int object, int type) { const byte *temp; - temp = getObjectName(object, type); + temp = getObjOrActorName(OBJECT_V0(object, type)); if (temp) { _sentenceBuf += " "; _sentenceBuf += (const char *)temp; @@ -443,25 +430,25 @@ void ScummEngine_v0::drawSentence() { return; } - if (_activeObject) { + if (_activeObjectNr) { // Draw the 1st active object - drawSentenceObject(_activeObject, _activeObjectType); + drawSentenceObject(_activeObjectNr, _activeObjectType); // Append verb preposition - int sentencePrep = verbPrep(); + int sentencePrep = activeVerbPrep(); if (sentencePrep) { drawPreposition(sentencePrep); // Draw the 2nd active object - if (_activeObject2) { + if (_activeObject2Nr) { // 2nd Object is an actor if (_activeObject2Type == kObjectTypeActor) { - Actor *a = derefActor(_activeObject2, ""); + Actor *a = derefActor(_activeObject2Nr, ""); _sentenceBuf += " "; _sentenceBuf += (const char *)a->getActorName(); // 2nd Object is an inventory or room object } else { - drawSentenceObject(_activeObject2, _activeObject2Type); + drawSentenceObject(_activeObject2Nr, _activeObject2Type); } } } @@ -705,26 +692,13 @@ void ScummEngine_v0::o_putActorAtObject() { } void ScummEngine_v0::o_pickupObject() { - int obj = fetchScriptByte(); - if (obj == 0) { - if (_activeObject) { - obj = _activeObject; - } else { - // might happen if an inventory item was picked again - return; - } - } + int objNr = fetchScriptByte(); + int obj = OBJECT_V0((objNr ? objNr : _activeObjectNr), 0); - if (obj < 1) { - error("pickupObject received invalid index %d (script %d)", obj, vm.slot[_currentScript].number); - } - - if (getObjectIndex(obj) == -1) + /* Don't take an object twice */ + if (whereIsObject(obj) == WIO_INVENTORY) return; - if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY) /* Don't take an */ - return; /* object twice */ - addObjectToInventory(obj, _roomResource); markObjectRectAsDirty(obj); putOwner(obj, VAR(VAR_EGO)); @@ -822,8 +796,8 @@ void ScummEngine_v0::o_doSentence() { bool ScummEngine_v0::ifEqualActiveObject2Common(bool inventoryObject) { byte obj = fetchScriptByte(); - if (!inventoryObject || (_activeObject2Type == kObjectTypeInventory)) - return (obj == _activeObject2); + if (!inventoryObject || (_activeObject2Type == kObjectTypeFG)) + return (obj == _activeObject2Nr); return false; } @@ -920,7 +894,7 @@ void ScummEngine_v0::o_setOwnerOf() { owner = getVarOrDirectByte(PARAM_2); if (obj == 0) - obj = _activeObject; + obj = _activeObjectNr; // FIXME: the original interpreter seems to set the owner of // an item to remove (new owner 0) to 13 (purple tentacle). @@ -939,16 +913,15 @@ void ScummEngine_v0::resetSentence(bool walking) { // 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; - _activeObject = 0; - _activeObject2 = 0; + _activeObjectNr = 0; + _activeObjectType = kObjectTypeBG; + _activeObject2Nr = 0; + _activeObject2Type = kObjectTypeBG; } _verbExecuting = false; _verbPickup = false; - _activeObjectType = kObjectTypeRoom; - _activeObject2Type = kObjectTypeRoom; _activeObjectObtained = false; _activeObject2Obtained = false; } diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp index 003bafa27e..1ea3257c17 100644 --- a/engines/scumm/script_v2.cpp +++ b/engines/scumm/script_v2.cpp @@ -1223,8 +1223,6 @@ void ScummEngine_v2::o2_walkActorToObject() { int obj; Actor *a; - _v0ObjectFlag = 0; - a = derefActor(getVarOrDirectByte(PARAM_1), "o2_walkActorToObject"); obj = getVarOrDirectWord(PARAM_2); if (whereIsObject(obj) != WIO_NOT_FOUND) { diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index d3dc702395..423ad79b00 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -151,9 +151,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _fileHandle = 0; // Init all vars - _v0ObjectIndex = false; - _v0ObjectInInventory = false; - _v0ObjectFlag = 0; _imuse = NULL; _imuseDigital = NULL; _musicEngine = NULL; @@ -720,10 +717,10 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr) _currentMode = 0; _activeVerb = 0; - _activeObject = 0; - _activeObject2 = 0; - _activeObjectType = kObjectTypeRoom; - _activeObject2Type = kObjectTypeRoom; + _activeObjectNr = 0; + _activeObject2Nr = 0; + _activeObjectType = kObjectTypeBG; + _activeObject2Type = kObjectTypeBG; _activeObjectObtained = false; _activeObject2Obtained = false; diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index d9237b2b30..f004176da1 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -502,10 +502,6 @@ 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; @@ -799,7 +795,6 @@ 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); @@ -820,7 +815,7 @@ protected: virtual void clearDrawQueues(); uint32 getOBCDOffs(int object) const; - byte *getOBCDFromObject(int obj); + byte *getOBCDFromObject(int obj, bool v0CheckInventory = true); 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 d9629948fe..0bb4d1a4a9 100644 --- a/engines/scumm/scumm_v0.h +++ b/engines/scumm/scumm_v0.h @@ -33,9 +33,16 @@ namespace Scumm { class ScummEngine_v0 : public ScummEngine_v2 { protected: enum ObjectType { - kObjectTypeInventory = 0, - kObjectTypeRoom = 1, - kObjectTypeActor = 2 + 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: @@ -44,10 +51,10 @@ protected: bool _verbPickup; // are we picking up an object during a verb execute int _activeVerb; - int _activeObject; // 1st Object Number - int _activeObjectType; // 1st Object Type (0: inventory, 1: room) - int _activeObject2; // 2nd Object Number - int _activeObject2Type; // 2nd Object Type (0: inventory, 1: room, 2: actor) + 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) bool _activeObjectObtained; // collected _activeobject? bool _activeObject2Obtained; // collected _activeObject2? @@ -73,20 +80,20 @@ protected: virtual void saveOrLoad(Serializer *s); // V0 MM Verb commands - int verbPrep(); + int getVerbPrepId(); + int activeVerbPrep(); bool verbMove(int object, bool invObject); bool verbMoveToActor(int actor); - bool verbObtain(int object, int objType); + bool verbObtain(int object); bool verbExecutes(int object, bool inventory = false); bool verbExec(); virtual void checkExecVerbs(); virtual void handleMouseOver(bool updateInventory); + int verbPrepIdType(int verbid); void resetVerbs(); void setNewKidVerbs(); - const byte *getObjectName(int object, int type); - void drawSentenceObject(int object, int type); void drawSentence(); diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index dc4a47a231..467b587b63 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -37,51 +37,82 @@ enum { kSentenceLine = 6 }; +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 +}; + struct VerbSettings { int id; int x_pos; int y_pos; - int prep; const char *name; }; static const VerbSettings v0VerbTable_English[] = { - { 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"} + {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"} }; // FIXME: Replace * with the correct character static const VerbSettings v0VerbTable_German[] = { - { 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, "Drkey = 0; vs->center = 0; vs->imgindex = 0; - vs->prep = vtable[i - 1].prep; + vs->prep = verbPrepIdType(vtable[i - 1].id); 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); @@ -433,9 +464,7 @@ 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 @@ -518,7 +547,7 @@ void ScummEngine_v2::handleMouseOver(bool updateInventory) { } void ScummEngine_v0::handleMouseOver(bool updateInventory) { - drawSentence(); + //drawSentence(); ScummEngine_v2::handleMouseOver(updateInventory); } @@ -713,8 +742,6 @@ void ScummEngine_v2::checkExecVerbs() { } 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 @@ -724,23 +751,20 @@ void ScummEngine_v0::runObject(int obj, int entry) { } } - _v0ObjectInInventory = prev; - if (getVerbEntrypoint(obj, entry) != 0) { - _v0ObjectInInventory = prev; runObjectScript(obj, entry, false, false, NULL); } else if (entry != 13 && entry != 15) { - if (_activeVerb != 3) { + if (_activeVerb == kVerbGive) { + // For some reasons, certain objects don't have a "give" script + if (VAR(VAR_ACTIVE_ACTOR) > 0 && VAR(VAR_ACTIVE_ACTOR) < 8) { + if (OBJECT_V0_TYPE(obj) == kObjectTypeFG) { + assert(false); + setOwnerOf(obj, VAR(VAR_ACTIVE_ACTOR)); + } + } + } else { 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) { - // TODO - /* - if (_activeInventory) - setOwnerOf(_activeInventory, VAR(VAR_ACTIVE_ACTOR)); - */ } } } @@ -785,13 +809,16 @@ bool ScummEngine_v0::verbMove(int object, bool invObject) { } else { // Finished walk, are we picking up the item? if (_verbPickup) { - int oldActive = _activeObject; - _activeObject = object; + int oldActive = OBJECT_V0(_activeObjectNr, _activeObjectType); + + _activeObjectNr = OBJECT_V0_NR(object); + _activeObjectType = OBJECT_V0_TYPE(object); // Execute pickup runObject(object, 14); - _activeObject = oldActive; + _activeObjectNr = OBJECT_V0_NR(oldActive); + _activeObjectType = OBJECT_V0_TYPE(oldActive); // Finished picking up _verbPickup = false; @@ -801,7 +828,7 @@ bool ScummEngine_v0::verbMove(int object, bool invObject) { return false; } -bool ScummEngine_v0::verbObtain(int obj, int objType) { +bool ScummEngine_v0::verbObtain(int obj) { bool didPickup = false; int prep; int where; @@ -809,11 +836,11 @@ bool ScummEngine_v0::verbObtain(int obj, int objType) { if (!obj) return false; - where = whereIsObjectInventory(obj); + where = whereIsObject(obj); // Object in inventory ? if (where != WIO_INVENTORY) { - prep = verbPrep(); + prep = activeVerbPrep(); if (prep == 1 || prep == 4) { if (_activeVerb != 13 && _activeVerb != 14) { @@ -837,79 +864,63 @@ bool ScummEngine_v0::verbObtain(int obj, int objType) { if (didPickup && (prep == 1 || prep == 4)) if (_activeVerb != 13 && _activeVerb != 14) { - // TODO - /* - _v0ObjectInInventory = true; - +// TODO(TOBIAS) +#if 0 if (whereIsObject(obj) == WIO_INVENTORY) _activeInventory = obj; else resetSentence(false); - - _v0ObjectInInventory = false; - */ +#endif } } return false; } -int ScummEngine_v0::verbPrep() { +int ScummEngine_v0::getVerbPrepId() { if (_verbs[_activeVerb].prep != 0xFF) { return _verbs[_activeVerb].prep; } else { - if (!_v0ObjectInInventory) - _v0ObjectIndex = true; - else - _v0ObjectIndex = false; - - byte *ptr = getOBCDFromObject(_activeObject); - _v0ObjectIndex = false; + byte *ptr = getOBCDFromObject(OBJECT_V0(_activeObjectNr, _activeObjectType), true); assert(ptr); return (*(ptr + 11) >> 5); } } -bool ScummEngine_v0::verbExecutes(int object, bool inventory) { - _v0ObjectInInventory = inventory; - int prep = verbPrep(); - - if (prep == 2 || prep == 0) { - return true; - } - - return false; +int ScummEngine_v0::activeVerbPrep() { + if (!_activeVerb || !_activeObjectNr) + return 0; + return getVerbPrepId(); } bool ScummEngine_v0::verbExec() { int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15; - if (_activeObject && getObjectIndex(_activeObject) == -1) { + if (_activeObjectNr && getObjectIndex(OBJECT_V0(_activeObjectNr, _activeObjectType)) == -1) { resetSentence(false); return false; } // Lets try walk to the object - if (_activeObject && !_activeObjectObtained && _currentMode != 0) { - if (verbObtain(_activeObject, _activeObjectType)) + if (_activeObjectNr && !_activeObjectObtained && _currentMode != 0) { + if (verbObtain(OBJECT_V0(_activeObjectNr, _activeObjectType))) return true; _activeObjectObtained = true; } // Attempt to obtain/reach object2 - if (_activeObject2 && !_activeObject2Obtained && _currentMode != 0) { - _v0ObjectInInventory = false; - if (verbObtain(_activeObject2, _activeObject2Type)) + if (_activeObject2Nr && !_activeObject2Obtained && _currentMode != 0) { + if (verbObtain(OBJECT_V0(_activeObject2Nr, _activeObject2Type))) return true; _activeObject2Obtained = true; } // Give-To - if (_activeVerb == 3 && _activeObject && _activeObject2 && _activeObject2Type == kObjectTypeActor) { + if (_activeVerb == 3 && _activeObjectNr && _activeObject2Nr && _activeObject2Type == kObjectTypeActor) { // FIXME: Actors need to turn and face each other - if (verbMoveToActor(_activeObject2)) { + if (verbMoveToActor(_activeObject2Nr)) { // Ignore verbs? Actor *a = derefActor(VAR(VAR_EGO), "verbExec"); if (((ActorC64 *)a)->_miscflags & 0x40) { @@ -919,18 +930,16 @@ bool ScummEngine_v0::verbExec() { return true; } - _v0ObjectInInventory = true; - VAR(VAR_ACTIVE_ACTOR) = _activeObject2; - runObject(_activeObject , 3); - _v0ObjectInInventory = false; + VAR(VAR_ACTIVE_ACTOR) = _activeObject2Nr; + runObject(OBJECT_V0(_activeObjectNr, _activeObjectType), 3); resetSentence(false); return false; } // Where we performing an action on an actor? - if (_activeObject2 && _activeObject2Type == kObjectTypeActor) { - runObject(_activeObject2, entry); + if (_activeObject2Nr && _activeObject2Type == kObjectTypeActor) { + runObject(OBJECT_V0(_activeObject2Nr, _activeObject2Type), entry); _verbExecuting = false; resetSentence(false); @@ -938,8 +947,8 @@ bool ScummEngine_v0::verbExec() { } // If we've finished walking (now near target), execute the action - if (_activeObject && verbPrep() == 2) { - runObject(_activeObject, entry); + if (_activeObjectNr && activeVerbPrep() == 2) { + runObject(OBJECT_V0(_activeObjectNr, _activeObjectType), entry); _verbExecuting = false; if ((_currentMode == 3 || _currentMode == 2) && _activeVerb == 13) @@ -950,9 +959,8 @@ bool ScummEngine_v0::verbExec() { } // We acted on an inventory item - if (/*_activeInventory && verbExecutes(_activeInventory, true) &&*/ _activeVerb != 3) { - _v0ObjectInInventory = true; - runObject(_activeObject/*2*/, _activeVerb); + if (_activeVerb != 3) { + runObject(OBJECT_V0(_activeObjectNr/*2*/, _activeObjectType/*2*/), _activeVerb); _verbExecuting = false; @@ -965,36 +973,8 @@ bool ScummEngine_v0::verbExec() { return false; } - // Item not in inventory is executed - if (_activeObject) { - runObject(_activeObject, entry); - } else if (/*_activeInventory*/false) { -#if 0 - // Not sure this is the correct way to do this, - // however its working for most situations - segra - if (verbExecutes(_activeInventory, true) == false) { - if (_activeObject2 && _activeObject2Type == kObjectTypeInventory && 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); - } -#endif + if (_activeObjectNr) { + runObject(OBJECT_V0(_activeObjectNr, _activeObjectType), entry); } _verbExecuting = false; @@ -1009,17 +989,182 @@ bool ScummEngine_v0::verbExec() { return false; } +#if 0 +verbExec() { + cmdStackMaxLeft = 6; + cmdStackPos = 0xFF; + if (verbSelectedID == 15) // WHAT IS + return; + + if (verbSelectedID != 13 || objectSelectedID != 0) { + cmdStackPos++; + cmdVerbID[cmdStackPos] = verbSelectedID; + cmdObjectID[cmdStackPos] = objectSelectedID; + cmdObjectType[cmdStackPos] = objectSelectedType; + cmdVerbPrepID[cmdStackPos] = verbPrepID; + cmdObject2ID[cmdStackPos] = objectSelected2ID; + cmdObject2Type[cmdStackPos] = objectSelected2Type; + + if (verbSelectedID != 13) { // WALK TO + verbSelectedID = 13; + objectSelectedID = 0; + verbPrepID = 0; + } + scriptUpdateSkip = 0; + return; + } + + currentActor = scriptVARS[0]; + roomActor = gActorInRoom[currentActor]; + tmpX = cursorX(); + tmpY = cursorY(); + actorSetPosInBox(); + + scriptVARS[6] = tmpX; + scriptVARS[7] = tmpY; + + if (gActor_miscFlags[scriptVARS[0]] & 0x40) { + rActor_scriptWalkToX[roomActor] = tmpX; + rActor_scriptWalkToX[roomActor] = tmpY; + walk_1C4A(); + } +} +#endif + void ScummEngine_v0::checkExecVerbs() { ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "checkExecVerbs"); VirtScreen *zone = findVirtScreen(_mouse.y); + int scriptUpdateSkip; + int sentenceLineChanged = false; + + /* + if (_userPut <= 0 || _mouseAndKeyboardStat == 0) + return; + */ + + // Check if mouse click + if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) { + int over = findVerbAtPos(_mouse.x, _mouse.y); + if (over && _activeVerb != over) { + _activeVerb = over; + //_activeVerbPrep = 0; + _activeObjectNr = 0; + _activeObjectType = 0; + _activeObject2Nr = 0; + _activeObject2Type = 0; + sentenceLineChanged = true; + } + } + + if (a->_miscflags & 0x80) { + if (_activeVerb != kVerbNewKid) { + _activeVerb = kVerbNone; + } + } + + // mode 1: kid selection, 3: normal + if (_currentMode != 0) { + if (_currentMode == 1) { + // kid selection or dial pad + _activeVerb = kVerbPush; + } + + if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK) || _activeVerb == kVerbWhatIs) { + int id; + byte type; + if (_activeVerb == kVerbGive && _activeObjectNr) { + id = getActorFromPos(_virtualMouse.x, _virtualMouse.y); + type = kObjectTypeActor; + } else { + int obj = findObject(_virtualMouse.x, _virtualMouse.y); + id = OBJECT_V0_NR(obj); + type = OBJECT_V0_TYPE(obj); + debug("found 0x%03x", obj); + } + if (!id) { + if (_activeVerb == kVerbWalkTo) { + _activeObjectNr = 0; + _activeObject2Nr = 0; + } + } else { + //_activeVerbPrep: + // 0: no activeObject or activeObject but no prep + // > 0: activeObject + prep + if (activeVerbPrep() == 0) { + if (id == _activeObjectNr && type == _activeObjectType) { + _verbExecuting = true; + } else { + _activeObjectNr = id; + _activeObjectType = type; + } + //sentenceLineChanged = true; + if (_currentMode == 1) + _verbExecuting = true; + } else { + if (id == _activeObject2Nr && type == _activeObject2Type) + _verbExecuting = true; + if (!(id == _activeObjectNr && type == _activeObjectType)) { + _activeObject2Nr = id; + _activeObject2Type = type; + if (_currentMode == 1) + _verbExecuting = true; + } + } + } + + sentenceLineChanged = true; + if (_activeVerb == kVerbWalkTo) { + scriptUpdateSkip = 0; + _verbExecuting = true; + } + } + } + + if (sentenceLineChanged) + drawSentence(); + + if (_activeVerb == kVerbNewKid) { + // TODO + if (_currentMode == 3) { + // get kid + _activeVerb = kVerbWalkTo; + resetSentence(false); + //switchActor(_verbs[over].verbid - 1); + } + _activeVerb = kVerbWalkTo; + } + + if (_activeVerb == kVerbWalkTo) { + //exec(); + } + + /* + if (_activeVerbPrep == 0) { + int prep = activeVerbPrep(); + if (prep == 0) + ; //exec(); + else { + _activeVerbPrep = prep; + ; // draw() + } + } else { + if (_activeObject2 == 0) + ; //drawSentence(); + else + ; // exec(); + } + */ + +#if 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); + byte type; + int obj = findObject(_virtualMouse.x, _virtualMouse.y, &type); if (over && over != _activeVerb) { _activeVerb = over; @@ -1039,17 +1184,6 @@ void ScummEngine_v0::checkExecVerbs() { } } - // 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); - _activeObject = obj; - - if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK)) - _activeVerb = 13; // Walk-To - - return; - } - if (_userPut <= 0 || _mouseAndKeyboardStat == 0) return; @@ -1060,78 +1194,19 @@ void ScummEngine_v0::checkExecVerbs() { if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) { // TODO } else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) { -#if 0 - int prevInventory = _activeInventory; -#endif int invOff = _inventoryOffset; - // GIVE: actor must be selected (not possible via inventory) - if ((_activeVerb == 3) && _activeObject) - return; - // Click into V2 inventory checkV2Inventory(_mouse.x, _mouse.y); // Did the Inventory position changed (arrows pressed, do nothing) if (invOff != _inventoryOffset) return; - -#if 0 - // No inventory selected? - if (!_activeInventory) - return; - - // Did we just change the selected inventory item? - if (prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) { - // Setup object2 - _activeObject = 0; - _activeObject2Type = kObjectTypeInventory; - _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; -#endif - - if (_activeVerb == 11 && !(_activeObject || !_activeObject2)) - return; } else { int over = findVerbAtPos(_mouse.x, _mouse.y); int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y); int obj = findObject(_virtualMouse.x, _virtualMouse.y); - 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; - } - - setNewKidVerbs(); - _activeVerb = 7; - - return; - } // Clicked on nothing, walk here? if (!over && !act && _activeVerb == 13 && !obj && _currentMode != 0) { @@ -1154,77 +1229,10 @@ void ScummEngine_v0::checkExecVerbs() { } 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(false); - } - return; - } - - // Only allowing targetting actors if its the GIVE verb - if (_activeVerb == 3) { - if (_activeObject) { - // Once selected the object cannot be changed - obj = 0; - - // Different actor selected? - if (act) { - if (_activeObject2 != act || _activeObject2Type != kObjectTypeActor) { - _activeObject2 = act; - _activeObject2Type = kObjectTypeActor; - return; - } - } else { - return; - } - } else { - // An object has to be selected first - act = 0; - if (!obj) - return; - } - } - - if (obj && obj != _activeObject) { - // USE / UNLOCK - if (_activeVerb == 11 || _activeVerb == 8) { - if (obj != _activeObject && obj != _activeObject2) { - if (!_activeObject) { - _activeObject = obj; - return; - } else { - if (_activeObject2 != obj) { - _activeObject2 = obj; - return; - } - } - } - } else { - a->stopActorMoving(); - - _activeObject = obj; - if (_activeVerb != 13) - return; - - //return; - } - } - } - _verbExecuting = true; } // mouse k/b action +#endif } void ScummEngine::verbMouseOver(int verb) { -- cgit v1.2.3