diff options
Diffstat (limited to 'engines/titanic/pet_control')
66 files changed, 12205 insertions, 0 deletions
diff --git a/engines/titanic/pet_control/pet_control.cpp b/engines/titanic/pet_control/pet_control.cpp new file mode 100644 index 0000000000..b32a7907a4 --- /dev/null +++ b/engines/titanic/pet_control/pet_control.cpp @@ -0,0 +1,680 @@ +/* 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 "titanic/pet_control/pet_control.h" +#include "titanic/carry/carry.h" +#include "titanic/core/project_item.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/game_manager.h" +#include "titanic/game_state.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPetControl, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(MouseDoubleClickMsg) + ON_MESSAGE(KeyCharMsg) + ON_MESSAGE(VirtualKeyCharMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CPetControl::CPetControl() : CGameObject(), + _currentArea(PET_CONVERSATION), _inputLockCount(0), _areaLockCount(0), + _areaChangeType(-1), _activeNPC(nullptr), _remoteTarget(nullptr), + _hiddenRoom(nullptr), _drawBounds(20, 350, 620, 480) { + _sections[PET_INVENTORY] = &_inventory; + _sections[PET_CONVERSATION] = &_conversations; + _sections[PET_REMOTE] = &_remote; + _sections[PET_ROOMS] = &_rooms; + _sections[PET_REAL_LIFE] = &_realLife; + _sections[PET_STARFIELD] = &_starfield; + _sections[PET_MESSAGE] = &_message; +} + +void CPetControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeNumberLine(_currentArea, indent); + file->writeQuotedLine(_activeNPCName, indent); + file->writeQuotedLine(_remoteTargetName, indent); + + saveAreas(file, indent); + CGameObject::save(file, indent); +} + +void CPetControl::load(SimpleFile *file) { + int val = file->readNumber(); + isValid(); + + if (!val) { + _currentArea = (PetArea)file->readNumber(); + _activeNPCName = file->readString(); + _remoteTargetName = file->readString(); + + loadAreas(file, 0); + } + + CGameObject::load(file); +} + +void CPetControl::setup() { + _conversations.setup(this); + _rooms.setup(this); + _remote.setup(this); + _inventory.setup(this); + _starfield.setup(this); + _realLife.setup(this); + _message.setup(this); + _frame.setup(this); +} + +bool CPetControl::isValid() { + return _conversations.isValid(this) && + _rooms.isValid(this) && + _remote.isValid(this) && + _inventory.isValid(this) && + _starfield.isValid(this) && + _realLife.isValid(this) && + _message.isValid(this) && + _frame.isValid(this); +} + +void CPetControl::loadAreas(SimpleFile *file, int param) { + _conversations.load(file, param); + _rooms.load(file, param); + _remote.load(file, param); + _inventory.load(file, param); + _starfield.load(file, param); + _realLife.load(file, param); + _message.load(file, param); + _frame.load(file, param); +} + +void CPetControl::saveAreas(SimpleFile *file, int indent) { + _conversations.save(file, indent); + _rooms.save(file, indent); + _remote.save(file, indent); + _inventory.save(file, indent); + _starfield.save(file, indent); + _realLife.save(file, indent); + _message.save(file, indent); + _frame.save(file, indent); +} + +void CPetControl::draw(CScreenManager *screenManager) { + CGameManager *gameManager = getGameManager(); + Rect bounds = _drawBounds; + bounds.constrain(gameManager->_bounds); + + if (!bounds.isEmpty()) { + if (_areaChangeType >= 0) { + _inventory.changed(_areaChangeType); + _areaChangeType = -1; + } + + _frame.drawFrame(screenManager); + + // Draw the specific area that's currently active + _sections[_currentArea]->draw(screenManager); + } +} + +Rect CPetControl::getBounds() const { + return _sections[_currentArea]->getBounds(); +} + +void CPetControl::postLoad() { + CProjectItem *root = getRoot(); + + if (!_activeNPCName.empty() && root) + _activeNPC = root->findByName(_activeNPCName); + if (!_remoteTargetName.empty() && root) + _remoteTarget = static_cast<CGameObject *>(root->findByName(_remoteTargetName)); + + setArea(_currentArea); + loaded(); +} + +void CPetControl::loaded() { + _conversations.postLoad(); + _rooms.postLoad(); + _remote.postLoad(); + _inventory.postLoad(); + _starfield.postLoad(); + _realLife.postLoad(); + _message.postLoad(); + _frame.postLoad(); +} + +void CPetControl::enterNode(CNodeItem *node) { + getGameManager()->_gameState.enterNode(); +} + +void CPetControl::enterRoom(CRoomItem *room) { + _rooms.enterRoom(room); + _remote.enterRoom(room); +} + +void CPetControl::resetRemoteTarget() { + _remoteTarget = nullptr; + _remoteTargetName.clear(); +} + +void CPetControl::setActiveNPC(CTrueTalkNPC *npc) { + if (_activeNPC == npc) { + if (_activeNPC) { + _activeNPCName = npc->getName(); + _conversations.displayNPCName(npc); + } else { + _activeNPCName = ""; + } + } +} + +void CPetControl::refreshNPC() { + _conversations.setNPC(_activeNPCName); +} + +void CPetControl::resetActiveNPC() { + _activeNPC = nullptr; + _activeNPCName = ""; +} + +PetArea CPetControl::setArea(PetArea newArea) { + if (newArea == _currentArea || !isAreaActive()) + return _currentArea; + + // Signal the currently active area that it's being left + _sections[_currentArea]->leave(); + + // Change the current area + PetArea oldArea = _currentArea; + _frame.setArea(newArea); + _currentArea = newArea; + + // Signal to the new view that it's been activated + _sections[_currentArea]->enter(oldArea); + + makeDirty(); + return newArea; +} + +void CPetControl::hideCursor() { + _sections[_currentArea]->hideCursor(); +} + +void CPetControl::showCursor() { + _sections[_currentArea]->showCursor(); +} + +void CPetControl::highlightGlyph(int id) { + _sections[_currentArea]->highlight(id); +} + +void CPetControl::setRemoteTarget(CGameObject *item) { + _remoteTarget = item; + if (item) + _remoteTargetName = item->getName(); + else + _remoteTargetName.clear(); +} + +CRoomItem *CPetControl::getHiddenRoom() { + if (!_hiddenRoom) + _hiddenRoom = CGameObject::getHiddenRoom(); + + return _hiddenRoom; +} + +CGameObject *CPetControl::getHiddenObject(const CString &name) { + CRoomItem *room = getHiddenRoom(); + return room ? static_cast<CGameObject *>(findUnder(room, name)) : nullptr; +} + +bool CPetControl::containsPt(const Common::Point &pt) const { + return _drawBounds.contains(pt); +} + +bool CPetControl::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!containsPt(msg->_mousePos) || isInputLocked()) + return false; + + bool result = false; + if (isAreaActive()) + result = _frame.MouseButtonDownMsg(msg); + + if (!result) { + result = _sections[_currentArea]->MouseButtonDownMsg(msg); + } + + makeDirty(); + return result; +} + +bool CPetControl::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!containsPt(msg->_mousePos) || isInputLocked()) + return false; + + return _sections[_currentArea]->MouseDragStartMsg(msg); +} + +bool CPetControl::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + return _sections[_currentArea]->MouseDragMoveMsg(msg); +} + +bool CPetControl::MouseDragEndMsg(CMouseDragEndMsg *msg) { + return _sections[_currentArea]->MouseDragEndMsg(msg); +} + +bool CPetControl::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (!containsPt(msg->_mousePos) || isInputLocked()) + return false; + + bool result = false; + if (isAreaActive()) + result = _frame.MouseButtonUpMsg(msg); + + if (!result) + result = _sections[_currentArea]->MouseButtonUpMsg(msg); + + makeDirty(); + return result; +} + +bool CPetControl::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + if (!containsPt(msg->_mousePos) || isInputLocked()) + return false; + + return _sections[_currentArea]->MouseDoubleClickMsg(msg); +} + +bool CPetControl::KeyCharMsg(CKeyCharMsg *msg) { + if (isInputLocked()) + return false; + + return _sections[_currentArea]->KeyCharMsg(msg); +} + +bool CPetControl::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + if (isInputLocked()) + return false; + + bool result = _sections[_currentArea]->VirtualKeyCharMsg(msg); + + if (!result) { + switch (msg->_keyState.keycode) { + case Common::KEYCODE_F1: + result = true; + setArea(PET_INVENTORY); + break; + case Common::KEYCODE_F2: + result = true; + setArea(PET_CONVERSATION); + break; + case Common::KEYCODE_F3: + result = true; + setArea(PET_REMOTE); + break; + case Common::KEYCODE_F4: + result = true; + setArea(PET_ROOMS); + break; + case Common::KEYCODE_F5: + result = true; + setArea(PET_REAL_LIFE); + break; + default: + break; + } + } + + return result; +} + +bool CPetControl::TimerMsg(CTimerMsg *msg) { + warning("TODO: CPetControl::CTimerMsg"); + return true; +} + +void CPetControl::drawSquares(CScreenManager *screenManager, int count) { + _frame.drawSquares(screenManager, count); +} + +CGameObject *CPetControl::dragEnd(const Point &pt) const { + return _currentArea == PET_INVENTORY ? _inventory.dragEnd(pt) : nullptr; +} + +bool CPetControl::checkDragEnd(CGameObject *item) const { + return _sections[_currentArea]->checkDragEnd(item); +} + +void CPetControl::displayMessage(const CString &msg) const { + _sections[_currentArea]->displayMessage(msg); +} + +CGameObject *CPetControl::getFirstObject() const { + return static_cast<CGameObject *>(getFirstChild()); +} + +CGameObject *CPetControl::getNextObject(CGameObject *prior) const { + if (!prior || prior->getParent() != this) + return nullptr; + + return static_cast<CGameObject *>(prior->getNextSibling()); +} + +void CPetControl::addToInventory(CGameObject *item) { + item->detach(); + + if (item->getName() == "CarryParcel") { + CCarry *child = static_cast<CCarry *>(getLastChild()); + if (child) + child->detach(); + + item->petMoveToHiddenRoom(); + if (!child) + return; + + item = child; + } + + item->addUnder(this); + _inventory.itemsChanged(); + + setArea(PET_INVENTORY); + if (_currentArea == PET_INVENTORY) + _inventory.highlightItem(item); + + makeDirty(); + CPETGainedObjectMsg msg; + msg.execute(item); +} + +void CPetControl::removeFromInventory(CGameObject *item, CTreeItem *newParent, + bool refreshUI, bool sendMsg) { + if (item && newParent) { + item->detach(); + item->addUnder(newParent); + + if (refreshUI) + _inventory.itemRemoved(item); + if (sendMsg) { + CPETLostObjectMsg lostMsg; + lostMsg.execute(item); + } + } +} + +void CPetControl::removeFromInventory(CGameObject *item, bool refreshUI, bool sendMsg) { + CViewItem *view = getGameManager()->getView(); + removeFromInventory(item, view, refreshUI, sendMsg); +} + +void CPetControl::invChange(CGameObject *item) { + _inventory.change(item); +} + +void CPetControl::moveToHiddenRoom(CTreeItem *item) { + CRoomItem *room = getHiddenRoom(); + if (room) { + item->detach(); + room->addUnder(item); + } +} + +bool CPetControl::checkNode(const CString &name) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return true; + if (name == "NULL") + return false; + + CViewItem *view = gameManager->getView(); + if (!view) + return true; + + CNodeItem *node = view->findNode(); + if (!node) + return true; + + CString viewName = view->getName(); + CString nodeName = node->getName(); + CRoomItem *room = getGameManager()->getRoom(); + + if (room) { + CString roomName = room->getName(); + CString newNode; + + if (roomName == "1stClassRestaurant") { + } else if (nodeName == "Lobby Node") { + nodeName = "Node 1"; + } else if (nodeName == "Entrance Node") { + nodeName = "Node 2"; + } else if (nodeName == "MaitreD Node") { + nodeName = "Node 3"; + } else if (nodeName == "Scraliontis Table Standing Node") { + nodeName = "Node 4"; + } else if (nodeName == "Pellerator Node") { + nodeName = "Node 5"; + } else if (nodeName == "SUB Node") { + nodeName = "Node 6"; + } else if (nodeName == "Phonograph Node") { + nodeName = "Node 7"; + } else if (nodeName == "Scraliontis Table Seated Node") { + nodeName = "Node 8"; + } + + if (roomName == "MusicRoom") { + if (nodeName == "Musical Instruments") + nodeName = "Node 1"; + if (nodeName == "Phonograph Node") + nodeName = "Node 2"; + } + } + + CString str = CString::format("%s.%s", nodeName.c_str(), viewName.c_str()); + str = str.right(5); + str.toLowercase(); + + CString nameLower = name; + nameLower.toLowercase(); + + return nameLower.contains(str); +} + +void CPetControl::playSound(int soundNum) { + CTreeItem *player = getHiddenObject("PETSoundPlayer"); + if (player) { + CPETPlaySoundMsg playMsg(soundNum); + playMsg.execute(player); + } +} + +int CPetControl::canSummonBot(const CString &name) { + // If player is the very same view as the NPC, then it's already present + if (isBotInView(name)) + return SUMMON_CAN; + + // Get the room + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return SUMMON_CANT; + CRoomItem *room = gameManager->getRoom(); + if (!room) + return SUMMON_CANT; + + // Query current room to see whether the bot can be summoned to it + CSummonBotQueryMsg queryMsg(name); + return queryMsg.execute(room) ? SUMMON_CAN : SUMMON_CANT; +} + +bool CPetControl::isBotInView(const CString &name) const { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return false; + CViewItem *view = gameManager->getView(); + if (!view) + return false; + + // Iterate to find NPC + for (CTreeItem *child = view->getFirstChild(); child; child = child->scan(view)) { + CGameObject *gameObject = static_cast<CGameObject *>(child); + if (gameObject) { + if (!gameObject->getName().compareToIgnoreCase(name)) + return true; + } + } + + return false; +} + +void CPetControl::summonBot(const CString &name, int val) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + CRoomItem *room = gameManager->getRoom(); + + if (room) { + CSummonBotMsg summonMsg(name, val); + summonMsg.execute(room); + } + } +} + +void CPetControl::onSummonBot(const CString &name, int val) { + CGameObject *bot = findBot(name, getHiddenRoom()); + if (!bot) { + bot = findBot(name, getRoot()); + } + + if (bot) { + removeFromInventory(bot, false, false); + + COnSummonBotMsg summonMsg(val); + summonMsg.execute(bot); + } +} + +bool CPetControl::dismissBot(const CString &name) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return false; + CViewItem *view = gameManager->getView(); + if (!view) + return false; + + bool result = false; + CDismissBotMsg dismissMsg; + for (CTreeItem *treeItem = view->getFirstChild(); treeItem; + treeItem = treeItem->scan(view)) { + if (!treeItem->getName().compareToIgnoreCase(name)) + dismissMsg.execute(treeItem); + else + result = true; + } + + return result; +} + +bool CPetControl::isDoorOrBellbotPresent() const { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return false; + CViewItem *view = gameManager->getView(); + if (!view) + return false; + + for (CTreeItem *treeItem = view->getFirstChild(); treeItem; + treeItem = treeItem->scan(view)) { + CString name = treeItem->getName(); + if (static_cast<CGameObject *>(treeItem) && + (name.contains("Doorbot") || name.contains("BellBot"))) + return true; + } + + return false; +} + +void CPetControl::startPetTimer(uint timerIndex, uint firstDuration, uint duration, CPetSection *target) { + stopPetTimer(timerIndex); + _timers[timerIndex]._id = addTimer(timerIndex, firstDuration, duration); + _timers[timerIndex]._target = target; + setTimerPersisent(_timers[timerIndex]._id, false); +} + +void CPetControl::stopPetTimer(uint timerIndex) { + if (_timers[timerIndex]._target) { + stopTimer(_timers[timerIndex]._id); + _timers[timerIndex]._target = nullptr; + } +} + +void CPetControl::setTimerPersisent(int id, bool flag) { + getGameManager()->setTimerPersisent(id, flag); +} + +CGameObject *CPetControl::findBot(const CString &name, CTreeItem *root) { + for (CTreeItem *item = root; item; item = item->scan(root)) { + if (!item->getName().compareToIgnoreCase(name)) { + CGameObject *obj = static_cast<CGameObject *>(item); + if (obj) + return obj; + } + } + + return nullptr; +} + +bool CPetControl::isSuccUBusActive() const { + if (!_activeNPC) + return false; + + CString name = getName(); + return name.contains("Succubus") || name.contains("Sub"); +} + +void CPetControl::convResetDials(int flag) { + if (flag == 1) + _conversations.resetDials(_activeNPCName); +} + +int CPetControl::getMailDest(const CRoomFlags &roomFlags) const { + if (!roomFlags.isSuccUBusRoomFlags()) + return roomFlags.getPassengerClassNum(); + + return roomFlags.getSuccUBusNum(roomFlags.getSuccUBusRoomName()); +} + +void CPetControl::starsSetButtons(int val1, int val2) { + _starfield.setButtons(val1, val2); + if (_currentArea == PET_STARFIELD) + _starfield.makePetDirty(); +} + +void CPetControl::starsSetReference(bool hasRef) { + _starfield.setHasReference(hasRef); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_control.h b/engines/titanic/pet_control/pet_control.h new file mode 100644 index 0000000000..a86d110458 --- /dev/null +++ b/engines/titanic/pet_control/pet_control.h @@ -0,0 +1,574 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_CONTROL_H +#define TITANIC_PET_CONTROL_H + +#include "titanic/core/game_object.h" +#include "titanic/core/node_item.h" +#include "titanic/core/room_item.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/pet_control/pet_conversations.h" +#include "titanic/pet_control/pet_frame.h" +#include "titanic/pet_control/pet_inventory.h" +#include "titanic/pet_control/pet_message.h" +#include "titanic/pet_control/pet_starfield.h" +#include "titanic/pet_control/pet_real_life.h" +#include "titanic/pet_control/pet_remote.h" +#include "titanic/pet_control/pet_rooms.h" +#include "titanic/room_flags.h" + +namespace Titanic { + +enum SummonResult { SUMMON_CANT = 0, SUMMON_PRESENT = 1, SUMMON_CAN = 2 }; + +class CPetControl : public CGameObject { + DECLARE_MESSAGE_MAP; + struct PetEventInfo { + int _id; + CPetSection *_target; + PetEventInfo() : _id(0), _target(nullptr) {} + }; +private: + int _inputLockCount; + int _areaLockCount; + int _areaChangeType; + CPetSection *_sections[7]; + CPetConversations _conversations; + CPetInventory _inventory; + CPetStarfield _starfield; + CPetRemote _remote; + CPetRooms _rooms; + CPetRealLife _realLife; + CPetMessage _message; + CPetFrame _frame; + CString _activeNPCName; + CString _remoteTargetName; + CRoomItem *_hiddenRoom; + Rect _drawBounds; + PetEventInfo _timers[2]; +private: + /** + * Returns true if the control is in a valid state + */ + bool isValid(); + + /** + * Loads data for the individual areas + */ + void loadAreas(SimpleFile *file, int param); + + /** + * Saves data for the individual areas + */ + void saveAreas(SimpleFile *file, int indent); + + /** + * Called at the end of the post game-load handling + */ + void loaded(); + + /** + * Returns true if the draw bounds contains the specified point + */ + bool containsPt(const Common::Point &pt) const; + + /** + * Checks whether a designated NPC in present in the current view + */ + bool isBotInView(const CString &name) const; + + /** + * Find a bot under a given root + */ + CGameObject *findBot(const CString &name, CTreeItem *root); + + /** + * Flags whether the timer will be persisent across save & loads + */ + void setTimerPersisent(int id, bool flag); +protected: + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + bool KeyCharMsg(CKeyCharMsg *msg); + bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + bool TimerMsg(CTimerMsg *msg); +public: + PetArea _currentArea; + CTreeItem *_activeNPC; + CGameObject *_remoteTarget; +public: + CLASSDEF; + CPetControl(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); + + /** + * Allows the item to draw itself + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Gets the bounds occupied by the item + */ + virtual Rect getBounds() const; + + /** + * Setups the sections within the PET + */ + void setup(); + + /** + * Called after loading a game has finished + */ + void postLoad(); + + /** + * Called when a new node is entered + */ + void enterNode(CNodeItem *node); + + /** + * Called when a new room is entered + */ + void enterRoom(CRoomItem *room); + + /** + * Called to reset the remote target + */ + void resetRemoteTarget(); + + /** + * Set the remote target + */ + void setRemoteTarget(CGameObject *item); + + /** + * Sets the currently viewed area within the PET + */ + PetArea setArea(PetArea newSection); + + /** + * Hides the text cursor in the current section, if applicable + */ + void hideCursor(); + + /** + * Shows the text cursor in the current section, if applicable + */ + void showCursor(); + + /** + * Highlights a glyph item in the currently active section, if applicable + */ + void highlightGlyph(int id); + + + /** + * Returns a game object used by the PET by name from within the + * special hidden room container + */ + CGameObject *getHiddenObject(const CString &name); + + /** + * Returns a reference to the special hidden room container + */ + CRoomItem *getHiddenRoom(); + + /** + * Draws squares for showing glyphs inside + */ + void drawSquares(CScreenManager *screenManager, int count); + + /** + * Returns true if the point is within the PET's draw bounds + */ + bool contains(const Point &pt) const { + return _drawBounds.contains(pt); + } + + /** + * Handles drag ends within the PET + */ + CGameObject *dragEnd(const Point &pt) const; + + /** + * Handles checking when a drag-drop operation ends + */ + bool checkDragEnd(CGameObject *item) const; + + /** + * Display a message + */ + void displayMessage(const CString &msg) const; + + /** + * Get the first game object stored in the PET + */ + CGameObject *getFirstObject() const; + + /** + * Get the next game object stored in the PET following + * the passed game object + */ + CGameObject *getNextObject(CGameObject *prior) const; + + /** + * Adds an item to the PET inventory + */ + void addToInventory(CGameObject *item); + + /** + * Remove an item from the inventory + */ + void removeFromInventory(CGameObject *item, CTreeItem *newParent, + bool refreshUI = true, bool sendMsg = true); + + /** + * Remove an item from the inventory + */ + void removeFromInventory(CGameObject *item, bool refreshUI = true, bool sendMsg = true); + + /** + * Called when the status of an item in the inventory has changed + */ + void invChange(CGameObject *item); + + /** + * Moves a tree item from it's original position to be under the hidden room + */ + void moveToHiddenRoom(CTreeItem *item); + + /** + * Sets a change for the PET Area's glyphs. Only applicable when + * the Inventory is the active tab + */ + void setAreaChangeType(int changeType) { _areaChangeType = changeType; } + + bool checkNode(const CString &name); + + /** + * Play a sound + */ + void playSound(int soundNum); + + /** + * Check whether an NPC can be summoned + */ + int canSummonBot(const CString &name); + + /** + * Summon an NPC to the player + */ + void summonBot(const CString &name, int val); + + /** + * Summon a bot to the player + */ + void onSummonBot(const CString &name, int val); + + /** + * Dismiss an NPC + */ + bool dismissBot(const CString &name); + + /** + * Returns true if Doorbot or Bellbot present + */ + bool isDoorOrBellbotPresent() const; + + /** + * Start a timer for a Pet Area + */ + void startPetTimer(uint timerIndex, uint firstDuration, uint duration, CPetSection *target); + + /** + * Stop a timer + */ + void stopPetTimer(uint timerIndex); + + /** + * Returns true if all input is currently locked (disabled) + */ + bool isInputLocked() const { return _inputLockCount > 0; } + + /** + * Increments the input locked count + */ + void incInputLocks() { ++_inputLockCount; } + + /** + * Decremenst the input locked count + */ + void decInputLocks() { --_inputLockCount; } + + /** + * Returns true if the PET is currently unlocked + */ + bool isAreaActive() const { return _areaLockCount == 0; } + + /** + * Increment the number of PET area (tab) locks + */ + void incAreaLocks() { ++_areaLockCount; } + + /** + * Decrement the number of PET area (tab) locks + */ + void decAreaLocks() { + _areaLockCount = MAX(_areaLockCount - 1, 0); + } + + bool isSuccUBusActive() const; + + /*--- CPetConversations methods ---*/ + + /** + * Sets the active NPC + */ + void setActiveNPC(const CString &name) { + _conversations.setActiveNPC(name); + } + + /** + * Sets the actie NPC + */ + void setActiveNPC(CTrueTalkNPC *npc); + + /** + * Refresh the currently active NPC + */ + void refreshNPC(); + + /** + * Resets the Active NPC + */ + void resetActiveNPC(); + + /** + * Resets NPC in conversations + */ + void convResetNPC() { + _conversations.resetNPC(); + } + + /** + * Resets the conversation dials back to 0 position + */ + void resetDials0() { _conversations.resetDials0(); } + + /** + * Resets the dial display in the conversation tab to reflect new values + */ + void convResetDials(int flag = 1); + + /** + * Adds a line to the conversation log + */ + void convAddLine(const CString &line) { + _conversations.addLine(line); + } + + /*--- CPetRooms methods ---*/ + + /** + * Gives the player a new assigned room in the specified passenger class + */ + void reassignRoom(int passClassNum) { + _rooms.reassignRoom(passClassNum); + } + + /** + * Change the current location passenger class + */ + bool changeLocationClass(int newClassNum) { + return _rooms.changeLocationClass(newClassNum); + } + + /** + * Returns true if the Rooms list has a room with the given flags + */ + bool hasRoomFlags() const { + return _rooms.hasRoomFlags(getRoomFlags()); + } + + uint getRoomFlags() const { + return _rooms.getRoomFlags(); + } + + /** + * Set the current elevator number to use for room glyphs + */ + void setRoomsElevatorNum(int elevNum) { + _rooms.setElevatorNum(elevNum); + } + + /** + * Get the current elevator number used by room glyphs + */ + int getRoomsElevatorNum() const { + return _rooms.getElevatorNum(); + } + + /** + * Set the current floor number to use for room glyphs + */ + void setRoomsFloorNum(int floorNum) { + _rooms.setFloorNum(floorNum); + } + + /** + * Get the current floor number used by room glyphs + */ + int getRoomsFloorNum() const { + return _rooms.getFloorNum(); + } + + /** + * Set the current room number to use for room glyphs + */ + void setRoomsRoomNum(int roomNum) { + _rooms.setRoomNum(roomNum); + } + + /** + * Get the current floor number used by room glyphs + */ + int getRoomsRoomNum() const { + return _rooms.getRoomNum(); + } + + /** + * Sets the entry number for arriving at the well + */ + void setRoomsWellEntry(int entryNum) { + _rooms.setWellEntry(entryNum); + } + + /** + * Gets the entry number used when last arriving at the well + */ + int getRoomsWellEntry() const { + return _rooms.getWellEntry(); + } + + void setRooms1CC(int v) { + _rooms.set1CC(v); + } + int getRooms1CC() const { + return _rooms.get1CC(); + } + + /** + * Reset the highlight + */ + void resetRoomsHighlight() { + _rooms.resetHighlight(); + } + + int getAssignedRoomFlags() const { + return _rooms.getAssignedRoomFlags(); + } + + uint getSpecialRoomFlags(const CString &name) { + return CRoomFlags::getSpecialRoomFlags(name); + } + + /** + * Get mail destination given the specified flags + */ + int getMailDest(const CRoomFlags &roomFlags) const; + + bool testRooms5(uint roomFlags) { + return CRoomFlags(roomFlags).not5(); + } + + /** + * Returns the room number for the player's currently assigned room + */ + int getAssignedRoomNum() const { + return _rooms.getAssignedRoomNum(); + } + + /** + * Returns the floor number for the player's currently assigned room + */ + int getAssignedFloorNum() const { + return _rooms.getAssignedFloorNum(); + } + + /** + * Returns the elevator number for the player's currently assigned room + */ + int getAssignedElevatorNum() const { + return _rooms.getAssignedElevatorNum(); + } + + void setRooms1D4(int val) { + _rooms.set1D4(val); + } + + bool isRoom59706() const { + return CRoomFlags(getRoomFlags()).is59706(); + } + + /** + * Returns true if the passed room flags indicate the room has a succubus + */ + bool isSuccUBusRoom(const CRoomFlags &roomFlags) { + return roomFlags.isSuccUBusRoomFlags(); + } + + /** + * Called with a phonograph action for Send, Receive, or Record + */ + void phonographAction(const CString &action) { + // Original had some code that had no effect + } + + /** + * Sets the status buttons for the starfield control + */ + void starsSetButtons(int val1, int val2); + + /** + * Set whether the user has the galactic reference material + */ + void starsSetReference(bool hasRef); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_CONTROL_H */ diff --git a/engines/titanic/pet_control/pet_conversations.cpp b/engines/titanic/pet_control/pet_conversations.cpp new file mode 100644 index 0000000000..dc096afcfe --- /dev/null +++ b/engines/titanic/pet_control/pet_conversations.cpp @@ -0,0 +1,579 @@ +/* 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 "titanic/pet_control/pet_conversations.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +CPetConversations::CPetConversations() : CPetSection(), + _logChanged(false), _field418(0), _npcNum(-1), + _rect1(22, 352, 598, 478) { + Rect logRect(85, 18, 513, 87); + logRect.translate(20, 350); + _log.setBounds(logRect); + _log.resize(50); + _log.setHasBorder(false); + _log.setColor(getColor(2)); + _log.setup(); + _log.addLine("Welcome to your PET v1.0a"); + + Rect inputRect(85, 95, 513, 135); + inputRect.translate(20, 350); + _textInput.setBounds(inputRect); + _textInput.setHasBorder(false); + _textInput.resize(2); + _textInput.setMaxCharsPerLine(74); + _textInput.setColor(getColor(0)); + _textInput.setup(); + + _npcLevels[0] = _npcLevels[1] = _npcLevels[2] = 0; +} + +bool CPetConversations::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +bool CPetConversations::reset() { + _dials[0].setup(MODE_UNSELECTED, "3PetDial1", _petControl); + _dials[1].setup(MODE_UNSELECTED, "3PetDial2", _petControl); + _dials[2].setup(MODE_UNSELECTED, "3PetDial3", _petControl); + + _dialBackground.reset("PetDialBack", _petControl); + _scrollUp.reset("PetScrollUp", _petControl); + _scrollDown.reset("PetScrollDown", _petControl); + + _doorBot.reset("PetCallDoorOut", _petControl, MODE_UNSELECTED); + _doorBot.reset("PetCallDoorIn", _petControl, MODE_SELECTED); + _bellBot.reset("PetCallBellOut", _petControl, MODE_UNSELECTED); + _bellBot.reset("PetCallBellIn", _petControl, MODE_SELECTED); + + _indent.reset("PetSmallCharacterIndent", _petControl); + _splitter.reset("PetSplitter", _petControl); + + _npcIcons[0].setup(MODE_UNSELECTED, "3PetSmlDoorbot", _petControl); + _npcIcons[1].setup(MODE_UNSELECTED, "3PetSmlDeskbot", _petControl); + _npcIcons[2].setup(MODE_UNSELECTED, "3PetSmlLiftbot", _petControl); + _npcIcons[3].setup(MODE_UNSELECTED, "3PetSmlParrot", _petControl); + _npcIcons[4].setup(MODE_UNSELECTED, "3PetSmlBarbot", _petControl); + _npcIcons[5].setup(MODE_UNSELECTED, "3PetSmlChatterbot", _petControl); + _npcIcons[6].setup(MODE_UNSELECTED, "3PetSmlBellbot", _petControl); + _npcIcons[7].setup(MODE_UNSELECTED, "3PetSmlMaitreD", _petControl); + _npcIcons[8].setup(MODE_UNSELECTED, "3PetSmlSuccubus", _petControl); + + if (_petControl->getPassengerClass() == 1) { + uint col = getColor(0); + _textInput.setColor(col); + _textInput.setLineColor(0, col); + + // Replace the log colors with new 1st class ones + uint colors1[5], colors2[5]; + copyColors(2, colors1); + copyColors(1, colors2); + _log.remapColors(5, colors1, colors2); + + _log.setColor(getColor(2)); + } + + return true; +} + +void CPetConversations::draw(CScreenManager *screenManager) { + _dialBackground.draw(screenManager); + _splitter.draw(screenManager); + _dials[0].draw(screenManager); + _dials[1].draw(screenManager); + _dials[2].draw(screenManager); + + _indent.draw(screenManager); + _doorBot.draw(screenManager); + _bellBot.draw(screenManager); + _scrollUp.draw(screenManager); + _scrollDown.draw(screenManager); + _log.draw(screenManager); + _textInput.draw(screenManager); + + if (_logChanged) { + int startIndex = _log.getLinesStart(); + if (startIndex >= 0) { + int npcNum = _log.getNPCNum(1, startIndex); + if (npcNum > 0 && npcNum < 10) + _npcNum = npcNum; + } + + _logChanged = false; + } + + if (_npcNum >= 0) + _npcIcons[_npcNum].draw(screenManager); +} + +Rect CPetConversations::getBounds() const { + Rect rect = _dials[0].getBounds(); + rect.combine(_dials[1].getBounds()); + rect.combine(_dials[2].getBounds()); + + return rect; +} + +bool CPetConversations::isValid(CPetControl *petControl) { + return setupControl(petControl); +} + +bool CPetConversations::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_scrollDown.MouseButtonDownMsg(msg->_mousePos)) { + scrollDown(); + return true; + } else if (_scrollUp.MouseButtonDownMsg(msg->_mousePos)) { + scrollUp(); + return true; + } + + return + _doorBot.MouseButtonDownMsg(msg->_mousePos) || + _bellBot.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetConversations::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (_scrollUp.MouseButtonUpMsg(msg->_mousePos) || + _scrollDown.MouseButtonUpMsg(msg->_mousePos)) + return true; + + if (_doorBot.MouseButtonUpMsg(msg->_mousePos)) { + switch (canSummonBot("DoorBot")) { + case SUMMON_CANT: + _log.addLine("Sadly, it is not possible to summon the DoorBot from this location.", getColor(1)); + break; + case SUMMON_CAN: + summonBot("DoorBot"); + return true; + default: + break; + } + + // Scroll to the bottom of the log + scrollToBottom(); + return true; + } + + if (_bellBot.MouseButtonUpMsg(msg->_mousePos)) { + switch (canSummonBot("BellBot")) { + case SUMMON_CANT: + _log.addLine("Sadly, it is not possible to summon the BellBot from this location.", getColor(1)); + break; + case SUMMON_CAN: + summonBot("BellBot"); + return true; + default: + break; + } + + // Scroll to the bottom of the log + scrollToBottom(); + return true; + } + + return false; +} + +bool CPetConversations::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return _scrollDown.MouseDoubleClickMsg(msg->_mousePos) + || _scrollUp.MouseDoubleClickMsg(msg->_mousePos); +} + +bool CPetConversations::KeyCharMsg(CKeyCharMsg *msg) { + Common::KeyState keyState; + keyState.ascii = msg->_key; + return handleKey(keyState); +} + +bool CPetConversations::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + return handleKey(msg->_keyState); +} + +void CPetConversations::displayMessage(const CString &msg) { + _log.addLine(msg, getColor(1)); + scrollToBottom(); +} + +void CPetConversations::load(SimpleFile *file, int param) { + _textInput.load(file, param); + _log.load(file, param); + + for (int idx = 0; idx < TOTAL_DIALS; ++idx) + _npcLevels[idx] = file->readNumber(); +} + +void CPetConversations::postLoad() { + reset(); +} + +void CPetConversations::save(SimpleFile *file, int indent) { + _textInput.save(file, indent); + _log.save(file, indent); + + for (int idx = 0; idx < TOTAL_DIALS; ++idx) + file->writeNumberLine(_npcLevels[idx], indent); +} + +void CPetConversations::enter(PetArea oldArea) { + resetDials(); + + if (_petControl && _petControl->_activeNPC) + // Start a timer for the NPC + startNPCTimer(); + + // Show the text cursor + _textInput.showCursor(-2); +} + +void CPetConversations::leave() { + _textInput.hideCursor(); + stopNPCTimer(); +} + +void CPetConversations::timerExpired(int val) { + if (val == 1) { + CPetSection::timerExpired(val); + } else { + CString name = _field418 ? _npcName : getActiveNPCName(); + + for (int idx = 0; idx < TOTAL_DIALS; ++idx) { + if (!_dials[idx].hasActiveMovie()) + updateDial(idx, name); + } + } +} + +void CPetConversations::displayNPCName(CGameObject *npc) { + if (npc) { + displayMessage(CString()); + CString msg = "Talking to "; + CString name = npc->getName(); + int id = 1; + + if (name.contains("Doorbot")) { + msg += "the DoorBot"; + } else if (name.contains("DeskBot")) { + id = 2; + msg += "the DeskBot"; + } else if (name.contains("LiftBot")) { + id = 3; + msg += "a LiftBot"; + } else if (name.contains("Parrot")) { + id = 4; + msg += "the Parrot"; + } else if (name.contains("BarBot")) { + id = 5; + msg += "the BarBot"; + } else if (name.contains("ChatterBot")) { + id = 6; + msg += "a ChatterBot"; + } else if (name.contains("BellBot")) { + id = 7; + msg += "the BellBot"; + } else if (name.contains("Maitre")) { + id = 8; + msg += "the Maitre d'Bot"; + } else if (name.contains("Succubus") || name.contains("Sub")) { + id = 9; + msg += "a Succ-U-Bus"; + } else { + msg += "Unknown"; + } + + _log.setNPC(1, id); + displayMessage(msg); + } +} + +void CPetConversations::setNPC(const CString &name) { + _field418 = 0; + resetDials(name); + startNPCTimer(); +} + +void CPetConversations::resetNPC() { + stopNPCTimer(); + resetDials("0"); +} + +void CPetConversations::showCursor() { + _textInput.showCursor(-2); +} + +void CPetConversations::hideCursor() { + _textInput.hideCursor(); +} + +bool CPetConversations::setupControl(CPetControl *petControl) { + if (petControl) { + _petControl = petControl; + + _dialBackground.setBounds(Rect(0, 0, 21, 130)); + _dialBackground.translate(20, 350); + + const Rect rect1(0, 0, 22, 36); + _dials[0].setBounds(rect1); + _dials[0].translate(20, 359); + _dials[1].setBounds(rect1); + _dials[1].translate(20, 397); + _dials[2].setBounds(rect1); + _dials[2].translate(20, 434); + + const Rect rect2(0, 0, 11, 24); + _scrollUp.setBounds(rect2); + _scrollUp.translate(87, 374); + _scrollDown.setBounds(rect2); + _scrollDown.translate(87, 421); + + const Rect rect3(0, 0, 39, 39); + _doorBot.setBounds(rect3); + _doorBot.translate(546, 372); + _bellBot.setBounds(rect3); + _bellBot.translate(546, 418); + + _indent.setBounds(Rect(0, 0, 37, 70)); + _indent.translate(46, 374); + _splitter.setBounds(Rect(0, 0, 435, 3)); + _splitter.translate(102, 441); + + const Rect rect4(0, 0, 33, 66); + for (int idx = 0; idx < 9; ++idx) { + _npcIcons[idx].setBounds(rect4); + _npcIcons[idx].translate(48, 376); + } + } + + return true; +} + +void CPetConversations::scrollUp() { + _log.scrollUp(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +void CPetConversations::scrollDown() { + _log.scrollDown(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +void CPetConversations::scrollUpPage() { + _log.scrollUpPage(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +void CPetConversations::scrollDownPage() { + _log.scrollDownPage(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +void CPetConversations::scrollToTop() { + _log.scrollToTop(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +void CPetConversations::scrollToBottom() { + _log.scrollToBottom(CScreenManager::_screenManagerPtr); + if (_petControl) + _petControl->makeDirty(); + _logChanged = true; +} + +int CPetConversations::canSummonBot(const CString &name) { + return _petControl ? _petControl->canSummonBot(name) : SUMMON_CANT; +} + +void CPetConversations::summonBot(const CString &name) { + if (_petControl) { + if (_petControl->getPassengerClass() >= 4) { + _petControl->displayMessage("Sorry, you must be at least 3rd class before you can summon for help."); + } else { + _petControl->summonBot(name, 0); + } + } +} + +void CPetConversations::startNPCTimer() { + _petControl->startPetTimer(1, 1000, 1000, this); +} + +void CPetConversations::stopNPCTimer() { + _petControl->stopPetTimer(1); +} + +TTnpcScript *CPetConversations::getNPCScript(const CString &name) const { + if (name.empty() || !_petControl) + return nullptr; + CGameManager *gameManager = _petControl->getGameManager(); + if (!gameManager) + return nullptr; + CTrueTalkManager *trueTalk = gameManager->getTalkManager(); + if (!trueTalk) + return nullptr; + + return trueTalk->getTalker(name); +} + +bool CPetConversations::handleKey(const Common::KeyState &keyState) { + switch (keyState.keycode) { + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + scrollUp(); + break; + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + scrollDown(); + break; + case Common::KEYCODE_PAGEUP: + case Common::KEYCODE_KP9: + scrollUpPage(); + break; + case Common::KEYCODE_PAGEDOWN: + case Common::KEYCODE_KP3: + scrollDownPage(); + break; + case Common::KEYCODE_HOME: + case Common::KEYCODE_KP7: + scrollToTop(); + break; + case Common::KEYCODE_END: + case Common::KEYCODE_KP1: + scrollToBottom(); + break; + default: + if (keyState.ascii > 0 && keyState.ascii) { + if (_textInput.handleKey(keyState.ascii)) + // Text line finished, so process line + textLineEntered(_textInput.getText()); + } + return true; + } + + return false; +} + +void CPetConversations::textLineEntered(const CString &textLine) { + if (textLine.empty() || !_petControl) + return; + + if (_petControl->_activeNPC) { + _log.addLine("- " + textLine, getColor(0)); + + CTextInputMsg inputMsg(textLine, ""); + inputMsg.execute(_petControl->_activeNPC); + + if (!inputMsg._response.empty()) + _log.addLine(inputMsg._response); + } else { + _log.addLine("There is no one here to talk to", getColor(1)); + } + + // Clear input line and scroll log down to end to show response + _textInput.setup(); + scrollToBottom(); +} + +void CPetConversations::setActiveNPC(const CString &name) { + _npcName = name; + _field418 = 1; + resetDials(); + startNPCTimer(); +} + +void CPetConversations::updateDial(uint dialNum, const CString &npcName) { + TTnpcScript *script = getNPCScript(npcName); + uint newLevel = getDialLevel(dialNum, script); + npcDialChange(dialNum, _npcLevels[dialNum], newLevel); + _npcLevels[dialNum] = newLevel; +} + +uint CPetConversations::getDialLevel(uint dialNum, TTnpcScript *script, int v) { + bool flag = v != 0; + + if (!script) + return 0; + else + return MAX(script->getDialLevel(dialNum, flag), 15); +} + +void CPetConversations::npcDialChange(uint dialNum, int oldLevel, int newLevel) { + const uint range1[2] = { 0, 21 }; + const uint range2[2] = { 22, 43 }; + + if (newLevel != oldLevel) { + uint src = range1[0], dest = range1[1]; + if (oldLevel < newLevel) { + src = range2[0]; + dest = range2[1]; + } + + int64 val1 = (oldLevel * dest) + (100 - oldLevel) * src; + uint startFrame = val1 / 100; + + int64 val2 = (newLevel * dest) + (100 - newLevel) * src; + uint endFrame = val2 / 100; + + if (startFrame != endFrame) + _dials[dialNum].playMovie(startFrame, endFrame); + } +} + +void CPetConversations::resetDials() { + resetDials(getActiveNPCName()); +} + +void CPetConversations::resetDials(const CString &name) { + TTnpcScript *script = getNPCScript(name); + + for (int idx = 0; idx < TOTAL_DIALS; ++idx) { + uint oldLevel = _npcLevels[idx]; + uint newLevel = getDialLevel(idx, script); + npcDialChange(idx, oldLevel, newLevel); + _npcLevels[idx] = newLevel; + } +} + +void CPetConversations::resetDials0() { + stopNPCTimer(); + resetDials("0"); +} + +void CPetConversations::addLine(const CString &line) { + _log.addLine(line); + scrollToBottom(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_conversations.h b/engines/titanic/pet_control/pet_conversations.h new file mode 100644 index 0000000000..9e8b093d62 --- /dev/null +++ b/engines/titanic/pet_control/pet_conversations.h @@ -0,0 +1,267 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_CONVERSATIONS_H +#define TITANIC_PET_CONVERSATIONS_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_text.h" +#include "titanic/pet_control/pet_gfx_element.h" +#include "titanic/true_talk/true_talk_manager.h" + +namespace Titanic { + +#define TOTAL_DIALS 3 + +class CPetConversations : public CPetSection { +private: + CPetGfxElement _scrollUp; + CPetGfxElement _scrollDown; + CPetGfxElement _dialBackground; + CPetGfxElement _dials[TOTAL_DIALS]; + uint _npcLevels[TOTAL_DIALS]; + CPetGfxElement _val4; + CPetGfxElement _val5; + CPetGfxElement _indent; + Rect _rect1; + CPetGfxElement _doorBot; + CPetGfxElement _bellBot; + CPetGfxElement _splitter; + CPetGfxElement _npcIcons[9]; + int _npcNum; + CPetText _log; + CPetText _textInput; + bool _logChanged; + int _field418; + CString _npcName; +private: + /** + * Sets up the control + */ + bool setupControl(CPetControl *petControl); + + /** + * Scroll up the conversation log + */ + void scrollUp(); + + /** + * Scroll down the conversation log + */ + void scrollDown(); + + /** + * Scroll up one page in the conversation log + */ + void scrollUpPage(); + + /** + * Scroll down one page in the conversation log + */ + void scrollDownPage(); + + /** + * Scroll to the top of the conversation log + */ + void scrollToTop(); + + /** + * Scroll to the bottom of the conversation log + */ + void scrollToBottom(); + + /** + * Check whether an NPC can be summoned + */ + int canSummonBot(const CString &name); + + /** + * Summon an NPC + */ + void summonBot(const CString &name); + + /** + * Starts the NPC timer + */ + void startNPCTimer(); + + /** + * Stops the NPC timer + */ + void stopNPCTimer(); + + /** + * Get the TrueTalk script associated with a given NPC + */ + TTnpcScript *getNPCScript(const CString &name) const; + + /** + * Handle a keypress + */ + bool handleKey(const Common::KeyState &keyState); + + /** + * Handles an entered text line + */ + void textLineEntered(const CString &textLine); + + /** + * Updates one of the dials with data from a given NPC + */ + void updateDial(uint dialNum, const CString &npcName); + + /** + * Get a dial level + */ + uint getDialLevel(uint dialNum, TTnpcScript *script, int v = 1); + + /** + * Called when the dial for an NPC is being changed + */ + void npcDialChange(uint dialNum, int oldLevel, int newLevel); +public: + CPetConversations(); + virtual ~CPetConversations() {} + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Get the bounds for the section + */ + virtual Rect getBounds() const; + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + virtual bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + virtual bool KeyCharMsg(CKeyCharMsg *msg); + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * Display a message + */ + virtual void displayMessage(const CString &msg); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea); + + /** + * Called when a section is being left, to switch to another area + */ + virtual void leave(); + + /** + * Called when a previously set up PET timer expires + */ + virtual void timerExpired(int val); + + /** + * Display a title for an NPC + */ + virtual void displayNPCName(CGameObject *npc); + + /** + * Sets the NPC to use + */ + virtual void setNPC(const CString &name); + + /** + * Resets the active NPC + */ + virtual void resetNPC(); + + /** + * Show the text cursor + */ + virtual void showCursor(); + + /** + * Hide the text cursor + */ + virtual void hideCursor(); + + /** + * Set the active NPC + */ + void setActiveNPC(const CString &name); + + /** + * Resets the dials with the data for the currently active NPC + */ + void resetDials(); + + /** + * Reset the dials with those for a given NPC + */ + void resetDials(const CString &name); + + /** + * Reset the dials to the '0' position + */ + void resetDials0(); + + /** + * Adds a line to the log + */ + void addLine(const CString &line); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_CONVERSATIONS_H */ diff --git a/engines/titanic/pet_control/pet_drag_chev.cpp b/engines/titanic/pet_control/pet_drag_chev.cpp new file mode 100644 index 0000000000..d437d43799 --- /dev/null +++ b/engines/titanic/pet_control/pet_drag_chev.cpp @@ -0,0 +1,76 @@ +/* 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 "titanic/pet_control/pet_drag_chev.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/messages.h" +#include "titanic/npcs/succubus.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPetDragChev, CPetGraphic2) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(MouseDragEndMsg) +END_MESSAGE_MAP() + +void CPetDragChev::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic2::save(file, indent); +} + +void CPetDragChev::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic2::load(file); +} + +bool CPetDragChev::MouseDragStartMsg(CMouseDragStartMsg *msg) { + getName(); + return checkStartDragging(msg); +} + +bool CPetDragChev::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + dragMove(msg->_mousePos); + return true; +} + +bool CPetDragChev::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (msg->_dropTarget) { + CSuccUBus *succubus = static_cast<CSuccUBus *>(msg->_dropTarget); + + if (succubus) { + CSetChevRoomBits chevMsg(_id); + chevMsg.execute(succubus); + } else { + CPetControl *petControl = getPetControl(); + if (petControl && petControl->contains(msg->_mousePos) + && msg->_mousePos.x < 528) { + if (petControl->checkDragEnd(this)) + petMoveToHiddenRoom(); + } + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_drag_chev.h b/engines/titanic/pet_control/pet_drag_chev.h new file mode 100644 index 0000000000..9f4a6f0dc9 --- /dev/null +++ b/engines/titanic/pet_control/pet_drag_chev.h @@ -0,0 +1,52 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_DRAG_CHEV_H +#define TITANIC_PET_DRAG_CHEV_H + +#include "titanic/pet_control/pet_graphic2.h" + +namespace Titanic { + +class CPetDragChev : public CPetGraphic2 { + DECLARE_MESSAGE_MAP; +protected: + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_DRAG_CHEV_H */ diff --git a/engines/titanic/pet_control/pet_element.cpp b/engines/titanic/pet_control/pet_element.cpp new file mode 100644 index 0000000000..c5e1a6ea9c --- /dev/null +++ b/engines/titanic/pet_control/pet_element.cpp @@ -0,0 +1,106 @@ +/* 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/textconsole.h" +#include "titanic/pet_control/pet_element.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +CPetElement::CPetElement() : _mode(MODE_UNSELECTED) {} + +Rect CPetElement::getBounds() const { + return Rect(); +} + +bool CPetElement::MouseButtonDownMsg(const Point &pt) { + bool result = _bounds.contains(pt); + if (result) + setMode(MODE_SELECTED); + return result; +} + +bool CPetElement::MouseButtonUpMsg(const Point &pt) { + bool result = _bounds.contains(pt); + if (result) + setMode(MODE_UNSELECTED); + return result; +} + +bool CPetElement::MouseDoubleClickMsg(const Point &pt) const { + return _bounds.contains(pt); +} + +bool CPetElement::MouseMoveMsg(const Point &pt) { + bool result = _bounds.contains(pt); + if (result) + setMode(MODE_FOCUSED); + return result; +} + +bool CPetElement::contains2(const Point &pt) const { + return _bounds.contains(pt); +} + +void CPetElement::playMovie(uint startFrame, uint endFrame) const { + CGameObject *gameObject = getObject(); + + if (gameObject) + gameObject->playMovie(startFrame, endFrame, 0); +} + +void CPetElement::changeStatus(int val) const { + CGameObject *gameObject = getObject(); + + if (gameObject) + gameObject->playMovie(val); +} + +bool CPetElement::hasActiveMovie() const { + CGameObject *gameObject = getObject(); + return gameObject ? gameObject->hasActiveMovie() : false; +} + +void CPetElement::loadFrame(int frameNumber) { + CGameObject *gameObject = getObject(); + if (gameObject) + gameObject->loadFrame(frameNumber); +} + +int CPetElement::getMovieFrame() const { + CGameObject *gameObject = getObject(); + return gameObject ? gameObject->getMovieFrame() : 0; +} + +void CPetElement::setMode(PetElementMode newMode) { + if (newMode >= MODE_UNSELECTED && newMode <= MODE_FOCUSED) + changeMode(newMode); +} + +void CPetElement::setSelected(bool flag) { + if (flag) + changeMode(MODE_SELECTED); + else + changeMode(MODE_UNSELECTED); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_element.h b/engines/titanic/pet_control/pet_element.h new file mode 100644 index 0000000000..bbf3e83537 --- /dev/null +++ b/engines/titanic/pet_control/pet_element.h @@ -0,0 +1,154 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_ELEMENT_H +#define TITANIC_PET_ELEMENT_H + +#include "titanic/support/simple_file.h" +#include "titanic/support/string.h" +#include "titanic/core/link_item.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +enum PetElementMode { MODE_UNSELECTED = 0, MODE_SELECTED = 1, MODE_FOCUSED = 2 }; + +class CGameObject; +class CPetControl; + +class CPetElement { +protected: + Rect _bounds; + PetElementMode _mode; +public: + CPetElement(); + virtual ~CPetElement() {} + + /** + * Sets up the element + */ + virtual void setup(PetElementMode mode, const CString &name, + CPetControl *petControl) {} + + /** + * Reset the element + */ + virtual void reset(const CString &name, CPetControl *petControl, PetElementMode mode) {} + + /** + * Draw the item + */ + virtual void draw(CScreenManager *screenManager) {} + + /** + * Draw the item + */ + virtual void draw(CScreenManager *screenManager, const Point &destPos) {} + + /** + * Get the bounds for the element + */ + virtual Rect getBounds() const; + + /** + * Handles processing mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles processing mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Handles processing mouse button double click messages + */ + virtual bool MouseDoubleClickMsg(const Point &pt) const; + + /** + * Handles processing mouse move messages + */ + virtual bool MouseMoveMsg(const Point &pt); + + /** + * Returns whether the passed point falls inside the item + */ + virtual bool contains2(const Point &pt) const; + + /** + * Plays back a range of frames in the loaded video file for the element + */ + virtual void playMovie(uint startFrame, uint endFrame) const; + + /** + * Change the status of the associated object + */ + virtual void changeStatus(int newStatus) const; + + /** + * Returns true if the object associated with the item has an active movie + */ + virtual bool hasActiveMovie() const; + + /** + * Loads a frame + */ + virtual void loadFrame(int frameNumber); + + /** + * Get the current frame + */ + virtual int getMovieFrame() const; + + /** + * Get the game object associated with this item + */ + virtual CGameObject *getObject() const { return nullptr; } + + virtual void changeMode(PetElementMode newMode) { _mode = newMode; } + + void setMode(PetElementMode mode); + + /** + * Set whether the element is selected + */ + void setSelected(bool flag); + + /** + * Set the bounds for the element + */ + void setBounds(const Rect &r) { _bounds = r; } + + /** + * Translate the position of the element + */ + void translate(int deltaX, int deltaY) { _bounds.translate(deltaX, deltaY); } + + /** + * Translate the position of the element + */ + void translate(const Point &delta) { _bounds.translate(delta.x, delta.y); } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_ELEMENT_H */ diff --git a/engines/titanic/pet_control/pet_frame.cpp b/engines/titanic/pet_control/pet_frame.cpp new file mode 100644 index 0000000000..bc1a8e93b6 --- /dev/null +++ b/engines/titanic/pet_control/pet_frame.cpp @@ -0,0 +1,154 @@ +/* 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 "titanic/pet_control/pet_frame.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +static const PetArea PET_AREAS[6] = { + PET_CONVERSATION, PET_INVENTORY, PET_REMOTE, + PET_ROOMS, PET_REAL_LIFE, PET_STARFIELD +}; + +CPetFrame::CPetFrame() : CPetSection() { +} + +bool CPetFrame::setup(CPetControl *petControl) { + if (setPetControl(petControl)) + return reset(); + return false; +} + +bool CPetFrame::reset() { + if (_petControl) { + _background.reset("PetBackground", _petControl, MODE_UNSELECTED); + _modeBackground.reset("PetModeBackground", _petControl, MODE_UNSELECTED); + + for (int idx = 0; idx < 5; ++idx) { + CString resName = Common::String::format("PetMode%d", idx + 1); + _modeButtons[idx].reset(resName, _petControl, MODE_SELECTED); + } + + for (int idx = 0; idx < 6; ++idx) { + CString resName = Common::String::format("3Pettitle%d", idx + 1); + _titles[idx].reset(resName, _petControl, MODE_UNSELECTED); + } + + for (int idx = 0; idx < TOTAL_GLYPHS; ++idx) { + CString resName = Common::String::format("PetIndent%d", idx + 1); + _squares[idx].reset(resName, _petControl, MODE_UNSELECTED); + } + } + + return true; +} + +bool CPetFrame::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + for (int idx = 0; idx < 5; ++idx) { + if (_modeButtons[idx].MouseButtonUpMsg(msg->_mousePos)) { + _petControl->setArea(PET_AREAS[idx]); + resetArea(); + _modeButtons[idx].setMode(MODE_SELECTED); + return true; + } + } + + return false; +} + +bool CPetFrame::isValid(CPetControl *petControl) { + bool result = setPetControl(petControl); + if (result) { + _modeButtons[PET_AREAS[0]].setMode(MODE_UNSELECTED); + _modeButtons[PET_AREAS[4]].setMode(MODE_SELECTED); + } + + return result; +} + +void CPetFrame::postLoad() { + reset(); +} + +bool CPetFrame::setPetControl(CPetControl *petControl) { + if (petControl) { + _petControl = petControl; + + // Set the bounds of the individual elements + _background.setBounds(Rect(20, 350, 620, 480)); + _modeBackground.setBounds(Rect(590, 365, 611, 467)); + + // Squares used for holding glyphs in various tabs + Rect r(35, 373, 91, 429); + for (int idx = 0, xp = 0; idx < TOTAL_GLYPHS; ++idx, xp += 70) { + _squares[idx].setBounds(r); + _squares[idx].translate(xp, 0); + } + + // Draw the mode buttons vertically on the right edge of the PET + r = Rect(590, 365, 606, 381); + const int YLIST[] = { 7, 27, 45, 66, 84 }; + for (int idx = 0; idx < 5; ++idx) { + _modeButtons[idx].setBounds(r); + _modeButtons[idx].translate(4, YLIST[idx]); + } + _modeButtons[PET_AREAS[0]].setMode(MODE_SELECTED); + + const int XLIST[] = { 73, 54, 85, 109, 38, 71 }; + for (int idx = 0; idx < 6; ++idx) { + _titles[idx].setBounds(Rect(0, 0, 110, 11)); + _titles[idx].translate(600 - XLIST[idx], 471); + } + } + + return true; +} + +void CPetFrame::setArea(PetArea newArea) { + resetArea(); + if (newArea < PET_MESSAGE) + _modeButtons[PET_AREAS[newArea]].setMode(MODE_SELECTED); +} + +void CPetFrame::resetArea() { + for (int idx = 0; idx < 6; ++idx) + _modeButtons[idx].setMode(MODE_UNSELECTED); +} + +void CPetFrame::drawFrame(CScreenManager *screenManager) { + _background.draw(screenManager); + _modeBackground.draw(screenManager); + + for (int idx = 0; idx < 5; ++idx) + _modeButtons[idx].draw(screenManager); + + _titles[_petControl->_currentArea].draw(screenManager); +} + +void CPetFrame::drawSquares(CScreenManager *screenManager, int count) { + count = CLIP(count, 0, TOTAL_GLYPHS); + for (int idx = 0; idx < count; ++idx) + _squares[idx].draw(screenManager); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_frame.h b/engines/titanic/pet_control/pet_frame.h new file mode 100644 index 0000000000..d8924e83d3 --- /dev/null +++ b/engines/titanic/pet_control/pet_frame.h @@ -0,0 +1,101 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_FRAME_H +#define TITANIC_PET_FRAME_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_gfx_element.h" + +namespace Titanic { + +/** + * This implements the frame and background for the PET display. + * This includes the area buttons and title + */ +class CPetFrame : public CPetSection { +private: + CPetGfxElement _modeButtons[6]; + CPetGfxElement _titles[6]; + CPetGfxElement _modeBackground; + CPetGfxElement _val2; + CPetGfxElement _val3; + CPetGfxElement _background; + CPetGfxElement _squares[7]; +private: + /** + * Called to set the owning PET instance and set some initial state + */ + bool setPetControl(CPetControl *petControl); +public: + CPetFrame(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Sets up the section + */ + virtual bool reset(); + + /** + * Handles mouse down messages + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg) { return false; } + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Called when the current PET area changes + */ + void setArea(PetArea newArea); + + /** + * Reset the currently selected area + */ + void resetArea(); + + /** + * Draws the PET frame + */ + void drawFrame(CScreenManager *screenManager); + + /** + * Draws the indent + */ + void drawSquares(CScreenManager *screenManager, int count); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_FRAME_H */ diff --git a/engines/titanic/pet_control/pet_gfx_element.cpp b/engines/titanic/pet_control/pet_gfx_element.cpp new file mode 100644 index 0000000000..6022885770 --- /dev/null +++ b/engines/titanic/pet_control/pet_gfx_element.cpp @@ -0,0 +1,103 @@ +/* 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/textconsole.h" +#include "titanic/core/game_object.h" +#include "titanic/pet_control/pet_element.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +void CPetGfxElement::setup(PetElementMode mode, const CString &name, + CPetControl *petControl) { + switch (mode) { + case MODE_UNSELECTED: + _object0 = petControl->getHiddenObject(name); + break; + case MODE_SELECTED: + _object1 = petControl->getHiddenObject(name); + break; + case MODE_FOCUSED: + _object2 = petControl->getHiddenObject(name); + break; + default: + break; + } +} + +void CPetGfxElement::reset(const CString &name, CPetControl *petControl, PetElementMode mode) { + if (!petControl) + return; + + CString numString(3); + int classNum = petControl->getPassengerClass(); + + if (classNum >= 1 && classNum <= 3) { + numString = CString(classNum); + } else if (classNum == 4) { + int stateC = petControl->getPriorClass(); + if (stateC == 1) + numString = CString(stateC); + } + + CString resName = numString + name; + setup(mode, resName, petControl); +} + +void CPetGfxElement::draw(CScreenManager *screenManager) { + draw(screenManager, Common::Point(_bounds.left, _bounds.top)); +} + +void CPetGfxElement::draw(CScreenManager *screenManager, const Common::Point &destPos) { + CGameObject *obj = getObject(); + if (!obj) + obj = _object0; + + if (obj) + obj->draw(screenManager, destPos); +} + +Rect CPetGfxElement::getBounds() const { + CGameObject *obj = getObject(); + if (!obj) + obj = _object0; + + if (obj && obj->surfaceHasFrame()) + return _bounds; + else + return Rect(); +} + +CGameObject *CPetGfxElement::getObject() const { + switch (_mode) { + case MODE_UNSELECTED: + return _object0; + case MODE_SELECTED: + return _object1; + case MODE_FOCUSED: + return _object2; + default: + return nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_gfx_element.h b/engines/titanic/pet_control/pet_gfx_element.h new file mode 100644 index 0000000000..91d9b9ccb2 --- /dev/null +++ b/engines/titanic/pet_control/pet_gfx_element.h @@ -0,0 +1,74 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_GFX_ELEMENT_H +#define TITANIC_PET_GFX_ELEMENT_H + +#include "titanic/pet_control/pet_element.h" + +namespace Titanic { + +class CPetGfxElement: public CPetElement { +public: + CGameObject *_object0; + CGameObject *_object1; + CGameObject *_object2; +public: + CPetGfxElement() : CPetElement(), _object0(nullptr), _object1(nullptr), + _object2(nullptr) {} + + /** + * Setup the element + */ + virtual void setup(PetElementMode mode, const CString &name, + CPetControl *petControl); + + /** + * Reset the element + */ + virtual void reset(const CString &name, CPetControl *petControl, + PetElementMode mode = MODE_UNSELECTED); + + /** + * Draw the item + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Draw the item + */ + virtual void draw(CScreenManager *screenManager, const Common::Point &destPos); + + /** + * Get the bounds for the element + */ + virtual Rect getBounds() const; + + /** + * Get the game object associated with this item + */ + virtual CGameObject *getObject() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_GFX_ELEMENT_H */ diff --git a/engines/titanic/pet_control/pet_glyphs.cpp b/engines/titanic/pet_control/pet_glyphs.cpp new file mode 100644 index 0000000000..bd05342095 --- /dev/null +++ b/engines/titanic/pet_control/pet_glyphs.cpp @@ -0,0 +1,566 @@ +/* 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 "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +bool CPetGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + _element.setBounds(Rect(0, 0, 52, 50)); + _owner = owner; + return true; +} + +void CPetGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted_) { + _element.translate(pt.x, pt.y); + _element.draw(screenManager); + _element.translate(-pt.x, -pt.y); +} + +void CPetGlyph::updateTooltip() { + CPetText *petText = getPetSection()->getText(); + if (petText) { + petText->setColor(getPetSection()->getColor(0)); + getTooltip(petText); + + if (_owner) + getPetSection()->stopTextTimer(); + } +} + +bool CPetGlyph::contains(const Point &delta, const Point &pt) { + translate(delta); + bool result = _element.contains2(pt); + translateBack(delta); + + return result; +} + +CPetSection *CPetGlyph::getPetSection() const { + return _owner ? _owner->getOwner() : nullptr; +} + +CPetControl *CPetGlyph::getPetControl() const { + return _owner ? _owner->getPetControl() : nullptr; +} + +void CPetGlyph::setName(const CString &name, CPetControl *petControl) { + Rect r(0, 0, 52, 52); + _element.setBounds(r); + _element.reset(name, petControl, MODE_UNSELECTED); +} + +bool CPetGlyph::isHighlighted() const { + return _owner->isGlyphHighlighted(this); +} + +/*------------------------------------------------------------------------*/ + +CPetGlyphs::CPetGlyphs() : _firstVisibleIndex(0), _numVisibleGlyphs(TOTAL_GLYPHS), + _highlightIndex(-1), _field1C(-1), _flags(0), + _dragGlyph(nullptr), _owner(nullptr) { +} + +void CPetGlyphs::setNumVisible(int total) { + if (total > 0) + _numVisibleGlyphs = total; +} + +void CPetGlyphs::clear() { + changeHighlight(-1); + destroyContents(); + _firstVisibleIndex = 0; +} + +void CPetGlyphs::setup(int numVisible, CPetSection *owner) { + setNumVisible(numVisible); + _owner = owner; + _selection.setBounds(Rect(0, 0, 76, 76)); + + int buttonsLeft = numVisible * 70 + 21; + + _scrollLeft.setBounds(Rect(0, 0, 31, 15)); + _scrollLeft.translate(buttonsLeft, 373); + _scrollRight.setBounds(Rect(0, 0, 31, 15)); + _scrollRight.translate(buttonsLeft, 413); +} + +void CPetGlyphs::reset() { + if (_owner && _owner->_petControl) { + CPetControl *pet = _owner->_petControl; + + _scrollLeft.reset("PetScrollLeft", pet, MODE_UNSELECTED); + _scrollRight.reset("PetScrollRight", pet, MODE_UNSELECTED); + _selection.reset("PetSelection", pet, MODE_UNSELECTED); + + for (iterator i = begin(); i != end(); ++i) { + (*i)->reset(); + } + } +} + +void CPetGlyphs::enter() { + if (_highlightIndex != -1) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph) + glyph->enter(); + } +} + +void CPetGlyphs::leave() { + if (_highlightIndex != -1) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph) + glyph->leave(); + } +} + +void CPetGlyphs::draw(CScreenManager *screenManager) { + if (_highlightIndex != -1) { + int index = getHighlightedIndex(_highlightIndex); + if (index != -1) { + Point tempPoint; + Point pt = getPosition(index); + pt -= Point(12, 13); + _selection.translate(pt.x, pt.y); + _selection.draw(screenManager); + _selection.translate(-pt.x, -pt.y); + } + } + + // Iterate through displaying glyphs on the screen + int listSize = size(); + for (int index = 0; index < _numVisibleGlyphs; ++index) { + int itemIndex = getItemIndex(index); + + if (itemIndex >= 0 && itemIndex < listSize) { + Point pt = getPosition(itemIndex); + CPetGlyph *glyph = getGlyph(itemIndex); + + if (glyph) + glyph->drawAt(screenManager, pt, index == _highlightIndex); + } + } + + // Draw scrolling arrows if more than a screen's worth of items are showing + if (listSize > _numVisibleGlyphs || (_flags & GFLAG_16)) { + _scrollLeft.draw(screenManager); + _scrollRight.draw(screenManager); + } + + // Handle secondary highlight + if (_highlightIndex != -1) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph) + glyph->draw2(screenManager); + } +} + +Point CPetGlyphs::getPosition(int index) const { + Point tempPoint(37 + index * 70, 375); + return tempPoint; +} + +Rect CPetGlyphs::getRect(int index) const { + Point pt = getPosition(index); + return Rect(pt.x, pt.y, pt.x + 52, pt.y + 52); +} + +void CPetGlyphs::changeHighlight(int index) { + if (index == _highlightIndex) + return; + + if (_highlightIndex >= 0 && (_flags & GFLAG_4)) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph) + glyph->unhighlightCurrent(); + } + + _highlightIndex = index; + if (index >= 0) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + + if (glyph) { + if (_flags & GFLAG_4) { + Point pt; + int idx = getHighlightedIndex(_highlightIndex); + if (idx >= 0) + pt = getPosition(idx); + + glyph->highlightCurrent(pt); + } + + glyph->updateTooltip(); + } + } else if (_owner) { + _owner->removeText(); + } +} + +void CPetGlyphs::highlight(int index) { + if (index >= 0) { + setSelectedIndex(index); + changeHighlight(index); + makePetDirty(); + } +} + +void CPetGlyphs::highlight(const CPetGlyph *glyph) { + highlight(indexOf(glyph)); +} + +int CPetGlyphs::getHighlightedIndex(int index) const { + int idx = index - _firstVisibleIndex; + return (idx >= 0 && idx < _numVisibleGlyphs) ? idx : -1; +} + +int CPetGlyphs::getItemIndex(int index) const { + return _firstVisibleIndex + index; +} + +void CPetGlyphs::setSelectedIndex(int index) { + if (index >= 0 && index < (int)size() && getHighlightedIndex(index) == -1) { + if (_firstVisibleIndex <= index) + index -= _numVisibleGlyphs - 1; + + setFirstVisible(index); + } +} + +CPetGlyph *CPetGlyphs::getGlyph(int index) const { + for (const_iterator i = begin(); i != end(); ++i) { + if (index-- == 0) + return *i; + } + + return nullptr; +} + +CPetControl *CPetGlyphs::getPetControl() const { + return _owner ? _owner->getPetControl() : nullptr; +} + +void CPetGlyphs::setFirstVisible(int index) { + if (index != _firstVisibleIndex) { + _firstVisibleIndex = index; + + if ((_flags & GFLAG_8) && _highlightIndex != -1) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + + if (glyph) { + int idx = getHighlightedIndex(_highlightIndex); + if (idx != -1) { + Point tempPt = getPosition(idx); + glyph->glyphFocused(tempPt, true); + } + } + } + } +} + +void CPetGlyphs::scrollLeft() { + if (_firstVisibleIndex > 0) { + setFirstVisible(_firstVisibleIndex - 1); + if (_highlightIndex != -1) { + int index = getHighlightedIndex(_highlightIndex); + if (index == -1) + changeHighlight(_highlightIndex - 1); + } + + makePetDirty(); + } +} + +void CPetGlyphs::scrollRight() { + int count = size(); + int right = count - _numVisibleGlyphs; + + if (_firstVisibleIndex < right) { + setFirstVisible(_firstVisibleIndex + 1); + if (_highlightIndex != -1) { + int index = getHighlightedIndex(_highlightIndex); + if (index == -1) + changeHighlight(_highlightIndex + 1); + } + + makePetDirty(); + } +} + +void CPetGlyphs::makePetDirty() { + if (_owner && _owner->_petControl) + _owner->_petControl->makeDirty(); +} + +bool CPetGlyphs::MouseButtonDownMsg(const Point &pt) { + if (_scrollLeft.contains2(pt)) { + scrollLeft(); + return true; + } + + if (_scrollRight.contains2(pt)) { + scrollRight(); + return true; + } + + for (int idx = 0; idx < _numVisibleGlyphs; ++idx) { + Rect glyphRect = getRect(idx); + if (glyphRect.contains(pt)) { + int index = getItemIndex(idx); + CPetGlyph *glyph = getGlyph(index); + if (glyph) { + if (_highlightIndex == index) { + glyph->selectGlyph(glyphRect, pt); + glyph->updateTooltip(); + } else { + changeHighlight(index); + makePetDirty(); + } + + return true; + } + } + } + + if (_highlightIndex != -1) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + + if (glyph) { + if (glyph->MouseButtonDownMsg(pt)) + return true; + + if (!(_flags & GFLAG_2)) { + changeHighlight(-1); + makePetDirty(); + } + } + } + + return false; +} + +bool CPetGlyphs::MouseButtonUpMsg(const Point &pt) { + if (_highlightIndex >= 0) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph) { + if (glyph->MouseButtonUpMsg(pt)) + return true; + } + } + + return false; +} + +bool CPetGlyphs::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!(_flags & GFLAG_1) && _highlightIndex >= 0) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + int index = getHighlightedIndex(_highlightIndex); + Rect glyphRect = getRect(index); + + if (glyphRect.contains(msg->_mousePos)) + return glyph->dragGlyph(glyphRect, msg); + else + return glyph->MouseDragStartMsg(msg); + } + + return false; +} + +bool CPetGlyphs::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + if (_dragGlyph) { + return _dragGlyph->MouseDragMoveMsg(msg); + } else { + return false; + } +} + +bool CPetGlyphs::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (_dragGlyph) { + return _dragGlyph->MouseDragEndMsg(msg); + } else { + return false; + } +} + +bool CPetGlyphs::KeyCharMsg(int key) { + if (_highlightIndex >= 0) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + + if (glyph && glyph->KeyCharMsg(key)) + return true; + } + + return false; +} + +bool CPetGlyphs::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + Common::KeyCode key = msg->_keyState.keycode; + + switch (key) { + case Common::KEYCODE_LEFT: + decSelection(); + return true; + + case Common::KEYCODE_RIGHT: + incSelection(); + return true; + + default: + break; + } + + if (_highlightIndex >= 0) { + CPetGlyph *glyph = getGlyph(_highlightIndex); + if (glyph && glyph->VirtualKeyCharMsg(msg)) + return true; + } + + return false; +} + +bool CPetGlyphs::enterHighlighted() { + if (_highlightIndex >= 0) + return getGlyph(_highlightIndex)->enterHighlighted(); + else + return false; +} + +void CPetGlyphs::leaveHighlighted() { + if (_highlightIndex >= 0) + getGlyph(_highlightIndex)->leaveHighlighted(); +} + +void CPetGlyphs::startDragging(CPetGlyph *glyph, CMouseDragStartMsg *msg) { + if (glyph) { + _dragGlyph = glyph; + msg->_dragItem = getPetControl(); + } +} + +void CPetGlyphs::endDragging() { + _dragGlyph = nullptr; +} + +bool CPetGlyphs::highlighted14() { + if (_highlightIndex != -1) { + CPetGlyph *pet = getGlyph(_highlightIndex); + if (pet) { + pet->updateTooltip(); + return true; + } + } + + return false; +} + +int CPetGlyphs::indexOf(const CPetGlyph *glyph) const { + int index = 0; + for (const_iterator i = begin(); i != end(); ++i, ++index) { + if (*i == glyph) + return index; + } + + return -1; +} + +void CPetGlyphs::incSelection() { + if (_highlightIndex >= 0 && _highlightIndex < ((int)size() - 1)) { + if (getHighlightedIndex(_highlightIndex) >= (_numVisibleGlyphs - 1)) + scrollRight(); + + changeHighlight(_highlightIndex + 1); + makePetDirty(); + } +} + +void CPetGlyphs::decSelection() { + if (_highlightIndex > 0) { + if (getHighlightedIndex(_highlightIndex) == 0) + scrollLeft(); + + changeHighlight(_highlightIndex - 1); + makePetDirty(); + } +} + +CGameObject *CPetGlyphs::getObjectAt(const Point &pt) const { + for (int idx = 0; idx < _numVisibleGlyphs; ++idx) { + Rect glyphRect = getRect(idx); + if (glyphRect.contains(pt)) { + CPetGlyph *glyph = getGlyph(getItemIndex(idx)); + if (glyph) + return glyph->getObjectAt(); + } + } + + return nullptr; +} + +bool CPetGlyphs::isGlyphHighlighted(const CPetGlyph *glyph) const { + if (_highlightIndex == -1) + return false; + + return indexOf(glyph) == _highlightIndex; +} + +Point CPetGlyphs::getHighlightedGlyphPos() const { + if (_highlightIndex != -1) { + int idx = getHighlightedIndex(_highlightIndex); + if (idx >= 0) + return getPosition(idx); + } + + return Point(0, 0); +} + +bool CPetGlyphs::areItemsValid() const { + for (const_iterator i = begin(); i != end(); ++i) { + if (!(*i)->isValid()) + return false; + } + + return true; +} + +void CPetGlyphs::removeInvalid() { + if (!areItemsValid()) { + changeHighlight(-1); + + for (iterator i = begin(); i != end(); ) { + CPetGlyph *glyph = *i; + + if (!glyph->isValid()) { + i = erase(i); + delete glyph; + } else { + ++i; + } + } + + _firstVisibleIndex = CLIP(_firstVisibleIndex, 0, + (int)size() - _numVisibleGlyphs); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_glyphs.h b/engines/titanic/pet_control/pet_glyphs.h new file mode 100644 index 0000000000..c07cc5ed9a --- /dev/null +++ b/engines/titanic/pet_control/pet_glyphs.h @@ -0,0 +1,492 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_GLYPHS_H +#define TITANIC_PET_GLYPHS_H + +#include "common/keyboard.h" +#include "titanic/core/list.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/pet_control/pet_gfx_element.h" +#include "titanic/support/rect.h" + +namespace Titanic { + +#define TOTAL_GLYPHS 7 + +class CPetGlyphs; +class CPetSection; +class CPetText; + +enum GlyphActionMode { ACTION_REMOVE = 0, ACTION_REMOVED = 1, ACTION_CHANGE = 2 }; + +enum GlyphFlag { GFLAG_1 = 1, GFLAG_2 = 2, GFLAG_4 = 4, GFLAG_8 = 8, GFLAG_16 = 16 }; + +class CGlyphAction { +protected: + GlyphActionMode _mode; +public: + CGlyphAction() : _mode(ACTION_REMOVED) {} + CGlyphAction(GlyphActionMode mode) : _mode(mode) {} + + GlyphActionMode getMode() const { return _mode; } +}; + +class CPetGlyph : public ListItem { +protected: + /** + * Get the overall pet section owner + */ + CPetSection *getPetSection() const; +public: + CPetGfxElement _element; + CPetGlyphs *_owner; +public: + CPetGlyph() : ListItem(), _owner(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Reset the glyph + */ + virtual bool reset() { return false; } + + /** + * Called when the PET area is entered + */ + virtual void enter() {} + + /** + * Called when the PET area is left + */ + virtual void leave() {} + + /** + * Draw the glyph at a specified position + */ + virtual void drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager) {} + + /** + * Updates the tooltip being shown for the glyph + */ + virtual void updateTooltip(); + + /** + * Get the bounds for the glyph + */ + virtual Rect getBounds() const { return Rect(); } + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { return false; } + + /** + * Called when mouse drag starts + */ + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg) { return false; } + + /** + * Called during mouse drags + */ + virtual bool MouseDragMoveMsg(CMouseDragMoveMsg *msg) { return false; } + + /** + * Called when mouse drag ends + */ + virtual bool MouseDragEndMsg(CMouseDragEndMsg *msg) { return false; } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { return false; } + + /** + * Handles mouse double-click messages + */ + virtual bool MouseDoubleClickMsg(const CMouseDoubleClickMsg *msg) { return false; } + + /** + * Handles keypresses + */ + virtual bool KeyCharMsg(int key) { return false; } + + /** + * Handles keypresses + */ + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { return false; } + + /** + * Unhighlight any currently highlighted element + */ + virtual void unhighlightCurrent() {} + + /** + * Highlight any currently highlighted element + */ + virtual void highlightCurrent(const Point &pt) {} + + /** + * Glyph has been shifted to be first visible one + */ + virtual void glyphFocused(const Point &topLeft, bool flag) {} + + /** + * Selects a glyph + */ + virtual void selectGlyph(const Point &topLeft, const Point &pt) {} + + /** + * Called when a glyph drag starts + */ + virtual bool dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg) { return false; } + + /** + * Returns true if the glyph's bounds, shifted to a given position, + * will contain the specified point + */ + virtual bool contains(const Point &delta, const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text) {} + + /** + * Saves the data for the glyph + */ + virtual void saveGlyph(SimpleFile *file, int indent) {} + + virtual bool proc33(CPetGlyph *glyph) { return true; } + + /** + * Return whether the glyph is currently valid + */ + virtual bool isValid() const { return true; } + + /** + * Called on a highlighted item when PET area is entered + */ + virtual bool enterHighlighted() { return false; } + + /** + * Called on a highlighted item when PET area is left + */ + virtual void leaveHighlighted() {} + + /** + * Returns the object associated with the glyph + */ + virtual CGameObject *getObjectAt() { return nullptr; } + + /** + * Does a processing action on the glyph + */ + virtual bool doAction(CGlyphAction *action) { return true; } + + /** + * Translate the glyph's position + */ + void translate(const Point &pt) { _element.translate(pt.x, pt.y); } + + /** + * Translate the glyph's position back + */ + void translateBack(const Point &pt) { _element.translate(-pt.x, -pt.y); } + + /** + * Get the parent RealLife area + */ + CPetGlyphs *getOwner() { return _owner; } + + /** + * Get the PET control + */ + CPetControl *getPetControl() const; + + /** + * Sets new name and default bounds for glyph + */ + void setName(const CString &name, CPetControl *petControl); + + /** + * Returns true if the specified glyph is the currently highlighted one + */ + bool isHighlighted() const; +}; + +class CPetGlyphs : public List<CPetGlyph> { +private: + /** + * Get a position for the glyph + */ + Point getPosition(int index) const; + + /** + * Get a rect for the glyph + */ + Rect getRect(int index) const; + + /** + * Returns the on-screen index for the highlight to be shown at + */ + int getHighlightedIndex(int index) const; + + /** + * Returns the index of a glyph given the visible on-screen glyph number + */ + int getItemIndex(int index) const; + + /** + * Set the item index + */ + void setSelectedIndex(int index); + + /** + * Return a specified glyph + */ + CPetGlyph *getGlyph(int index) const; + + /** + * Scrolls the glyphs to the left + */ + void scrollLeft(); + + /** + * Scrolls the glyphs to the right + */ + void scrollRight(); + + /** + * Set the first visible glyph index + */ + void setFirstVisible(int index); + + /** + * Make the PET dirty + */ + void makePetDirty(); + + /** + * Returns true if all the glyphs are in a valid state + */ + bool areItemsValid() const; +protected: + int _firstVisibleIndex; + int _totalGlyphs; + int _numVisibleGlyphs; + int _highlightIndex; + int _field1C; + int _flags; + CPetGlyph *_dragGlyph; + CPetSection *_owner; + CPetGfxElement _selection; + CPetGfxElement _scrollLeft; + CPetGfxElement _scrollRight; +protected: + /** + * Change the currently selected glyph + */ + void changeHighlight(int index); +public: + CPetGlyphs(); + + /** + * Set the number of visible glyphs + */ + void setNumVisible(int total); + + /** + * Clears the glyph list + */ + void clear(); + + + /** + * The visual dimensions for the control and it's components + */ + virtual void setup(int numVisible, CPetSection *owner); + + /** + * Set up the control + */ + virtual void reset(); + + /** + * Called when PET area is entered + */ + virtual void enter(); + + /** + * Called when PET area is left + */ + virtual void leave(); + + void setFlags(int flags) { _flags = flags; } + + /** + * Draw the control + */ + void draw(CScreenManager *screenManager); + + /** + * Highlight a specific glyph by indexe + */ + void highlight(int index); + + /** + * Highlight a specific glyph + */ + void highlight(const CPetGlyph *glyph); + + /** + * Get the owning section for the glyphs + */ + CPetSection *getOwner() const { return _owner; } + + /** + * Get the PET control + */ + CPetControl *getPetControl() const; + + /** + * Mouse button down message + */ + bool MouseButtonDownMsg(const Point &pt); + + /** + * Mouse button up message + */ + bool MouseButtonUpMsg(const Point &pt); + + /** + * Mouse double click message + */ + bool MouseDoubleClickMsg(const Point &pt) { return true; } + + /** + * Mouse drag start messagge + */ + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + + /** + * Mouse drag move message + */ + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + + /** + * Mouse drag end message + */ + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + + /** + * Key character message + */ + bool KeyCharMsg(int key); + + /** + * Virtual key message + */ + bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * When the PET section is entered, passes onto the highlighted + * glyph, if any + */ + bool enterHighlighted(); + + /** + * When the PET section is left, passes onto the highlighted + * glyph, if any + */ + void leaveHighlighted(); + + /** + * Called when a dragging operation starts + */ + void startDragging(CPetGlyph *glyph, CMouseDragStartMsg *msg); + + /** + * Called when a dragging operation ends + */ + void endDragging(); + + /** + * Reset the highlight + */ + void resetHighlight() { changeHighlight(-1); } + + bool highlighted14(); + + /** + * Returns the index of the specified glyph in the lsit + */ + int indexOf(const CPetGlyph *glyph) const; + + /** + * Resets the scrolling of the glyphs list back to the start + */ + void scrollToStart() { _firstVisibleIndex = 0; } + + /** + * Increment the currently selected index + */ + void incSelection(); + + /** + * Decrement the currently selected index + */ + void decSelection(); + + /** + * Returns the object associated the glyph under the specified position + */ + CGameObject *getObjectAt(const Point &pt) const; + + /** + * Returns true if the specified glyph is the currently highlighted one + */ + bool isGlyphHighlighted(const CPetGlyph *glyph) const; + + /** + * Get the top-left position of the currently highlighted glyph + */ + Point getHighlightedGlyphPos() const; + + /** + * Removes any glyphs from the list that no longer have any images + * associated with them + */ + void removeInvalid(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_GLYPHS_H */ diff --git a/engines/titanic/pet_control/pet_graphic.cpp b/engines/titanic/pet_control/pet_graphic.cpp new file mode 100644 index 0000000000..bc7d86142d --- /dev/null +++ b/engines/titanic/pet_control/pet_graphic.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetGraphic, CGameObject); + +void CPetGraphic::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPetGraphic::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_graphic.h b/engines/titanic/pet_control/pet_graphic.h new file mode 100644 index 0000000000..630c8446eb --- /dev/null +++ b/engines/titanic/pet_control/pet_graphic.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_GRAPHIC_H +#define TITANIC_PET_GRAPHIC_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPetGraphic : public CGameObject { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_GRAPHIC_H */ diff --git a/engines/titanic/pet_control/pet_graphic2.cpp b/engines/titanic/pet_control/pet_graphic2.cpp new file mode 100644 index 0000000000..36c4d0f55a --- /dev/null +++ b/engines/titanic/pet_control/pet_graphic2.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_graphic2.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetGraphic2, CGameObject); + +void CPetGraphic2::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPetGraphic2::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_graphic2.h b/engines/titanic/pet_control/pet_graphic2.h new file mode 100644 index 0000000000..58852fc65e --- /dev/null +++ b/engines/titanic/pet_control/pet_graphic2.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_GRAPHIC2_H +#define TITANIC_PET_GRAPHIC2_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPetGraphic2 : public CGameObject { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_GRAPHIC2_H */ diff --git a/engines/titanic/pet_control/pet_inventory.cpp b/engines/titanic/pet_control/pet_inventory.cpp new file mode 100644 index 0000000000..55176d8b0e --- /dev/null +++ b/engines/titanic/pet_control/pet_inventory.cpp @@ -0,0 +1,255 @@ +/* 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 "titanic/pet_control/pet_inventory.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/carry/carry.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CPetInventory::CPetInventory() : CPetSection(), + _movie(nullptr), _field290(false), _field294(0), _field298(0) { + for (int idx = 0; idx < TOTAL_ITEMS; ++idx) { + _itemBackgrounds[idx] = _itemGlyphs[idx] = nullptr; + } +} + +bool CPetInventory::setup(CPetControl *petControl) { + return setPetControl(petControl) && reset(); +} + +bool CPetInventory::reset() { + _items.reset(); + _text.setup(); + _text.setColor(getColor(0)); + _text.setLineColor(0, getColor(0)); + + return true; +} + +void CPetInventory::draw(CScreenManager *screenManager) { + _petControl->drawSquares(screenManager, 7); + _items.draw(screenManager); + _text.draw(screenManager); +} + +Rect CPetInventory::getBounds() const { + return _movie ? _movie->getBounds() : Rect(); +} + +void CPetInventory::changed(int changeType) { + switch (changeType) { + case 0: + case 2: + itemsChanged(); + break; + case 1: + removeInvalid(); + break; + default: + break; + } +} + +bool CPetInventory::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return _items.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetInventory::MouseDragStartMsg(CMouseDragStartMsg *msg) { + bool result = _items.MouseDragStartMsg(msg); + if (result) + _petControl->makeDirty(); + return result; +} + +bool CPetInventory::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return _items.MouseButtonUpMsg(msg->_mousePos); +} + +bool CPetInventory::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return _items.MouseDoubleClickMsg(msg->_mousePos); +} + +bool CPetInventory::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + return _items.VirtualKeyCharMsg(msg); +} + +CGameObject *CPetInventory::dragEnd(const Point &pt) const { + return _items.getObjectAt(pt); +} + +bool CPetInventory::isValid(CPetControl *petControl) { + setPetControl(petControl); + return true; +} + +void CPetInventory::load(SimpleFile *file, int param) { + _field298 = file->readNumber(); +} + +void CPetInventory::postLoad() { + reset(); + _field290 = 1; + itemsChanged(); + _field290 = 0; +} + +void CPetInventory::save(SimpleFile *file, int indent) { + file->writeNumberLine(_field298, indent); +} + +void CPetInventory::enter(PetArea oldArea) { + _items.enter(); +} + +void CPetInventory::leave() { + _items.leave(); +} + +CGameObject *CPetInventory::getBackground(int index) const { + return (index >= 0 && index < 46) ? _itemBackgrounds[index] : nullptr; +} + +bool CPetInventory::setPetControl(CPetControl *petControl) { + if (!petControl) + return false; + + _petControl = petControl; + _items.setup(7, this); + _items.setFlags(28); + + Rect tempRect(0, 0, 52, 52); + for (uint idx = 0; idx < TOTAL_ITEMS; ++idx) { + if (!g_vm->_itemNames[idx].empty()) { + CString name = "3Pet" + g_vm->_itemNames[idx]; + _itemBackgrounds[idx] = petControl->getHiddenObject(name); + } + + if (!g_vm->_itemObjects[idx].empty()) { + _itemGlyphs[idx] = petControl->getHiddenObject(g_vm->_itemObjects[idx]); + } + } + + tempRect = Rect(0, 0, 580, 15); + tempRect.translate(32, 445); + _text.setBounds(tempRect); + _text.setHasBorder(false); + + return true; +} + +void CPetInventory::change(CGameObject *item) { + if (item) { + CInventoryGlyphAction action(item, ACTION_CHANGE); + _items.doAction(&action); + } +} + +void CPetInventory::itemRemoved(CGameObject *item) { + if (item) { + CInventoryGlyphAction action(item, ACTION_REMOVED); + _items.doAction(&action); + } +} + +void CPetInventory::itemsChanged() { + _items.clear(); + + CGameObject *item = _petControl->getFirstObject(); + while (item) { + CPetInventoryGlyph *glyph = new CPetInventoryGlyph(); + glyph->setup(_petControl, &_items); + glyph->setItem(item, _field290); + + _items.push_back(glyph); + item = _petControl->getNextObject(item); + } +} + +void CPetInventory::highlightItem(CGameObject *item) { + int itemIndex = getItemIndex(item); + _items.highlight(itemIndex); +} + +int CPetInventory::getItemIndex(CGameObject *item) const { + int index = 0; + for (CGameObject *obj = _petControl->getFirstObject(); obj && obj != item; + ++index, obj = _petControl->getNextObject(obj)) { + } + + return index; +} + +CGameObject *CPetInventory::getImage(int index) { + if (index >= 0 && index < 46) { + int bits = 0; + switch (index) { + case 20: + bits = 4; + break; + case 21: + bits = 8; + break; + case 22: + bits = 1; + break; + case 23: + bits = 2; + break; + case 36: + bits = 32; + break; + case 39: + bits = 16; + break; + default: + break; + } + + if (!(bits & _field298)) { + _field298 = bits | _field298; + return _itemGlyphs[index]; + } + } + + return nullptr; +} + +void CPetInventory::playMovie(CGameObject *movie, int flag) { + if (_movie) + _movie->stopMovie(); + _movie = movie; + + if (_movie) { + if (flag) + _movie->playMovie(0, 14, 1); + else + _movie->playMovie(0); + } +} + +void CPetInventory::removeInvalid() { + _items.removeInvalid(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_inventory.h b/engines/titanic/pet_control/pet_inventory.h new file mode 100644 index 0000000000..17649546ce --- /dev/null +++ b/engines/titanic/pet_control/pet_inventory.h @@ -0,0 +1,174 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_INVENTORY_H +#define TITANIC_PET_INVENTORY_H + +#include "titanic/support/simple_file.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_inventory_glyphs.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +/** + * Handles displaying the player's inventory in the PET + */ +class CPetInventory : public CPetSection { +private: + CPetText _text; + CPetInventoryGlyphs _items; + CGameObject *_itemBackgrounds[46]; + CGameObject *_itemGlyphs[46]; + CGameObject *_movie; + bool _field290; + int _field294; + int _field298; +private: + /** + * Handles initial setup + */ + bool setPetControl(CPetControl *petControl); + + /** + * Get the index of an item added to the PET + */ + int getItemIndex(CGameObject *item) const; + + /** + * Remove any invalid inventory glyphs + */ + void removeInvalid(); +public: + CPetInventory(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Sets up the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Get the bounds for the section + */ + virtual Rect getBounds() const; + + /** + * Called when a general change occurs + */ + virtual void changed(int changeType); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + virtual bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * Returns item a drag-drop operation has dropped on, if any + */ + virtual CGameObject *dragEnd(const Point &pt) const; + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea); + + /** + * Called when a section is being left, to switch to another area + */ + virtual void leave(); + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText() { return &_text; } + + /** + * Special retrieval of glyph background image + */ + virtual CGameObject *getBackground(int index) const; + + /** + * + */ + void change(CGameObject *item); + + /** + * Called when an item has been removed from the PET + */ + void itemRemoved(CGameObject *item); + + /** + * Called when the items under the PET have changed + */ + void itemsChanged(); + + /** + * Called when the inventory can't be shown after adding an item + */ + void highlightItem(CGameObject *item); + + CGameObject *getImage(int index); + + /** + * Play the animated movie for an object + */ + void playMovie(CGameObject *movie, int flag); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_INVENTORY_H */ diff --git a/engines/titanic/pet_control/pet_inventory_glyphs.cpp b/engines/titanic/pet_control/pet_inventory_glyphs.cpp new file mode 100644 index 0000000000..ae306649a2 --- /dev/null +++ b/engines/titanic/pet_control/pet_inventory_glyphs.cpp @@ -0,0 +1,342 @@ +/* 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 "titanic/pet_control/pet_inventory_glyphs.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_inventory.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/titanic.h" + +namespace Titanic { + +const uint ITEM_MODES[40] = { + 0, 2, 11, 10, 12, 13, 9, 40, 7, 6, + 4, 5, 8, 15, 19, 24, 25, 26, 30, 20, + 21, 22, 23, 36, 39, 39, 31, 31, 32, 32, + 33, 34, 35, 38, 41, 42, 43, 44, 45, 37 +}; + +void CPetInventoryGlyph::enter() { + startBackgroundMovie(); +} + +void CPetInventoryGlyph::leave() { + stopMovie(); +} + +void CPetInventoryGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted_) { + if (!_field34) + return; + + if (_image) { + if (_image->hasActiveMovie()) { + if (isHighlighted_) + _image->draw(screenManager); + else + _image->draw(screenManager, pt); + return; + } + + _image = nullptr; + if (_background && isHighlighted_) { + _background->setPosition(pt); + startBackgroundMovie(); + } + } + + if (_background) { + if (isHighlighted_) + _background->draw(screenManager); + else + _background->draw(screenManager, pt); + } else if (_image) { + _image->draw(screenManager, pt, Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + } +} + + +void CPetInventoryGlyph::unhighlightCurrent() { + if (_image) { + _image->setPosition(Point(0, 0)); + stopMovie(); + } else if (_background) { + _background->setPosition(Point(0, 0)); + _background->loadFrame(0); + stopMovie(); + } +} + +void CPetInventoryGlyph::highlightCurrent(const Point &pt) { + reposition(pt); + if (_item) { + CPETObjectSelectedMsg selectedMsg; + selectedMsg.execute(_item); + } +} + +void CPetInventoryGlyph::glyphFocused(const Point &topLeft, bool flag) { + if (_background && flag) + _background->setPosition(topLeft); +} + +bool CPetInventoryGlyph::dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg) { + if (!_item) + return false; + + if (_background) { + _field34 = 0; + stopMovie(); + } + + CPetControl *petControl = getPetControl(); + if (!petControl) + return false; + + CGameObject *carryParcel = petControl->getHiddenObject("CarryParcel"); + + if (petControl->isSuccUBusActive() && carryParcel) { + petControl->removeFromInventory(_item, carryParcel, false, true); + petControl->removeFromInventory(_item, false, false); + + carryParcel->setPosition(Point(msg->_mousePos.x - carryParcel->getBounds().width() / 2, + msg->_mousePos.y - carryParcel->getBounds().height() / 2)); + _item->setPosition(Point(SCREEN_WIDTH, SCREEN_HEIGHT)); + } else { + petControl->removeFromInventory(_item, false, true); + + _item->setPosition(Point(msg->_mousePos.x - carryParcel->getBounds().width() / 2, + msg->_mousePos.y - carryParcel->getBounds().height() / 2)); + _item->setVisible(true); + } + + msg->_handled = true; + if (msg->execute(carryParcel)) { + _item = nullptr; + _background = nullptr; + _field34 = 0; + petControl->setAreaChangeType(1); + return true; + } else { + petControl->addToInventory(carryParcel); + return false; + } +} + +void CPetInventoryGlyph::getTooltip(CPetText *text) { + if (text) { + text->setText(""); + + if (_field34 && _item) { + int itemIndex = populateItem(_item, 0); + if (itemIndex >= 14 && itemIndex <= 18) { + CPETObjectStateMsg stateMsg(0); + stateMsg.execute(_item); + + text->setText(CString::format("%s %s", + stateMsg._value ? "A hot " : "A cold ", + g_vm->_itemDescriptions[itemIndex].c_str() + )); + + } else { + text->setText(g_vm->_itemDescriptions[itemIndex]); + } + } + } +} + +bool CPetInventoryGlyph::doAction(CGlyphAction *action) { + CInventoryGlyphAction *invAction = static_cast<CInventoryGlyphAction *>(action); + CPetInventoryGlyphs *owner = static_cast<CPetInventoryGlyphs *>(_owner); + if (!invAction) + return false; + + switch (invAction->getMode()) { + case ACTION_REMOVED: + if (invAction->_item == _item) { + _item = nullptr; + _background = nullptr; + _field34 = 0; + } + break; + + case ACTION_REMOVE: + if (_item == invAction->_item && _owner) { + int v = populateItem(_item, 0); + _background = owner->getBackground(v); + + if (isHighlighted()) { + Point glyphPos = _owner->getHighlightedGlyphPos(); + reposition(glyphPos); + updateTooltip(); + } + } + break; + + default: + break; + } + + return true; +} + +void CPetInventoryGlyph::setItem(CGameObject *item, int val) { + _item = item; + + if (_owner && item) { + int v1 = populateItem(item, val); + _background = static_cast<CPetInventoryGlyphs *>(_owner)->getBackground(v1); + _image = static_cast<CPetInventory *>(getPetSection())->getImage(v1); + } +} + +int CPetInventoryGlyph::populateItem(CGameObject *item, int val) { + // Scan the master item names list + CString itemName = item->getName(); + int itemIndex = -1; + for (int idx = 0; idx < 40 && itemIndex == -1; ++idx) { + if (itemName == g_vm->_itemIds[idx]) + itemIndex = idx; + } + if (itemIndex == -1) + return -1; + + switch (ITEM_MODES[itemIndex]) { + case 0: + switch (subMode(item, val)) { + case 0: + case 1: + return 0; + case 2: + case 3: + return 1; + default: + return 0; + } + + case 2: + switch (subMode(item, val)) { + case 0: + return 2; + default: + return 3; + } + break; + + case 15: + switch (subMode(item, val)) { + case 0: + case 1: + return 14; + case 2: + return 16; + case 3: + return 15; + case 4: + return 17; + case 5: + return 18; + default: + return 15; + } + break; + + case 26: + switch (subMode(item, val)) { + case 0: + return 26; + case 1: + return 29; + case 2: + return 28; + case 3: + return 27; + default: + return 26; + } + break; + + default: + break; + } + + return ITEM_MODES[itemIndex]; +} + +int CPetInventoryGlyph::subMode(CGameObject *item, int val) { + int frameNum = item->getFrameNumber(); + int movieFrame = item->getMovieFrame(); + + if (val && frameNum != -1 && frameNum != movieFrame) + item->loadFrame(frameNum); + + return frameNum; +} + +void CPetInventoryGlyph::startBackgroundMovie() { + if (_owner) { + CPetInventory *section = static_cast<CPetInventory *>(_owner->getOwner()); + if (section) + section->playMovie(_background, 1); + } +} + +void CPetInventoryGlyph::startForegroundMovie() { + if (_owner) { + CPetInventory *section = static_cast<CPetInventory *>(_owner->getOwner()); + if (section) + section->playMovie(_image, 1); + } +} + +void CPetInventoryGlyph::stopMovie() { + if (_owner) { + CPetInventory *section = static_cast<CPetInventory *>(_owner->getOwner()); + if (section) + section->playMovie(nullptr, 1); + } +} + +void CPetInventoryGlyph::reposition(const Point &pt) { + if (_image) { + _image->setPosition(pt); + startForegroundMovie(); + } else if (_background) { + _background->setPosition(pt); + startBackgroundMovie(); + } +} + +/*------------------------------------------------------------------------*/ + +bool CPetInventoryGlyphs::doAction(CInventoryGlyphAction *action) { + for (iterator i = begin(); i != end(); ++i) { + (*i)->doAction(action); + } + + return true; +} + +CGameObject *CPetInventoryGlyphs::getBackground(int index) { + return _owner ? _owner->getBackground(index) : nullptr; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_inventory_glyphs.h b/engines/titanic/pet_control/pet_inventory_glyphs.h new file mode 100644 index 0000000000..716c9d1ad1 --- /dev/null +++ b/engines/titanic/pet_control/pet_inventory_glyphs.h @@ -0,0 +1,153 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_INVENTORY_GLYPHS_H +#define TITANIC_PET_INVENTORY_GLYPHS_H + +#include "titanic/carry/carry.h" +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +class CPetInventoryGlyph : public CPetGlyph { +private: + /** + * Populate the details for an item + */ + int populateItem(CGameObject *item, int val); + + int subMode(CGameObject *item, int val); + + /** + * Start any movie for the background + */ + void startBackgroundMovie(); + + /** + * Start any movie for the foreground item + */ + void startForegroundMovie(); + + /** + * Stop any previously started foreground or background movie + */ + void stopMovie(); + + /** + * Reposition the inventory item + */ + void reposition(const Point &pt); +public: + CGameObject *_item; + int _field34; + CGameObject *_background; + CGameObject *_image; +public: + CPetInventoryGlyph() : _item(nullptr), _field34(1), + _background(nullptr), _image(nullptr) {} + CPetInventoryGlyph(CCarry *item, int val) : _item(item), + _field34(val), _background(nullptr), _image(nullptr) {} + + /** + * Called when the PET area is entered + */ + virtual void enter(); + + /** + * Called when the PET area is left + */ + virtual void leave(); + + /** + * Draw the glyph at a specified position + */ + virtual void drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted); + + /** + * Unhighlight any currently highlighted element + */ + virtual void unhighlightCurrent(); + + /** + * Highlight any currently highlighted element + */ + virtual void highlightCurrent(const Point &pt); + + /** + * Glyph has been shifted to be first visible one + */ + virtual void glyphFocused(const Point &topLeft, bool flag); + + /** + * Called when a glyph drag starts + */ + virtual bool dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); + + /** + * Return whether the glyph is currently valid + */ + virtual bool isValid() const { return _item && _background; } + + /** + * Returns the object associated with the glyph + */ + virtual CGameObject *getObjectAt() { return _item; } + + /** + * Does a processing action on the glyph + */ + virtual bool doAction(CGlyphAction *action); + + /** + * Set the inventory item + */ + void setItem(CGameObject *item, int val); +}; + +class CInventoryGlyphAction : public CGlyphAction { +public: + CGameObject *_item; +public: + CInventoryGlyphAction(CGameObject *item, GlyphActionMode mode) : + CGlyphAction(mode), _item(item) {} +}; + +class CPetInventoryGlyphs : public CPetGlyphs { + friend class CPetInventoryGlyph; +private: + CGameObject *getBackground(int index); +public: + /** + * Do an action on the glyphs + */ + bool doAction(CInventoryGlyphAction *item); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_INVENTORY_GLYPHS_H */ diff --git a/engines/titanic/pet_control/pet_leaf.cpp b/engines/titanic/pet_control/pet_leaf.cpp new file mode 100644 index 0000000000..718ffe5e6e --- /dev/null +++ b/engines/titanic/pet_control/pet_leaf.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_leaf.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(PETLeaf, CGameObject); + +void PETLeaf::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void PETLeaf::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_leaf.h b/engines/titanic/pet_control/pet_leaf.h new file mode 100644 index 0000000000..0c21352e39 --- /dev/null +++ b/engines/titanic/pet_control/pet_leaf.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_LEAF_H +#define TITANIC_PET_LEAF_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class PETLeaf : public CGameObject { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_LEAF_H */ diff --git a/engines/titanic/pet_control/pet_load.cpp b/engines/titanic/pet_control/pet_load.cpp new file mode 100644 index 0000000000..04eec54f25 --- /dev/null +++ b/engines/titanic/pet_control/pet_load.cpp @@ -0,0 +1,70 @@ +/* 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 "titanic/pet_control/pet_load.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/core/project_item.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +bool CPetLoad::reset() { + CPetLoadSave::reset(); + + CPetControl *pet = getPetControl(); + if (pet) { + setName("PetLoad", pet); + _btnLoadSave.reset("PetLoadOut", pet, MODE_UNSELECTED); + _btnLoadSave.reset("PetLoadIn", pet, MODE_SELECTED); + } + + return true; +} + +bool CPetLoad::MouseButtonUpMsg(const Point &pt) { + if (_btnLoadSave.MouseButtonUpMsg(pt)) { + execute(); + return true; + } else { + return false; + } +} + +void CPetLoad::getTooltip(CPetText *text) { + text->setText("Load the game."); +} + +void CPetLoad::execute() { + CPetControl *pet = getPetControl(); + + if (_savegameSlotNum >= 0 && _slotInUse[_savegameSlotNum]) { + CMainGameWindow *window = g_vm->_window; + + // WORKAROUND: Schedule the savegame to be loaded after frame rendering ends + window->loadGame(_savegameSlotNum); + } else if (pet) { + pet->displayMessage("You must select a game to load first."); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_load.h b/engines/titanic/pet_control/pet_load.h new file mode 100644 index 0000000000..421531974d --- /dev/null +++ b/engines/titanic/pet_control/pet_load.h @@ -0,0 +1,70 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_LOAD_H +#define TITANIC_PET_LOAD_H + +#include "titanic/pet_control/pet_load_save.h" + +namespace Titanic { + +class CPetLoad : public CPetLoadSave { +public: + /** + * Reset the glyph + */ + virtual bool reset(); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Highlight any currently highlighted element + */ + virtual void highlightCurrent(const Point &pt) { resetSlots(); } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); + + /** + * Highlights a save slot + */ + virtual void highlightSave(int index) {} + + /** + * Unhighlight a save slot + */ + virtual void unhighlightSave(int index) {} + + /** + * Executes the loading or saving + */ + virtual void execute(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_LOAD_H */ diff --git a/engines/titanic/pet_control/pet_load_save.cpp b/engines/titanic/pet_control/pet_load_save.cpp new file mode 100644 index 0000000000..aebe43551e --- /dev/null +++ b/engines/titanic/pet_control/pet_load_save.cpp @@ -0,0 +1,191 @@ +/* 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 "titanic/pet_control/pet_load_save.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/core/project_item.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int CPetLoadSave::_savegameSlotNum; + +bool CPetLoadSave::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetGlyph::setup(petControl, owner); + _savegameSlotNum = -1; + + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) { + Rect slotRect = getSlotBounds(idx); + _slotNames[idx].setBounds(slotRect); + _slotNames[idx].resize(3); + _slotNames[idx].setMaxCharsPerLine(22); + _slotNames[idx].setHasBorder(false); + _slotNames[idx].setup(); + } + + Rect r1(0, 0, 68, 52); + r1.moveTo(496, 388); + _btnLoadSave.setBounds(r1); + + Rect r2(0, 0, 168, 78); + r2.moveTo(309, 377); + _gutter.setBounds(r2); + return true; +} + +bool CPetLoadSave::reset() { + highlightChange(); + resetSlots(); + + CPetControl *pet = getPetControl(); + if (pet) { + _gutter.reset("PetSaveGutter", pet, MODE_UNSELECTED); + } + + return true; +} + +void CPetLoadSave::draw2(CScreenManager *screenManager) { + _gutter.draw(screenManager); + + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) + _slotNames[idx].draw(screenManager); + + _btnLoadSave.draw(screenManager); +} + +bool CPetLoadSave::MouseButtonDownMsg(const Point &pt) { + if (_btnLoadSave.MouseButtonDownMsg(pt)) + return true; + + checkSlotsHighlight(pt); + return false; +} + +bool CPetLoadSave::KeyCharMsg(int key) { + switch (key) { + case Common::KEYCODE_TAB: + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + if (_savegameSlotNum != -1) { + highlightSlot((_savegameSlotNum + 1) % 5); + getPetControl()->makeDirty(); + } + return true; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (_savegameSlotNum != -1) { + int slotNum = --_savegameSlotNum; + highlightSlot((slotNum == -1) ? SAVEGAME_SLOTS_COUNT - 1 : slotNum); + getPetControl()->makeDirty(); + } + return true; + + case Common::KEYCODE_RETURN: + case Common::KEYCODE_KP_ENTER: + execute(); + return true; + + default: + return false; + } +} + +Rect CPetLoadSave::getSlotBounds(int index) { + return Rect(323, 376 + index * 16, 473, 392 + index * 16); +} + +void CPetLoadSave::resetSlots() { + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) { + _slotNames[idx].setText("Empty"); + _slotInUse[idx] = false; + + // Try and open up the savegame for access + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading( + g_vm->generateSaveName(idx)); + + if (in) { + // Read in the savegame header data + CompressedFile file; + file.open(in); + + TitanicSavegameHeader header; + if (CProjectItem::readSavegameHeader(&file, header)) { + _slotInUse[idx] = true; + _slotNames[idx].setText(header._saveName); + } + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + file.close(); + } + } + + highlightSlot(_savegameSlotNum); +} + +void CPetLoadSave::highlightSlot(int index) { + unhighlightSave(_savegameSlotNum); + _savegameSlotNum = index; + highlightChange(); + highlightSave(_savegameSlotNum); +} + +void CPetLoadSave::highlightChange() { + CPetSection *section = getPetSection(); + + uint col = section ? section->getColor(3) : 0; + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) + _slotNames[idx].setColor(col); + + if (_savegameSlotNum != -1) { + col = section ? section->getColor(4) : 0; + _slotNames[_savegameSlotNum].setLineColor(0, col); + } +} + +bool CPetLoadSave::checkSlotsHighlight(const Point &pt) { + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) { + if (isSlotHighlighted(idx, pt)) { + highlightSlot(idx); + return true; + } + } + + return false; +} + +bool CPetLoadSave::isSlotHighlighted(int index, const Point &pt) { + Rect r = getSlotBounds(index); + if (r.contains(pt)) { + highlightSlot(index); + return true; + } else { + return false; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_load_save.h b/engines/titanic/pet_control/pet_load_save.h new file mode 100644 index 0000000000..dd1c907ef1 --- /dev/null +++ b/engines/titanic/pet_control/pet_load_save.h @@ -0,0 +1,119 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_LOAD_SAVE_H +#define TITANIC_PET_LOAD_SAVE_H + +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +#define SAVEGAME_SLOTS_COUNT 5 + +class CPetLoadSave : public CPetGlyph { +private: + /** + * Get the rect area for a given savegame name will be displayed in + */ + Rect getSlotBounds(int index); + + /** + * Highlight one of the slots + */ + void highlightSlot(int index); + + /** + * Called when savegame slot highlight changes or the view is reset + */ + void highlightChange(); + + /** + * Check for whether a slot is under the passed point + */ + bool checkSlotsHighlight(const Point &pt); + + /** + * Checks if a point is within a given saveame slot + */ + bool isSlotHighlighted(int index, const Point &pt); +protected: + CPetText _slotNames[SAVEGAME_SLOTS_COUNT]; + bool _slotInUse[SAVEGAME_SLOTS_COUNT]; + CPetGfxElement _btnLoadSave; + CPetGfxElement _gutter; + static int _savegameSlotNum; +protected: + /** + * Reset the slot names list + */ + void resetSlots(); +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Reset the glyph + */ + virtual bool reset(); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles keypresses when the glyph is focused + */ + virtual bool KeyCharMsg(int key); + + /** + * Resets highlighting on the save slots + */ + virtual void resetSaves() { resetSlots(); } + + /** + * Highlights a save slot + */ + virtual void highlightSave(int index) = 0; + + /** + * Unhighlight a save slot + */ + virtual void unhighlightSave(int index) = 0; + + /** + * Executes the loading or saving + */ + virtual void execute() = 0; +}; + +} // End of namespace Titanic + +#endif diff --git a/engines/titanic/pet_control/pet_message.cpp b/engines/titanic/pet_control/pet_message.cpp new file mode 100644 index 0000000000..783c9019e2 --- /dev/null +++ b/engines/titanic/pet_control/pet_message.cpp @@ -0,0 +1,57 @@ +/* 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 "titanic/pet_control/pet_message.h" + +namespace Titanic { + +CPetMessage::CPetMessage() { + Rect rect1(0, 0, 580, 70); + rect1.translate(32, 368); + _message.setBounds(rect1); + _message.resize(50); + _message.setHasBorder(false); + + Rect rect2(0, 0, 580, 15); + rect2.translate(32, 445); + _tooltip.setBounds(rect2); + _tooltip.setHasBorder(false); +} + +bool CPetMessage::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +void CPetMessage::draw(CScreenManager *screenManager) { + _message.draw(screenManager); + _tooltip.draw(screenManager); +} + +bool CPetMessage::setupControl(CPetControl *petControl) { + if (petControl) + _petControl = petControl; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_message.h b/engines/titanic/pet_control/pet_message.h new file mode 100644 index 0000000000..499f274c54 --- /dev/null +++ b/engines/titanic/pet_control/pet_message.h @@ -0,0 +1,96 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_MESSAGE_H +#define TITANIC_PET_MESSAGE_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +class CPetMessage : public CPetSection { +private: + CPetText _message; + CPetText _tooltip; +private: + /** + * Setup the control + */ + bool setupControl(CPetControl *petControl); +public: + CPetMessage(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset() { return true; } + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg) { return false; } + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg) { return false; } + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl) { + return setupControl(petControl); + } + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param) {} + + /** + * Called after a game has been loaded + */ + virtual void postLoad() { reset(); } + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent) {} + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText() { return &_tooltip; } + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_MESSAGE_H */ diff --git a/engines/titanic/pet_control/pet_mode_off.cpp b/engines/titanic/pet_control/pet_mode_off.cpp new file mode 100644 index 0000000000..119c15a65c --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_off.cpp @@ -0,0 +1,42 @@ +/* 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 "titanic/pet_control/pet_mode_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetModeOff, CToggleSwitch); + +CPetModeOff::CPetModeOff() : CToggleSwitch() { +} + +void CPetModeOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CPetModeOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_mode_off.h b/engines/titanic/pet_control/pet_mode_off.h new file mode 100644 index 0000000000..9162270953 --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_off.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_MODE_OFF_H +#define TITANIC_PET_MODE_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CPetModeOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CPetModeOff(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_MODE_OFF_H */ diff --git a/engines/titanic/pet_control/pet_mode_on.cpp b/engines/titanic/pet_control/pet_mode_on.cpp new file mode 100644 index 0000000000..2b61461a24 --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_on.cpp @@ -0,0 +1,42 @@ +/* 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 "titanic/pet_control/pet_mode_on.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetModeOn, CToggleSwitch); + +CPetModeOn::CPetModeOn() : CToggleSwitch() { +} + +void CPetModeOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CPetModeOn::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_mode_on.h b/engines/titanic/pet_control/pet_mode_on.h new file mode 100644 index 0000000000..f77fd1f447 --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_on.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_MODE_ON_H +#define TITANIC_PET_MODE_ON_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CPetModeOn : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CPetModeOn(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_MODE_ON_H */ diff --git a/engines/titanic/pet_control/pet_mode_panel.cpp b/engines/titanic/pet_control/pet_mode_panel.cpp new file mode 100644 index 0000000000..8579c31cea --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_panel.cpp @@ -0,0 +1,42 @@ +/* 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 "titanic/pet_control/pet_mode_panel.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetModePanel, CToggleSwitch); + +CPetModePanel::CPetModePanel() : CToggleSwitch() { +} + +void CPetModePanel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CPetModePanel::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_mode_panel.h b/engines/titanic/pet_control/pet_mode_panel.h new file mode 100644 index 0000000000..f37c543b98 --- /dev/null +++ b/engines/titanic/pet_control/pet_mode_panel.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_MODE_PANEL_H +#define TITANIC_PET_MODE_PANEL_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CPetModePanel : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CPetModePanel(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_MODE_PANEL_H */ diff --git a/engines/titanic/pet_control/pet_pannel1.cpp b/engines/titanic/pet_control/pet_pannel1.cpp new file mode 100644 index 0000000000..7a757bfe57 --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel1.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_pannel1.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetPannel1, CPetGraphic); + +void CPetPannel1::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CPetPannel1::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_pannel1.h b/engines/titanic/pet_control/pet_pannel1.h new file mode 100644 index 0000000000..f39314fed9 --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel1.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_PANNEL1_H +#define TITANIC_PET_PANNEL1_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CPetPannel1 : public CPetGraphic { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_PANNEL1_H */ diff --git a/engines/titanic/pet_control/pet_pannel2.cpp b/engines/titanic/pet_control/pet_pannel2.cpp new file mode 100644 index 0000000000..096a39afbf --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel2.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_pannel2.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetPannel2, CPetGraphic); + +void CPetPannel2::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CPetPannel2::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_pannel2.h b/engines/titanic/pet_control/pet_pannel2.h new file mode 100644 index 0000000000..f820847035 --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel2.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_PANNEL2_H +#define TITANIC_PET_PANNEL2_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CPetPannel2 : public CPetGraphic { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_PANNEL2_H */ diff --git a/engines/titanic/pet_control/pet_pannel3.cpp b/engines/titanic/pet_control/pet_pannel3.cpp new file mode 100644 index 0000000000..0d095a62c5 --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel3.cpp @@ -0,0 +1,39 @@ +/* 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 "titanic/pet_control/pet_pannel3.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPetPannel3, CPetGraphic); + +void CPetPannel3::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CPetPannel3::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_pannel3.h b/engines/titanic/pet_control/pet_pannel3.h new file mode 100644 index 0000000000..dd0d2f9fa2 --- /dev/null +++ b/engines/titanic/pet_control/pet_pannel3.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_PANNEL3_H +#define TITANIC_PET_PANNEL3_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CPetPannel3 : public CPetGraphic { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_PANNEL3_H */ diff --git a/engines/titanic/pet_control/pet_quit.cpp b/engines/titanic/pet_control/pet_quit.cpp new file mode 100644 index 0000000000..218ed89812 --- /dev/null +++ b/engines/titanic/pet_control/pet_quit.cpp @@ -0,0 +1,90 @@ +/* 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 "titanic/pet_control/pet_quit.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_real_life.h" +#include "titanic/support/rect.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +bool CPetQuit::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetGlyph::setup(petControl, owner); + + Rect tempRect(0, 0, 280, 16); + tempRect.moveTo(322, 407); + _text.setBounds(tempRect); + _text.resize(3); + _text.setHasBorder(false); + _text.setup(); + + Rect btnRect(0, 0, 68, 52); + btnRect.moveTo(496, 388); + _btnYes.setBounds(btnRect); + + return true; +} + +bool CPetQuit::reset() { + CPetControl *pet = getPetControl(); + if (!pet) + return false; + + setName("PetExit", pet); + + uint col = getPetSection()->getColor(0); + _text.setText("Are you sure you want to quit?"); + _text.setLineColor(0, col); + + _btnYes.reset("PetQuitOut", pet, MODE_UNSELECTED); + _btnYes.reset("PetQuitIn", pet, MODE_SELECTED); + + return true; +} + +void CPetQuit::draw2(CScreenManager *screenManager) { + _text.draw(screenManager); + _btnYes.draw(screenManager); +} + +bool CPetQuit::MouseButtonDownMsg(const Point &pt) { + return !_btnYes.MouseButtonDownMsg(pt); +} + +bool CPetQuit::MouseButtonUpMsg(const Point &pt) { + CPetControl *pet = getPetControl(); + if (_btnYes.MouseButtonUpMsg(pt) && pet) { + CGameManager *gameManager = pet->getGameManager(); + if (gameManager) + gameManager->_gameState._quitGame = true; + return true; + } else { + return false; + } +} + +void CPetQuit::getTooltip(CPetText *text) { + text->setText("Quit the game."); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_quit.h b/engines/titanic/pet_control/pet_quit.h new file mode 100644 index 0000000000..87d8aefbbf --- /dev/null +++ b/engines/titanic/pet_control/pet_quit.h @@ -0,0 +1,75 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_QUIT_H +#define TITANIC_PET_QUIT_H + +#include "titanic/pet_control/pet_gfx_element.h" +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +class CPetQuit : public CPetGlyph { +private: + CPetText _text; + CPetGfxElement _btnYes; +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Reset the glyph + */ + virtual bool reset(); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText() { return &_text; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_QUIT_H */ diff --git a/engines/titanic/pet_control/pet_real_life.cpp b/engines/titanic/pet_control/pet_real_life.cpp new file mode 100644 index 0000000000..b9e1990dd2 --- /dev/null +++ b/engines/titanic/pet_control/pet_real_life.cpp @@ -0,0 +1,129 @@ +/* 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 "titanic/pet_control/pet_real_life.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_load.h" +#include "titanic/pet_control/pet_save.h" +#include "titanic/pet_control/pet_sound.h" +#include "titanic/pet_control/pet_quit.h" + +namespace Titanic { + +bool CPetRealLife::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +bool CPetRealLife::reset() { + _glyphs.reset(); + uint col = getColor(0); + _text.setColor(col); + _text.setLineColor(0, col); + + return true; +} + +void CPetRealLife::draw(CScreenManager *screenManager) { + _petControl->drawSquares(screenManager, 4); + _glyphs.draw(screenManager); + _text.draw(screenManager); +} + +bool CPetRealLife::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return _glyphs.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetRealLife::MouseDragStartMsg(CMouseDragStartMsg *msg) { + return _glyphs.MouseDragStartMsg(msg); +} + +bool CPetRealLife::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + return _glyphs.MouseDragMoveMsg(msg); +} + +bool CPetRealLife::MouseDragEndMsg(CMouseDragEndMsg *msg) { + return _glyphs.MouseDragEndMsg(msg); +} + +bool CPetRealLife::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return _glyphs.MouseButtonUpMsg(msg->_mousePos); +} + +bool CPetRealLife::KeyCharMsg(CKeyCharMsg *msg) { + _glyphs.KeyCharMsg(msg->_key); + return true; +} + +bool CPetRealLife::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + return _glyphs.VirtualKeyCharMsg(msg); +} + +void CPetRealLife::postLoad() { + reset(); +} + +bool CPetRealLife::isValid(CPetControl *petControl) { + setupControl(petControl); + return true; +} + +void CPetRealLife::enter(PetArea oldArea) { + _glyphs.enterHighlighted(); +} + +void CPetRealLife::leave() { + _glyphs.leaveHighlighted(); +} + +bool CPetRealLife::setupControl(CPetControl *petControl) { + if (petControl) { + _petControl = petControl; + _glyphs.setup(4, this); + _glyphs.setFlags(6); + + addButton(new CPetLoad()); + addButton(new CPetSave()); + addButton(new CPetSound()); + addButton(new CPetQuit()); + + Rect textRect(0, 0, 276, 30); + textRect.moveTo(32, 436); + _text.setBounds(textRect); + _text.setHasBorder(false); + _text.setup(); + } + + return true; +} + +void CPetRealLife::addButton(CPetGlyph *glyph) { + if (glyph) { + if (glyph->setup(_petControl, &_glyphs)) + _glyphs.push_back(glyph); + } +} + + + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_real_life.h b/engines/titanic/pet_control/pet_real_life.h new file mode 100644 index 0000000000..40bc87d9b5 --- /dev/null +++ b/engines/titanic/pet_control/pet_real_life.h @@ -0,0 +1,138 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_REAL_LIFE_H +#define TITANIC_PET_REAL_LIFE_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +class CPetSaveGlyphs : public CPetGlyphs { +}; + +class CPetRealLife : public CPetSection { +private: + CPetGlyphs _glyphs; + CPetText _text; +private: + /** + * Does setup + */ + bool setupControl(CPetControl *petControl); + + /** + * Adds one of the four button glyphs for display + */ + void addButton(CPetGlyph *glyph); +public: + virtual ~CPetRealLife() {} + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Get the bounds for the section + */ + virtual Rect getBounds() const { return Rect(); } + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg); + virtual bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + virtual bool MouseDragEndMsg(CMouseDragEndMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + virtual bool KeyCharMsg(CKeyCharMsg *msg); + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * Returns item a drag-drop operation has dropped on, if any + */ + virtual CGameObject *dragEnd(const Point &pt) const { return nullptr; } + + /** + * Display a message + */ + virtual void displayMessage(const CString &msg) {} + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param) {} + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent) {} + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea); + + /** + * Called when a section is being left, to switch to another area + */ + virtual void leave(); + + /** + * Called when a new room is entered + */ + virtual void enterRoom(CRoomItem *room) {} + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText() { return &_text; } + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_REAL_LIFE_H */ diff --git a/engines/titanic/pet_control/pet_remote.cpp b/engines/titanic/pet_control/pet_remote.cpp new file mode 100644 index 0000000000..9b43b8dab9 --- /dev/null +++ b/engines/titanic/pet_control/pet_remote.cpp @@ -0,0 +1,495 @@ +/* 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 "titanic/pet_control/pet_remote.h" +#include "titanic/pet_control/pet_remote_glyphs.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +static const byte REMOTE_DATA[] = { + 0x00, 0x02, + GLYPH_SUMMON_ELEVATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x01, 0x02, + GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x02, 0x03, + GLYPH_TELEVISION_CONTROL, GLYPH_OPERATE_LIGHTS, GLYPH_SUCCUBUS_DELIVERY, + 0x03, 0x02, + GLYPH_SUMMON_ELEVATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x04, 0x02, + GLYPH_TELEVISION_CONTROL, GLYPH_SUCCUBUS_DELIVERY, + 0x05, 0x02, + GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x06, 0x02, + GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x07, 0x03, + GLYPH_TELEVISION_CONTROL, GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x08, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x09, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x0A, 0x02, GLYPH_SUMMON_ELEVATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x0B, 0x01, + GLYPH_NAVIGATION_CONTROLLER, + 0x0C, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x0D, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x0E, 0x00, + 0x0F, 0x01, + GLYPH_TELEVISION_CONTROL, + 0x10, 0x03, + GLYPH_GOTO_BOTTOM_OF_WELL, GLYPH_GOTO_STATEROOM, GLYPH_GOTO_TOP_OF_WELL, + 0x11, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x12, 0x00, + 0x13, 0x02, + GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x14, 0x00, + 0x15, 0x02, + GLYPH_SUCCUBUS_DELIVERY, GLYPH_TELEVISION_CONTROL, + 0x16, 0x00, + 0x17, 0x02, + GLYPH_SUMMON_PELLERATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x18, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x19, 0x00, + 0x1A, 0x00, + 0x1B, 0x00, + 0x1C, 0x00, + 0x1D, 0x02, + GLYPH_SUMMON_ELEVATOR, GLYPH_SUCCUBUS_DELIVERY, + 0x1E, 0x0C, + GLYPH_DEPLOY_FLORAL, GLYPH_DEPLOY_FULLY_RELAXATION, GLYPH_DEPLOY_COMFORT, + GLYPH_DEPLOY_MINOR_STORAGE, GLYPH_ENTERTAINMENT_DEVICE, + GLYPH_DEPLOY_MAJOR_RELAXATION, GLYPH_INFLATE_RELAXATION, + GLYPH_DEPLOY_MAINTENANCE, GLYPH_DEPLOY_WORK_SURFACE, + GLYPH_DEPLOY_MINOR_RELAXATION, GLYPH_DEPLOY_SINK, + GLYPH_DEPLOY_MAJOR_STORAGE, + 0x1F, 0x01, + GLYPH_SUCCUBUS_DELIVERY, + 0x20, 0x02, + GLYPH_SUMMON_ELEVATOR, GLYPH_SUMMON_PELLERATOR, + 0x21, 0x00 +}; + +CPetRemote::CPetRemote() : CPetSection() { +} + +bool CPetRemote::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +bool CPetRemote::reset() { + if (_petControl) { + _onOff.reset("PetSwitchOn", _petControl, MODE_SELECTED); + _onOff.reset("PetSwitchOff", _petControl, MODE_UNSELECTED); + + _up.reset("PetUp", _petControl, MODE_UNSELECTED); + _down.reset("PetDown", _petControl, MODE_UNSELECTED); + + _left.reset("PetLeftUp", _petControl, MODE_SELECTED); + _left.reset("PetLeft", _petControl, MODE_UNSELECTED); + _right.reset("PetRightUp", _petControl, MODE_SELECTED); + _right.reset("PetRight", _petControl, MODE_UNSELECTED); + _top.reset("PetTopUp", _petControl, MODE_SELECTED); + _top.reset("PetTop", _petControl, MODE_UNSELECTED); + _bottom.reset("PetBottomUp", _petControl, MODE_SELECTED); + _bottom.reset("PetBottom", _petControl, MODE_UNSELECTED); + _action.reset("PetActionUp", _petControl, MODE_SELECTED); + _action.reset("PetAction", _petControl, MODE_UNSELECTED); + + _send.reset("PetActSend0", _petControl, MODE_UNSELECTED); + _send.reset("PetActSend1", _petControl, MODE_SELECTED); + _receive.reset("PetActReceive0", _petControl, MODE_UNSELECTED); + _receive.reset("PetActReceive1", _petControl, MODE_SELECTED); + _call.reset("PetActCall0", _petControl, MODE_UNSELECTED); + _call.reset("PetActCall1", _petControl, MODE_SELECTED); + + _items.reset(); + uint col = getColor(0); + _text.setColor(col); + _text.setLineColor(0, col); + } + + return true; +} + +void CPetRemote::draw(CScreenManager *screenManager) { + _petControl->drawSquares(screenManager, 6); + _items.draw(screenManager); + _text.draw(screenManager); +} + +bool CPetRemote::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return _items.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetRemote::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return _items.MouseButtonUpMsg(msg->_mousePos); +} + +bool CPetRemote::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return _items.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetRemote::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + return _items.VirtualKeyCharMsg(msg); +} + +bool CPetRemote::isValid(CPetControl *petControl) { + return setupControl(petControl); +} + +void CPetRemote::postLoad() { + reset(); + CRoomItem *room = getRoom(); + if (room) + enterRoom(room); +} + +void CPetRemote::enter(PetArea oldArea) { + if (_items.highlighted14()) + _text.setText(CString()); +} + +void CPetRemote::enterRoom(CRoomItem *room) { + clearGlyphs(); + + if (room) { + CString roomName = room->getName(); + int roomIndex = roomIndexOf(roomName); + if (roomIndex != -1) { + Common::Array<uint> indexes; + if (getRemoteData(roomIndex, indexes)) { + loadGlyphs(indexes); + _items.scrollToStart(); + } + } + } +} + +CPetText *CPetRemote::getText() { + return &_text; +} + +CPetGfxElement *CPetRemote::getElement(uint id) { + switch (id) { + case 0: + return &_onOff; + case 1: + return &_up; + case 2: + return &_down; + case 3: + return &_left; + case 4: + return &_right; + case 5: + return &_top; + case 6: + return &_bottom; + case 7: + return &_action; + case 16: + return &_send; + case 17: + return &_receive; + case 18: + return &_call; + default: + return nullptr; + } +} + +void CPetRemote::highlight(int id) { + int highlightIndex = getHighlightIndex((RemoteGlyph)id); + if (highlightIndex != -1) + _items.highlight(highlightIndex); +} + +bool CPetRemote::setupControl(CPetControl *petControl) { + _petControl = petControl; + if (!petControl) + return false; + + _onOff.setBounds(Rect(0, 0, 15, 43)); + _onOff.translate(519, 381); + _up.setBounds(Rect(0, 0, 21, 24)); + _up.translate(551, 381); + _down.setBounds(Rect(0, 0, 21, 24)); + _down.translate(551, 402); + _left.setBounds(Rect(0, 0, 22, 21)); + _left.translate(518, 393); + _right.setBounds(Rect(0, 0, 21, 21)); + _right.translate(560, 393); + _top.setBounds(Rect(0, 0, 21, 22)); + _top.translate(539, 371); + _bottom.setBounds(Rect(0, 0, 21, 22)); + _bottom.translate(539, 414); + _action.setBounds(Rect(0, 0, 21, 21)); + _action.translate(539, 393); + _send.setBounds(Rect(0, 0, 62, 38)); + _send.translate(503, 373); + _receive.setBounds(Rect(0, 0, 62, 38)); + _receive.translate(503, 420); + _call.setBounds(Rect(0, 0, 62, 38)); + _call.translate(503, 383); + + Rect rect(0, 0, 580, 15); + rect.moveTo(32, 445); + _text.setBounds(rect); + _text.setHasBorder(false); + + _items.setup(6, this); + _items.setFlags(19); + return true; +} + +CRoomItem *CPetRemote::getRoom() const { + if (_petControl) { + CGameManager *gameManager = _petControl->getGameManager(); + if (gameManager) + return gameManager->getRoom(); + } + + return nullptr; +} + +int CPetRemote::getHighlightIndex(RemoteGlyph val) { + CRoomItem *room = getRoom(); + if (!room) + return -1; + + int roomIndex = roomIndexOf(room->getName()); + if (roomIndex == -1) + return -1; + + Common::Array<uint> remoteData; + getRemoteData(roomIndex, remoteData); + + // Loop through the data for the room + for (uint idx = 0; idx < remoteData.size(); ++idx) { + if ((RemoteGlyph)remoteData[idx + 1] == val) + return idx; + } + + return -1; +} + +int CPetRemote::roomIndexOf(const CString &name) { + for (int idx = 0; idx < TOTAL_ROOMS; ++idx) { + if (g_vm->_roomNames[idx] == name) + return idx; + } + + return -1; +} + +bool CPetRemote::getRemoteData(int roomIndex, Common::Array<uint> &indexes) { + const byte *p = &REMOTE_DATA[0]; + for (int idx = 0; idx < TOTAL_ROOMS; ++idx) { + if (*p == roomIndex) { + for (int ctr = 0; ctr < *p; ++ctr) + indexes.push_back(p[ctr + 1]); + return true; + } + + p += *(p + 1) + 2; + } + + return false; +} + +bool CPetRemote::loadGlyphs(const Common::Array<uint> &indexes) { + for (uint idx = 0; idx < indexes.size(); ++idx) { + if (!loadGlyph(indexes[idx])) + return false; + } + + return true; +} + +bool CPetRemote::loadGlyph(int glyphIndex) { + CPetRemoteGlyph *glyph = nullptr; + + switch (glyphIndex) { + case GLYPH_SUMMON_ELEVATOR: + glyph = new CSummonElevatorGlyph(); + break; + + case GLYPH_SUMMON_PELLERATOR: + glyph = new CSummonPelleratorGlyph(); + break; + + case GLYPH_TELEVISION_CONTROL: + glyph = new CTelevisionControlGlyph(); + break; + + case GLYPH_ENTERTAINMENT_DEVICE: + glyph = new CEntertainmentDeviceGlyph(); + break; + + case GLYPH_OPERATE_LIGHTS: + glyph = new COperateLightsGlyph(); + break; + + case GLYPH_DEPLOY_FLORAL: + glyph = new CDeployFloralGlyph(); + break; + + case GLYPH_DEPLOY_FULLY_RELAXATION: + glyph = new CDeployFullyRelaxationGlyph(); + break; + + case GLYPH_DEPLOY_COMFORT: + glyph = new CDeployComfortGlyph(); + break; + + case GLYPH_DEPLOY_MINOR_STORAGE: + glyph = new CDeployMinorStorageGlyph(); + break; + + case GLYPH_DEPLOY_MAJOR_RELAXATION: + glyph = new CDeployMajorRelaxationGlyph(); + break; + + case GLYPH_INFLATE_RELAXATION: + glyph = new CInflateRelaxationGlyph(); + break; + + case GLYPH_DEPLOY_MAINTENANCE: + glyph = new CDeployMaintenanceGlyph(); + break; + + case GLYPH_DEPLOY_WORK_SURFACE: + glyph = new CDeployWorkSurfaceGlyph(); + break; + + case GLYPH_DEPLOY_MINOR_RELAXATION: + glyph = new CDeployMinorRelaxationGlyph(); + break; + + case GLYPH_DEPLOY_SINK: + glyph = new CDeploySinkGlyph(); + break; + + case GLYPH_DEPLOY_MAJOR_STORAGE: + glyph = new CDeployMajorStorageGlyph(); + break; + + case GLYPH_SUCCUBUS_DELIVERY: + glyph = new CSuccubusDeliveryGlyph(); + break; + + case GLYPH_NAVIGATION_CONTROLLER: + glyph = new CNavigationControllerGlyph(); + break; + + case GLYPH_GOTO_BOTTOM_OF_WELL: + glyph = new CGotoBottomOfWellGlyph(); + break; + + case GLYPH_GOTO_TOP_OF_WELL: + glyph = new CGotoTopOfWellGlyph(); + break; + + case GLYPH_GOTO_STATEROOM: + glyph = new CGotoStateroomGlyph(); + break; + + case GLYPH_GOTO_BAR: + glyph = new CGotoBarGlyph(); + + case GLYPH_GOTO_PROMENADE: + glyph = new CGotoPromenadeDeckGlyph(); + break; + + case GLYPH_GOTO_ARBORETUM: + glyph = new CGotoArboretumGlyph(); + break; + + case GLYPH_GOTO_MUSIC_ROOM: + glyph = new CGotoMusicRoomGlyph(); + break; + + case GLYPH_GOTO_RESTAURANT: + glyph = new CGotoRestaurantGlyph(); + break; + + default: + break; + } + + if (glyph) { + if (glyph->setup(_petControl, &_items)) { + _items.push_back(glyph); + return true; + } + } + + return false; +} + +void CPetRemote::generateMessage(RemoteMessage msgNum, const CString &name, int num) { + switch (msgNum) { + case RMSG_LEFT: { + CPETLeftMsg msg(name, num); + msg.execute(_petControl->_remoteTarget); + break; + } + + case RMSG_RIGHT: { + CPETRightMsg msg(name, num); + msg.execute(_petControl->_remoteTarget); + break; + } + + case RMSG_UP: { + CPETUpMsg msg(name, num); + msg.execute(_petControl->_remoteTarget); + break; + } + + case RMSG_DOWN: { + CPETDownMsg msg(name, num); + msg.execute(_petControl->_remoteTarget); + break; + } + + case RMSG_ACTIVATE: { + CPETActivateMsg msg(name, num); + msg.execute(_petControl->_remoteTarget); + break; + } + + default: + break; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_remote.h b/engines/titanic/pet_control/pet_remote.h new file mode 100644 index 0000000000..22ea1e05ad --- /dev/null +++ b/engines/titanic/pet_control/pet_remote.h @@ -0,0 +1,159 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_REMOTE_H +#define TITANIC_PET_REMOTE_H + +#include "common/array.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_remote_glyphs.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +class CPetRemote : public CPetSection { +private: + CPetRemoteGlyphs _items; + CPetGfxElement _onOff; + CPetGfxElement _up; + CPetGfxElement _down; + CPetGfxElement _left; + CPetGfxElement _right; + CPetGfxElement _top; + CPetGfxElement _bottom; + CPetGfxElement _action; + CPetGfxElement _send; + CPetGfxElement _receive; + CPetGfxElement _call; + CPetText _text; +private: + /** + * Setup the control + */ + bool setupControl(CPetControl *petControl); + + /** + * Get the current room + */ + CRoomItem *getRoom() const; + + /** + * Return a highlight index + */ + int getHighlightIndex(RemoteGlyph val); + + /** + * Return the index of a room name in the master room names list + */ + int roomIndexOf(const CString &name); + + /** + * Return a list of remote action glyph indexes for a given room + */ + bool getRemoteData(int roomIndex, Common::Array<uint> &indexes); + + /** + * Clear the list of rooms glyphs + */ + void clearGlyphs() { _items.clear(); } + + /** + * Load the room glyphs + */ + bool loadGlyphs(const Common::Array<uint> &indexes); + + /** + * Load a single room glyph + */ + bool loadGlyph(int glyphIndex); +public: + CPetRemote(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + virtual bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea); + + /** + * Called when a new room is entered + */ + virtual void enterRoom(CRoomItem *room); + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText(); + + /** + * Get an element from the section by a designated Id + */ + virtual CPetGfxElement *getElement(uint id); + + /** + * Highlights a glyph item in the section + */ + virtual void highlight(int id); + + /** + * Generates a PET message + */ + void generateMessage(RemoteMessage msgNum, const CString &name, int num); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_REMOTE_H */ diff --git a/engines/titanic/pet_control/pet_remote_glyphs.cpp b/engines/titanic/pet_control/pet_remote_glyphs.cpp new file mode 100644 index 0000000000..6b7c8cb4ae --- /dev/null +++ b/engines/titanic/pet_control/pet_remote_glyphs.cpp @@ -0,0 +1,562 @@ +/* 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 "titanic/pet_control/pet_remote_glyphs.h" +#include "titanic/pet_control/pet_remote.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CPetRemote *CPetRemoteGlyphs::getOwner() const { + return static_cast<CPetRemote *>(_owner); +} + +void CPetRemoteGlyphs::generateMessage(RemoteMessage msgNum, const CString &name, int num) { + getOwner()->generateMessage(msgNum, name, num); +} + +/*------------------------------------------------------------------------*/ + +void CPetRemoteGlyph::setDefaults(const CString &name, CPetControl *petControl) { + _element.setBounds(Rect(0, 0, 52, 52)); + _element.setup(MODE_UNSELECTED, name, petControl); +} + +CPetRemoteGlyphs *CPetRemoteGlyph::getOwner() const { + return static_cast<CPetRemoteGlyphs *>(_owner); +} + +CPetGfxElement *CPetRemoteGlyph::getElement(uint id) const { + CPetRemote *remote = static_cast<CPetRemote *>(_owner->getOwner()); + return remote->getElement(id); +} + +/*------------------------------------------------------------------------*/ + +bool CBasicRemoteGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults(_gfxName, petControl); + if (owner) + _gfxElement = getElement(18); + return true; +} + +void CBasicRemoteGlyph::draw2(CScreenManager *screenManager) { + if (_gfxElement) + _gfxElement->draw(screenManager); +} + +bool CBasicRemoteGlyph::MouseButtonDownMsg(const Point &pt) { + return _gfxElement && _gfxElement->MouseButtonDownMsg(pt); +} + +bool CBasicRemoteGlyph::MouseButtonUpMsg(const Point &pt) { + if (_gfxElement && _gfxElement->MouseButtonUpMsg(pt)) { + getOwner()->generateMessage(RMSG_ACTIVATE, "Lift"); + return true; + } + + return false; +} + +void CBasicRemoteGlyph::getTooltip(CPetText *text) { + text->setText(_tooltip); +} + +/*------------------------------------------------------------------------*/ + +bool CToggleRemoteGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetGlyph::setup(petControl, owner); + if (owner) + _gfxElement = getElement(0); + return true; +} + +void CToggleRemoteGlyph::draw2(CScreenManager *screenManager) { + _gfxElement->setMode(_flag ? MODE_SELECTED : MODE_UNSELECTED); + _gfxElement->draw(screenManager); +} + +bool CToggleRemoteGlyph::elementMouseButtonDownMsg(const Point &pt, int petNum) { + return _gfxElement->MouseButtonDownMsg(pt); +} + +bool CToggleRemoteGlyph::elementMouseButtonUpMsg(const Point &pt, int petNum) { + if (!_gfxElement->MouseButtonUpMsg(pt)) + return false; + + CTreeItem *target = getPetControl()->_remoteTarget; + if (target) { + CPETActivateMsg msg("SGTSelector", petNum); + msg.execute(target); + _flag = !_flag; + _gfxElement->setMode(_flag ? MODE_SELECTED : MODE_UNSELECTED); + } + + return true; +} + +/*------------------------------------------------------------------------*/ + +bool CRemoteGotoGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults(_gfxName, petControl); + + if (owner) + _gfxElement = getElement(7); + + return true; +} + +void CRemoteGotoGlyph::draw2(CScreenManager *screenManager) { + if (_gfxElement) + _gfxElement->draw(screenManager); +} + +bool CRemoteGotoGlyph::MouseButtonDownMsg(const Point &pt) { + return _gfxElement && _gfxElement->MouseButtonDownMsg(pt); +} + +bool CRemoteGotoGlyph::MouseButtonUpMsg(const Point &pt) { + if (!_gfxElement || !_gfxElement->MouseButtonUpMsg(pt)) + return false; + + CPetControl *petControl = getPetControl(); + if (petControl) { + CGameManager *gameManager = petControl->getGameManager(); + + if (gameManager) { + CRoomItem *room = gameManager->getRoom(); + + if (room) { + CTransportMsg msg(g_vm->_roomNames[_roomIndex], 1, 0); + msg.execute(room); + } + } + } + + return true; +} + +void CRemoteGotoGlyph::getTooltip(CPetText *text) { + text->setText(_tooltip); +} + +/*------------------------------------------------------------------------*/ + +bool CTelevisionControlGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults("3PetTV", petControl); + if (owner) { + _up = getElement(1); + _down = getElement(2); + _onOff = getElement(4); + } + + return true; +} + +void CTelevisionControlGlyph::draw2(CScreenManager *screenManager) { + _onOff->setSelected(_flag); + _onOff->draw(screenManager); + _up->draw(screenManager); + _down->draw(screenManager); +} + +bool CTelevisionControlGlyph::MouseButtonDownMsg(const Point &pt) { + if (_onOff && _onOff->MouseButtonDownMsg(pt)) + return true; + if (_up && _up->MouseButtonDownMsg(pt)) + return true; + if (_down && _down->MouseButtonDownMsg(pt)) + return true; + + return false; +} + +bool CTelevisionControlGlyph::MouseButtonUpMsg(const Point &pt) { + if (_onOff && _onOff->MouseButtonUpMsg(pt)) { + _flag = !_flag; + getOwner()->generateMessage(RMSG_ACTIVATE, "Television"); + return true; + } + + if (_up && _up->MouseButtonUpMsg(pt)) { + getOwner()->generateMessage(RMSG_UP, "Television"); + return true; + } + + if (_down && _down->MouseButtonUpMsg(pt)) { + getOwner()->generateMessage(RMSG_DOWN, "Television"); + return true; + } + + return false; +} + +void CTelevisionControlGlyph::getTooltip(CPetText *text) { + text->setText("Television control"); +} + +/*------------------------------------------------------------------------*/ + +bool CEntertainmentDeviceGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + if (owner) { + _gfxElement2 = getElement(1); + _gfxElement3 = getElement(2); + } + + return true; +} + +void CEntertainmentDeviceGlyph::draw2(CScreenManager *screenManager) { + CString viewName = getPetControl()->getFullViewName(); + if (viewName == "SGTState.Node 1.S") { + _gfxElement->setSelected(_flag); + _gfxElement->draw(screenManager); + } else if (viewName == "SGTState.Node 4.E") { + _gfxElement->setSelected(_flag2); + _gfxElement->draw(screenManager); + _gfxElement2->draw(screenManager); + _gfxElement3->draw(screenManager); + } +} + +bool CEntertainmentDeviceGlyph::MouseButtonDownMsg(const Point &pt) { + CString viewName = getPetControl()->getFullViewName(); + if (viewName == "SGTState.Node 1.S") { + return elementMouseButtonDownMsg(pt, 4); + } else if (viewName == "SGTState.Node 4.E") { + return _gfxElement->MouseButtonDownMsg(pt) + || _gfxElement2->MouseButtonDownMsg(pt) + || _gfxElement3->MouseButtonDownMsg(pt); + } + + return false; +} + +bool CEntertainmentDeviceGlyph::MouseButtonUpMsg(const Point &pt) { + CString viewName = getPetControl()->getFullViewName(); + if (viewName == "SGTState.Node 1.S") { + return elementMouseButtonUpMsg(pt, 4); + } else if (viewName == "SGTState.Node 4.E") { + if (_gfxElement->MouseButtonUpMsg(pt)) { + _flag2 = !_flag2; + getOwner()->generateMessage(RMSG_ACTIVATE, "Television"); + return true; + } else if (_gfxElement2->MouseButtonUpMsg(pt)) { + getOwner()->generateMessage(RMSG_UP, "Television"); + return true; + } + else if (_gfxElement3->MouseButtonUpMsg(pt)) { + getOwner()->generateMessage(RMSG_DOWN, "Television"); + return true; + } + } + + return false; +} + +void CEntertainmentDeviceGlyph::getTooltip(CPetText *text) { + text->setText("Operate visual entertainment device"); +} + +/*------------------------------------------------------------------------*/ + +bool COperateLightsGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults("3PetLights", petControl); + + if (owner) { + _left = getElement(3); + _right = getElement(4); + _up = getElement(5); + _down = getElement(6); + _activate = getElement(7); + } + + return true; +} + +void COperateLightsGlyph::draw2(CScreenManager *screenManager) { + _left->draw(screenManager); + _right->draw(screenManager); + _up->draw(screenManager); + _down->draw(screenManager); + _activate->draw(screenManager); +} + +bool COperateLightsGlyph::MouseButtonDownMsg(const Point &pt) { + if (_left->MouseButtonDownMsg(pt) + || _right->MouseButtonDownMsg(pt) + || _up->MouseButtonDownMsg(pt) + || _down->MouseButtonDownMsg(pt) + || _activate->MouseButtonDownMsg(pt)) + return true; + return true; +} + +bool COperateLightsGlyph::MouseButtonUpMsg(const Point &pt) { + if (_left && _left->MouseButtonUpMsg(pt)) + getOwner()->generateMessage(RMSG_LEFT, "Light"); + else if (_right && _right->MouseButtonUpMsg(pt)) + getOwner()->generateMessage(RMSG_RIGHT, "Light"); + else if (_up && _up->MouseButtonUpMsg(pt)) + getOwner()->generateMessage(RMSG_UP, "Light"); + else if (_down && _down->MouseButtonUpMsg(pt)) + getOwner()->generateMessage(RMSG_DOWN, "Light"); + else + getOwner()->generateMessage(RMSG_ACTIVATE, "Light"); + + return true; +} + +void COperateLightsGlyph::getTooltip(CPetText *text) { + text->setText("Operate the lights"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployFloralGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetVase", petControl); + return true; +} + +void CDeployFloralGlyph::getTooltip(CPetText *text) { + text->setText("Deploy floral enhancement"); +} + + +/*------------------------------------------------------------------------*/ + +bool CDeployFullyRelaxationGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetBedfoot", petControl); + return true; +} + +void CDeployFullyRelaxationGlyph::getTooltip(CPetText *text) { + text->setText("Deploy fully recumbent relaxation device"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployComfortGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetToilet", petControl); + return true; +} + +void CDeployComfortGlyph::getTooltip(CPetText *text) { + text->setText("Deploy comfort workstation"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployMinorStorageGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetDraw", petControl); + return true; +} + +void CDeployMinorStorageGlyph::getTooltip(CPetText *text) { + text->setText("Deploy minor horizontally mobile storage compartment"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployMajorRelaxationGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetArmChair", petControl); + return true; +} + +void CDeployMajorRelaxationGlyph::getTooltip(CPetText *text) { + text->setText("Deploy major semi-recumbent relaxation device"); +} + +/*------------------------------------------------------------------------*/ + +bool CInflateRelaxationGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetBedhead", petControl); + return true; +} + +void CInflateRelaxationGlyph::getTooltip(CPetText *text) { + text->setText("Inflate fully recumbent relaxation device "); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployMaintenanceGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetWashstand", petControl); + return true; +} + +void CDeployMaintenanceGlyph::getTooltip(CPetText *text) { + text->setText("Deploy personal maintenance hub"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployWorkSurfaceGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetTable", petControl); + return true; +} + +void CDeployWorkSurfaceGlyph::getTooltip(CPetText *text) { + text->setText("Deploy executive horizontal worksurface"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployMinorRelaxationGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetDeskchair", petControl); + return true; +} + +void CDeployMinorRelaxationGlyph::getTooltip(CPetText *text) { + text->setText("Deploy minor semi-recumbent relaxation device"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeploySinkGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetDeskchair", petControl); + return true; +} + +void CDeploySinkGlyph::getTooltip(CPetText *text) { + text->setText("Deploy aqueous cleansing receptacle"); +} + +/*------------------------------------------------------------------------*/ + +bool CDeployMajorStorageGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CToggleRemoteGlyph::setup(petControl, owner); + setDefaults("3PetChest", petControl); + return true; +} + +void CDeployMajorStorageGlyph::getTooltip(CPetText *text) { + text->setText("Deploy major horizontally mobile storage compartment"); +} + +/*------------------------------------------------------------------------*/ + +bool CSuccubusDeliveryGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults("3PetSuccubus", petControl); + + if (owner) { + _gfxElement1 = getElement(16); + _gfxElement2 = getElement(17); + } + + return true; +} + +void CSuccubusDeliveryGlyph::draw2(CScreenManager *screenManager) { + _gfxElement1->draw(screenManager); + _gfxElement2->draw(screenManager); +} + +bool CSuccubusDeliveryGlyph::MouseButtonDownMsg(const Point &pt) { + return _gfxElement1->MouseButtonDownMsg(pt) + || _gfxElement2->MouseButtonDownMsg(pt); +} + +bool CSuccubusDeliveryGlyph::MouseButtonUpMsg(const Point &pt) { + CTreeItem *target = getPetControl()->_remoteTarget; + + if (_gfxElement1 && _gfxElement1->MouseButtonUpMsg(pt)) { + if (target) { + CPETDeliverMsg msg; + msg.execute(target); + } + } else if (_gfxElement2 && _gfxElement2->MouseButtonUpMsg(pt)) { + if (target) { + CPETReceiveMsg msg; + msg.execute(target); + } + } else { + return false; + } + + return true; +} + +void CSuccubusDeliveryGlyph::getTooltip(CPetText *text) { + text->setText("Succ-U-Bus delivery system control"); +} + +/*------------------------------------------------------------------------*/ + +bool CNavigationControllerGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetRemoteGlyph::setup(petControl, owner); + setDefaults("3PetStarField", petControl); + + if (owner) + _gfxElement = getElement(0); + + return true; +} + +void CNavigationControllerGlyph::draw2(CScreenManager *screenManager) { + _gfxElement->setMode(_flag ? MODE_SELECTED : MODE_UNSELECTED); + _gfxElement->draw(screenManager); +} + +bool CNavigationControllerGlyph::MouseButtonDownMsg(const Point &pt) { + return _gfxElement->MouseButtonDownMsg(pt); +} + +bool CNavigationControllerGlyph::MouseButtonUpMsg(const Point &pt) { + if (!_gfxElement->MouseButtonUpMsg(pt)) + return false; + + _flag = !_flag; + CTreeItem *target = getPetControl()->_remoteTarget; + if (target) { + CPETHelmetOnOffMsg msg; + msg.execute(target); + } + + return true; +} + +void CNavigationControllerGlyph::getTooltip(CPetText *text) { + text->setText("Navigation controller"); +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_remote_glyphs.h b/engines/titanic/pet_control/pet_remote_glyphs.h new file mode 100644 index 0000000000..d3541d6a94 --- /dev/null +++ b/engines/titanic/pet_control/pet_remote_glyphs.h @@ -0,0 +1,715 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_REMOTE_GLYPHS_H +#define TITANIC_PET_REMOTE_GLYPHS_H + +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_gfx_element.h" + +namespace Titanic { + +enum RemoteGlyph { + GLYPH_SUMMON_ELEVATOR = 0, GLYPH_SUMMON_PELLERATOR = 1, + GLYPH_TELEVISION_CONTROL = 2, GLYPH_ENTERTAINMENT_DEVICE = 3, + GLYPH_OPERATE_LIGHTS = 4, GLYPH_DEPLOY_FLORAL = 5, + GLYPH_DEPLOY_FULLY_RELAXATION = 6, GLYPH_DEPLOY_COMFORT = 7, + GLYPH_DEPLOY_MINOR_STORAGE = 8, GLYPH_DEPLOY_MAJOR_RELAXATION = 9, + GLYPH_INFLATE_RELAXATION = 10, GLYPH_DEPLOY_MAINTENANCE = 11, + GLYPH_DEPLOY_WORK_SURFACE = 12, GLYPH_DEPLOY_MINOR_RELAXATION = 13, + GLYPH_DEPLOY_SINK = 14, GLYPH_DEPLOY_MAJOR_STORAGE = 15, + GLYPH_SUCCUBUS_DELIVERY = 16, GLYPH_NAVIGATION_CONTROLLER = 17, + GLYPH_GOTO_BOTTOM_OF_WELL = 18, GLYPH_GOTO_TOP_OF_WELL = 19, + GLYPH_GOTO_STATEROOM = 20, GLYPH_GOTO_BAR = 21, + GLYPH_GOTO_PROMENADE = 22, GLYPH_GOTO_ARBORETUM = 23, + GLYPH_GOTO_MUSIC_ROOM = 24, GLYPH_GOTO_RESTAURANT = 25 +}; + +enum RemoteMessage { + RMSG_LEFT = 0, RMSG_RIGHT = 1, RMSG_UP = 2, RMSG_DOWN = 3, RMSG_ACTIVATE = 4 +}; + +class CPetRemote; + +class CPetRemoteGlyphs : public CPetGlyphs { +public: + /** + * Returns the owning CPetRemote + */ + CPetRemote *getOwner() const; + + /** + * Generates a PET message + */ + void generateMessage(RemoteMessage msgNum, const CString &name, int num = -1); +}; + +class CPetRemoteGlyph : public CPetGlyph { +protected: + CPetGfxElement *_gfxElement; +protected: + CPetRemoteGlyph() : CPetGlyph(), _gfxElement(nullptr) {} + + /** + * Set defaults for the glyph + */ + void setDefaults(const CString &name, CPetControl *petControl); + + /** + * Get the owner + */ + CPetRemoteGlyphs *getOwner() const; + + /** + * Get an element by id from the parent Remote section + */ + CPetGfxElement *getElement(uint id) const; +}; + +class CBasicRemoteGlyph : public CPetRemoteGlyph { +private: + CString _gfxName, _tooltip, _msgString; +public: + CBasicRemoteGlyph(const CString &gfxName, const CString &tooltip, + const CString &msgString) : CPetRemoteGlyph(), + _gfxName(gfxName), _tooltip(tooltip), _msgString(msgString) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CToggleRemoteGlyph : public CPetRemoteGlyph { +protected: + CPetGfxElement *_gfxElement; + bool _flag; +public: + CToggleRemoteGlyph() : CPetRemoteGlyph(), _gfxElement(nullptr), _flag(false) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages to the default element + */ + bool elementMouseButtonDownMsg(const Point &pt, int petNum); + + /** + * Called for mouse button up messages to the default element + */ + bool elementMouseButtonUpMsg(const Point &pt, int petNum); +}; + +class CRemoteGotoGlyph : public CPetRemoteGlyph { +protected: + int _roomIndex; + CPetGfxElement *_gfxElement; + CString _gfxName, _tooltip; +public: + CRemoteGotoGlyph() : CPetRemoteGlyph(), _gfxElement(nullptr), _roomIndex(21) {} + CRemoteGotoGlyph(const CString &gfxName, const CString &tooltip) : + CPetRemoteGlyph(), _gfxElement(nullptr), _roomIndex(21), + _gfxName(gfxName), _tooltip(tooltip) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CSummonElevatorGlyph : public CBasicRemoteGlyph { +public: + CSummonElevatorGlyph() : CBasicRemoteGlyph( + "3PetLift", "Summon Elevator", "Lift") {} +}; + +class CSummonPelleratorGlyph : public CBasicRemoteGlyph { +public: + CSummonPelleratorGlyph() : CBasicRemoteGlyph( + "3PetPellerator", "Summon Pellerator", "Pellerator") {} +}; + +class CTelevisionControlGlyph : public CPetRemoteGlyph { +private: + bool _flag; + CPetGfxElement *_up, *_down, *_onOff; +public: + CTelevisionControlGlyph() : CPetRemoteGlyph(), _flag(false), + _up(nullptr), _down(nullptr), _onOff(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CEntertainmentDeviceGlyph : public CToggleRemoteGlyph { +public: + bool _flag2; + CPetGfxElement *_gfxElement2, *_gfxElement3; +public: + CEntertainmentDeviceGlyph() : CToggleRemoteGlyph(), + _flag2(false), _gfxElement2(nullptr), _gfxElement3(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + + +class COperateLightsGlyph : public CPetRemoteGlyph { +public: + CPetGfxElement *_left, *_right, *_up, *_down, *_activate; +public: + COperateLightsGlyph() : CPetRemoteGlyph(), _left(nullptr), _right(nullptr), + _up(nullptr), _down(nullptr), _activate(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployFloralGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 0); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 0); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployFullyRelaxationGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 1); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 1); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployComfortGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 2); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 2); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployMinorStorageGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 3); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 3); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployMajorRelaxationGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 5); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 5); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CInflateRelaxationGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 6); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 6); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployMaintenanceGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 7); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 7); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployWorkSurfaceGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 8); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 8); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployMinorRelaxationGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 9); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 9); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeploySinkGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 10); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 10); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CDeployMajorStorageGlyph : public CToggleRemoteGlyph { +public: + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt) { + return elementMouseButtonDownMsg(pt, 11); + } + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt) { + return elementMouseButtonUpMsg(pt, 11); + } + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CSuccubusDeliveryGlyph : public CPetRemoteGlyph { +private: + CPetGfxElement *_gfxElement1, *_gfxElement2; +public: + CSuccubusDeliveryGlyph() : CPetRemoteGlyph(), + _gfxElement1(nullptr), _gfxElement2(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CNavigationControllerGlyph : public CPetRemoteGlyph { +private: + bool _flag; + CPetGfxElement *_gfxElement; +public: + CNavigationControllerGlyph() : CPetRemoteGlyph(), + _flag(false), _gfxElement(nullptr) {} + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +class CGotoBottomOfWellGlyph : public CRemoteGotoGlyph { +public: + CGotoBottomOfWellGlyph() : CRemoteGotoGlyph("3PetBotOfWell", + "Go to the Bottom of the Well") {} +}; + +class CGotoTopOfWellGlyph : public CRemoteGotoGlyph { +public: + CGotoTopOfWellGlyph() : CRemoteGotoGlyph("3PetTopOfWell", + "Go to the Top of the Well") {} +}; + +class CGotoStateroomGlyph : public CRemoteGotoGlyph { +public: + CGotoStateroomGlyph() : CRemoteGotoGlyph("3PetRoom", + "Go to your stateroom") {} +}; + +class CGotoBarGlyph : public CRemoteGotoGlyph { +public: + CGotoBarGlyph() : CRemoteGotoGlyph("3PetBar", + "Go to the Bar") {} +}; + +class CGotoPromenadeDeckGlyph : public CRemoteGotoGlyph { +public: + CGotoPromenadeDeckGlyph() : CRemoteGotoGlyph("3PetPromDeck", + "Go to the Promenade Deck") {} +}; + +class CGotoArboretumGlyph : public CRemoteGotoGlyph { +public: + CGotoArboretumGlyph() : CRemoteGotoGlyph("3PetArboretum", + "Go to the Arboretum") {} +}; + +class CGotoMusicRoomGlyph : public CRemoteGotoGlyph { +public: + CGotoMusicRoomGlyph() : CRemoteGotoGlyph("3PetMusicRoom", + "Go to the Music Room") {} +}; + +class CGotoRestaurantGlyph : public CRemoteGotoGlyph { +public: + CGotoRestaurantGlyph() : CRemoteGotoGlyph("3Pet1stClassRest", + "Go to the First Class Restaurant") {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_REMOTE_GLYPHS_H */ diff --git a/engines/titanic/pet_control/pet_rooms.cpp b/engines/titanic/pet_control/pet_rooms.cpp new file mode 100644 index 0000000000..2415c96966 --- /dev/null +++ b/engines/titanic/pet_control/pet_rooms.cpp @@ -0,0 +1,380 @@ +/* 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 "titanic/pet_control/pet_rooms.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +CPetRooms::CPetRooms() : + _chevLeftOnDim(nullptr), _chevLeftOffDim(nullptr), + _chevRightOnDim(nullptr), _chevRightOffDim(nullptr), + _chevLeftOnLit(nullptr), _chevLeftOffLit(nullptr), + _chevRightOnLit(nullptr), _chevRightOffLit(nullptr), + _floorNum(0), _elevatorNum(0), _roomNum(0), _field1CC(0), + _wellEntry(0), _field1D4(0) { +} + +bool CPetRooms::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +bool CPetRooms::reset() { + if (_petControl) { + _plinth.reset("PetChevPlinth", _petControl, MODE_UNSELECTED); + _glyphs.reset(); + + uint col = getColor(0); + _text.setColor(col); + _text.setLineColor(0, col); + } + + return true; +} + +void CPetRooms::draw(CScreenManager *screenManager) { + _petControl->drawSquares(screenManager, 6); + _plinth.draw(screenManager); + _glyphItem.drawAt(screenManager, getGlyphPos(), false); + _text.draw(screenManager); +} + +bool CPetRooms::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_glyphs.MouseButtonDownMsg(msg->_mousePos)) + return true; + + if (!_glyphItem.contains(getGlyphPos(), msg->_mousePos)) + return false; + + _glyphItem.MouseButtonDownMsg(msg->_mousePos); + return true; +} + +bool CPetRooms::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (_glyphs.MouseDragStartMsg(msg)) + return true; + + Point topLeft = getGlyphPos(); + if (!_glyphItem.contains(topLeft, msg->_mousePos)) + return false; + + _glyphItem.dragGlyph(topLeft, msg); + return true; +} + +bool CPetRooms::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return false; +} + +bool CPetRooms::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return !_glyphs.MouseButtonDownMsg(msg->_mousePos); +} + +bool CPetRooms::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { + return _glyphs.VirtualKeyCharMsg(msg); +} + +bool CPetRooms::checkDragEnd(CGameObject *item) { + // Ignore any item drops except valid mail items + if (!item->_isMail) + return false; + + uint roomFlags = item->_id; + CPetRoomsGlyph *glyph = _glyphs.findGlyphByFlags(roomFlags); + if (glyph) { + if (_glyphs.findGlyphByFlags(0)) { + _glyphs.highlight(glyph); + return false; + } + + roomFlags = 0; + } + + addRoom(roomFlags, true); + return false; +} + +void CPetRooms::displayMessage(const CString &msg) { + _glyphs.resetHighlight(); + CPetSection::displayMessage(msg); +} + +bool CPetRooms::isValid(CPetControl *petControl) { + return setupControl(petControl); +} + +void CPetRooms::load(SimpleFile *file, int param) { + if (!param) { + int count = file->readNumber(); + + for (int idx = 0; idx < count; ++idx) { + CPetRoomsGlyph *glyph = addGlyph(file->readNumber(), false); + glyph->setMode((RoomGlyphMode)file->readNumber()); + } + + _glyphItem.setMode((RoomGlyphMode)file->readNumber()); + file->readNumber(); + _floorNum = file->readNumber(); + _elevatorNum = file->readNumber(); + _roomNum = file->readNumber(); + _field1CC = file->readNumber(); + _wellEntry = file->readNumber(); + _field1D4 = file->readNumber(); + } +} + +void CPetRooms::postLoad() { + reset(); +} + +void CPetRooms::save(SimpleFile *file, int indent) { + _glyphs.saveGlyphs(file, indent); + _glyphItem.saveGlyph(file, indent); + file->writeNumberLine(_floorNum, indent); + file->writeNumberLine(_elevatorNum, indent); + file->writeNumberLine(_roomNum, indent); + file->writeNumberLine(_field1CC, indent); + file->writeNumberLine(_wellEntry, indent); + file->writeNumberLine(_field1D4, indent); +} + +void CPetRooms::enter(PetArea oldArea) { + if (!_glyphs.highlighted14()) + _text.setText(""); +} + +void CPetRooms::enterRoom(CRoomItem *room) { + +} + +CPetText *CPetRooms::getText() { + return &_text; +} + +CGameObject *CPetRooms::getBackground(int index) const { + switch (index) { + case 8: + return _chevLeftOnDim; + case 9: + return _chevLeftOffDim; + case 10: + return _chevLeftOnLit; + case 11: + return _chevLeftOffLit; + case 12: + return _chevRightOnDim; + case 13: + return _chevRightOffDim; + case 14: + return _chevRightOnLit; + case 15: + return _chevRightOffLit; + default: + return nullptr; + } +} + +bool CPetRooms::setupControl(CPetControl *petControl) { + _petControl = petControl; + if (!petControl) + return false; + + Rect rect1(0, 0, 470, 15); + rect1.moveTo(32, 445); + _text.setBounds(rect1); + _text.setHasBorder(false); + + Rect rect2(0, 0, 81, 81); + _plinth.setBounds(rect2); + _plinth.translate(494, 374); + + _chevLeftOnDim = petControl->getHiddenObject("3PetChevLeftOnDim"); + _chevLeftOffDim = petControl->getHiddenObject("3PetChevLeftOffDim"); + _chevRightOnDim = petControl->getHiddenObject("3PetChevRightOnDim"); + _chevRightOffDim = petControl->getHiddenObject("3PetChevRightOffDim"); + _chevLeftOnLit = petControl->getHiddenObject("3PetChevLeftOnLit"); + _chevLeftOffLit = petControl->getHiddenObject("3PetChevLeftOffLit"); + _chevRightOnLit = petControl->getHiddenObject("3PetChevRightOnLit"); + _chevRightOffLit = petControl->getHiddenObject("3PetChevRightOffLit"); + + _glyphs.setup(6, this); + _glyphs.setFlags(GFLAG_16); + _glyphItem.setup(petControl, &_glyphs); + _glyphItem.set38(1); + return true; +} + +void CPetRooms::resetHighlight() { + _glyphItem.setRoomFlags(getRoomFlags()); + _glyphs.resetHighlight(); + _glyphItem.updateTooltip(); + areaChanged(PET_ROOMS); +} + +uint CPetRooms::getRoomFlags() const { + CRoomFlags roomFlags; + CString roomName = _petControl->getRoomName(); + + uint flags = roomFlags.getSpecialRoomFlags(roomName); + if (flags) + return flags; + + int classNum = roomFlags.whatPassengerClass(_floorNum); + roomFlags.setPassengerClassBits(classNum); + roomFlags.setFloorNum(_floorNum); + + switch (classNum) { + case 1: + roomFlags.setElevatorNum(_elevatorNum); + roomFlags.setRoomBits(_roomNum); + break; + + case 2: + if (_roomNum > 0) { + if (_roomNum >= 3) { + roomFlags.setElevatorNum(_elevatorNum == 1 || _elevatorNum == 2 ? 1 : 3); + } else { + roomFlags.setElevatorNum(_elevatorNum == 1 || _elevatorNum == 2 ? 2 : 4); + } + + roomFlags.setRoomBits(((_roomNum - 1) & 1) + (_field1CC > 1 ? 3 : 2)); + } else { + roomFlags.setRoomBits(0); + } + break; + + case 3: + roomFlags.setElevatorNum(_elevatorNum); + roomFlags.setRoomBits(_roomNum + _field1CC * 6 - 6); + break; + + default: + break; + } + + return roomFlags.get(); +} + +void CPetRooms::reassignRoom(int passClassNum) { + CPetRoomsGlyph *glyph = _glyphs.findAssignedRoom(); + if (glyph) + // Flag the old assigned room as no longer assigned + glyph->setMode(RGM_PREV_ASSIGNED_ROOM); + + CRoomFlags roomFlags; + roomFlags.setRandomLocation(passClassNum, _field1D4); + glyph = addRoom(roomFlags, true); + if (glyph) { + // Flag the new room as assigned to the player, and highlight it + glyph->setMode(RGM_ASSIGNED_ROOM); + _glyphs.highlight(glyph); + } +} + +CPetRoomsGlyph *CPetRooms::addRoom(uint roomFlags, bool highlight_) { + // Ensure that we don't add room if the room is already present + if (_glyphs.hasFlags(roomFlags)) + return nullptr; + + if (_glyphs.size() >= 32) + // Too many rooms already + return nullptr; + + // Do a preliminary scan of the glyph list for any glyph that is + // no longer valid, and thus can be removed + for (CPetRoomsGlyphs::iterator i = _glyphs.begin(); i != _glyphs.end(); ++i) { + CPetRoomsGlyph *glyph = static_cast<CPetRoomsGlyph *>(*i); + if (!glyph->isAssigned()) { + _glyphs.erase(i); + break; + } + } + + // Add the glyph + return addGlyph(roomFlags, highlight_); +} + +CPetRoomsGlyph *CPetRooms::addGlyph(uint roomFlags, bool highlight_) { + CPetRoomsGlyph *glyph = new CPetRoomsGlyph(roomFlags); + if (!glyph->setup(_petControl, &_glyphs)) { + delete glyph; + return nullptr; + } else { + _glyphs.push_back(glyph); + if (highlight_) + _glyphs.highlight(glyph); + + return glyph; + } +} + +bool CPetRooms::changeLocationClass(int newClassNum) { + CPetRoomsGlyph *glyph = _glyphs.findAssignedRoom(); + if (!glyph) + return 0; + + glyph->changeLocation(newClassNum); + return true; +} + +bool CPetRooms::hasRoomFlags(uint roomFlags) const { + for (CPetRoomsGlyphs::const_iterator i = _glyphs.begin(); i != _glyphs.end(); ++i) { + const CPetRoomsGlyph *glyph = static_cast<const CPetRoomsGlyph *>(*i); + if (glyph->isAssigned() && glyph->getRoomFlags() == roomFlags) + return true; + } + + return false; +} + +uint CPetRooms::getAssignedRoomFlags() const { + CPetRoomsGlyph *glyph = _glyphs.findAssignedRoom(); + return glyph ? glyph->getRoomFlags() : 0; +} + +int CPetRooms::getAssignedRoomNum() const { + uint flags = getAssignedRoomFlags(); + if (!flags) + return 0; + + return CRoomFlags(flags).getRoomNum(); +} + +int CPetRooms::getAssignedFloorNum() const { + uint flags = getAssignedRoomFlags(); + if (!flags) + return 0; + + return CRoomFlags(flags).getFloorNum(); +} + +int CPetRooms::getAssignedElevatorNum() const { + uint flags = getAssignedRoomFlags(); + if (!flags) + return 0; + + return CRoomFlags(flags).getElevatorNum(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_rooms.h b/engines/titanic/pet_control/pet_rooms.h new file mode 100644 index 0000000000..af1ea2ae4f --- /dev/null +++ b/engines/titanic/pet_control/pet_rooms.h @@ -0,0 +1,219 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_ROOMS_H +#define TITANIC_PET_ROOMS_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_text.h" +#include "titanic/pet_control/pet_rooms_glyphs.h" + +namespace Titanic { + +class CPetRooms : public CPetSection { +private: + CPetRoomsGlyphs _glyphs; + CPetRoomsGlyph _glyphItem; + CGameObject *_chevLeftOnDim; + CGameObject *_chevLeftOffDim; + CGameObject *_chevRightOnDim; + CGameObject *_chevRightOffDim; + CGameObject *_chevLeftOnLit; + CGameObject *_chevLeftOffLit; + CGameObject *_chevRightOnLit; + CGameObject *_chevRightOffLit; + CPetGfxElement _plinth; + CPetText _text; + int _floorNum; + int _elevatorNum; + int _roomNum; + int _field1CC; + int _wellEntry; + int _field1D4; +private: + /** + * Setup the control + */ + bool setupControl(CPetControl *petControl); + + /** + * Returns the glyth position + */ + Point getGlyphPos() const { return Point(509, 388); } + + /** + * Adds a glyph to the list + */ + CPetRoomsGlyph *addRoom(uint roomFlags, bool highlight); + + /** + * Adds a glyph to the list + */ + CPetRoomsGlyph *addGlyph(uint roomFlags, bool highlight); +public: + CPetRooms(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + virtual bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg); + + /** + * Check whether a drag drop can occur + */ + virtual bool checkDragEnd(CGameObject *item); + + /** + * Display a message + */ + virtual void displayMessage(const CString &msg); + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea); + + /** + * Called when a new room is entered + */ + virtual void enterRoom(CRoomItem *room); + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText(); + + /** + * Special retrieval of glyph background image + */ + virtual CGameObject *getBackground(int index) const; + + /** + * Reset the highlight + */ + void resetHighlight(); + + /** + * Gives the player a new assigned room in the specified passenger class + */ + void reassignRoom(int passClassNum); + + /** + * Change the current location passenger class + */ + bool changeLocationClass(int newClassNum); + + /** + * Returns true if a room glyph exists with the given flags + */ + bool hasRoomFlags(uint roomFlags) const; + + /** + * Returns the room flags for the player's currently assigned room + */ + uint getAssignedRoomFlags() const; + + /** + * Returns the room number for the player's currently assigned room + */ + int getAssignedRoomNum() const; + + /** + * Returns the floor number for the player's currently assigned room + */ + int getAssignedFloorNum() const; + + /** + * Returns the elevator number for the player's currently assigned room + */ + int getAssignedElevatorNum() const; + + /** + * Gets room flags to use for glyphs + */ + uint getRoomFlags() const; + + void setFloorNum(int floorNum) { _floorNum = floorNum; } + int getFloorNum() const { return _floorNum; } + void setElevatorNum(int elevNum) { _elevatorNum = elevNum; } + int getElevatorNum() const { return _elevatorNum; } + void setRoomNum(int roomNum) { _roomNum = roomNum; } + int getRoomNum() const { return _roomNum; } + void set1CC(int val) { _field1CC = val; } + int get1CC() const { return _field1CC; } + + /** + * Sets the entry number for arriving at the well + */ + void setWellEntry(int val) { _wellEntry = val; } + + /** + * Gets the entry number used when last arriving at the well + */ + int getWellEntry() const { return _wellEntry; } + + void set1D4(int val) { _field1D4 = val; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_ROOMS_SECTION_H */ diff --git a/engines/titanic/pet_control/pet_rooms_glyphs.cpp b/engines/titanic/pet_control/pet_rooms_glyphs.cpp new file mode 100644 index 0000000000..d9e19b1f67 --- /dev/null +++ b/engines/titanic/pet_control/pet_rooms_glyphs.cpp @@ -0,0 +1,257 @@ +/* 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 "titanic/pet_control/pet_rooms_glyphs.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/support/screen_manager.h" +#include "titanic/room_flags.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CPetRoomsGlyph::CPetRoomsGlyph() : CPetGlyph(), + _roomFlags(0), _field38(0), _mode(RGM_UNASSIGNED), + _object0(nullptr), _object1(nullptr), _object2(nullptr), _object3(nullptr), + _object4(nullptr), _object5(nullptr), _object6(nullptr), _object7(nullptr) { +} + +CPetRoomsGlyph::CPetRoomsGlyph(uint flags) : CPetGlyph(), + _roomFlags(flags), _field38(0), _mode(RGM_UNASSIGNED), + _object0(nullptr), _object1(nullptr), _object2(nullptr), _object3(nullptr), + _object4(nullptr), _object5(nullptr), _object6(nullptr), _object7(nullptr) { +} + +bool CPetRoomsGlyph::setup(CPetControl *petControl, CPetGlyphs *owner) { + if (!CPetGlyph::setup(petControl, owner)) + return false; + + CPetSection *section = owner->getOwner(); + _object0 = section->getBackground(9); + _object1 = section->getBackground(12); + _object4 = section->getBackground(13); + _object5 = section->getBackground(10); + _object2 = section->getBackground(11); + _object3 = section->getBackground(14); + _object6 = section->getBackground(15); + _object7 = _object6; + return true; +} + +void CPetRoomsGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted_) { + // Clear background + Rect rect(pt.x, pt.y, pt.x + 52, pt.y + 52); + screenManager->fillRect(SURFACE_BACKBUFFER, &rect, 0, 0, 0); + + CRoomFlags roomFlags(_roomFlags); + uint elevBits = roomFlags.getElevatorBits(); + uint classBits = roomFlags.getPassengerClassBits(); + uint floorBits = roomFlags.getFloorBits(); + uint roomBits = roomFlags.getRoomBits(); + + // Save a copy of object pointers that may be modified + CGameObject *obj0 = _object0; + CGameObject *obj1 = _object1; + CGameObject *obj4 = _object4; + CGameObject *obj5 = _object5; + + if (_field38 == 1 || isHighlighted_) { + _object0 = _object2; + _object1 = _object3; + _object4 = _object6; + _object5 = _object7; + } + + // Draw the images + Point destPt = pt; + drawObjects(classBits + elevBits * 4, destPt, screenManager); + destPt.y += 10; + drawObjects((floorBits >> 4) & 15, destPt, screenManager); + destPt.y += 10; + drawObjects(floorBits & 15, destPt, screenManager); + destPt.y += 10; + drawObjects(roomBits >> 3, destPt, screenManager); + destPt.y += 7; + drawObjects(((roomBits & 7) << 1) + (roomFlags.getBit0() ? 1 : 0), + destPt, screenManager); + + // Restore original object pointers + _object0 = obj0; + _object1 = obj1; + _object4 = obj4; + _object5 = obj5; +} + +void CPetRoomsGlyph::selectGlyph(const Point &topLeft, const Point &pt) { + if (isAssigned()) { + bool isShiftPressed = g_vm->_window->getSpecialButtons() & MK_SHIFT; + + if (isShiftPressed) { + int selection = getSelection(topLeft, pt); + if (selection >= 0) + _roomFlags |= 1 << selection; + } + + updateTooltip(); + } +} + +bool CPetRoomsGlyph::dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg) { + bool isShiftPressed = g_vm->_window->getSpecialButtons() & MK_SHIFT; + CPetControl *petControl = getPetControl(); + + if (!isShiftPressed && petControl) { + CGameObject *chevron = petControl->getHiddenObject("3PetChevron"); + + if (chevron) { + chevron->_id = _roomFlags; + chevron->_isMail = _field38; + petControl->removeFromInventory(chevron, false, false); + chevron->loadSurface(); + + chevron->dragMove(msg->_mousePos); + msg->_handled = true; + + if (msg->execute(chevron)) + return true; + } + } + + return false; +} + +void CPetRoomsGlyph::getTooltip(CPetText *text) { + CRoomFlags roomFlags(_roomFlags); + CPetRooms *owner = static_cast<CPetRooms *>(getPetSection()); + + CString msg; + if (isCurrentlyAssigned()) { + msg = "Your assigned room: "; + } else if (isPreviouslyAssigned()) { + msg = "A previously assigned room: "; + } else if (!_field38) { + msg = "Saved Chevron: "; + } else if (_field38 == 1 && owner->getRoomFlags() == _roomFlags) { + msg = "Current location: "; + } + + // Get the room description + CString roomStr = roomFlags.getRoomDesc(); + + if (roomStr == "The Elevator") { + int elevNum = owner->getElevatorNum(); + roomStr = CString::format("Elevator %d", elevNum); + } + + roomStr += " (shift-click edits)"; + text->setText(roomStr); +} + +void CPetRoomsGlyph::saveGlyph(SimpleFile *file, int indent) { + file->writeNumberLine(_roomFlags, indent); + file->writeNumberLine(_mode, indent); +} + +bool CPetRoomsGlyph::proc33(CPetGlyph *glyph) { + CPetRoomsGlyph *roomGlyph = static_cast<CPetRoomsGlyph *>(glyph); + + return CPetGlyph::proc33(glyph) && _roomFlags == roomGlyph->_roomFlags; +} + +void CPetRoomsGlyph::loadFlags(SimpleFile *file, int val) { + if (!val) { + _roomFlags = file->readNumber(); + } +} + +void CPetRoomsGlyph::changeLocation(int newClassNum) { + CRoomFlags roomFlags(_roomFlags); + roomFlags.changeLocation(newClassNum); + _roomFlags = roomFlags.get(); +} + +int CPetRoomsGlyph::getSelection(const Point &topLeft, const Point &pt) { + Rect rects[4] = { + Rect(topLeft.x, topLeft.y, topLeft.x + 13, topLeft.y + 10), + Rect(topLeft.x + 13, topLeft.y, topLeft.x + 26, topLeft.y + 10), + Rect(topLeft.x + 26, topLeft.y, topLeft.x + 39, topLeft.y + 10), + Rect(topLeft.x + 39, topLeft.y, topLeft.x + 52, topLeft.y + 10) + }; + + for (int idx = 0, btnIndex = 19; idx < 5; ++idx, btnIndex -= 4) { + // Iterate through each of the four rects, seeing if there's a match. + // If not, move it down to the next row for the next loop iteration + for (int i = 0; i < 4; ++i) { + if (rects[i].contains(pt)) + return btnIndex - i; + + rects[i].translate(0, 10); + } + } + + return -1; +} + +void CPetRoomsGlyph::drawObjects(uint flags, const Point &pt, CScreenManager *screenManager) { + if (_object0 && _object1 && _object4 && _object5) { + Point destPos = pt; + ((flags & 8) ? _object0 : _object5)->draw(screenManager, destPos); + destPos.x += 13; + ((flags & 4) ? _object4 : _object5)->draw(screenManager, destPos); + destPos.x += 13; + ((flags & 2) ? _object0 : _object1)->draw(screenManager, destPos); + destPos.x += 13; + ((flags & 1) ? _object4 : _object5)->draw(screenManager, destPos); + } +} + + +/*------------------------------------------------------------------------*/ + +void CPetRoomsGlyphs::saveGlyphs(SimpleFile *file, int indent) { + file->writeNumberLine(size(), indent); + + for (const_iterator i = begin(); i != end(); ++i) + (*i)->saveGlyph(file, indent); +} + +CPetRoomsGlyph *CPetRoomsGlyphs::findAssignedRoom() const { + for (const_iterator i = begin(); i != end(); ++i) { + CPetRoomsGlyph *glyph = static_cast<CPetRoomsGlyph *>(*i); + if (glyph->isCurrentlyAssigned()) + return glyph; + } + + return nullptr; +} + +CPetRoomsGlyph *CPetRoomsGlyphs::findGlyphByFlags(uint flags) const { + for (const_iterator i = begin(); i != end(); ++i) { + CPetRoomsGlyph *glyph = static_cast<CPetRoomsGlyph *>(*i); + if (glyph->getRoomFlags() == flags) + return glyph; + } + + return nullptr; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_rooms_glyphs.h b/engines/titanic/pet_control/pet_rooms_glyphs.h new file mode 100644 index 0000000000..5d0fec84f8 --- /dev/null +++ b/engines/titanic/pet_control/pet_rooms_glyphs.h @@ -0,0 +1,166 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_ROOMS_GLYPHS_H +#define TITANIC_PET_ROOMS_GLYPHS_H + +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +enum RoomGlyphMode { + RGM_UNASSIGNED = 0, RGM_ASSIGNED_ROOM = 1, RGM_PREV_ASSIGNED_ROOM = 2 +}; + +class CPetRoomsGlyph : public CPetGlyph { +private: + uint _roomFlags; + int _field38; + RoomGlyphMode _mode; + CGameObject *_object0; + CGameObject *_object1; + CGameObject *_object2; + CGameObject *_object3; + CGameObject *_object4; + CGameObject *_object5; + CGameObject *_object6; + CGameObject *_object7; +private: + /** + * Find the selected button under the given point, based on the buttons + * starting at a designated top/left position + */ + int getSelection(const Point &topLeft, const Point &pt); + + /** + * Draws the objects + */ + void drawObjects(uint flags, const Point &pt, CScreenManager *screenManager); +public: + CPetRoomsGlyph(); + CPetRoomsGlyph(uint flags); + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Draw the glyph at a specified position + */ + virtual void drawAt(CScreenManager *screenManager, const Point &pt, bool isHighlighted); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager) {} + + /** + * Selects a glyph + */ + virtual void selectGlyph(const Point &topLeft, const Point &pt); + + /** + * Called when a glyph drag starts + */ + virtual bool dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); + + /** + * Saves the data for the glyph + */ + virtual void saveGlyph(SimpleFile *file, int indent); + + virtual bool proc33(CPetGlyph *glyph); + + /** + * Loads flags for the glyph + */ + virtual void loadFlags(SimpleFile *file, int val); + + /** + * Set the room flags for the glyph + */ + void setRoomFlags(uint flags) { _roomFlags = flags; } + + /** + * Get the room flags for the glyph + */ + uint getRoomFlags() const { return _roomFlags; } + + void set38(int val) { _field38 = val; } + + /** + * Sets the mode of the glyph + */ + void setMode(RoomGlyphMode mode) { _mode = mode; } + + void changeLocation(int newClassNum); + + /** + * Returns true if the room is either currently or previously assigned + */ + bool isAssigned() const { return _mode != RGM_UNASSIGNED; } + + /** + * Returns true if the room is the one currently assigned to the player + */ + bool isCurrentlyAssigned() const { return _mode == RGM_ASSIGNED_ROOM; } + + /** + * Returns true if the room was previously assigned to the player + */ + bool isPreviouslyAssigned() const { return _mode == RGM_PREV_ASSIGNED_ROOM; } +}; + +class CPetRoomsGlyphs : public CPetGlyphs { +private: +public: + /** + * Save the list + */ + void saveGlyphs(SimpleFile *file, int indent); + + /** + * Returns the glyph for hte player's assigned room + */ + CPetRoomsGlyph *findAssignedRoom() const; + + /** + * Finds a glyph in the list by it's room flags + */ + CPetRoomsGlyph *findGlyphByFlags(uint flags) const; + + /** + * Returns true if there's a glyph in the list with a given room flags + */ + bool hasFlags(uint flags) const { return findGlyphByFlags(flags) != nullptr; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_ROOMS_GLYPHS_H */ diff --git a/engines/titanic/pet_control/pet_save.cpp b/engines/titanic/pet_control/pet_save.cpp new file mode 100644 index 0000000000..b5e16736bc --- /dev/null +++ b/engines/titanic/pet_control/pet_save.cpp @@ -0,0 +1,72 @@ +/* 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 "titanic/pet_control/pet_save.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +bool CPetSave::reset() { + CPetLoadSave::reset(); + + CPetControl *pet = getPetControl(); + if (pet) { + setName("PetSave", pet); + _btnLoadSave.reset("PetSaveOut", pet, MODE_UNSELECTED); + _btnLoadSave.reset("PetSaveIn", pet, MODE_SELECTED); + } + + return true; +} + +bool CPetSave::MouseButtonUpMsg(const Point &pt) { + if (_btnLoadSave.MouseButtonUpMsg(pt)) { + execute(); + resetSlots(); + return true; + } else { + return false; + } +} + +void CPetSave::highlightCurrent(const Point &pt) { + resetSlots(); + highlightSave(_savegameSlotNum); +} + +void CPetSave::getTooltip(CPetText *text) { + text->setText("Save the game."); +} + +void CPetSave::highlightSave(int index) { + warning("TODO: CPetSave::highlightSave"); +} + +void CPetSave::unhighlightSave(int index) { + warning("TODO: CPetSave::unhighlightSave"); +} + +void CPetSave::execute() { + warning("TODO: CPetSave::execute"); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_save.h b/engines/titanic/pet_control/pet_save.h new file mode 100644 index 0000000000..54e91e4c76 --- /dev/null +++ b/engines/titanic/pet_control/pet_save.h @@ -0,0 +1,88 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_SAVE_H +#define TITANIC_PET_SAVE_H + +#include "titanic/pet_control/pet_load_save.h" + +namespace Titanic { + +class CPetSave : public CPetLoadSave { +public: + /** + * Reset the glyph + */ + virtual bool reset(); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Unhighlight any currently highlighted element + */ + virtual void unhighlightCurrent() { unhighlightSave(_savegameSlotNum); } + + /** + * Highlight any currently highlighted element + */ + virtual void highlightCurrent(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); + + /** + * Called on a highlighted item when PET area is entered + */ + virtual bool enterHighlighted() { + highlightSave(_savegameSlotNum); + return true; + } + + /** + * Called on a highlighted item when PET area is left + */ + virtual void leaveHighlighted() { unhighlightSave(_savegameSlotNum); } + + /** + * Highlights a save slot + */ + virtual void highlightSave(int index); + + /** + * Unhighlight a save slot + */ + virtual void unhighlightSave(int index); + + /** + * Executes the loading or saving + */ + virtual void execute(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_SAVE_H */ diff --git a/engines/titanic/pet_control/pet_section.cpp b/engines/titanic/pet_control/pet_section.cpp new file mode 100644 index 0000000000..50d6c7615c --- /dev/null +++ b/engines/titanic/pet_control/pet_section.cpp @@ -0,0 +1,109 @@ +/* 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/textconsole.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +static const uint PALETTE1[6] = { + 0xA7C0DB, 0x9CFFFE, 0x73AEFF, 0xA7C0DB, 0x9CFFFE, 0 +}; + +static const uint PALETTE2[6] = { + 0x10101, 0x1013C, 0xC80101, 0x10101, 0x800101, 0 +}; + +static const uint PALETTE3[5] = { + 0x10101, 0x1013C, 0xC80101, 0x10101, 0x800101 +}; + +void CPetSection::displayMessage(const CString &msg) { + CPetText *text = getText(); + + if (text) { + text->setColor(getColor(1)); + _petControl->makeDirty(); + removeText(5000); + } +} + +void CPetSection::timerExpired(int val) { + if (!val) { + removeText(); + _petControl->makeDirty(); + } +} + +void CPetSection::removeText(int duration) { + if (duration > 0) + _petControl->startPetTimer(0, duration, 0, this); + else + removeText(); +} + +void CPetSection::removeText() { + CPetText *text = getText(); + if (text) + text->setup(); +} + +void CPetSection::stopTextTimer() { + _petControl->stopPetTimer(0); +} + +uint CPetSection::getColor(uint index) { + return getColorTable()[index]; +} + +const uint *CPetSection::getColorTable(int tableNum) { + if (tableNum == -1) { + CPetControl *pet = getPetControl(); + tableNum = pet ? pet->getPassengerClass() : 3; + } + + switch (tableNum) { + case 1: return PALETTE1; + case 2: return PALETTE2; + default: return PALETTE3; + } +} + +void CPetSection::areaChanged(PetArea area) { + if (_petControl && _petControl->_currentArea == area) + _petControl->makeDirty(); +} + +CString CPetSection::getActiveNPCName() const { + if (_petControl && _petControl->_activeNPC) + return _petControl->_activeNPC->getName(); + else + return CString(); +} + +void CPetSection::copyColors(uint tableNum, uint colors[5]) { + const uint *src = getColorTable(tableNum); + Common::copy(src, src + 5, colors); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_section.h b/engines/titanic/pet_control/pet_section.h new file mode 100644 index 0000000000..8bc427e842 --- /dev/null +++ b/engines/titanic/pet_control/pet_section.h @@ -0,0 +1,250 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_SECTION_H +#define TITANIC_PET_SECTION_H + +#include "titanic/messages/mouse_messages.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +enum PetArea { + PET_INVENTORY = 0, PET_CONVERSATION = 1, PET_REMOTE = 2, + PET_ROOMS = 3, PET_REAL_LIFE = 4, PET_STARFIELD = 5, PET_MESSAGE = 6 +}; + +class CPetControl; +class CPetElement; +class CPetText; +class CScreenManager; +class CRoomItem; + +struct CPetSectionSubData { + int _field0; + int _field4; + int _field8; + int _fieldC; + + CPetSectionSubData() : _field0(0), _field4(0), _field8(0), + _fieldC(0) {} +}; + +class CPetSection { +public: + CPetControl *_petControl; +protected: + /** + * Called when the current area is changed + */ + void areaChanged(PetArea area); + + /** + * Returns the name of the currently active NPC, if any + */ + CString getActiveNPCName() const; + + /** + * Create a color table + */ + void copyColors(uint tableNum, uint colors[5]); +public: + CPetSection() : _petControl(nullptr) {} + virtual ~CPetSection() {} + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl) { return false; } + + /** + * Reset the section + */ + virtual bool reset() { return false; } + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager) {} + + /** + * Get the bounds for the section + */ + virtual Rect getBounds() const { return Rect(); } + + /** + * Called when a general change occurs + */ + virtual void changed(int changeType) {} + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg) { return false; } + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg) { return false; } + virtual bool MouseDragMoveMsg(CMouseDragMoveMsg *msg) { return false; } + virtual bool MouseDragEndMsg(CMouseDragEndMsg *msg) { return false; } + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg) { return false; } + virtual bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { return false; } + virtual bool KeyCharMsg(CKeyCharMsg *msg) { return false; } + virtual bool VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) { return false; } + + /** + * Check whether a drag drop can occur + */ + virtual bool checkDragEnd(CGameObject *item) { return false; } + + /** + * Returns item a drag-drop operation has dropped on, if any + */ + virtual CGameObject *dragEnd(const Point &pt) const { return nullptr; } + + /** + * Display a message + */ + virtual void displayMessage(const CString &msg); + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl) { return false; } + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param) {} + + /** + * Called after a game has been loaded + */ + virtual void postLoad() {} + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent) {} + + /** + * Called when a section is switched to + */ + virtual void enter(PetArea oldArea) {} + + /** + * Called when a section is being left, to switch to another area + */ + virtual void leave() {} + + virtual void proc23() {} + + /** + * Called when a new room is entered + */ + virtual void enterRoom(CRoomItem *room) {} + + /** + * Called when a previously set up PET timer expires + */ + virtual void timerExpired(int val); + + /** + * Get a reference to the tooltip text associated with the section + */ + virtual CPetText *getText() { return nullptr; } + + /** + * Removes text after a given duration + */ + virtual void removeText(int duration); + + /** + * Removes text after a given duration + */ + virtual void removeText(); + + /** + * Stops the text removal timer + */ + virtual void stopTextTimer(); + + /** + * Get an element from the section by a designated Id + */ + virtual CPetElement *getElement(uint id) { return nullptr; } + + /** + * Special retrieval of glyph background image + */ + virtual CGameObject *getBackground(int index) const { return nullptr; } + + /** + * Display a title for an NPC + */ + virtual void displayNPCName(CGameObject *npc) {} + + virtual void proc33() {} + + /** + * Sets the NPC to use + */ + virtual void setNPC(const CString &name) {} + + /** + * Resets the active NPC + */ + virtual void resetNPC() {} + + /** + * Show the text cursor + */ + virtual void showCursor() {} + + /** + * Hide the text cursor + */ + virtual void hideCursor() {} + + /** + * Highlights a glyph item in the section, if applicable + */ + virtual void highlight(int id) {} + + /** + * Get the PET control + */ + CPetControl *getPetControl() const { return _petControl; } + + /** + * Get a specified color in the currently active UI color table + */ + uint getColor(uint index); + + /** + * Get one of the game's three UI color tables. If the default + * tableNum of -1 is used, the table is taken from the game state + */ + const uint *getColorTable(int tableNum = -1); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_SECTION_H */ diff --git a/engines/titanic/pet_control/pet_slider.cpp b/engines/titanic/pet_control/pet_slider.cpp new file mode 100644 index 0000000000..eb07012f43 --- /dev/null +++ b/engines/titanic/pet_control/pet_slider.cpp @@ -0,0 +1,246 @@ +/* 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 "titanic/pet_control/pet_slider.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +CPetSlider::CPetSlider() { + _orientation = 0; + _thumbWidth = 0; + _thumbHeight = 0; + _sliderOffset = 0; + _thumbFocused = false; +} + +Rect CPetSlider::clearDirtyArea() { + Rect result = _dirtyArea; + _dirtyArea.clear(); + return result; +} + +bool CPetSlider::checkThumb(const Point &pt) { + _thumbFocused = thumbContains(pt); + if (_thumbFocused) + return true; + else + return containsPt(pt); +} + +bool CPetSlider::resetThumbFocus() { + bool result = _thumbFocused; + _thumbFocused = false; + return result; +} + +bool CPetSlider::MouseDragMoveMsg(const Point &pt) { + int newOffset = calcSliderOffset(pt); + setOffsetPixels(newOffset); + return true; +} + +bool CPetSlider::MouseButtonUpMsg(const Point &pt) { + if (thumbContains(pt)) + return true; + if (!containsPt(pt)) + return false; + + int newOffset = calcSliderOffset(pt); + setOffsetPixels(newOffset); + return true; +} + +bool CPetSlider::contains(const Point &pt) const { + return thumbContains(pt) || containsPt(pt); +} + +double CPetSlider::getOffsetPixels() const { + int maxVal = 0, minVal = 0; + if (_orientation & ORIENTATION_HORIZONTAL) { + maxVal = _slidingRect.right; + minVal = _slidingRect.left; + } + + if (_orientation & ORIENTATION_VERTICAL) { + maxVal = _slidingRect.bottom; + minVal = _slidingRect.top; + } + + if (minVal == maxVal) + return 0.0; + + return _sliderOffset / (maxVal - minVal); +} + +void CPetSlider::setSliderOffset(double offset) { + if (_orientation & ORIENTATION_HORIZONTAL) + _sliderOffset = (int)(offset * (_slidingRect.right - _slidingRect.left)); + + if (_orientation & ORIENTATION_VERTICAL) + _sliderOffset = (int)(offset * (_slidingRect.bottom - _slidingRect.top)); +} + +void CPetSlider::setOffsetPixels(int offset) { + // Add the slider's old position to the dirty area + Rect tempRect = getThumbRect(); + _dirtyArea.combine(tempRect); + + // Set the new offset + _sliderOffset = offset; + + // Add the thumb's new location to the dirty area + tempRect = getThumbRect(); + _dirtyArea.combine(tempRect); +} + +Point CPetSlider::getBackgroundDrawPos() { + return Point(_bounds.left, _bounds.top); +} + +Point CPetSlider::getThumbDrawPos() { + Point thumbPos = getThumbCentroidPos(); + thumbPos -= Point(_thumbWidth / 2, _thumbHeight / 2); + return thumbPos; +} + +Point CPetSlider::getThumbCentroidPos() const { + Point pt; + + if (_orientation & ORIENTATION_HORIZONTAL) { + pt = Point(_slidingRect.left + _sliderOffset, + _slidingRect.top + _slidingRect.height() / 2); + } + + if (_orientation & ORIENTATION_VERTICAL) { + pt = Point(_slidingRect.left + _slidingRect.width() / 2, + _slidingRect.top + _sliderOffset); + } + + return pt; +} + +bool CPetSlider::thumbContains(const Point &pt) const { + return getThumbRect().contains(pt); +} + +Rect CPetSlider::getThumbRect() const { + Rect thumbRect(0, 0, _thumbWidth, _thumbHeight); + Point centroid = getThumbCentroidPos(); + thumbRect.moveTo(centroid.x - _thumbWidth / 2, centroid.y - _thumbHeight / 2); + + return thumbRect; +} + +int CPetSlider::calcSliderOffset(const Point &pt) const { + int result = 0; + + if (_orientation & ORIENTATION_HORIZONTAL) { + result = CLIP(pt.x, _slidingRect.left, _slidingRect.right) - _slidingRect.left; + } + + if (_orientation & ORIENTATION_VERTICAL) { + result = CLIP(pt.y, _slidingRect.top, _slidingRect.bottom) - _slidingRect.top; + } + + return result; +} + +void CPetSlider::setOrientation(SliderOrientation orientation) { + _orientation |= orientation; +} + +void CPetSlider::stepPosition(int direction) { + double val = getOffsetPixels(); + + if (direction == -1) { + val = MAX<double>(val - 0.1, 0.0); + } else if (direction == 1) { + val = MIN<double>(val + 0.1, 1.0); + } + + setSliderOffset(val); +} + +/*------------------------------------------------------------------------*/ + +void CPetSoundSlider::setupBackground(const CString &name, CPetControl *petControl) { + if (petControl) { + _background = petControl->getHiddenObject(name); + } +} + +void CPetSoundSlider::setupThumb(const CString &name, CPetControl *petControl) { + if (petControl) { + _thumb = petControl->getHiddenObject(name); + } +} + +void CPetSoundSlider::setupBackground2(const CString &name, CPetControl *petControl) { + if (petControl) { + CString numStr = "3"; + int mode = petControl->getPassengerClass(); + if (mode <= 3) { + numStr = CString(mode); + } else if (mode == 4) { + mode = petControl->getPriorClass(); + if (mode == 1) { + numStr = CString(mode); + } + } + + CString fullName = numStr + name; + setupBackground(fullName, petControl); + } +} + +void CPetSoundSlider::setupThumb2(const CString &name, CPetControl *petControl) { + if (petControl) { + CString numStr = "3"; + int mode = petControl->getPassengerClass(); + if (mode <= 3) { + numStr = CString(mode); + } else if (mode == 4) { + mode = petControl->getPriorClass(); + if (mode == 1) { + numStr = CString(mode); + } + } + + CString fullName = numStr + name; + setupThumb(fullName, petControl); + } +} + +void CPetSoundSlider::draw(CScreenManager *screenManager) { + if (_background) { + Point pt = getBackgroundDrawPos(); + _background->draw(screenManager, pt); + } + + if (_thumb) { + Point pt = getThumbDrawPos(); + _thumb->draw(screenManager, pt); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_slider.h b/engines/titanic/pet_control/pet_slider.h new file mode 100644 index 0000000000..0bc9e825cd --- /dev/null +++ b/engines/titanic/pet_control/pet_slider.h @@ -0,0 +1,239 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_SLIDER_H +#define TITANIC_PET_SLIDER_H + +#include "titanic/support/rect.h" +#include "titanic/support/string.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +enum SliderOrientation { ORIENTATION_HORIZONTAL = 1, ORIENTATION_VERTICAL = 2 }; + +class CPetControl; + +class CPetSlider { +private: + int _orientation; + Rect _bounds; + Rect _slidingRect; + int _thumbWidth; + int _thumbHeight; + int _sliderOffset; + bool _thumbFocused; + Rect _dirtyArea; +private: + /** + * Center the center position of the slider's thumb + */ + Point getThumbCentroidPos() const; + + /** + * Returns true if the passed point is within the thumb + */ + bool thumbContains(const Point &pt) const; + + /** + * Gets the area the slider's thumbnail covers + */ + Rect getThumbRect() const; + + /** + * Calculates the slider offset at the specificed position + */ + int calcSliderOffset(const Point &pt) const; +protected: + /** + * Get the position to draw the background at + */ + Point getBackgroundDrawPos(); + + /** + * Get the position to draw the slider thumbnail at + */ + Point getThumbDrawPos(); + + /** + * Returns true if the passed point falls within the slider's bounds + */ + bool containsPt(const Point &pt) const { return _bounds.contains(pt); } +public: + CPetSlider(); + virtual ~CPetSlider() {} + + /** + * Setup the background + */ + virtual void setupBackground(const CString &name, CPetControl *petControl) {} + + /** + * Setup the thumb + */ + virtual void setupThumb(const CString &name, CPetControl *petControl) {} + + /** + * Setup the background + */ + virtual void setupBackground2(const CString &name, CPetControl *petControl) {} + + /** + * Setup the thumb + */ + virtual void setupThumb2(const CString &name, CPetControl *petControl) {} + + /** + * Reset the slider + */ + virtual void reset(const CString &name) {} + + /** + * Draw the slider + */ + virtual void draw(CScreenManager *screenManager) {} + + /** + * Reset the dirty area + */ + virtual Rect clearDirtyArea(); + + /** + * Checks whether the slider is highlighted + */ + virtual bool checkThumb(const Point &pt); + + /** + * Resets the thumb focused flag + */ + virtual bool resetThumbFocus(); + + /** + * Handles dragging the slider + */ + virtual bool MouseDragMoveMsg(const Point &pt); + + /** + * Called when a slider drag ends + */ + virtual bool MouseDragEndMsg(const Point &pt) { return true; } + + /** + * Handles mouse button up messaes + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + virtual bool proc13() { return false; } + virtual bool proc14() { return false; } + + + virtual bool contains(const Point &pt) const; + + /** + * Returns the slider offset in pixels + */ + virtual double getOffsetPixels() const; + + /** + * Sets the slider offset + */ + virtual void setSliderOffset(double offset); + + /** + * Set a new slider offset in pixels + */ + virtual void setOffsetPixels(int offset); + + /** + * Enables a given orientation + */ + void setOrientation(SliderOrientation orientation); + + /** + * Set the bounds for the slider + */ + void setBounds(const Rect &r) { _bounds = r; } + + /** + * Set the sliding bounds for the slider + */ + void setSlidingBounds(const Rect &r) { _slidingRect = r; } + + /** + * Set the size of the slider thumb + */ + void setThumbSize(const Point &pt) { + _thumbWidth = pt.x; + _thumbHeight = pt.y; + } + + /** + * Move the slider + */ + void translate(const Point &pt) { + _bounds.translate(pt.x, pt.y); + _slidingRect.translate(pt.x, pt.y); + } + + /** + * Change the current position of a slider by a step amount + */ + void stepPosition(int direction); +}; + +class CPetSoundSlider : public CPetSlider { +public: + CGameObject *_background; + CGameObject *_thumb; +public: + CPetSoundSlider() : CPetSlider(), _background(nullptr), + _thumb(0) {} + + /** + * Setup the background + */ + virtual void setupBackground(const CString &name, CPetControl *petControl); + + /** + * Setup the thumb + */ + virtual void setupThumb(const CString &name, CPetControl *petControl); + + /** + * Setup the background + */ + virtual void setupBackground2(const CString &name, CPetControl *petControl); + + /** + * Setup the thumb + */ + virtual void setupThumb2(const CString &name, CPetControl *petControl); + + /** + * Draw the slider + */ + virtual void draw(CScreenManager *screenManager); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_SLIDER_H */ diff --git a/engines/titanic/pet_control/pet_sound.cpp b/engines/titanic/pet_control/pet_sound.cpp new file mode 100644 index 0000000000..7bfeb25722 --- /dev/null +++ b/engines/titanic/pet_control/pet_sound.cpp @@ -0,0 +1,282 @@ +/* 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 "titanic/pet_control/pet_sound.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_real_life.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +CPetSound::CPetSound() : CPetGlyph(), _draggingSlider(nullptr), _draggingSliderNum(0) { +} + +bool CPetSound::setup(CPetControl *petControl, CPetGlyphs *owner) { + CPetGlyph::setup(petControl, owner); + + _masterVolume.setOrientation(ORIENTATION_HORIZONTAL); + _masterVolume.setBounds(Rect(17, 0, 147, 15)); + _masterVolume.setSlidingBounds(Rect(35, 5, 127, 11)); + _masterVolume.setThumbSize(Point(25, 15)); + _masterVolume.translate(Point(415, 376)); + + _musicVolume.setOrientation(ORIENTATION_HORIZONTAL); + _musicVolume.setBounds(Rect(17, 20, 147, 35)); + _musicVolume.setSlidingBounds(Rect(35, 25, 127, 31)); + _musicVolume.setThumbSize(Point(25, 15)); + _musicVolume.translate(Point(415, 376)); + + _parrotVolume.setOrientation(ORIENTATION_HORIZONTAL); + _parrotVolume.setBounds(Rect(17, 40, 147, 55)); + _parrotVolume.setSlidingBounds(Rect(35, 45, 127, 51)); + _parrotVolume.setThumbSize(Point(25, 15)); + _parrotVolume.translate(Point(415, 376)); + + _parrotVolume.setOrientation(ORIENTATION_HORIZONTAL); + _parrotVolume.setBounds(Rect(17, 60, 147, 75)); + _parrotVolume.setSlidingBounds(Rect(35, 65, 127, 71)); + _parrotVolume.setThumbSize(Point(25, 15)); + _parrotVolume.translate(Point(415, 376)); + + _element.setBounds(Rect(0, 0, 165, 77)); + _element.translate(Point(415, 376)); + + Rect rect(0, 0, 88, 16); + rect.translate(320, 376); + _textMasterVolume.setBounds(rect); + _textMasterVolume.resize(3); + _textMasterVolume.setHasBorder(false); + _textMasterVolume.setText("Master volume"); + + rect.translate(0, 20); + _textMusicVolume.setBounds(rect); + _textMusicVolume.resize(3); + _textMusicVolume.setHasBorder(false); + _textMusicVolume.setText("Music volume"); + + rect.translate(0, 20); + _textParrotVolume.setBounds(rect); + _textParrotVolume.resize(3); + _textParrotVolume.setHasBorder(false); + _textParrotVolume.setText("Parrot volume"); + + rect.translate(0, 20); + _textSpeechVolume.setBounds(rect); + _textSpeechVolume.resize(3); + _textSpeechVolume.setHasBorder(false); + _textSpeechVolume.setText("Speech volume"); + + return true; +} + +bool CPetSound::reset() { + CPetControl *pet = getPetControl(); + if (pet) { + setName("PetSound", pet); + _element.reset("PetVolChannels", pet, MODE_UNSELECTED); + _musicVolume.reset("PetVolSlug"); + _masterVolume.reset("PetVolSlug"); + _parrotVolume.reset("PetVolSlug"); + _speechVolume.reset("PetVolSlug"); + + CPetSection *section = getPetSection(); + uint col = section->getColor(0); + _textMusicVolume.setLineColor(0, col); + _textMasterVolume.setLineColor(0, col); + _textParrotVolume.setLineColor(0, col); + _textSpeechVolume.setLineColor(0, col); + } + + return false; +} + +void CPetSound::draw2(CScreenManager *screenManager) { + _element.draw(screenManager); + + _musicVolume.draw(screenManager); + _masterVolume.draw(screenManager); + _parrotVolume.draw(screenManager); + _speechVolume.draw(screenManager); + + _textMusicVolume.draw(screenManager); + _textMasterVolume.draw(screenManager); + _textParrotVolume.draw(screenManager); + _textSpeechVolume.draw(screenManager); +} + +bool CPetSound::MouseButtonDownMsg(const Point &pt) { + if (_musicVolume.checkThumb(pt) || _masterVolume.checkThumb(pt) || + _speechVolume.checkThumb(pt)) + return true; + + if (_parrotVolume.checkThumb(pt)) { + CPetControl *pet = getPetControl(); + if (pet) + pet->playSound(2); + + return true; + } + + Rect rectLeft(0, 0, 10, 11); + Rect rectRight(0, 0, 10, 11); + rectLeft.translate(415, 379); + rectRight.translate(567, 378); + + CPetSlider *sliders[4] = { &_masterVolume, &_musicVolume, &_parrotVolume, &_speechVolume }; + for (int idx = 0; idx < 4; ++idx) { + CPetSlider *slider = sliders[idx]; + bool isLeft = rectLeft.contains(pt); + bool isRight = rectRight.contains(pt); + double offset; + + if (isLeft) { + slider->stepPosition(-1); + offset = slider->getOffsetPixels(); + } else if (isRight) { + slider->stepPosition(1); + offset = slider->getOffsetPixels(); + } + + if (isLeft || isRight) { + sliderChanged(offset, idx); + return true; + } + + // Move to next slider row + rectLeft.translate(0, 20); + rectRight.translate(0, 20); + } + + return false; +} + +void CPetSound::sliderChanged(double offset, int sliderNum) { + CPetControl *pet = getPetControl(); + if (!pet) + return; + + CGameManager *gameManager = pet->getGameManager(); + if (!gameManager) + return; + + QSoundManager &soundManager = gameManager->_sound._soundManager; + double percent = offset * 100.0; + + switch (sliderNum) { + case 0: + soundManager.setMasterPercent(percent); + break; + case 1: + soundManager.setMusicPercent(percent); + break; + case 2: + soundManager.setParrotPercent(percent); + break; + case 3: + soundManager.setSpeechPercent(percent); + break; + default: + break; + } +} + +bool CPetSound::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (_musicVolume.resetThumbFocus()) { + _draggingSlider = &_musicVolume; + getOwner()->startDragging(this, msg); + _draggingSliderNum = 0; + return true; + } else if (_masterVolume.resetThumbFocus()) { + _draggingSlider = &_masterVolume; + getOwner()->startDragging(this, msg); + _draggingSliderNum = 1; + return true; + } else if (_parrotVolume.resetThumbFocus()) { + _draggingSlider = &_parrotVolume; + getOwner()->startDragging(this, msg); + _draggingSliderNum = 2; + return true; + } else if (_speechVolume.resetThumbFocus()) { + _draggingSlider = &_speechVolume; + getOwner()->startDragging(this, msg); + _draggingSliderNum = 3; + return true; + } + + _draggingSlider = nullptr; + return false; +} + +bool CPetSound::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + if (!_draggingSlider) + return false; + + if (_draggingSlider->MouseDragMoveMsg(msg->_mousePos)) { + double offset = _draggingSlider->getOffsetPixels(); + sliderChanged(offset, _draggingSliderNum); + getPetControl()->makeDirty(); + return true; + } + + return false; +} + +bool CPetSound::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (!_draggingSlider) + return false; + + _draggingSlider->MouseDragEndMsg(msg->_mousePos); + getOwner()->endDragging(); + + return false; +} + +bool CPetSound::MouseButtonUpMsg(const Point &pt) { + int sliderNum = 0; + CPetSlider *slider = nullptr; + + if (_musicVolume.MouseButtonUpMsg(pt)) { + sliderNum = 0; + slider = &_musicVolume; + } else if (_masterVolume.MouseButtonUpMsg(pt)) { + sliderNum = 1; + slider = &_masterVolume; + } else if (_parrotVolume.MouseButtonUpMsg(pt)) { + sliderNum = 2; + slider = &_parrotVolume; + } else if (_speechVolume.MouseButtonUpMsg(pt)) { + sliderNum = 3; + slider = &_speechVolume; + } else { + return false; + } + + double offset = slider->getOffsetPixels(); + sliderChanged(offset, sliderNum); + return true; +} + +void CPetSound::getTooltip(CPetText *text) { + text->setText("Change the volume settings."); +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_sound.h b/engines/titanic/pet_control/pet_sound.h new file mode 100644 index 0000000000..c4b663ad44 --- /dev/null +++ b/engines/titanic/pet_control/pet_sound.h @@ -0,0 +1,104 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_SOUND_H +#define TITANIC_PET_SOUND_H + +#include "titanic/pet_control/pet_glyphs.h" +#include "titanic/pet_control/pet_gfx_element.h" +#include "titanic/pet_control/pet_text.h" +#include "titanic/pet_control/pet_slider.h" + +namespace Titanic { + +class CPetRealLife; + +class CPetSound : public CPetGlyph { +private: + CPetGfxElement _element; + CPetSlider _masterVolume; + CPetSlider _musicVolume; + CPetSlider _parrotVolume; + CPetSlider _speechVolume; + CPetText _textMasterVolume; + CPetText _textMusicVolume; + CPetText _textParrotVolume; + CPetText _textSpeechVolume; + CPetSlider *_draggingSlider; + int _draggingSliderNum; +private: + /** + * Called when a slider has changed + */ + void sliderChanged(double offset, int sliderNum); +public: + CPetSound(); + + /** + * Setup the glyph + */ + virtual bool setup(CPetControl *petControl, CPetGlyphs *owner); + + /** + * Reset the glyph + */ + virtual bool reset(); + + /** + * Handles any secondary drawing of the glyph + */ + virtual void draw2(CScreenManager *screenManager); + + /** + * Called for mouse button down messages + */ + virtual bool MouseButtonDownMsg(const Point &pt); + + /** + * Called when mouse drag starts + */ + virtual bool MouseDragStartMsg(CMouseDragStartMsg *msg); + + /** + * Called during mouse drags + */ + virtual bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + + /** + * Called when mouse drag ends + */ + virtual bool MouseDragEndMsg(CMouseDragEndMsg *msg); + + /** + * Handles mouse button up messages + */ + virtual bool MouseButtonUpMsg(const Point &pt); + + /** + * Returns the tooltip text for when the glyph is selected + */ + virtual void getTooltip(CPetText *text); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_SOUND_H */ diff --git a/engines/titanic/pet_control/pet_starfield.cpp b/engines/titanic/pet_control/pet_starfield.cpp new file mode 100644 index 0000000000..34d696e09c --- /dev/null +++ b/engines/titanic/pet_control/pet_starfield.cpp @@ -0,0 +1,257 @@ +/* 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 "titanic/pet_control/pet_starfield.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/star_control/star_control.h" + +namespace Titanic { + +CPetStarfield::CPetStarfield() : _field18C(0), _photoOn(true), + _hasReference(false), _rect1(22, 352, 598, 478) { + _btnOffsets[0] = _btnOffsets[1] = _btnOffsets[2] = 0; +} + +bool CPetStarfield::setup(CPetControl *petControl) { + if (petControl && setupControl(petControl)) + return reset(); + return false; +} + +bool CPetStarfield::reset() { + if (_petControl) { + _imgStarfield.setup(MODE_UNSELECTED, "3PetStarField", _petControl); + _imgPhoto.setup(MODE_UNSELECTED, "HomePhotoOnOff", _petControl); + _btnSetDest.setup(MODE_UNSELECTED, "3PetSetDestin", _petControl); + _btnSetDest.setup(MODE_SELECTED, "3PetSetDestin1", _petControl); + _imgStarCtrl.setup(MODE_UNSELECTED, "3PetStarCtrl", _petControl); + + _leds[0].setup(MODE_UNSELECTED, "LEDOff1", _petControl); + _leds[1].setup(MODE_UNSELECTED, "LEDOn1", _petControl); + _leds[2].setup(MODE_UNSELECTED, "LEDOff2", _petControl); + _leds[3].setup(MODE_UNSELECTED, "LEDOn2", _petControl); + _leds[4].setup(MODE_UNSELECTED, "LEDOff3", _petControl); + _leds[5].setup(MODE_UNSELECTED, "LEDOn3", _petControl); + + uint col = getColor(0); + _text.setColor(col); + _text.setLineColor(0, col); + } + + return true; +} + +void CPetStarfield::draw(CScreenManager *screenManager) { + _petControl->drawSquares(screenManager, 2); + + _imgStarfield.draw(screenManager); + if (_photoOn) { + _imgPhoto.draw(screenManager); + } else { + _imgStarCtrl.draw(screenManager); + } + + _btnSetDest.draw(screenManager); + drawButton(_btnOffsets[0], 0, screenManager); + drawButton(_btnOffsets[1], 2, screenManager); + drawButton(_btnOffsets[2], 4, screenManager); + _text.draw(screenManager); +} + +bool CPetStarfield::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_petControl->_remoteTarget) + return false; + + if (_imgStarfield.MouseButtonDownMsg(msg->_mousePos)) { + CPETHelmetOnOffMsg helmetMsg; + helmetMsg.execute(_petControl->_remoteTarget); + } else if (_imgPhoto.MouseButtonDownMsg(msg->_mousePos)) { + if (_hasReference) { + _photoOn = !_photoOn; + CPETPhotoOnOffMsg photoMsg; + photoMsg.execute(_petControl->_remoteTarget); + } else { + _petControl->displayMessage("Please supply Galactic reference material."); + } + } else if (!_btnSetDest.MouseButtonDownMsg(msg->_mousePos)) { + return elementsMouseDown(msg); + } + + return true; +} + +bool CPetStarfield::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (!_petControl->_remoteTarget || !_btnSetDest.MouseButtonUpMsg(msg->_mousePos)) + return false; + + if (_petControl) { + CStarControl *starControl = _petControl->getStarControl(); + + if (starControl && starControl->canSetStarDestination()) { + CPETSetStarDestinationMsg starfieldMsg; + starfieldMsg.execute(_petControl->_remoteTarget); + starControl->starDestinationSet(); + } + } + + return true; +} + +bool CPetStarfield::isValid(CPetControl *petControl) { + return setupControl(petControl); +} + +void CPetStarfield::load(SimpleFile *file, int param) { + if (!param) { + _photoOn = file->readNumber(); + _hasReference = file->readNumber(); + } +} + +void CPetStarfield::postLoad() { + reset(); +} + +void CPetStarfield::save(SimpleFile *file, int indent) { + file->writeNumberLine(_photoOn, indent); + file->writeNumberLine(_hasReference, indent); +} + +bool CPetStarfield::setupControl(CPetControl *petControl) { + if (petControl) { + _petControl = petControl; + + Rect r(0, 0, 64, 64); + r.translate(_rect1.left, _rect1.top); + + _imgStarfield.setBounds(r); + _imgStarfield.translate(15, 23); + _imgPhoto.setBounds(r); + _imgPhoto.translate(85, 23); + _imgStarCtrl.setBounds(r); + _imgStarCtrl.translate(85, 23); + + r = Rect(0, 0, 34, 34); + r.translate(468, 396); + _leds[0].setBounds(r); + _leds[1].setBounds(r); + + r.translate(36, 0); + _leds[2].setBounds(r); + _leds[3].setBounds(r); + + r.translate(36, 0); + _leds[4].setBounds(r); + _leds[5].setBounds(r); + + r = Rect(0, 0, 157, 51); + r.translate(224, 33); + r.translate(20, 350); + _btnSetDest.setBounds(r); + + r = Rect(0, 0, 580, 15); + r.translate(32, 445); + _text.setBounds(r); + _text.setHasBorder(false); + } + + return true; +} + +void CPetStarfield::drawButton(int offset, int index, CScreenManager *screenManager) { + if (_field18C < 4 && (offset / 3) == 1) + --offset; + if (offset == 2) + offset = 1; + + _leds[index + offset].draw(screenManager); +} + +void CPetStarfield::setButtons(int val1, int val2) { + _btnOffsets[0] = 0; + _btnOffsets[1] = 0; + _btnOffsets[2] = 0; + + if (val1 >= 0) + _btnOffsets[0] = 2; + if (val1 >= 1) + _btnOffsets[1] = 2; + if (val1 >= 2) + _btnOffsets[2] = 2; + + if (val2) { + if (val1 == -1) + _btnOffsets[0] = 1; + if (val1 == 0) + _btnOffsets[1] = 1; + if (val1 == 1) + _btnOffsets[2] = 1; + } + + _field18C = (_field18C + 1) % 8; +} + +void CPetStarfield::makePetDirty() { + _petControl->makeDirty(); +} + +bool CPetStarfield::elementsMouseDown(CMouseButtonDownMsg *msg) { + if (elementMouseButton(0, msg, _leds[0].getBounds())) + return true; + if (elementMouseButton(1, msg, _leds[2].getBounds())) + return true; + if (elementMouseButton(2, msg, _leds[4].getBounds())) + return true; + + return false; +} + +bool CPetStarfield::elementMouseButton(int index, CMouseButtonDownMsg *msg, const Rect &rect) { + if (!rect.contains(msg->_mousePos)) + return false; + + switch (_btnOffsets[index]) { + case 1: + if (_petControl->_remoteTarget) { + CPETStarFieldLockMsg lockMsg(1); + lockMsg.execute(_petControl->_remoteTarget); + } + break; + + case 2: + if (index < 2 && _btnOffsets[index] >= 2) { + if (_petControl->_remoteTarget) { + CPETStarFieldLockMsg lockMsg(1); + lockMsg.execute(_petControl->_remoteTarget); + } + } + break; + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_starfield.h b/engines/titanic/pet_control/pet_starfield.h new file mode 100644 index 0000000000..9550e0acf9 --- /dev/null +++ b/engines/titanic/pet_control/pet_starfield.h @@ -0,0 +1,125 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_STARFIELD_H +#define TITANIC_PET_STARFIELD_H + +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_text.h" +#include "titanic/pet_control/pet_gfx_element.h" + +namespace Titanic { + +class CPetStarfield : public CPetSection { +private: + CPetGfxElement _imgStarfield; + CPetGfxElement _imgPhoto; + CPetGfxElement _imgStarCtrl; + CPetGfxElement _btnSetDest; + int _btnOffsets[3]; + CPetGfxElement _leds[6]; + Rect _rect1; + int _field18C; + CPetText _text; + bool _photoOn; + bool _hasReference; +private: + /** + * Setup the control + */ + bool setupControl(CPetControl *petControl); + + /** + * Draw a button + */ + void drawButton(int offset, int index, CScreenManager *screenManager); + + /** + * Mouse down handling for Nav elements + */ + bool elementsMouseDown(CMouseButtonDownMsg *msg); + + bool elementMouseButton(int index, CMouseButtonDownMsg *msg, const Rect &rect); +public: + CPetStarfield(); + + /** + * Sets up the section + */ + virtual bool setup(CPetControl *petControl); + + /** + * Reset the section + */ + virtual bool reset(); + + /** + * Draw the section + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Following are handlers for the various messages that the PET can + * pass onto the currently active section/area + */ + virtual bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + virtual bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + + /** + * Returns true if the object is in a valid state + */ + virtual bool isValid(CPetControl *petControl); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param); + + /** + * Called after a game has been loaded + */ + virtual void postLoad(); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Sets the offsets for each of the buttons + */ + void setButtons(int val1, int val2); + + /** + * Sets whether the player has the galactic reference material + */ + void setHasReference(bool hasRef) { _hasReference = hasRef; } + + /** + * Make the PET as dirty, requiring a redraw + */ + void makePetDirty(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_STARFIELD_H */ diff --git a/engines/titanic/pet_control/pet_text.cpp b/engines/titanic/pet_control/pet_text.cpp new file mode 100644 index 0000000000..6813095626 --- /dev/null +++ b/engines/titanic/pet_control/pet_text.cpp @@ -0,0 +1,478 @@ +/* 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(0), you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation(0), 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(0), 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(0), if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +CPetText::CPetText(uint count) : + _stringsMerged(false), _maxCharsPerLine(-1), _lineCount(0), + _linesStart(-1), _field3C(0), _field40(0), _field44(0), + _backR(0xff), _backG(0xff), _backB(0xff), + _textR(0), _textG(0), _textB(200), + _fontNumber(0), _field64(0), _field68(0), _field6C(0), + _hasBorder(true), _scrollTop(0), _textCursor(nullptr), _field7C(0) { + setupArrays(count); +} + +void CPetText::setupArrays(int count) { + freeArrays(); + if (count < 10 || count > 60) + count = 10; + _array.resize(count); +} + +void CPetText::freeArrays() { + _array.clear(); +} + +void CPetText::setup() { + for (int idx = 0; idx < (int)_array.size(); ++idx) { + _array[idx]._line.clear(); + setLineColor(idx, _textR, _textG, _textB); + _array[idx]._string3.clear(); + } + + _lineCount = 0; + _stringsMerged = false; +} + +void CPetText::setLineColor(uint lineNum, uint col) { + setLineColor(lineNum, col & 0xff, (col >> 16) & 0xff, (col >> 8) & 0xff); +} + +void CPetText::setLineColor(uint lineNum, byte r, byte g, byte b) { + char buffer[6]; + if (!r) + r = 1; + if (!g) + g = 1; + if (!b) + b = 1; + + buffer[0] = TEXTCMD_SET_COLOR; + buffer[1] = r; + buffer[2] = g; + buffer[3] = b; + buffer[4] = TEXTCMD_SET_COLOR; + buffer[5] = '\0'; + _array[lineNum]._rgb = buffer; + + _stringsMerged = false; +} + +void CPetText::load(SimpleFile *file, int param) { + if (!param) { + uint numLines = file->readNumber(); + uint charsPerLine = file->readNumber(); + uint count = file->readNumber(); + _bounds = file->readRect(); + _field3C = file->readNumber(); + _field40 = file->readNumber(); + _field44 = file->readNumber(); + _backR = file->readNumber(); + _backG = file->readNumber(); + _backB = file->readNumber(); + _textR = file->readNumber(); + _textG = file->readNumber(); + _textB = file->readNumber(); + _hasBorder = file->readNumber() != 0; + _scrollTop = file->readNumber(); + + resize(numLines); + setMaxCharsPerLine(charsPerLine); + + assert(_array.size() >= count); + for (uint idx = 0; idx < count; ++idx) { + _array[idx]._line = file->readString(); + _array[idx]._rgb = file->readString(); + _array[idx]._string3 = file->readString(); + } + } +} + +void CPetText::save(SimpleFile *file, int indent) { + int numLines = _lineCount + 1; + + file->writeNumberLine(_array.size(), indent); + file->writeNumberLine(_maxCharsPerLine, indent); + file->writeNumberLine(numLines, indent); + + file->writeRect(_bounds, indent); + file->writeNumberLine(_field3C, indent); + file->writeNumberLine(_field40, indent); + file->writeNumberLine(_field44, indent); + file->writeNumberLine(_backR, indent); + file->writeNumberLine(_backG, indent); + file->writeNumberLine(_backB, indent); + file->writeNumberLine(_textR, indent); + file->writeNumberLine(_textG, indent); + file->writeNumberLine(_textB, indent); + file->writeNumberLine(_hasBorder, indent); + file->writeNumberLine(_scrollTop, indent); + + for (int idx = 0; idx < numLines; ++idx) { + file->writeQuotedLine(_array[idx]._line, indent); + file->writeQuotedLine(_array[idx]._rgb, indent); + file->writeQuotedLine(_array[idx]._string3, indent); + } +} + +void CPetText::draw(CScreenManager *screenManager) { + Rect tempRect = _bounds; + + if (_hasBorder) { + // Create border effect + // Top edge + tempRect.bottom = tempRect.top + 1; + screenManager->fillRect(SURFACE_BACKBUFFER, &tempRect, _backR, _backG, _backB); + + // Bottom edge + tempRect.top = _bounds.bottom - 1; + tempRect.bottom = _bounds.bottom; + screenManager->fillRect(SURFACE_BACKBUFFER, &tempRect, _backR, _backG, _backB); + + // Left edge + tempRect = _bounds; + tempRect.right = tempRect.left + 1; + screenManager->fillRect(SURFACE_BACKBUFFER, &tempRect, _backR, _backG, _backB); + + // Right edge + tempRect = _bounds; + tempRect.left = tempRect.right - 1; + screenManager->fillRect(SURFACE_BACKBUFFER, &tempRect, _backR, _backG, _backB); + } + + getTextHeight(screenManager); + + tempRect = _bounds; + tempRect.grow(-2); + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + + screenManager->writeString(SURFACE_BACKBUFFER, tempRect, _scrollTop, _lines, _textCursor); + + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::mergeStrings() { + if (!_stringsMerged) { + _lines.clear(); + + for (int idx = 0; idx <= _lineCount; ++idx) { + CString line = _array[idx]._rgb + _array[idx]._string3 + + _array[idx]._line + "\n"; + _lines += line; + } + + _stringsMerged = true; + } +} + +void CPetText::resize(uint count) { + if (!count || _array.size() == count) + return; + _array.clear(); + _array.resize(count); +} + +CString CPetText::getText() const { + CString result = ""; + for (int idx = 0; idx <= _lineCount; ++idx) + result += _array[idx]._line; + + return result; +} + +void CPetText::setText(const CString &str) { + setup(); + appendText(str); +} + +void CPetText::appendText(const CString &str) { + int lineSize = _array[_lineCount]._line.size(); + int strSize = str.size(); + + if (_maxCharsPerLine == -1) { + // No limit on horizontal characters, so append string to current line + _array[_lineCount]._line += str; + } else if ((lineSize + strSize) <= _maxCharsPerLine) { + // New string fits into line, so add it on + _array[_lineCount]._line += str; + } else { + // Only add part of the str up to the maximum allowed limit for line + _array[_lineCount]._line += str.left(_maxCharsPerLine - lineSize); + } + + updateStr3(_lineCount); + _stringsMerged = false; +} + +void CPetText::setColor(uint col) { + _textR = col & 0xff; + _textG = (col >> 8) & 0xff; + _textB = (col >> 16) & 0xff; +} + +void CPetText::setColor(byte r, byte g, byte b) { + _textR = r; + _textG = g; + _textB = b; +} + +void CPetText::remapColors(uint count, uint *srcColors, uint *destColors) { + if (_lineCount >= 0) { + for (int lineNum = 0; lineNum <= _lineCount; ++lineNum) { + // Get the rgb values + uint r = _array[lineNum]._rgb[1]; + uint g = _array[lineNum]._rgb[2]; + uint b = _array[lineNum]._rgb[3]; + uint color = r | (g << 8) | (b << 16); + + for (uint index = 0; index < count; ++index) { + if (color == srcColors[index]) { + // Found a match, so replace the color + setLineColor(lineNum, destColors[lineNum]); + break; + } + } + } + } + + _stringsMerged = false; +} + +void CPetText::setMaxCharsPerLine(int maxChars) { + if (maxChars >= -1 && maxChars < 257) + _maxCharsPerLine = maxChars; +} + +void CPetText::updateStr3(int lineNum) { + if (_field64 > 0 && _field68 > 0) { + char line[5]; + line[0] = line[3] = TEXTCMD_NPC; + line[1] = _field64; + line[2] = _field68; + line[4] = '\0'; + _array[lineNum]._string3 = CString(line); + + _stringsMerged = false; + _field64 = _field68 = 0; + } +} + +int CPetText::getTextWidth(CScreenManager *screenManager) { + mergeStrings(); + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + int textWidth = screenManager->stringWidth(_lines); + screenManager->setFontNumber(oldFontNumber); + + return textWidth; +} + +int CPetText::getTextHeight(CScreenManager *screenManager) { + mergeStrings(); + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + int textHeight = screenManager->getTextBounds(_lines, _bounds.width()); + screenManager->setFontNumber(oldFontNumber); + + return textHeight; +} + +void CPetText::deleteLastChar() { + if (!_array[_lineCount]._line.empty()) { + _array[_lineCount]._line.deleteLastChar(); + _stringsMerged = false; + } +} + +void CPetText::setNPC(int val1, int npcId) { + _field64 = val1; + _field68 = npcId; +} + +void CPetText::scrollUp(CScreenManager *screenManager) { + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + _scrollTop -= screenManager->getFontHeight(); + constrainScrollUp(screenManager); + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::scrollDown(CScreenManager *screenManager) { + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + _scrollTop += screenManager->getFontHeight(); + constrainScrollDown(screenManager); + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::scrollUpPage(CScreenManager *screenManager) { + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + _scrollTop -= getPageHeight(screenManager); + constrainScrollUp(screenManager); + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::scrollDownPage(CScreenManager *screenManager) { + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + _scrollTop += getPageHeight(screenManager); + constrainScrollDown(screenManager); + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::scrollToTop(CScreenManager *screenManager) { + _scrollTop = 0; +} + +void CPetText::scrollToBottom(CScreenManager *screenManager) { + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + _scrollTop = getTextHeight(screenManager); + constrainScrollDown(screenManager); + screenManager->setFontNumber(oldFontNumber); +} + +void CPetText::constrainScrollUp(CScreenManager *screenManager) { + if (_scrollTop < 0) + _scrollTop = 0; +} + +void CPetText::constrainScrollDown(CScreenManager *screenManager) { + // Figure out the maximum scroll amount allowed + int maxScroll = getTextHeight(screenManager) - _bounds.height() - 4; + if (maxScroll < 0) + maxScroll = 0; + + if (_scrollTop > maxScroll) + _scrollTop = maxScroll; +} + +int CPetText::getPageHeight(CScreenManager *screenManager) { + int textHeight = _bounds.height(); + int oldFontNumber = screenManager->setFontNumber(_fontNumber); + int fontHeight = screenManager->getFontHeight(); + screenManager->setFontNumber(oldFontNumber); + + if (fontHeight) { + int lines = textHeight / fontHeight; + if (lines > 1) + --lines; + return lines * fontHeight; + } else { + return 0; + } +} + +void CPetText::addLine(const CString &str) { + addLine(str, _textR, _textG, _textB); +} + +void CPetText::addLine(const CString &str, uint color) { + addLine(str, color & 0xff, (color >> 8) & 0xff, + (color >> 16) & 0xff); +} + +void CPetText::addLine(const CString &str, byte r, byte g, byte b) { + if (_lineCount == ((int)_array.size() - 1)) { + // Lines array is full + if (_array.size() > 1) { + // Delete the oldest line, and add a new entry at the end + _array.remove_at(0); + _array.resize(_array.size() + 1); + } + + --_lineCount; + } + + setLineColor(_lineCount, r, g, b); + appendText(str); + ++_lineCount; +} + +bool CPetText::handleKey(char c) { + switch (c) { + case (char)Common::KEYCODE_BACKSPACE: + deleteLastChar(); + break; + + case (char)Common::KEYCODE_RETURN: + return true; + + default: + if ((byte)c >= 32 && (byte)c <= 127) + appendText(CString(c, 1)); + break; + } + + return false; +} + +void CPetText::showCursor(int mode) { + CScreenManager *screenManager = CScreenManager::setCurrent(); + _textCursor = screenManager->_textCursor; + if (_textCursor) { + _textCursor->setPos(Point(0, 0)); + _textCursor->setSize(Point(2, 10)); + _textCursor->setColor(0, 0, 0); + _textCursor->setBlinkRate(300); + _textCursor->setMode(mode); + _textCursor->setBounds(_bounds); + _textCursor->show(); + } +} + +void CPetText::hideCursor() { + if (_textCursor) { + _textCursor->setMode(-1); + _textCursor->hide(); + _textCursor = nullptr; + } +} + +int CPetText::getNPCNum(uint npcId, uint startIndex) { + if (!_stringsMerged) { + mergeStrings(); + if (!_stringsMerged) + return -1; + } + + uint size = _lines.size(); + if (startIndex < 5 || startIndex >= size) + return -1; + + // Loop through string + for (const char *strP = _lines.c_str(); size >= 5; ++strP, --size) { + if (*strP == 26) { + byte id = *(strP - 2); + if (id == npcId) + return *(strP - 1); + } else if (*strP == 27) { + strP += 4; + } + } + + return - 1; +} + +void CPetText::setFontNumber(int fontNumber) { + if (fontNumber >= 0 && fontNumber <= 2) + _fontNumber = fontNumber; +} + +} // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_text.h b/engines/titanic/pet_control/pet_text.h new file mode 100644 index 0000000000..f5d4235690 --- /dev/null +++ b/engines/titanic/pet_control/pet_text.h @@ -0,0 +1,270 @@ +/* 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. + * + */ + +#ifndef TITANIC_PET_TEXT_H +#define TITANIC_PET_TEXT_H + +#include "common/keyboard.h" +#include "titanic/support/simple_file.h" +#include "titanic/support/screen_manager.h" +#include "titanic/support/text_cursor.h" + +namespace Titanic { + +class CPetText { + struct ArrayEntry { + CString _line; + CString _rgb; + CString _string3; + }; +private: + Common::Array<ArrayEntry> _array; + CString _lines; + bool _stringsMerged; + Rect _bounds; + int _maxCharsPerLine; + int _lineCount; + int _linesStart; + int _field3C; + int _field40; + int _field44; + int _backR; + int _backG; + int _backB; + int _textR; + int _textG; + int _textB; + int _fontNumber; + int _field64; + int _field68; + int _field6C; + bool _hasBorder; + int _scrollTop; + CTextCursor *_textCursor; + int _field7C; +private: + void setupArrays(int count); + + void freeArrays(); + + /** + * Merges the strings in the strings array + */ + void mergeStrings(); + + /** + * Append text to the current text line + */ + void appendText(const CString &str); + + void updateStr3(int lineNum); + + /** + * Ensures the Y scrolling for the text is in the valid range + */ + void constrainScrollUp(CScreenManager *screenManager); + + /** + * Ensures the Y scrolling for the text is in the valid range + */ + void constrainScrollDown(CScreenManager *screenManager); + + /** + * Get the page height for paging up and down + */ + int getPageHeight(CScreenManager *screenManager); +public: + CPetText(uint count = 10); + + /** + * Set up the control + */ + void setup(); + + /** + * Load the data for the control + */ + void load(SimpleFile *file, int param); + + /** + * Save the data for the control + */ + void save(SimpleFile *file, int indent); + + /** + * Set the bounds for the control + */ + void setBounds(const Rect &bounds) { _bounds = bounds; } + + /** + * Sets the flag for whether to draw a frame border around the control + */ + void setHasBorder(bool val) { _hasBorder = val; } + + /** + * Draw the control + */ + void draw(CScreenManager *screenManager); + + void resize(uint count); + + /** + * Returns the text from all the lines as a single string + */ + CString getText() const; + + /** + * Set the text + */ + void setText(const CString &str); + + /** + * Set text color + */ + void setColor(uint col); + + /** + * Set text color + */ + void setColor(byte r, byte g, byte b); + + /** + * Set the color for a line + */ + void setLineColor(uint lineNum, byte r, byte g, byte b); + + /** + * Set the color for a line + */ + void setLineColor(uint lineNum, uint col); + + /** + * Sets the maximum number of characters per line + */ + void setMaxCharsPerLine(int maxChars); + + /** + * Delete the last character from the last line + */ + void deleteLastChar(); + + void setNPC(int val1, int npcId); + + /** + * Get the index into _lines where on-screen text starts + */ + int getLinesStart() const { return _linesStart; } + + /** + * Scroll the text up + */ + void scrollUp(CScreenManager *screenManager); + + /** + * Scroll the text down + */ + void scrollDown(CScreenManager *screenManager); + + /** + * Scroll the text up one page + */ + void scrollUpPage(CScreenManager *screenManager); + + /** + * Scroll the text down one page + */ + void scrollDownPage(CScreenManager *screenManager); + + /** + * Scroll to the top of the text + */ + void scrollToTop(CScreenManager *screenManager); + + /** + * Scroll to the bottom of the text + */ + void scrollToBottom(CScreenManager *screenManager); + + /** + * Add a line to the text + */ + void addLine(const CString &str); + + /** + * Add a line to the text + */ + void addLine(const CString &str, uint color); + + /** + * Add a line to the text + */ + void addLine(const CString &str, byte r, byte g, byte b); + + /** + * Handles character processing to add or remove characters to + * the current text line + * @returns True if the Enter key was pressed + */ + bool handleKey(char c); + + /** + * Attaches the current system cursor to the text control, + * and give it suitable defaults + */ + void showCursor(int mode); + + /** + * Removes the cursor attached to the text + */ + void hideCursor(); + + /** + * Get an NPC Number embedded within on-screen text. + * Used by the PET log to encode which NPC spoke + */ + int getNPCNum(uint npcId, uint startIndex); + + /** + * Replaces any occurances of line colors that appear in the + * first list with the entry at the same index in the dest list + */ + void remapColors(uint count, uint *srcColors, uint *destColors); + + /** + * Set the font number to use + */ + void setFontNumber(int fontNumber); + + /** + * Get the width of the text + */ + int getTextWidth(CScreenManager *screenManager); + + /** + * Get the required height to draw the text + */ + int getTextHeight(CScreenManager *screenManager); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PET_TEXT_H */ |