diff options
Diffstat (limited to 'engines/scumm/verbs.cpp')
-rw-r--r-- | engines/scumm/verbs.cpp | 542 |
1 files changed, 275 insertions, 267 deletions
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, "Dr<cke"}, - {10, 0, 1, 0, "Ziehe"}, - {11, 23, 2, 255, "Benutz"}, - {12, 7, 2, 0, "Lese"}, - {13, 13, 0, 0, "Gehe zu"}, - {14, 7, 1, 0, "Nimm"}, - {15, 13, 2, 0, "Was ist"} + {kVerbOpen, 7, 0, "$ffne"}, + {kVerbClose, 13, 1, "Schlie*e"}, + {kVerbGive, 0, 2, "Gebe"}, + {kVerbTurnOn, 37, 1, "Ein"}, + {kVerbTurnOff, 37, 0, "Aus"}, + {kVerbFix, 23, 1, "Repariere"}, + {kVerbNewKid, 34, 2, "Person"}, + {kVerbUnlock, 23, 0, "Schlie*e auf"}, + {kVerbPush, 0, 0, "Dr<cke"}, + {kVerbPull, 0, 1, "Ziehe"}, + {kVerbUse, 23, 2, "Benutz"}, + {kVerbRead, 7, 2, "Lese"}, + {kVerbWalkTo, 13, 0, "Gehe zu"}, + {kVerbPickUp, 7, 1, "Nimm"}, + {kVerbWhatIs, 13, 2, "Was ist"} }; +int ScummEngine_v0::verbPrepIdType(int verbid) { + switch (verbid) { + case kVerbUse: // depends on object1 + return 0xFF; + case kVerbGive: + return 4; + case kVerbUnlock: case kVerbFix: + return 2; + default: + return 0; + } +} + void ScummEngine_v0::resetVerbs() { VirtScreen *virt = &_virtscr[kVerbVirtScreen]; VerbSlot *vs; @@ -112,7 +143,7 @@ void ScummEngine_v0::resetVerbs() { vs->key = 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) { |