aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/pet_control
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/pet_control')
-rw-r--r--engines/titanic/pet_control/pet_control.cpp680
-rw-r--r--engines/titanic/pet_control/pet_control.h574
-rw-r--r--engines/titanic/pet_control/pet_conversations.cpp579
-rw-r--r--engines/titanic/pet_control/pet_conversations.h267
-rw-r--r--engines/titanic/pet_control/pet_drag_chev.cpp76
-rw-r--r--engines/titanic/pet_control/pet_drag_chev.h52
-rw-r--r--engines/titanic/pet_control/pet_element.cpp106
-rw-r--r--engines/titanic/pet_control/pet_element.h154
-rw-r--r--engines/titanic/pet_control/pet_frame.cpp154
-rw-r--r--engines/titanic/pet_control/pet_frame.h101
-rw-r--r--engines/titanic/pet_control/pet_gfx_element.cpp103
-rw-r--r--engines/titanic/pet_control/pet_gfx_element.h74
-rw-r--r--engines/titanic/pet_control/pet_glyphs.cpp566
-rw-r--r--engines/titanic/pet_control/pet_glyphs.h492
-rw-r--r--engines/titanic/pet_control/pet_graphic.cpp39
-rw-r--r--engines/titanic/pet_control/pet_graphic.h48
-rw-r--r--engines/titanic/pet_control/pet_graphic2.cpp39
-rw-r--r--engines/titanic/pet_control/pet_graphic2.h48
-rw-r--r--engines/titanic/pet_control/pet_inventory.cpp255
-rw-r--r--engines/titanic/pet_control/pet_inventory.h174
-rw-r--r--engines/titanic/pet_control/pet_inventory_glyphs.cpp342
-rw-r--r--engines/titanic/pet_control/pet_inventory_glyphs.h153
-rw-r--r--engines/titanic/pet_control/pet_leaf.cpp39
-rw-r--r--engines/titanic/pet_control/pet_leaf.h48
-rw-r--r--engines/titanic/pet_control/pet_load.cpp70
-rw-r--r--engines/titanic/pet_control/pet_load.h70
-rw-r--r--engines/titanic/pet_control/pet_load_save.cpp191
-rw-r--r--engines/titanic/pet_control/pet_load_save.h119
-rw-r--r--engines/titanic/pet_control/pet_message.cpp57
-rw-r--r--engines/titanic/pet_control/pet_message.h96
-rw-r--r--engines/titanic/pet_control/pet_mode_off.cpp42
-rw-r--r--engines/titanic/pet_control/pet_mode_off.h49
-rw-r--r--engines/titanic/pet_control/pet_mode_on.cpp42
-rw-r--r--engines/titanic/pet_control/pet_mode_on.h49
-rw-r--r--engines/titanic/pet_control/pet_mode_panel.cpp42
-rw-r--r--engines/titanic/pet_control/pet_mode_panel.h49
-rw-r--r--engines/titanic/pet_control/pet_pannel1.cpp39
-rw-r--r--engines/titanic/pet_control/pet_pannel1.h48
-rw-r--r--engines/titanic/pet_control/pet_pannel2.cpp39
-rw-r--r--engines/titanic/pet_control/pet_pannel2.h48
-rw-r--r--engines/titanic/pet_control/pet_pannel3.cpp39
-rw-r--r--engines/titanic/pet_control/pet_pannel3.h48
-rw-r--r--engines/titanic/pet_control/pet_quit.cpp90
-rw-r--r--engines/titanic/pet_control/pet_quit.h75
-rw-r--r--engines/titanic/pet_control/pet_real_life.cpp129
-rw-r--r--engines/titanic/pet_control/pet_real_life.h138
-rw-r--r--engines/titanic/pet_control/pet_remote.cpp495
-rw-r--r--engines/titanic/pet_control/pet_remote.h159
-rw-r--r--engines/titanic/pet_control/pet_remote_glyphs.cpp562
-rw-r--r--engines/titanic/pet_control/pet_remote_glyphs.h715
-rw-r--r--engines/titanic/pet_control/pet_rooms.cpp380
-rw-r--r--engines/titanic/pet_control/pet_rooms.h219
-rw-r--r--engines/titanic/pet_control/pet_rooms_glyphs.cpp257
-rw-r--r--engines/titanic/pet_control/pet_rooms_glyphs.h166
-rw-r--r--engines/titanic/pet_control/pet_save.cpp72
-rw-r--r--engines/titanic/pet_control/pet_save.h88
-rw-r--r--engines/titanic/pet_control/pet_section.cpp109
-rw-r--r--engines/titanic/pet_control/pet_section.h250
-rw-r--r--engines/titanic/pet_control/pet_slider.cpp246
-rw-r--r--engines/titanic/pet_control/pet_slider.h239
-rw-r--r--engines/titanic/pet_control/pet_sound.cpp282
-rw-r--r--engines/titanic/pet_control/pet_sound.h104
-rw-r--r--engines/titanic/pet_control/pet_starfield.cpp257
-rw-r--r--engines/titanic/pet_control/pet_starfield.h125
-rw-r--r--engines/titanic/pet_control/pet_text.cpp478
-rw-r--r--engines/titanic/pet_control/pet_text.h270
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 */