/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/scummsys.h" #include "mads/mads.h" #include "mads/action.h" #include "mads/inventory.h" #include "mads/scene.h" #include "mads/staticres.h" namespace MADS { MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) { clear(); _currentAction = VERB_NONE; _startWalkFlag = false; _statusTextIndex = -1; _selectedAction = 0; _inProgress = false; _savedSelectedRow = false; } void MADSAction::clear() { _v83338 = 1; _actionMode = ACTIONMODE_NONE; _actionMode2 = ACTIONMODE2_0; _v86F42 = 0; _v86F4E = 0; _articleNumber = 0; _lookFlag = false; _v86F4A = 0; _selectedRow = -1; _hotspotId = -1; _v86F3A = -1; _v86F4C = -1; _action._verbId = -1; _action._objectNameId = -1; _action._indirectObjectId = -1; _textChanged = true; _walkFlag = false; } void MADSAction::appendVocab(int vocabId, bool capitalise) { Common::String vocabStr = _vm->_game->_scene.getVocab(vocabId); if (capitalise) vocabStr.setChar(toupper(vocabStr[0]), 0); _statusText += vocabStr; _statusText += " "; } void MADSAction::set() { Scene &scene = _vm->_game->_scene; UserInterface &userInterface = scene._userInterface; bool flag = false; _statusText = ""; _action._verbId = -1; _action._objectNameId = -1; _action._indirectObjectId = -1; if (_actionMode == ACTIONMODE_TALK) { // Handle showing the conversation selection. Rex at least doesn't actually seem to use this if (_selectedRow >= 0) { Common::String desc = userInterface._talkStrings[userInterface._talkIds[_selectedRow]]; if (!desc.empty()) _statusText = desc; } } else if (_lookFlag && (_selectedRow == 0)) { // Two 'look' actions in succession, so the action becomes 'Look around' _statusText = kLookAroundStr; } else { if ((_actionMode == ACTIONMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) { // Use/to action int invIndex = userInterface._selectedInvIndex; InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); _action._objectNameId = objEntry._descId; _action._verbId = objEntry._vocabList[_selectedRow]._vocabId; // Set up the status text stirng _statusText = kUseStr; appendVocab(_action._objectNameId); _statusText += kToStr; appendVocab(_action._verbId); } else { // Handling for if an action has been selected if (_selectedRow >= 0) { if (_actionMode == ACTIONMODE_VERB) { // Standard verb action _currentAction = scene._verbList[_selectedRow]._id; } else { // Selected action on an inventory object int invIndex = userInterface._selectedInvIndex; InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); _currentAction = objEntry._vocabList[_selectedRow]._vocabId; } appendVocab(_action._verbId, true); if (_currentAction == VERB_LOOK) { // Add in the word 'add' _statusText += kAtStr; _statusText += " "; } } // Handling for if a hotspot has been selected/highlighted if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) { flag = true; _statusText += kArticleList[_articleNumber]; _statusText += " "; } if (_hotspotId >= 0) { if (_selectedRow < 0) { int verbId; if (_hotspotId < (int)scene._hotspots.size()) { // Get the verb Id from the hotspot verbId = scene._hotspots[_hotspotId]._verbId; } else { // Get the verb Id from the scene object verbId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._vocabId; } if (verbId > 0) { // Set the specified action _currentAction = verbId; appendVocab(_currentAction, true); } else { // Default to a standard 'walk to' _currentAction = VERB_WALKTO; _statusText += kWalkToStr; } } if ((_actionMode2 == ACTIONMODE2_2) || (_actionMode2 == ACTIONMODE2_5)) { // Get name from given inventory object InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); _action._objectNameId = invObject._descId; } else if (_hotspotId < (int)scene._hotspots.size()) { // Get name from scene hotspot _action._objectNameId = scene._hotspots[_hotspotId]._vocabId; } else { // Get name from temporary scene hotspot _action._objectNameId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._vocabId; } appendVocab(_action._objectNameId); } } if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) { if (_articleNumber == -1) { if (_v86F3A >= 0) { int articleNum = 0; if ((_v86F42 == 2) || (_v86F42 == 5)) { InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); articleNum = invObject._article; } else if (_v86F3A < (int)scene._hotspots.size()) { articleNum = scene._hotspots[_hotspotId]._articleNumber; } else { articleNum = scene._hotspots[_hotspotId - scene._hotspots.size()]._articleNumber; } _statusText += kArticleList[articleNum]; _statusText += " "; } } else if ((_articleNumber == VERB_LOOK) || (_vm->getGameID() != GType_RexNebular) || (scene._vocabStrings[_action._indirectObjectId] != kFenceStr)) { // Write out the article _statusText += kArticleList[_articleNumber]; } else { // Special case for a 'fence' entry in Rex Nebular _statusText += kOverStr; } _statusText += " "; } // Append object description if necessary if (_v86F3A >= 0) appendVocab(_action._indirectObjectId); // Remove any trailing space character if (_statusText.hasSuffix(" ")) _statusText.deleteLastChar(); } _textChanged = true; } void MADSAction::refresh() { Scene &scene = _vm->_game->_scene; // Exit immediately if nothing has changed if (!_textChanged) return; // Remove any old copy of the status text if (_statusTextIndex >= 0) { scene._textDisplay.expire(_statusTextIndex); _statusTextIndex = -1; } if (!_statusText.empty()) { if ((_vm->_game->_screenObjects._v832EC == 0) || (_vm->_game->_screenObjects._v832EC == 2)) { Font *font = _vm->_font->getFont(FONT_MAIN); int textSpacing = -1; int strWidth = font->getWidth(_statusText); if (strWidth > MADS_SCREEN_WIDTH) { // Too large to fit, so fall back on interface font font = _vm->_font->getFont(FONT_INTERFACE); strWidth = font->getWidth(_statusText, 0); textSpacing = 0; } // Add a new text display entry to display the status text at the bottom of the screen area _statusTextIndex = scene._textDisplay.add(160 - (strWidth / 2), MADS_SCENE_HEIGHT + scene._posAdjust.y - 13, 3, textSpacing, _statusText, font); } } _textChanged = false; } void MADSAction::startAction() { /* _madsVm->_player.moveComplete(); _inProgress = true; _v8453A = ABORTMODE_0; _savedFields.selectedRow = _selectedRow; _savedFields.articleNumber = _articleNumber; _savedFields.actionMode = _actionMode; _savedFields.actionMode2 = _actionMode2; _savedFields.lookFlag = _lookFlag; int savedHotspotId = _hotspotId; int savedV86F3A = _v86F3A; int savedV86F42 = _v86F42; // Copy the action to be active _activeAction = _action; strcpy(_dialogTitle, _statusText); if ((_savedFields.actionMode2 == ACTMODE2_4) && (savedV86F42 == 0)) _v8453A = ABORTMODE_1; _startWalkFlag = false; int hotspotId = -1; HotSpotList &dynHotspots = *_madsVm->scene()->getSceneResources().dynamicHotspots; HotSpotList &hotspots = *_madsVm->scene()->getSceneResources().hotspots; if (!_savedFields.lookFlag && (_madsVm->scene()->_screenObjects._v832EC != 1)) { if (_savedFields.actionMode2 == ACTMODE2_4) hotspotId = savedHotspotId; else if (savedV86F42 == 4) hotspotId = savedV86F3A; if (hotspotId >= hotspots.size()) { HotSpot &hs = dynHotspots[hotspotId - hotspots.size()]; if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) { if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) { _startWalkFlag = true; _madsVm->scene()->_destPos = _madsVm->scene()->_customDest; } } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) { _startWalkFlag = true; _madsVm->scene()->_destPos.x = hs.getFeetX(); _madsVm->scene()->_destPos.y = hs.getFeetY(); } _madsVm->scene()->_destFacing = hs.getFacing(); hotspotId = -1; } } if (hotspotId >= 0) { HotSpot &hs = hotspots[hotspotId]; if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) { if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) { _startWalkFlag = true; _madsVm->scene()->_destPos = _madsVm->scene()->_customDest; } } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) { _startWalkFlag = true; _madsVm->scene()->_destPos.x = hs.getFeetX(); _madsVm->scene()->_destPos.y = hs.getFeetY(); } _madsVm->scene()->_destFacing = hs.getFacing(); } _walkFlag = _startWalkFlag; */ } void MADSAction::checkAction() { /* if (isAction(kVerbLookAt) || isAction(kVerbThrow)) _startWalkFlag = 0; */ } bool MADSAction::isAction(int verbId, int objectNameId, int indirectObjectId) { /* if (_activeAction.verbId != verbId) return false; if ((objectNameId != 0) && (_activeAction.objectNameId != objectNameId)) return false; if ((indirectObjectId != 0) && (_activeAction.indirectObjectId != indirectObjectId)) return false; */ return true; } void MADSAction::checkActionAtMousePos() { Scene &scene = _vm->_game->_scene; UserInterface &userInterface = scene._userInterface; ScreenObjects &screenObjects = _vm->_game->_screenObjects; if ((userInterface._category == CAT_ACTION || userInterface._category == CAT_INV_VOCAB) && _v83338 != 1 && scene._highlightedHotspot >= 0) { if (_v86F4E == userInterface._category || _v86F4C != scene._highlightedHotspot || (_v83338 != 2 && _v83338 != 3)) clear(); else if (_selectedRow != 0 || userInterface._category != CAT_ACTION) scene._lookFlag = false; else scene._lookFlag = true; } if (screenObjects._v7FECA && _vm->_events->_mouseButtons) { switch (userInterface._category) { case CAT_ACTION: case CAT_INV_VOCAB: return; case CAT_INV_LIST: case CAT_TALK_ENTRY: if (_v83338 != 3) { if (userInterface._selectedActionIndex >= 0) { _actionMode = ACTIONMODE_VERB; _selectedRow = userInterface._selectedActionIndex; _flags1 = scene._verbList[_selectedRow]._action1; _flags2 = scene._verbList[_selectedRow]._action2; _v83338 = 2; } else if (userInterface._selectedItemVocabIdx >= 0) { _actionMode = ACTIONMODE_OBJECT; _selectedRow = userInterface._selectedItemVocabIdx; int objectId = _vm->_game->_objects._inventoryList[_selectedRow]; InventoryObject &invObject = _vm->_game->_objects[objectId]; _flags1 = invObject._vocabList[_selectedRow - 1]._actionFlags1; _flags2 = invObject._vocabList[_selectedRow - 1]._actionFlags2; _actionMode2 = ACTIONMODE2_2; _hotspotId = userInterface._selectedInvIndex; _articleNumber = _flags2; if ((_flags1 == 1 && _flags2 == 0) || (_flags1 == 2 && _flags2 != 0)) _v83338 = 4; else _v83338 = 3; } } break; } } switch (_v83338) { case 1: _articleNumber = 0; switch (userInterface._category) { case CAT_ACTION: _actionMode = ACTIONMODE_VERB; _selectedRow = scene._highlightedHotspot; if (_selectedRow >= 0) { _flags1 = scene._verbList[_selectedRow]._action1; _flags2 = scene._verbList[_selectedRow]._action2; } break; case CAT_INV_VOCAB: _actionMode = ACTIONMODE_OBJECT; _selectedRow = scene._highlightedHotspot; if (_selectedRow < 0) { _hotspotId = -1; _actionMode2 = ACTIONMODE2_0; } else { int objectId = _vm->_game->_objects._inventoryList[_selectedRow]; InventoryObject &invObject = _vm->_game->_objects[objectId]; _flags1 = invObject._vocabList[_selectedRow - 2]._actionFlags1; _flags2 = invObject._vocabList[_selectedRow - 2]._actionFlags2; _hotspotId = userInterface._selectedInvIndex; _actionMode2 = ACTIONMODE2_2; if (_flags1 == 2) _articleNumber = _flags2; } break; case CAT_HOTSPOT: _selectedRow = -1; _actionMode = ACTIONMODE_NONE; _actionMode2 = ACTIONMODE2_4; _hotspotId = scene._highlightedHotspot; break; case CAT_TALK_ENTRY: _actionMode = ACTIONMODE_TALK; _selectedRow = scene._highlightedHotspot; break; default: break; } break; case 2: _articleNumber = 0; switch (userInterface._category) { case CAT_INV_LIST: case CAT_HOTSPOT: case CAT_INV_ANIM: // TODO: We may not need a separate ActionMode2 enum _actionMode2 = (ActionMode2)userInterface._category; _hotspotId = scene._highlightedHotspot; break; default: break; } break; case 3: switch (userInterface._category) { case CAT_INV_LIST: case CAT_HOTSPOT: case CAT_INV_ANIM: _v86F42 = userInterface._category; _v86F3A = scene._highlightedHotspot; break; default: break; } break; default: break; } } void MADSAction::leftClick() { Scene &scene = _vm->_game->_scene; UserInterface &userInterface = scene._userInterface; ScreenObjects &screenObjects = _vm->_game->_screenObjects; bool abortFlag = false; if ((userInterface._category == CAT_ACTION || userInterface._category == CAT_INV_VOCAB) && _v83338 != 1 && scene._highlightedHotspot >= 0 && _v86F4E == userInterface._category && _v86F4C == scene._highlightedHotspot && (_v83338 == 2 || userInterface._category == CAT_INV_VOCAB)) { abortFlag = true; if (_selectedRow == 0 && userInterface._category == CAT_ACTION) { _selectedAction = CAT_ACTION; scene._lookFlag = true; } else { _selectedAction = CAT_NONE; scene._lookFlag = false; clear(); } } if (abortFlag || (screenObjects._v7FECA && (userInterface._category == CAT_ACTION || userInterface._category == CAT_INV_VOCAB))) return; switch (_v83338) { case 1: switch (userInterface._category) { case CAT_ACTION: if (_selectedRow >= 0) { if (!_flags1) { _selectedAction = -1; } else { _v86F4C = _selectedRow; _v86F4E = _actionMode; _v83338 = 2; } } break; case CAT_INV_LIST: if (scene._highlightedHotspot >= 0) { userInterface.selectObject(scene._highlightedHotspot); } break; case CAT_INV_VOCAB: if (_selectedRow >= 0) { if (_flags1 != 1 || _flags2 != 0) { if (_flags1 != 2 || _flags2 == 0) { _v83338 = 3; _articleNumber = _flags2; } else { _articleNumber = _flags2; _selectedAction = -1; } } else { _selectedAction = -1; } _v86F4C = _selectedRow; _v86F4E = _actionMode; } break; case CAT_HOTSPOT: _v86F4C = -1; _v86F4E = 0; if (_vm->_events->currentPos().y < MADS_SCENE_HEIGHT) scene._customDest = _vm->_events->currentPos() + scene._posAdjust; break; case CAT_TALK_ENTRY: if (_selectedRow >= 0) _selectedAction = -1; break; default: break; } break; case 2: switch (userInterface._category) { case CAT_INV_LIST: case CAT_HOTSPOT: case CAT_INV_ANIM: if (_hotspotId >= 0) { if (_flags2) { _articleNumber = _flags2; _v83338 = 3; } else { _selectedAction = -1; } if (userInterface._category == CAT_HOTSPOT) { scene._customDest = _vm->_events->mousePos() + scene._posAdjust; _v86F4A = true; } } break; default: break; } break; case 3: switch (userInterface._category) { case CAT_INV_LIST: case CAT_HOTSPOT: case CAT_INV_ANIM: if (_v86F3A >= 0) { _selectedAction = -1; if (userInterface._category == CAT_HOTSPOT) { if (!_v86F4A) { scene._customDest = _vm->_events->mousePos() + scene._posAdjust; _v86F4A = true; } } } break; default: break; } break; } } } // End of namespace MADS