Files
2026-02-02 04:50:13 +01:00

517 lines
12 KiB
C++

/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#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,
#if defined(DISABLE_SKIP)
0x0B, 0x01,
GLYPH_NAVIGATION_CONTROLLER,
#else
0x0B, 0x02,
GLYPH_NAVIGATION_CONTROLLER, GLYPH_SKIP_NAVIGATION,
#endif
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_UNSELECTED);
_left.reset("PetLeft", _petControl, MODE_SELECTED);
_right.reset("PetRightUp", _petControl, MODE_UNSELECTED);
_right.reset("PetRight", _petControl, MODE_SELECTED);
_top.reset("PetTopUp", _petControl, MODE_UNSELECTED);
_top.reset("PetTop", _petControl, MODE_SELECTED);
_bottom.reset("PetBottomUp", _petControl, MODE_UNSELECTED);
_bottom.reset("PetBottom", _petControl, MODE_SELECTED);
_action.reset("PetActionUp", _petControl, MODE_UNSELECTED);
_action.reset("PetAction", _petControl, MODE_SELECTED);
_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::ActionMsg(CActionMsg *msg) {
return _items.ActionMsg(msg);
}
bool CPetRemote::MouseWheelMsg(CMouseWheelMsg *msg) {
if (msg->_wheelUp)
_items.scrollLeft();
else
_items.scrollRight();
return true;
}
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();
}
}
}
}
CTextControl *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] == 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[1]; ++ctr)
indexes.push_back(p[ctr + 2]);
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;
#if !defined(DISABLE_SKIP)
case GLYPH_SKIP_NAVIGATION:
glyph = new CSkipNavigationGlyph();
break;
#endif
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();
break;
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