/* 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 "sherlock/user_interface.h" #include "sherlock/scalpel/scalpel.h" #include "sherlock/scalpel/scalpel_user_interface.h" #include "sherlock/tattoo/tattoo.h" #include "sherlock/tattoo/tattoo_user_interface.h" namespace Sherlock { UserInterface *UserInterface::init(SherlockEngine *vm) { if (vm->getGameID() == GType_SerratedScalpel) return new Scalpel::ScalpelUserInterface(vm); else return new Tattoo::TattooUserInterface(vm); } UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _menuMode = STD_MODE; _menuCounter = 0; _infoFlag = false; _windowOpen = false; _endKeyActive = true; _invLookFlag = 0; _slideWindows = true; _helpStyle = false; _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1); _lookScriptFlag = false; _exitZone = -1; _bgFound = _oldBgFound = -1; _key = _oldKey = '\0'; _selector = _oldSelector = -1; _temp = _oldTemp = 0; _temp1 = 0; _lookHelp = 0; } void UserInterface::checkAction(ActionType &action, int objNum, FixedTextActionId fixedTextActionId) { Events &events = *_vm->_events; FixedText &fixedText = *_vm->_fixedText; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; Point32 pt(-1, -1); if (action._useFlag) // Automatically set the given flag _vm->setFlags(action._useFlag); if (IS_SERRATED_SCALPEL && objNum >= 1000) // Ignore actions done on characters return; if (IS_SERRATED_SCALPEL && !action._cAnimSpeed) { // Invalid action, to print error message _infoFlag = true; clearInfo(); Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, action._cAnimNum); screen.print(Common::Point(0, INFO_LINE + 1), COL_INFO_FOREGROUND, "%s", errorMessage.c_str()); _infoFlag = true; // Set how long to show the message _menuCounter = 30; } else { BaseObject *obj; if (objNum >= 1000) obj = &people[objNum - 1000]; else obj = &scene._bgShapes[objNum]; int cAnimNum; if (action._cAnimNum == 0) // Really a 10 cAnimNum = 9; else cAnimNum = action._cAnimNum - 1; int dir = -1; if (action._cAnimNum != 99) { CAnim &anim = scene._cAnim[cAnimNum]; if (action._cAnimNum != 99) { if (action._cAnimSpeed & REVERSE_DIRECTION) { pt = anim._teleport[0]; dir = anim._teleport[0]._facing; } else { pt = anim._goto[0]; dir = anim._goto[0]._facing; } } } else { pt = Point32(-1, -1); dir = -1; } // Has a value, so do action // Show wait cursor whilst walking to object and doing action events.setCursor(WAIT); bool printed = false; for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) { if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2 && toupper(action._names[nameIdx][1]) == 'W') { if (obj->checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), fixedTextActionId)) { if (!talk._talkToAbort) printed = true; } } } bool doCAnim = true; for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) { if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2) { char ch = toupper(action._names[nameIdx][1]); if (ch == 'T' || ch == 'B') { printed = true; if (pt.x != -1) // Holmes needs to walk to object before the action is done people[HOLMES].walkToCoords(pt, dir); if (!talk._talkToAbort) { // Ensure Holmes is on the exact intended location people[HOLMES]._position = pt; people[HOLMES]._sequenceNumber = dir; people[HOLMES].gotoStand(); talk.talkTo(action._names[nameIdx].c_str() + 2); if (ch == 'T') doCAnim = false; } } } } if (doCAnim && !talk._talkToAbort) { if (pt.x != -1) // Holmes needs to walk to object before the action is done people[HOLMES].walkToCoords(pt, dir); } for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) { if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2 && toupper(action._names[nameIdx][1]) == 'F') { if (obj->checkNameForCodes(action._names[nameIdx].c_str() + 2, fixedTextActionId)) { if (!talk._talkToAbort) printed = true; } } } if (doCAnim && !talk._talkToAbort && action._cAnimNum != 99) scene.startCAnim(cAnimNum, action._cAnimSpeed); if (!talk._talkToAbort) { for (int nameIdx = 0; nameIdx < NAMES_COUNT && !talk._talkToAbort; ++nameIdx) { if (obj->checkNameForCodes(action._names[nameIdx], fixedTextActionId)) { if (!talk._talkToAbort) printed = true; } } // Unless we're leaving the scene, print a "Done" message unless the printed flag has been set if (IS_SERRATED_SCALPEL && scene._goToScene != 1 && !printed && !talk._talkToAbort) { _infoFlag = true; clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), COL_INFO_FOREGROUND, "Done..."); // Set how long to show the message _menuCounter = 30; } } } // Reset cursor back to arrow events.setCursor(ARROW); } void UserInterface::reset() { _bgFound = _oldBgFound = -1; _oldKey = -1; _oldTemp = _temp = -1; _exitZone = -1; } } // End of namespace Sherlock