Ticket #9052: v0_mm_verb.patch

File v0_mm_verb.patch, 29.2 KB (added by SF/segra, 15 years ago)
  • engines/scumm/object.cpp

     
    181181                // Alternatively, scan the inventory to see if the object is in there...
    182182                for (i = 0; i < _numInventory; i++) {
    183183                        if (_inventory[i] == obj) {
    184                                 assert(WIO_INVENTORY == whereIsObject(obj));
     184                                if(_game.version == 0)
     185                                        assert(WIO_INVENTORY == whereIsObjectInventory( obj ));
     186                                else
     187                                        assert(WIO_INVENTORY == whereIsObject(obj));
     188
    185189                                // Found the object! Nuke it from the inventory.
    186190                                _res->nukeResource(rtInventory, i);
    187191                                _inventory[i] = 0;
     
    286290                // it. Fortunately this does not prevent frustrated players from
    287291                // blowing up the mansion, should they feel the urge to.
    288292
    289                 if (_game.id == GID_MANIAC && (obj == 182 || obj == 193))
     293                if (_game.id == GID_MANIAC && _game.version != 0 && (obj == 182 || obj == 193))
    290294                        _objectStateTable[obj] |= kObjectState_08;
    291295        }
    292296
     
    317321        return -1;
    318322}
    319323
     324int ScummEngine::whereIsObjectInventory(int object) {
     325        int res = 0;
     326        _v0ObjectInInventory = true;
     327        res = whereIsObject(object);
     328        _v0ObjectInInventory = false;
     329       
     330        return res;
     331}
     332
    320333int ScummEngine::whereIsObject(int object) const {
    321334        int i;
    322335
     
    326339        if (object < 1)
    327340                return WIO_NOT_FOUND;
    328341
    329         if (_objectOwnerTable[object] != OF_OWNER_ROOM) {
     342        if ((_objectOwnerTable[object] != OF_OWNER_ROOM && _game.version != 0) || _v0ObjectInInventory) {
    330343                for (i = 0; i < _numInventory; i++)
    331344                        if (_inventory[i] == object)
    332345                                return WIO_INVENTORY;
     
    334347        }
    335348
    336349        for (i = (_numLocalObjects-1); i > 0; i--)
    337                 if (_objs[i].obj_nr == object) {
     350                if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) {
    338351                        if (_objs[i].fl_object_index)
    339352                                return WIO_FLOBJECT;
    340353                        return WIO_ROOM;
     
    379392 * Returns X, Y and direction in angles
    380393 */
    381394void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
    382         int idx = getObjectIndex(object);
     395        int idx;
     396        if(_v0ObjectIndex)
     397                idx = object;
     398        else
     399                idx = getObjectIndex(object);
    383400        assert(idx >= 0);
    384401        ObjectData &od = _objs[idx];
    385402        int state;
     
    475492        return getDist(x, y, x2, y2);
    476493}
    477494
     495int ScummEngine_v0::findObjectIndex(int x, int y) {
     496        int objIdx;
     497        _v0ObjectIndex = true;
     498        objIdx = findObject(x, y);
     499        _v0ObjectIndex = false;
     500        return objIdx;
     501}
     502
    478503int ScummEngine::findObject(int x, int y) {
    479504        int i, b;
    480505        byte a;
     
    505530#endif
    506531                                if (_objs[i].x_pos <= x && _objs[i].width + _objs[i].x_pos > x &&
    507532                                    _objs[i].y_pos <= y && _objs[i].height + _objs[i].y_pos > y)
    508                                         return _objs[i].obj_nr;
     533                                        if(_game.version == 0 && _v0ObjectIndex)
     534                                                return i;
     535                                        else
     536                                                return _objs[i].obj_nr;
    509537                                break;
    510538                        }
    511539                } while ((_objs[b].state & mask) == a);
     
    811839                if (_dumpScripts) {
    812840                        char buf[32];
    813841                        sprintf(buf, "roomobj-%d-", _roomResource);
     842                        if(_game.version == 0)
     843                                sprintf(buf + 11, "%d-", od->flags);
     844
    814845                        dumpResource(buf, od->obj_nr, room + od->OBCDoffset);
    815846                }
    816847        }
     
    10331064        int i;
    10341065        ObjectData *od = &_objs[1];
    10351066        for (i = 1; i < _numLocalObjects; i++, od++) {
     1067
     1068                // V0 MM, Room objects with Flag==1 are objects with 'no-state' (room specific objects, non-pickup)
     1069                if(_game.version == 0 && od->flags == 1)
     1070                        continue;
     1071
    10361072                if (od->obj_nr > 0)
    10371073                        od->state = getState(od->obj_nr);
    10381074        }
     
    11551191void ScummEngine::setObjectName(int obj) {
    11561192        int i;
    11571193
    1158         if (obj < _numActors)
     1194        if (obj < _numActors && _game.version != 0)
    11591195                error("Can't set actor %d name with new-name-of", obj);
    11601196
    11611197        for (i = 0; i < _numNewNames; i++) {
     
    11811217uint32 ScummEngine::getOBCDOffs(int object) const {
    11821218        int i;
    11831219
    1184         if (_objectOwnerTable[object] != OF_OWNER_ROOM)
     1220        if (_objectOwnerTable[object] != OF_OWNER_ROOM && (_game.version != 0) ||  _v0ObjectInInventory)
    11851221                return 0;
     1222
     1223        // V0 MM Return by Index
     1224        if(_v0ObjectIndex)
     1225                return _objs[object].OBCDoffset;
     1226
    11861227        for (i = (_numLocalObjects-1); i > 0; i--) {
    11871228                if (_objs[i].obj_nr == object) {
    11881229                        if (_objs[i].fl_object_index != 0)
     
    11941235}
    11951236
    11961237byte *ScummEngine::getOBCDFromObject(int obj) {
     1238        bool useInventory = _v0ObjectInInventory;
    11971239        int i;
    11981240        byte *ptr;
    11991241
    1200         if (_objectOwnerTable[obj] != OF_OWNER_ROOM) {
     1242        _v0ObjectInInventory = false;
     1243
     1244        if ((_objectOwnerTable[obj] != OF_OWNER_ROOM && (_game.version != 0)) || useInventory) {
    12011245                for (i = 0; i < _numInventory; i++) {
    12021246                        if (_inventory[i] == obj)
    12031247                                return getResourceAddress(rtInventory, i);
    12041248                }
    12051249        } else {
    12061250                for (i = (_numLocalObjects-1); i > 0; --i) {
    1207                         if (_objs[i].obj_nr == obj) {
     1251                        if ((_objs[i].obj_nr == obj && !_v0ObjectIndex) || (_v0ObjectIndex && i == obj)) {
    12081252                                if (_objs[i].fl_object_index) {
    12091253                                        assert(_objs[i].OBCDoffset == 8);
    12101254                                        ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index);
  • engines/scumm/saveload.cpp

     
    13701370void ScummEngine_v0::saveOrLoad(Serializer *s) {
    13711371        ScummEngine::saveOrLoad(s);
    13721372
    1373         // TODO: Save additional variables
    1374         // _currentMode
    1375         // _currentLights
     1373        const SaveLoadEntry v0Entrys[] = {
     1374                MKLINE( ScummEngine_v0, _currentMode, sleUint32, VER(77) ),
     1375                MKLINE( ScummEngine_v0, _currentLights, sleByte, VER(77) ),
     1376               
     1377                MKEND()
     1378        };
     1379        s->saveLoadEntries(this, v0Entrys);
    13761380}
    13771381
    13781382void ScummEngine_v5::saveOrLoad(Serializer *s) {
  • engines/scumm/script.cpp

     
    133133
    134134        initializeLocals(slot, vars);
    135135
     136        // V0 Ensure we don't try and access objects via index inside the script
     137        _v0ObjectIndex = false;
    136138        runScriptNested(slot);
    137139}
    138140
  • engines/scumm/script_v0.cpp

     
    410410        actorTalk(buffer);
    411411}
    412412
    413 void ScummEngine_v0::drawSentence() {
    414         Common::Rect sentenceline;
     413void ScummEngine_v0::drawSentenceWord( int object, bool usePrep, bool objInInventory) {
    415414        const byte *temp;
    416415        int sentencePrep = 0;
     416       
     417        // If object not in inventory, we except an index
     418        if(!objInInventory)
     419                _v0ObjectIndex = true;
     420        else
     421                _v0ObjectInInventory = true;
    417422
    418         if (!(_userState & 32))
    419                 return;
     423        temp = getObjOrActorName(object);
    420424
    421         if (getResourceAddress(rtVerb, _activeVerb)) {
    422                 strcpy(_sentenceBuf, (char*)getResourceAddress(rtVerb, _activeVerb));
    423         } else {
    424                 return;
     425        _v0ObjectInInventory = false;
     426        _v0ObjectIndex = false;
     427
     428        // Append the 'object-name'
     429        if (temp) {
     430                strcat(_sentenceBuf, " ");
     431                strcat(_sentenceBuf, (const char*)temp);
    425432        }
    426433
    427         if (_activeObject > 0) {
    428                 temp = getObjOrActorName(_activeObject);
    429                 if (temp) {
    430                         strcat(_sentenceBuf, " ");
    431                         strcat(_sentenceBuf, (const char*)temp);
    432                 }
     434        // Append the modifier? (With / On / To / In)
     435        if(!usePrep)
     436                return;
    433437
    434                 if (_verbs[_activeVerb].prep == 0xFF) {
    435                         byte *ptr = getOBCDFromObject(_activeObject);
    436                         assert(ptr);
    437                         sentencePrep = (*(ptr + 11) >> 5);
    438                 } else {
    439                         sentencePrep = _verbs[_activeVerb].prep;
    440                 }
     438        if (_verbs[_activeVerb].prep == 0xFF) {
     439                _v0ObjectInInventory = objInInventory;
     440                sentencePrep = verbPrep(object);
     441        } else {
     442                sentencePrep = _verbs[_activeVerb].prep;
    441443        }
    442444
    443445        if (sentencePrep > 0 && sentencePrep <= 4) {
    444446                // The prepositions, like the fonts, were hard code in the engine. Thus
    445447                // we have to do that, too, and provde localized versions for all the
    446448                // languages MM/Zak are available in.
    447                 const char *prepositions[][5] = {
     449                static const char *prepositions[][5] = {
    448450                        { " ", " in", " with", " on", " to" },   // English
    449451                        { " ", " mit", " mit", " mit", " zu" },  // German
    450452                        { " ", " dans", " avec", " sur", " <" }, // French
     
    471473
    472474                strcat(_sentenceBuf, prepositions[lang][sentencePrep]);
    473475        }
     476}
    474477
    475         if (_activeInventory > 0) {
    476                 temp = getObjOrActorName(_activeInventory);
    477                 if (temp) {
    478                         strcat(_sentenceBuf, " ");
    479                         strcat(_sentenceBuf, (const char*)temp);
     478void ScummEngine_v0::drawSentence() {
     479        Common::Rect sentenceline;
     480        bool             inventoryFirst = false;
     481
     482        if (!(_userState & 32))
     483                return;
     484
     485        // Current Verb, Walk/Use
     486        if (getResourceAddress(rtVerb, _activeVerb)) {
     487                strcpy(_sentenceBuf, (char*)getResourceAddress(rtVerb, _activeVerb));
     488        } else {
     489                return;
     490        }
     491
     492        // If using inventory first, draw it first
     493        if( _activeInvExecute && _activeInventory) {
     494                drawSentenceWord(_activeInventory, true, true);
     495        } else {
     496                // Not using inventory, use selected object
     497                if(_activeObject)
     498                        drawSentenceWord(_activeObjectIndex, true, false);
     499                else
     500                        inventoryFirst = true;
     501        }
     502               
     503
     504        // Draw the inventory?
     505        if (_activeInventory > 0 && _activeObject2 == 0) {
     506               
     507                // Only if inventory isnt first (it will already be drawn by now)
     508                if(!_activeInvExecute) {
     509                        drawSentenceWord(_activeInventory, inventoryFirst, true);
     510                } else {
     511
     512                        // Draw the active object, which could be inventory based, or room based
     513                        if(_activeObject && !_activeObjectIndex) {
     514                                drawSentenceWord(_activeObject, inventoryFirst, true);
     515                        } else // Room based
     516                                drawSentenceWord(_activeObjectIndex, inventoryFirst, false);
    480517                }
     518       
     519        // Draw the 2nd active object
     520        } else if(_activeObject2) {
     521
     522                // 2nd Object is in inventory
     523                if(_activeObject2Inv) {
     524                        _v0ObjectInInventory = true;
     525                        drawSentenceWord(_activeObject2, inventoryFirst, true);
     526                } else
     527                        drawSentenceWord(_activeObject2Index, inventoryFirst, false);
    481528        }
    482529
     530        // Draw the active actor
     531        if( _activeActor ) {
     532                Actor *a = derefActor( _activeActor, "" );
     533               
     534                strcat(_sentenceBuf, " ");
     535                strcat(_sentenceBuf, (const char*)a->getActorName());
     536        }
     537
    483538        _string[2].charset = 1;
    484539        _string[2].ypos = _virtscr[kVerbVirtScreen].topline;
    485540        _string[2].xpos = 0;
     
    664719        int act = getVarOrDirectByte(PARAM_1);
    665720        int anim = getVarOrDirectByte(PARAM_2);
    666721        int unk = fetchScriptByte();
     722
    667723        debug(0,"o_animateActor: unk %d", unk);
    668724
    669725        Actor *a = derefActor(act, "o_animateActor");
     
    713769        if (getObjectIndex(obj) == -1)
    714770                return;
    715771
    716         if (whereIsObject(obj) == WIO_INVENTORY)        /* Don't take an */
     772        if (whereIsObjectInventory( _activeObject2 ) == WIO_INVENTORY)  /* Don't take an */
    717773                return;                                 /* object twice */
    718 
     774       
    719775        addObjectToInventory(obj, _roomResource);
    720776        markObjectRectAsDirty(obj);
    721777        putOwner(obj, VAR(VAR_EGO));
     
    900956        setOwnerOf(obj, owner);
    901957}
    902958
    903 void ScummEngine_v0::resetSentence() {
    904         _activeInventory = 0;
    905         _activeObject = 0;
     959void ScummEngine_v0::resetSentence( bool walking ) {
    906960        _activeVerb = 13;
     961
     962        if(!walking) {
     963                _activeInventory = 0;
     964                _activeObject = 0;
     965                _activeObject2 = 0;
     966                _activeObjectIndex = 0;
     967                _activeObject2Index = 0;
     968        }
     969
     970        _verbExecuting = false;
     971        _verbPickup = false;
     972
     973        _activeActor = 0;
     974        _activeInvExecute = false;
     975        _activeObject2Inv = false;
     976        _activeObjectObtained = false;
     977        _activeObject2Obtained = false;
    907978}
    908979
    909980} // End of namespace Scumm
  • engines/scumm/scumm.cpp

     
    134134
    135135
    136136        // Init all vars
     137        _v0ObjectIndex = false;                 // V0 MM
     138        _v0ObjectInInventory = false;   // V0 MM
    137139        _imuse = NULL;
    138140        _imuseDigital = NULL;
    139141        _musicEngine = NULL;
     
    664666ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
    665667        : ScummEngine_v2(syst, dr) {
    666668
     669        _verbExecuting = false;
     670        _verbPickup = false;
    667671        _currentMode = 0;
     672
     673        _activeObject2 = 0;
     674        _activeObjectIndex = 0;
     675        _activeObject2Index = 0;
     676        _activeInvExecute = false;
     677        _activeObject2Inv = false;
     678        _activeObjectObtained = false;
     679        _activeObject2Obtained = false;
    668680}
    669681
    670682ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)
  • engines/scumm/scumm.h

     
    565565        int32 *_scummVars;
    566566        byte *_bitVars;
    567567
     568        bool _v0ObjectIndex;                    // V0 Use object index, instead of object number
     569        bool _v0ObjectInInventory;              // V0 Use object number from inventory
     570
    568571        /* Global resource tables */
    569572        int _numVariables, _numBitVariables, _numLocalObjects;
    570573        int _numGlobalObjects, _numArray, _numVerbs, _numFlObject;
     
    858861        int getObjNewDir(int obj);
    859862        int getObjectIndex(int object) const;
    860863        int getObjectImageCount(int object);
     864        int whereIsObjectInventory(int object);
    861865        int whereIsObject(int object) const;
    862866        int findObject(int x, int y);
    863867        void findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint object, uint room);
  • engines/scumm/scumm_v0.h

     
    3636class ScummEngine_v0 : public ScummEngine_v2 {
    3737protected:
    3838        int _currentMode;
     39        bool _verbExecuting;                    // is a verb executing
     40        bool _verbPickup;                               // are we picking up an object during a verb execute
    3941
     42        int _activeActor;                               // Actor Number
     43        int _activeObject2;                             // 2nd Object Number
     44
     45        bool _activeInvExecute;                 // is activeInventory first to be executed
     46        bool _activeObject2Inv;                 // is activeobject2 in the inventory
     47        bool _activeObjectObtained;             // collected _activeobject?
     48        bool _activeObject2Obtained;    // collected _activeObject2?
     49
     50        int _activeObjectIndex;
     51        int _activeObject2Index;
     52
    4053public:
    4154        ScummEngine_v0(OSystem *syst, const DetectorResult &dr);
    4255
     
    5366
    5467        virtual void processInput();
    5568
     69        virtual void runObject(int obj, int entry);
    5670        virtual void saveOrLoad(Serializer *s);
    5771
     72        // V0 MM Verb commands
     73        int  verbPrep(int object);
     74        bool verbMove(int object, int objectIndex, bool invObject);
     75        bool verbMoveToActor(int actor);
     76        bool verbObtain(int object, int objIndex);
     77        bool verbExecutes(int object, bool inventory = false);
     78        bool verbExec();
     79
     80        int findObjectIndex(int x, int y);
     81
    5882        virtual void checkExecVerbs();
    5983        virtual void handleMouseOver(bool updateInventory);
    6084        void resetVerbs();
    6185        void setNewKidVerbs();
     86
     87        void drawSentenceWord(int object, bool usePrep, bool objInInventory);
    6288        void drawSentence();
    6389
    6490        void switchActor(int slot);
     
    6894
    6995        virtual int getActiveObject();
    7096
    71         virtual void resetSentence();
     97        virtual void resetSentence(bool walking = false);
    7298
    7399        /* Version C64 script opcodes */
    74100        void o_stopCurrentScript();
  • engines/scumm/scumm_v2.h

     
    100100
    101101        virtual void setBuiltinCursor(int index);
    102102
    103         void runObject(int obj, int entry);
     103        virtual void runObject(int obj, int entry);
    104104
    105105        /* Version 2 script opcodes */
    106106        void o2_actorFromPos();
  • engines/scumm/vars.cpp

     
    538538#endif
    539539
    540540void ScummEngine_v0::resetScummVars() {
    541         _activeInventory = 0;
    542         _activeObject = 0;
    543         _activeVerb = 13;
     541        resetSentence();
    544542
    545543        VAR(VAR_EGO) = 3;
    546544
  • engines/scumm/verbs.cpp

     
    155155        VAR(VAR_EGO) = VAR(97 + slot);
    156156        actorFollowCamera(VAR(VAR_EGO));
    157157        resetVerbs();
     158        resetSentence(false);
    158159        setUserState(247);
    159160}
    160161
     
    376377
    377378        if (object > 0) {
    378379                if (_game.version == 0) {
    379                         if (_activeInventory != object) {
    380380                                _activeInventory = object;
    381                         } else if (_activeVerb != 3 && _activeVerb != 13) {
    382                                 if (_activeObject)
    383                                         runObject(_activeObject, _activeVerb);
    384                                 else
    385                                         runObject(_activeInventory, _activeVerb);
    386                         }
     381
    387382                } else {
    388383                        runInputScript(kInventoryClickArea, object, 0);
    389384                }
     
    425420                _string[1].right = _mouseOverBoxesV2[i].rect.right - 1;
    426421                _string[1].color = _mouseOverBoxesV2[i].color;
    427422
     423                _v0ObjectInInventory = true;
    428424                const byte *tmp = getObjOrActorName(obj);
     425                _v0ObjectInInventory = false;
    429426                assert(tmp);
    430427
    431428                // Prevent inventory entries from overflowing by truncating the text
     
    666663        }
    667664}
    668665
     666void ScummEngine_v0::runObject(int obj, int entry) {
     667        int prev = _v0ObjectInInventory;
     668
     669        if (getVerbEntrypoint(obj, entry) != 0) {
     670                _v0ObjectInInventory = prev;
     671                runObjectScript(obj, entry, false, false, NULL);
     672        } else if (entry != 13 && entry != 15) {
     673                if( _activeVerb != 0x03 ) {
     674                        VAR(9) = entry;
     675                        runScript(3, 0, 0, 0);
     676
     677                        // For some reasons, certain objects don't have a "give" script
     678                } else if(VAR(5) > 0 && VAR(5) < 8)
     679                                if(_activeInventory)
     680                                        setOwnerOf( _activeInventory, VAR(5) );
     681        }
     682}
     683
    669684void ScummEngine_v2::runObject(int obj, int entry) {
    670685        if (getVerbEntrypoint(obj, entry) != 0) {
    671686                runObjectScript(obj, entry, false, false, NULL);
     
    679694        _activeVerb = 13;
    680695}
    681696
     697static int getDist(int x, int y, int x2, int y2) {
     698        int a = ABS(y - y2);
     699        int b = ABS(x - x2);
     700        return MAX(a, b);
     701}
     702
     703bool ScummEngine_v0::verbMoveToActor(int actor) {
     704        Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
     705        Actor *a2 =derefActor(actor, "checkExecVerbs");
     706
     707
     708        if(!a->_moving) {
     709                int dist =  getDist(a->getRealPos().x, a->getRealPos().y, a2->getRealPos().x, a2->getRealPos().y);
     710
     711                if(dist>5)
     712                        a->startWalkActor( a2->getRealPos().x, a2->getRealPos().y, 1 );
     713                else
     714                        return false;
     715
     716                return true;
     717        }
     718
     719        return true;
     720}
     721
     722bool ScummEngine_v0::verbMove(int object, int objectIndex, bool invObject) {
     723        int x, y, dir;
     724        Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
     725
     726        if(_currentMode != 3 && _currentMode != 2)
     727                return false;
     728
     729        if(a->_moving)
     730                return true;
     731
     732        _v0ObjectIndex = true;
     733        getObjectXYPos(objectIndex, x, y, dir);
     734        _v0ObjectIndex = false;
     735        // Detect distance from target object, I wasn't able to use Scumm::getDist, it wouldn't compile
     736        // So i c/p it above
     737        int dist =  getDist(a->getRealPos().x, a->getRealPos().y, x, y);
     738
     739        // FIXME: This should be changed once the walkbox problem is fixed
     740        if(dist>0x5) {
     741                a->startWalkActor(x, y, dir);
     742                VAR(6) = x;
     743                VAR(7) = y;
     744                return true;
     745        } else {
     746
     747                // Finished walk, are we picking up the item?
     748                if(_verbPickup) {
     749                        int oldActive = _activeObject, oldIndex = _activeObjectIndex;
     750                        _activeObject = object;
     751                        _activeObjectIndex = objectIndex;
     752
     753                        _v0ObjectIndex = true;
     754                        // Execute pickup
     755                        runObject(objectIndex, 0x0E );                 
     756                        _v0ObjectIndex = false;
     757
     758                        _activeObject = oldActive;
     759                        _activeObjectIndex = oldIndex;
     760
     761                        // Finished picking up
     762                        _verbPickup = false;
     763                }       
     764        }
     765
     766        return false;
     767}
     768
     769bool ScummEngine_v0::verbObtain(int obj, int objIndex) {
     770        bool didPickup = false;
     771
     772        int prep, where = whereIsObjectInventory( obj );
     773
     774        if(objIndex==0)
     775                return false;
     776
     777        if(where != WIO_INVENTORY) {
     778                _v0ObjectIndex = true;
     779                prep = verbPrep( objIndex );
     780
     781                if(prep == 1 || prep == 4) {
     782                        if(_activeVerb != 13 && _activeVerb != 0x0E) {
     783                                _verbPickup = true;
     784                                didPickup = true;
     785                        }
     786                } else
     787                        _verbPickup = false;
     788
     789                if( verbMove( obj, objIndex, false ) )
     790                        return true;
     791
     792                if(didPickup && (prep == 1 || prep == 4))
     793                        if(_activeVerb != 13 && _activeVerb != 0x0E)
     794                                _activeInventory = obj;
     795        }
     796
     797        return false;
     798}
     799
     800int ScummEngine_v0::verbPrep(int object) {
     801        if(!_v0ObjectInInventory)       
     802                _v0ObjectIndex = true;
     803        else
     804                _v0ObjectIndex = false;
     805        byte *ptr = getOBCDFromObject(object);
     806        _v0ObjectIndex = false;
     807        assert(ptr);
     808        return (*(ptr + 11) >> 5);
     809}
     810
     811bool ScummEngine_v0::verbExecutes( int object, bool inventory ) {
     812        _v0ObjectInInventory = inventory;
     813        int prep = verbPrep( object );
     814
     815        if( prep == 2 || prep == 0) {
     816                return true;
     817        }
     818
     819        return false;
     820}
     821
     822bool ScummEngine_v0::verbExec() {
     823        int     where = 0, prep = 0;
     824        int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15;
     825
     826        if((!_activeInvExecute && _activeObject && getObjectIndex(_activeObject)==-1) ) {
     827                resetSentence();
     828                return false;
     829        }
     830
     831        // Lets try walk to the object
     832        if(_activeObject && _activeObjectIndex && !_activeObjectObtained && _currentMode != 0) {
     833                prep = verbPrep(_activeObjectIndex);
     834               
     835                if( verbObtain( _activeObject, _activeObjectIndex ) )
     836                        return true;
     837
     838                _activeObjectObtained = true;
     839        }
     840
     841        if(_activeObject2 && _activeObject2Index && !_activeObject2Obtained && _currentMode != 0) {
     842                prep = verbPrep(_activeObject2Index);
     843
     844                _v0ObjectInInventory = false;
     845                if(verbObtain(_activeObject2, _activeObject2Index))
     846                        return true;
     847               
     848                if(prep != 1 && prep != 4) {
     849                        _activeInventory = _activeObject;
     850                        _activeObject = _activeObject2;
     851                        _activeObjectIndex = _activeObject2Index;
     852                        _activeObject2 = 0;
     853                        _activeObject2Index = 0;
     854                }
     855
     856                _activeObject2Obtained = true;
     857        }
     858
     859        // Give-To
     860        if(_activeVerb==0x03 && _activeInventory && _activeActor) {
     861                // FIXME: Actors need to turn and face each other
     862                // And walk to each other
     863                //
     864                if( verbMoveToActor(_activeActor) )
     865                        return true;
     866
     867                _v0ObjectInInventory = true;
     868                VAR(5) = _activeActor;
     869                runObject(_activeInventory , 0x03 );
     870                _v0ObjectInInventory = false;
     871
     872                resetSentence();
     873                return false;
     874        }
     875
     876        if(_activeActor) {
     877                _v0ObjectIndex = true;
     878                runObject(_activeActor, entry);
     879                _v0ObjectIndex = false;
     880                _verbExecuting = false;
     881
     882                resetSentence();
     883                return false;
     884        }
     885
     886        // If we've finished walking (now near target), execute the action
     887        if(_activeObject && _activeObjectIndex && verbPrep(_activeObjectIndex) == 2) {
     888
     889                _v0ObjectIndex = true;
     890                runObject(_activeObjectIndex, entry);
     891                _v0ObjectIndex = false;
     892                _verbExecuting = false;
     893
     894                if((_currentMode == 3 || _currentMode == 2) && _activeVerb==13)
     895                        return false;
     896
     897                resetSentence();
     898                return false;
     899        }
     900
     901        // We acted on an inventory item
     902        if( _activeInventory && verbExecutes(_activeInventory, true) && _activeVerb != 0x03 ) {
     903               
     904                _v0ObjectInInventory = true;
     905                runObject(_activeInventory, _activeVerb);
     906               
     907                _verbExecuting = false;
     908
     909                if(_currentMode == 3 && _activeVerb==13) {
     910                        resetSentence(true);
     911                        return false;
     912                }
     913               
     914                resetSentence();
     915                return false;
     916        }
     917
     918        if(_activeObject) {
     919                _v0ObjectIndex = true;
     920                runObject(_activeObjectIndex, entry);
     921                _v0ObjectIndex = false;
     922        } else if(_activeInventory ) {
     923
     924                if(verbExecutes(_activeInventory, true) == false) {
     925                       
     926                        if(_activeObject2 && verbExecutes(_activeObject2, true)) {
     927                                _v0ObjectInInventory = true;
     928                               
     929                                _activeObject = _activeInventory;
     930                                _activeInventory = _activeObject2;
     931                               
     932                                runObject(_activeObject, _activeVerb);
     933                        } else {
     934                                _v0ObjectInInventory = true;
     935                                runObject(_activeInventory, _activeVerb);
     936                        }
     937                } else {
     938                        runObject(_activeInventory, _activeVerb);
     939                        _v0ObjectInInventory = true;
     940                }
     941        }
     942
     943        _verbExecuting = false;
     944
     945        if(_activeVerb==0xD) {
     946                resetSentence(true);
     947                return false;
     948        }
     949
     950        resetSentence();
     951
     952        return false;
     953}
     954
    682955void ScummEngine_v0::checkExecVerbs() {
    683956        Actor *a;
    684957        VirtScreen *zone = findVirtScreen(_mouse.y);
    685958
     959        // Is a verb currently executing
     960        if( _verbExecuting ) {
     961
     962                // Check if mouse click
     963                if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
     964                        int over = findVerbAtPos(_mouse.x, _mouse.y);
     965                        int act  = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
     966                        int obj  = findObject(_virtualMouse.x, _virtualMouse.y);
     967                       
     968                        if(over && over != _activeVerb) {
     969                                _activeVerb = over;
     970                                _verbExecuting = false;
     971                                return;
     972                        }
     973
     974                        if(!obj && !act && !over) {
     975                                resetSentence( false );
     976                        } else {
     977                                a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
     978                                a->stopActorMoving();
     979                        }
     980                } else {
     981                        if(_verbExecuting)
     982                                if(!verbExec())
     983                                        return;
     984                }
     985        }
     986
     987        // What-Is selected, any object we hover over is selected, on mouse press we set to WalkTo
     988        if(_activeVerb == 0x0F) {
     989                int obj = findObject(_virtualMouse.x, _virtualMouse.y);
     990                int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
     991                _activeObject = obj;
     992                _activeObjectIndex = objIdx;
     993
     994                if((_mouseAndKeyboardStat & MBS_MOUSE_MASK))
     995                        _activeVerb = 13;       // Walk-To
     996
     997                return;
     998        }
     999
    6861000        if (_userPut <= 0 || _mouseAndKeyboardStat == 0)
    6871001                return;
    6881002
     
    6931007                if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
    6941008                        // TODO
    6951009                } else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
     1010                        int prevInventory = _activeInventory;
     1011
    6961012                        // Click into V2 inventory
    6971013                        checkV2Inventory(_mouse.x, _mouse.y);
     1014                        if(!_activeInventory)
     1015                                return;
     1016                       
     1017                        // Did we just change the selected inventory item?
     1018                        if(prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) {
     1019                                _activeObject = 0;
     1020                                _activeInvExecute = true;
     1021                                _activeObject2Inv = true;
     1022                                _activeObject2 = _activeInventory;
     1023                                _activeInventory = prevInventory;
     1024                                return;
     1025                        }
     1026
     1027                        // is the new selected inventory the same as the last selected?, reset to previous if it is
     1028                        if(_activeInventory == _activeObject2)
     1029                                _activeInventory = prevInventory;
     1030
     1031                        // Inventory Selected changed
     1032                        if(prevInventory != _activeInventory)
     1033                                if(!_activeObject2 || prevInventory != _activeObject2 )
     1034                                        return;
     1035
     1036                        if(_activeVerb == 0x0B && !((!(_activeObject || _activeInventory)) || !_activeObject2))
     1037                                return;
     1038
    6981039                } else {
    6991040                        int over = findVerbAtPos(_mouse.x, _mouse.y);
     1041                        int act  = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
     1042                        int obj  = findObject(_virtualMouse.x, _virtualMouse.y);
     1043                        int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
    7001044
     1045                        if((_activeObject || _activeInventory) && act) {
     1046                                obj = 0;
     1047                                objIdx = 0;
     1048                        }
     1049
    7011050                        // Handle New Kid verb options
    702                         if (_activeVerb == 7) {
     1051                        if (_activeVerb == 7 || over == 7) {
     1052
     1053                                // Disable New-Kid (in the secret lab)
     1054                                if( _currentMode == 2 || _currentMode == 0)
     1055                                        return;
     1056
     1057                                if(_activeVerb != 7) {
     1058                                        _activeVerb = over;
     1059                                        over = 0;
     1060                                }
     1061
    7031062                                if (over) {
    7041063                                        _activeVerb = 13;
    7051064                                        switchActor(_verbs[over].verbid - 1);
     1065                                        return;
    7061066                                }
     1067
     1068                                setNewKidVerbs();
     1069
    7071070                                return;
    7081071                        }
     1072                       
     1073                        // Clicked on nothing, walk here?
     1074                        if(!over && !act && _activeVerb==13 && !obj && _currentMode != 0 ) {
    7091075
    710                         if (over) {
    711                                 _activeVerb = _verbs[over].verbid;
    712                                 // Selected New Kid verb
    713                                 if (_activeVerb == 7)
    714                                         setNewKidVerbs();
     1076                                // Clear all selected
     1077                                resetSentence();
    7151078
     1079                                // 0xB31
     1080                                VAR(6) = _virtualMouse.x / V12_X_MULTIPLIER;
     1081                                VAR(7) = _virtualMouse.y / V12_Y_MULTIPLIER;
     1082
     1083                                if (zone->number == kMainVirtScreen) {
     1084                                        a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
     1085                                        a->stopActorMoving();
     1086                                        a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
     1087                                }
    7161088                                return;
    7171089                        }
    7181090
    719                         int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
    720                         int obj = findObject(_virtualMouse.x, _virtualMouse.y);
    721                         if (act != 0 && _activeVerb == 3 && _activeInventory != 0) {
    722                                 // Give inventory item to actor
    723                                 VAR(5) = act;
    724                                 runObject(_activeInventory, _activeVerb);
    725                         } else if (obj) {
    726                                 if (_currentMode == 3 && _activeVerb != 13 && obj != _activeObject) {
    727                                         _activeObject = obj;
    728                                         return;
     1091                        // No new verb, use previous
     1092                        if(over==0)
     1093                                over = _activeVerb;
     1094
     1095                        // No verb selected, use walk-to
     1096                        if(!_activeVerb)
     1097                                _activeVerb = over = 13;                // Walk-To
     1098
     1099                        // New verb selected
     1100                        if(_activeVerb != over) {
     1101                                _activeVerb = over;
     1102                                if(_activeVerb==0x0D) {
     1103                                        resetSentence();
    7291104                                }
     1105                                return;
     1106                        }
    7301107
    731                                 _activeObject = obj;
    732                                 if (_currentMode == 3) {
    733                                         int x, y, dir;
    734                                         a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
    735                                         getObjectXYPos(obj, x, y, dir);
    736                                         a->startWalkActor(x, y, dir);
     1108                        // Only allowing targetting actors if its the GIVE/USE verb
     1109                        if(_activeVerb == 0x03 || _activeVerb == 0x0B) {
     1110                                // Different actor selected?
     1111                                if(act) {
     1112                                        if( _activeActor != act ) {
     1113                                                _activeActor = act;
     1114                                                return;
     1115                                        }
    7371116                                }
     1117                        }
    7381118
    739                                 int entry = (_currentMode == 3) ? _activeVerb : 15;
    740                                 runObject(_activeObject, entry);
    741                         } else if (zone->number == kMainVirtScreen) {
    742                                 a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
    743                                 a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
     1119                        if(obj && obj != _activeObject) {
     1120                                if(!_activeObject)
     1121                                        if(_activeInventory)
     1122                                                _activeInvExecute = true;
     1123
     1124                                // USE
     1125                                if(_activeVerb == 0x0b || _activeVerb == 0x08) {
     1126                                        if(obj != _activeObject || obj != _activeObject2 ) {
     1127                                                if(!_activeObject || _activeInventory) {
     1128                                                        _activeObject = obj;
     1129                                                        _activeObjectIndex = objIdx;
     1130                                                        return;
     1131                                                } else
     1132                                                        if(_activeObject2 != obj) {
     1133                                                                _activeObject2 = obj;
     1134                                                                _activeObject2Index = objIdx;
     1135                                                                return;
     1136                                                        }
     1137                                        }
     1138                                } else {
     1139                               
     1140                                        _activeObject = obj;
     1141                                        _activeObjectIndex = objIdx;
     1142                                               
     1143                                        if(_activeVerb!=13)
     1144                                                return;
     1145                                       
     1146                                        //return;
     1147                                }
    7441148                        }
     1149                }
    7451150
    746                         _activeInventory = 0;
    747                         _activeObject = 0;
    748                         _activeVerb = 13;
    749                 }
    750         }
     1151                _verbExecuting = true;
     1152
     1153        }       // mouse k/b action
     1154
    7511155}
    7521156
    7531157void ScummEngine::verbMouseOver(int verb) {